@stigmer/react 3.12.1 → 3.12.2

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 (658) hide show
  1. package/access/ManageAccessDialog.d.ts.map +1 -1
  2. package/access/ManageAccessDialog.js +7 -2
  3. package/access/ManageAccessDialog.js.map +1 -1
  4. package/activity/format-relative-time.d.ts +11 -9
  5. package/activity/format-relative-time.d.ts.map +1 -1
  6. package/activity/format-relative-time.js +11 -9
  7. package/activity/format-relative-time.js.map +1 -1
  8. package/agent/steps/CapabilitiesStep.js +5 -2
  9. package/agent/steps/CapabilitiesStep.js.map +1 -1
  10. package/agent/steps/IdentityStep.d.ts.map +1 -1
  11. package/agent/steps/IdentityStep.js +6 -5
  12. package/agent/steps/IdentityStep.js.map +1 -1
  13. package/agent-instance/CreateAgentInstanceDialog.d.ts.map +1 -1
  14. package/agent-instance/CreateAgentInstanceDialog.js +10 -2
  15. package/agent-instance/CreateAgentInstanceDialog.js.map +1 -1
  16. package/api-key/ApiKeyCreatedAlert.d.ts.map +1 -1
  17. package/api-key/ApiKeyCreatedAlert.js +12 -20
  18. package/api-key/ApiKeyCreatedAlert.js.map +1 -1
  19. package/api-key/ApiKeyListPanel.d.ts.map +1 -1
  20. package/api-key/ApiKeyListPanel.js +3 -23
  21. package/api-key/ApiKeyListPanel.js.map +1 -1
  22. package/api-key/CreateApiKeyForm.d.ts.map +1 -1
  23. package/api-key/CreateApiKeyForm.js +6 -10
  24. package/api-key/CreateApiKeyForm.js.map +1 -1
  25. package/approval-defaults-context.d.ts +47 -0
  26. package/approval-defaults-context.d.ts.map +1 -0
  27. package/approval-defaults-context.js +27 -0
  28. package/approval-defaults-context.js.map +1 -0
  29. package/attachment/index.d.ts +2 -0
  30. package/attachment/index.d.ts.map +1 -1
  31. package/attachment/index.js +1 -0
  32. package/attachment/index.js.map +1 -1
  33. package/attachment/vision-preflight.d.ts +113 -0
  34. package/attachment/vision-preflight.d.ts.map +1 -0
  35. package/attachment/vision-preflight.js +143 -0
  36. package/attachment/vision-preflight.js.map +1 -0
  37. package/billing/AutoRechargeCard.d.ts.map +1 -1
  38. package/billing/AutoRechargeCard.js +3 -2
  39. package/billing/AutoRechargeCard.js.map +1 -1
  40. package/billing/BillingSection.d.ts.map +1 -1
  41. package/billing/BillingSection.js +3 -2
  42. package/billing/BillingSection.js.map +1 -1
  43. package/channel/ChannelConversationsDialog.d.ts.map +1 -1
  44. package/channel/ChannelConversationsDialog.js +5 -4
  45. package/channel/ChannelConversationsDialog.js.map +1 -1
  46. package/channel/ChannelCredentialsDialog.d.ts.map +1 -1
  47. package/channel/ChannelCredentialsDialog.js +9 -4
  48. package/channel/ChannelCredentialsDialog.js.map +1 -1
  49. package/channel/ChannelTemplatesDialog.d.ts.map +1 -1
  50. package/channel/ChannelTemplatesDialog.js +5 -4
  51. package/channel/ChannelTemplatesDialog.js.map +1 -1
  52. package/channel/ConnectSlackDialog.d.ts.map +1 -1
  53. package/channel/ConnectSlackDialog.js +9 -4
  54. package/channel/ConnectSlackDialog.js.map +1 -1
  55. package/channel/ConnectWhatsAppDialog.d.ts.map +1 -1
  56. package/channel/ConnectWhatsAppDialog.js +9 -4
  57. package/channel/ConnectWhatsAppDialog.js.map +1 -1
  58. package/channel/useChannelSessions.d.ts.map +1 -1
  59. package/channel/useChannelSessions.js.map +1 -1
  60. package/channel-app/ChannelAppDetailPanel.d.ts.map +1 -1
  61. package/channel-app/ChannelAppDetailPanel.js +8 -5
  62. package/channel-app/ChannelAppDetailPanel.js.map +1 -1
  63. package/channel-app/CreateChannelAppForm.d.ts.map +1 -1
  64. package/channel-app/CreateChannelAppForm.js +12 -7
  65. package/channel-app/CreateChannelAppForm.js.map +1 -1
  66. package/channel-app/internal.d.ts +0 -1
  67. package/channel-app/internal.d.ts.map +1 -1
  68. package/channel-app/internal.js +5 -10
  69. package/channel-app/internal.js.map +1 -1
  70. package/composer/ComposerToolbar.js +2 -1
  71. package/composer/ComposerToolbar.js.map +1 -1
  72. package/composer/SessionComposer.d.ts +1 -1
  73. package/composer/SessionComposer.d.ts.map +1 -1
  74. package/composer/SessionComposer.js +120 -13
  75. package/composer/SessionComposer.js.map +1 -1
  76. package/composer/icons.d.ts +0 -1
  77. package/composer/icons.d.ts.map +1 -1
  78. package/composer/icons.js +0 -3
  79. package/composer/icons.js.map +1 -1
  80. package/conversation/ConversationComposer.js +1 -1
  81. package/conversation/ConversationComposer.js.map +1 -1
  82. package/conversation/ConversationListPane.d.ts.map +1 -1
  83. package/conversation/ConversationListPane.js +3 -2
  84. package/conversation/ConversationListPane.js.map +1 -1
  85. package/cursor-accounts/MemberCoverageTable.js +3 -14
  86. package/cursor-accounts/MemberCoverageTable.js.map +1 -1
  87. package/dashboard/DashboardFailedRuns.d.ts.map +1 -1
  88. package/dashboard/DashboardFailedRuns.js +2 -14
  89. package/dashboard/DashboardFailedRuns.js.map +1 -1
  90. package/environment/CreateEnvironmentForm.d.ts.map +1 -1
  91. package/environment/CreateEnvironmentForm.js +4 -8
  92. package/environment/CreateEnvironmentForm.js.map +1 -1
  93. package/environment/EnvVarForm.d.ts.map +1 -1
  94. package/environment/EnvVarForm.js +2 -4
  95. package/environment/EnvVarForm.js.map +1 -1
  96. package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
  97. package/environment/EnvironmentVariableEditor.js +5 -7
  98. package/environment/EnvironmentVariableEditor.js.map +1 -1
  99. package/execution/ArtifactApplyButton.d.ts.map +1 -1
  100. package/execution/ArtifactApplyButton.js +2 -4
  101. package/execution/ArtifactApplyButton.js.map +1 -1
  102. package/execution/ExecutionErrorNotice.d.ts +36 -0
  103. package/execution/ExecutionErrorNotice.d.ts.map +1 -0
  104. package/execution/ExecutionErrorNotice.js +39 -0
  105. package/execution/ExecutionErrorNotice.js.map +1 -0
  106. package/execution/FilePathLink.d.ts.map +1 -1
  107. package/execution/FilePathLink.js +5 -8
  108. package/execution/FilePathLink.js.map +1 -1
  109. package/execution/FileReviewCard.d.ts.map +1 -1
  110. package/execution/FileReviewCard.js +1 -6
  111. package/execution/FileReviewCard.js.map +1 -1
  112. package/execution/FollowUpInput.d.ts.map +1 -1
  113. package/execution/FollowUpInput.js +1 -3
  114. package/execution/FollowUpInput.js.map +1 -1
  115. package/execution/LivenessStatusLine.d.ts +40 -0
  116. package/execution/LivenessStatusLine.d.ts.map +1 -0
  117. package/execution/LivenessStatusLine.js +34 -0
  118. package/execution/LivenessStatusLine.js.map +1 -0
  119. package/execution/MessageEntry.d.ts.map +1 -1
  120. package/execution/MessageEntry.js +31 -3
  121. package/execution/MessageEntry.js.map +1 -1
  122. package/execution/MessageThread.d.ts +25 -0
  123. package/execution/MessageThread.d.ts.map +1 -1
  124. package/execution/MessageThread.js +51 -36
  125. package/execution/MessageThread.js.map +1 -1
  126. package/execution/SetupProgress.d.ts.map +1 -1
  127. package/execution/SetupProgress.js +1 -1
  128. package/execution/SetupProgress.js.map +1 -1
  129. package/execution/SubAgentSection.d.ts.map +1 -1
  130. package/execution/SubAgentSection.js +9 -7
  131. package/execution/SubAgentSection.js.map +1 -1
  132. package/execution/TerminalSession.d.ts +30 -0
  133. package/execution/TerminalSession.d.ts.map +1 -1
  134. package/execution/TerminalSession.js +37 -1
  135. package/execution/TerminalSession.js.map +1 -1
  136. package/execution/ToolCallDetail.d.ts +9 -0
  137. package/execution/ToolCallDetail.d.ts.map +1 -1
  138. package/execution/ToolCallDetail.js +16 -0
  139. package/execution/ToolCallDetail.js.map +1 -1
  140. package/execution/ToolCallItem.d.ts +20 -6
  141. package/execution/ToolCallItem.d.ts.map +1 -1
  142. package/execution/ToolCallItem.js +102 -29
  143. package/execution/ToolCallItem.js.map +1 -1
  144. package/execution/ToolRunGroup.d.ts.map +1 -1
  145. package/execution/ToolRunGroup.js +11 -11
  146. package/execution/ToolRunGroup.js.map +1 -1
  147. package/execution/WriteBackCard.d.ts.map +1 -1
  148. package/execution/WriteBackCard.js +5 -20
  149. package/execution/WriteBackCard.js.map +1 -1
  150. package/execution/index.d.ts +6 -2
  151. package/execution/index.d.ts.map +1 -1
  152. package/execution/index.js +3 -1
  153. package/execution/index.js.map +1 -1
  154. package/execution/tool-categories.d.ts +42 -7
  155. package/execution/tool-categories.d.ts.map +1 -1
  156. package/execution/tool-categories.js +38 -4
  157. package/execution/tool-categories.js.map +1 -1
  158. package/execution/tool-presenter.d.ts +17 -1
  159. package/execution/tool-presenter.d.ts.map +1 -1
  160. package/execution/tool-presenter.js +4 -1
  161. package/execution/tool-presenter.js.map +1 -1
  162. package/execution/useArtifactInspection.d.ts.map +1 -1
  163. package/execution/useArtifactInspection.js +4 -7
  164. package/execution/useArtifactInspection.js.map +1 -1
  165. package/iam-policy/GrantAccessForm.d.ts.map +1 -1
  166. package/iam-policy/GrantAccessForm.js +2 -4
  167. package/iam-policy/GrantAccessForm.js.map +1 -1
  168. package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
  169. package/iam-policy/OrgMembersPanel.js +3 -5
  170. package/iam-policy/OrgMembersPanel.js.map +1 -1
  171. package/iam-policy/RoleSelector.d.ts.map +1 -1
  172. package/iam-policy/RoleSelector.js +7 -1
  173. package/iam-policy/RoleSelector.js.map +1 -1
  174. package/identity-provider/CreateIdentityProviderForm.d.ts.map +1 -1
  175. package/identity-provider/CreateIdentityProviderForm.js +6 -9
  176. package/identity-provider/CreateIdentityProviderForm.js.map +1 -1
  177. package/identity-provider/IdentityProviderDetailPanel.d.ts.map +1 -1
  178. package/identity-provider/IdentityProviderDetailPanel.js +17 -26
  179. package/identity-provider/IdentityProviderDetailPanel.js.map +1 -1
  180. package/identity-provider/IdentityProviderListPanel.d.ts.map +1 -1
  181. package/identity-provider/IdentityProviderListPanel.js +2 -4
  182. package/identity-provider/IdentityProviderListPanel.js.map +1 -1
  183. package/identity-provider/IdentityProviderWizard.d.ts.map +1 -1
  184. package/identity-provider/IdentityProviderWizard.js +8 -7
  185. package/identity-provider/IdentityProviderWizard.js.map +1 -1
  186. package/identity-provider/SsoLoginPrompt.js +5 -6
  187. package/identity-provider/SsoLoginPrompt.js.map +1 -1
  188. package/index.d.ts +9 -8
  189. package/index.d.ts.map +1 -1
  190. package/index.js +4 -4
  191. package/index.js.map +1 -1
  192. package/internal/DecisionButton.d.ts.map +1 -1
  193. package/internal/DecisionButton.js +1 -6
  194. package/internal/DecisionButton.js.map +1 -1
  195. package/internal/SpinnerIcon.d.ts +22 -0
  196. package/internal/SpinnerIcon.d.ts.map +1 -0
  197. package/internal/SpinnerIcon.js +23 -0
  198. package/internal/SpinnerIcon.js.map +1 -0
  199. package/internal/select-element-text.d.ts +11 -0
  200. package/internal/select-element-text.d.ts.map +1 -0
  201. package/internal/select-element-text.js +19 -0
  202. package/internal/select-element-text.js.map +1 -0
  203. package/internal/thread-card/ThreadCardShell.d.ts +27 -10
  204. package/internal/thread-card/ThreadCardShell.d.ts.map +1 -1
  205. package/internal/thread-card/ThreadCardShell.js +11 -5
  206. package/internal/thread-card/ThreadCardShell.js.map +1 -1
  207. package/internal/thread-card/glyphs.d.ts +11 -2
  208. package/internal/thread-card/glyphs.d.ts.map +1 -1
  209. package/internal/thread-card/glyphs.js +9 -3
  210. package/internal/thread-card/glyphs.js.map +1 -1
  211. package/internal/thread-card/index.d.ts +1 -1
  212. package/internal/thread-card/index.d.ts.map +1 -1
  213. package/internal/thread-card/index.js.map +1 -1
  214. package/internal/useCopyFeedback.d.ts +28 -0
  215. package/internal/useCopyFeedback.d.ts.map +1 -0
  216. package/internal/useCopyFeedback.js +40 -0
  217. package/internal/useCopyFeedback.js.map +1 -0
  218. package/invitation/InvitationCreatedAlert.d.ts.map +1 -1
  219. package/invitation/InvitationCreatedAlert.js +12 -19
  220. package/invitation/InvitationCreatedAlert.js.map +1 -1
  221. package/invitation/InvitationManager.d.ts.map +1 -1
  222. package/invitation/InvitationManager.js +14 -21
  223. package/invitation/InvitationManager.js.map +1 -1
  224. package/invitation/InvitationRedemption.d.ts.map +1 -1
  225. package/invitation/InvitationRedemption.js +2 -4
  226. package/invitation/InvitationRedemption.js.map +1 -1
  227. package/library/useExportResource.d.ts.map +1 -1
  228. package/library/useExportResource.js +16 -27
  229. package/library/useExportResource.js.map +1 -1
  230. package/manifest/ApplyManifestDialog.js +1 -1
  231. package/manifest/EditResourceYamlDialog.js +1 -1
  232. package/mcp-server/DefinitionDriftNotice.d.ts +42 -0
  233. package/mcp-server/DefinitionDriftNotice.d.ts.map +1 -0
  234. package/mcp-server/DefinitionDriftNotice.js +52 -0
  235. package/mcp-server/DefinitionDriftNotice.js.map +1 -0
  236. package/mcp-server/McpServerConnectDialog.js +1 -1
  237. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  238. package/mcp-server/McpServerDetailView.js +47 -14
  239. package/mcp-server/McpServerDetailView.js.map +1 -1
  240. package/mcp-server/OAuthAppForm.d.ts.map +1 -1
  241. package/mcp-server/OAuthAppForm.js +2 -4
  242. package/mcp-server/OAuthAppForm.js.map +1 -1
  243. package/mcp-server/internal/definitionDrift.d.ts +39 -0
  244. package/mcp-server/internal/definitionDrift.d.ts.map +1 -0
  245. package/mcp-server/internal/definitionDrift.js +122 -0
  246. package/mcp-server/internal/definitionDrift.js.map +1 -0
  247. package/mcp-server/internal/mcpServerToInput.d.ts.map +1 -1
  248. package/mcp-server/internal/mcpServerToInput.js +3 -0
  249. package/mcp-server/internal/mcpServerToInput.js.map +1 -1
  250. package/mcp-server/steps/EnvironmentAuthStep.d.ts.map +1 -1
  251. package/mcp-server/steps/EnvironmentAuthStep.js +8 -4
  252. package/mcp-server/steps/EnvironmentAuthStep.js.map +1 -1
  253. package/mcp-server/steps/IdentityTransportStep.d.ts.map +1 -1
  254. package/mcp-server/steps/IdentityTransportStep.js +5 -4
  255. package/mcp-server/steps/IdentityTransportStep.js.map +1 -1
  256. package/mcp-server/useMcpServerConnect.d.ts +1 -1
  257. package/mcp-server/useMcpServerDefinitionDrift.d.ts +44 -0
  258. package/mcp-server/useMcpServerDefinitionDrift.d.ts.map +1 -0
  259. package/mcp-server/useMcpServerDefinitionDrift.js +61 -0
  260. package/mcp-server/useMcpServerDefinitionDrift.js.map +1 -0
  261. package/models/ModelRegistryContext.d.ts +7 -1
  262. package/models/ModelRegistryContext.d.ts.map +1 -1
  263. package/models/ModelRegistryContext.js.map +1 -1
  264. package/models/ModelSelector.js +9 -1
  265. package/models/ModelSelector.js.map +1 -1
  266. package/models/index.d.ts +2 -2
  267. package/models/index.d.ts.map +1 -1
  268. package/models/index.js +1 -1
  269. package/models/index.js.map +1 -1
  270. package/models/registry.d.ts +88 -6
  271. package/models/registry.d.ts.map +1 -1
  272. package/models/registry.js +133 -27
  273. package/models/registry.js.map +1 -1
  274. package/models/useModelRegistry.d.ts +7 -1
  275. package/models/useModelRegistry.d.ts.map +1 -1
  276. package/models/useModelRegistry.js +3 -2
  277. package/models/useModelRegistry.js.map +1 -1
  278. package/oauth-app/CreateOAuthAppForm.d.ts.map +1 -1
  279. package/oauth-app/CreateOAuthAppForm.js +4 -5
  280. package/oauth-app/CreateOAuthAppForm.js.map +1 -1
  281. package/oauth-app/OAuthAppDetailPanel.d.ts.map +1 -1
  282. package/oauth-app/OAuthAppDetailPanel.js +5 -6
  283. package/oauth-app/OAuthAppDetailPanel.js.map +1 -1
  284. package/organization/CreateOrganizationForm.d.ts.map +1 -1
  285. package/organization/CreateOrganizationForm.js +5 -9
  286. package/organization/CreateOrganizationForm.js.map +1 -1
  287. package/organization/OrgProfilePanel.d.ts.map +1 -1
  288. package/organization/OrgProfilePanel.js +7 -16
  289. package/organization/OrgProfilePanel.js.map +1 -1
  290. package/package.json +4 -4
  291. package/platform-client/CreatePlatformClientForm.d.ts.map +1 -1
  292. package/platform-client/CreatePlatformClientForm.js +5 -6
  293. package/platform-client/CreatePlatformClientForm.js.map +1 -1
  294. package/platform-client/PlatformClientDetailPanel.d.ts.map +1 -1
  295. package/platform-client/PlatformClientDetailPanel.js +6 -7
  296. package/platform-client/PlatformClientDetailPanel.js.map +1 -1
  297. package/platform-client/PlatformClientListPanel.d.ts.map +1 -1
  298. package/platform-client/PlatformClientListPanel.js +2 -4
  299. package/platform-client/PlatformClientListPanel.js.map +1 -1
  300. package/platform-client/PlatformClientSecretAlert.d.ts.map +1 -1
  301. package/platform-client/PlatformClientSecretAlert.js +18 -25
  302. package/platform-client/PlatformClientSecretAlert.js.map +1 -1
  303. package/provider.d.ts +34 -1
  304. package/provider.d.ts.map +1 -1
  305. package/provider.js +14 -7
  306. package/provider.js.map +1 -1
  307. package/resource-creation/WizardNav.d.ts.map +1 -1
  308. package/resource-creation/WizardNav.js +2 -4
  309. package/resource-creation/WizardNav.js.map +1 -1
  310. package/resource-detail/ConfirmDialog.js +1 -1
  311. package/resource-detail/useCopyResource.d.ts +4 -3
  312. package/resource-detail/useCopyResource.d.ts.map +1 -1
  313. package/resource-detail/useCopyResource.js +10 -19
  314. package/resource-detail/useCopyResource.js.map +1 -1
  315. package/schedule/ScheduleDetailView.d.ts.map +1 -1
  316. package/schedule/ScheduleDetailView.js +2 -4
  317. package/schedule/ScheduleDetailView.js.map +1 -1
  318. package/schedule/ScheduleForm.d.ts.map +1 -1
  319. package/schedule/ScheduleForm.js +6 -7
  320. package/schedule/ScheduleForm.js.map +1 -1
  321. package/session/NewSessionViewer.d.ts +52 -2
  322. package/session/NewSessionViewer.d.ts.map +1 -1
  323. package/session/NewSessionViewer.js +21 -6
  324. package/session/NewSessionViewer.js.map +1 -1
  325. package/session/SessionViewer.d.ts +63 -2
  326. package/session/SessionViewer.d.ts.map +1 -1
  327. package/session/SessionViewer.js +43 -17
  328. package/session/SessionViewer.js.map +1 -1
  329. package/session/audience.d.ts +17 -0
  330. package/session/audience.d.ts.map +1 -1
  331. package/session/index.d.ts +2 -1
  332. package/session/index.d.ts.map +1 -1
  333. package/session/index.js.map +1 -1
  334. package/session/run-config.d.ts +50 -0
  335. package/session/run-config.d.ts.map +1 -0
  336. package/session/run-config.js +15 -0
  337. package/session/run-config.js.map +1 -0
  338. package/session/useNewSessionFlow.d.ts +11 -0
  339. package/session/useNewSessionFlow.d.ts.map +1 -1
  340. package/session/useNewSessionFlow.js +29 -2
  341. package/session/useNewSessionFlow.js.map +1 -1
  342. package/session/useSessionConversation.d.ts +7 -7
  343. package/session/useSessionConversation.d.ts.map +1 -1
  344. package/session/useSessionConversation.js +2 -0
  345. package/session/useSessionConversation.js.map +1 -1
  346. package/session/useSessionPageFlow.d.ts +18 -4
  347. package/session/useSessionPageFlow.d.ts.map +1 -1
  348. package/session/useSessionPageFlow.js +33 -6
  349. package/session/useSessionPageFlow.js.map +1 -1
  350. package/session/useSessionPanel.d.ts +37 -2
  351. package/session/useSessionPanel.d.ts.map +1 -1
  352. package/session/useSessionPanel.js +44 -10
  353. package/session/useSessionPanel.js.map +1 -1
  354. package/settings/ApiKeysSection.d.ts.map +1 -1
  355. package/settings/ApiKeysSection.js +3 -2
  356. package/settings/ApiKeysSection.js.map +1 -1
  357. package/settings/ChannelAppsSection.d.ts.map +1 -1
  358. package/settings/ChannelAppsSection.js +3 -2
  359. package/settings/ChannelAppsSection.js.map +1 -1
  360. package/settings/EnvironmentsSection.js +5 -3
  361. package/settings/EnvironmentsSection.js.map +1 -1
  362. package/settings/IdentityProvidersSection.d.ts.map +1 -1
  363. package/settings/IdentityProvidersSection.js +3 -2
  364. package/settings/IdentityProvidersSection.js.map +1 -1
  365. package/settings/InvitationsSection.d.ts.map +1 -1
  366. package/settings/InvitationsSection.js +3 -1
  367. package/settings/InvitationsSection.js.map +1 -1
  368. package/settings/MembersSection.d.ts.map +1 -1
  369. package/settings/MembersSection.js +3 -1
  370. package/settings/MembersSection.js.map +1 -1
  371. package/settings/OAuthAppsSection.d.ts.map +1 -1
  372. package/settings/OAuthAppsSection.js +3 -2
  373. package/settings/OAuthAppsSection.js.map +1 -1
  374. package/settings/OrgProfileSection.d.ts.map +1 -1
  375. package/settings/OrgProfileSection.js +3 -2
  376. package/settings/OrgProfileSection.js.map +1 -1
  377. package/settings/PlatformClientsSection.d.ts.map +1 -1
  378. package/settings/PlatformClientsSection.js +3 -2
  379. package/settings/PlatformClientsSection.js.map +1 -1
  380. package/settings/UsageSection.d.ts.map +1 -1
  381. package/settings/UsageSection.js +3 -1
  382. package/settings/UsageSection.js.map +1 -1
  383. package/sharing/ShareAgentDialog.d.ts.map +1 -1
  384. package/sharing/ShareAgentDialog.js +18 -7
  385. package/sharing/ShareAgentDialog.js.map +1 -1
  386. package/sidebar/chrome.d.ts +3 -4
  387. package/sidebar/chrome.d.ts.map +1 -1
  388. package/sidebar/chrome.js +5 -4
  389. package/sidebar/chrome.js.map +1 -1
  390. package/skill/SkillDiffDialog.js +1 -1
  391. package/src/access/ManageAccessDialog.tsx +10 -4
  392. package/src/activity/format-relative-time.ts +11 -9
  393. package/src/agent/steps/CapabilitiesStep.tsx +6 -3
  394. package/src/agent/steps/IdentityStep.tsx +19 -12
  395. package/src/agent-instance/CreateAgentInstanceDialog.tsx +17 -8
  396. package/src/api-key/ApiKeyCreatedAlert.tsx +10 -19
  397. package/src/api-key/ApiKeyListPanel.tsx +3 -39
  398. package/src/api-key/CreateApiKeyForm.tsx +12 -26
  399. package/src/approval-defaults-context.ts +56 -0
  400. package/src/attachment/__tests__/vision-preflight.test.ts +311 -0
  401. package/src/attachment/index.ts +12 -0
  402. package/src/attachment/vision-preflight.ts +236 -0
  403. package/src/billing/AutoRechargeCard.tsx +5 -4
  404. package/src/billing/BillingSection.tsx +4 -3
  405. package/src/channel/ChannelConversationsDialog.tsx +8 -4
  406. package/src/channel/ChannelCredentialsDialog.tsx +14 -4
  407. package/src/channel/ChannelTemplatesDialog.tsx +8 -4
  408. package/src/channel/ConnectSlackDialog.tsx +14 -4
  409. package/src/channel/ConnectWhatsAppDialog.tsx +14 -4
  410. package/src/channel/useChannelSessions.ts +3 -0
  411. package/src/channel-app/ChannelAppDetailPanel.tsx +15 -12
  412. package/src/channel-app/CreateChannelAppForm.tsx +17 -12
  413. package/src/channel-app/internal.tsx +5 -25
  414. package/src/composer/ComposerToolbar.tsx +1 -1
  415. package/src/composer/SessionComposer.tsx +160 -13
  416. package/src/composer/__tests__/SessionComposer-modelCoherence.test.tsx +220 -0
  417. package/src/composer/__tests__/SessionComposer-visionPreflight.test.tsx +222 -0
  418. package/src/composer/icons.tsx +0 -18
  419. package/src/conversation/ConversationComposer.tsx +1 -1
  420. package/src/conversation/ConversationListPane.tsx +4 -3
  421. package/src/cursor-accounts/MemberCoverageTable.tsx +3 -14
  422. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +2 -10
  423. package/src/dashboard/DashboardFailedRuns.tsx +2 -12
  424. package/src/environment/CreateEnvironmentForm.tsx +8 -27
  425. package/src/environment/EnvVarForm.tsx +2 -18
  426. package/src/environment/EnvironmentVariableEditor.tsx +5 -21
  427. package/src/execution/ArtifactApplyButton.tsx +2 -17
  428. package/src/execution/ExecutionErrorNotice.tsx +99 -0
  429. package/src/execution/FilePathLink.tsx +5 -9
  430. package/src/execution/FileReviewCard.tsx +1 -20
  431. package/src/execution/FollowUpInput.tsx +1 -16
  432. package/src/execution/LivenessStatusLine.tsx +59 -0
  433. package/src/execution/MessageEntry.tsx +136 -25
  434. package/src/execution/MessageThread.tsx +84 -83
  435. package/src/execution/SetupProgress.tsx +5 -1
  436. package/src/execution/SubAgentSection.tsx +9 -20
  437. package/src/execution/TerminalSession.tsx +97 -10
  438. package/src/execution/ToolCallDetail.tsx +19 -0
  439. package/src/execution/ToolCallItem.tsx +157 -37
  440. package/src/execution/ToolRunGroup.tsx +30 -32
  441. package/src/execution/WriteBackCard.tsx +5 -24
  442. package/src/execution/__tests__/MessageEntry-copy.test.tsx +125 -0
  443. package/src/execution/__tests__/MessageThread.test.tsx +97 -0
  444. package/src/execution/__tests__/TerminalSession.test.tsx +71 -1
  445. package/src/execution/__tests__/ToolCallDetail.test.tsx +33 -1
  446. package/src/execution/__tests__/ToolCallItem.test.tsx +299 -11
  447. package/src/execution/__tests__/ToolRunGroup.test.tsx +41 -9
  448. package/src/execution/__tests__/message-thread-slots.test.tsx +92 -0
  449. package/src/execution/__tests__/tool-presenter.test.tsx +41 -4
  450. package/src/execution/index.ts +8 -2
  451. package/src/execution/tool-categories.ts +72 -8
  452. package/src/execution/tool-presenter.ts +22 -1
  453. package/src/execution/useArtifactInspection.ts +4 -8
  454. package/src/iam-policy/GrantAccessForm.tsx +2 -18
  455. package/src/iam-policy/OrgMembersPanel.tsx +3 -19
  456. package/src/iam-policy/RoleSelector.tsx +8 -1
  457. package/src/identity-provider/CreateIdentityProviderForm.tsx +13 -31
  458. package/src/identity-provider/IdentityProviderDetailPanel.tsx +24 -49
  459. package/src/identity-provider/IdentityProviderListPanel.tsx +2 -18
  460. package/src/identity-provider/IdentityProviderWizard.tsx +15 -32
  461. package/src/identity-provider/SsoLoginPrompt.tsx +6 -21
  462. package/src/index.ts +23 -1
  463. package/src/internal/DecisionButton.tsx +1 -20
  464. package/src/internal/SpinnerIcon.tsx +42 -0
  465. package/src/internal/__tests__/ThreadCardShell.test.tsx +43 -7
  466. package/src/internal/__tests__/useCopyFeedback.test.ts +92 -0
  467. package/src/internal/select-element-text.ts +17 -0
  468. package/src/internal/thread-card/ThreadCardShell.tsx +53 -21
  469. package/src/internal/thread-card/glyphs.tsx +24 -3
  470. package/src/internal/thread-card/index.ts +1 -0
  471. package/src/internal/useCopyFeedback.ts +61 -0
  472. package/src/invitation/InvitationCreatedAlert.tsx +10 -18
  473. package/src/invitation/InvitationManager.tsx +23 -34
  474. package/src/invitation/InvitationRedemption.tsx +2 -18
  475. package/src/library/useExportResource.ts +15 -29
  476. package/src/manifest/ApplyManifestDialog.tsx +1 -1
  477. package/src/manifest/EditResourceYamlDialog.tsx +1 -1
  478. package/src/mcp-server/DefinitionDriftNotice.tsx +120 -0
  479. package/src/mcp-server/McpServerConnectDialog.tsx +1 -1
  480. package/src/mcp-server/McpServerDetailView.tsx +58 -26
  481. package/src/mcp-server/OAuthAppForm.tsx +2 -18
  482. package/src/mcp-server/__tests__/DefinitionDriftNotice.test.tsx +57 -0
  483. package/src/mcp-server/__tests__/definitionDrift.test.ts +245 -0
  484. package/src/mcp-server/__tests__/mcpServerToInput.test.ts +201 -0
  485. package/src/mcp-server/__tests__/useMcpServerDefinitionDrift.test.tsx +173 -0
  486. package/src/mcp-server/internal/definitionDrift.ts +158 -0
  487. package/src/mcp-server/internal/mcpServerToInput.ts +3 -0
  488. package/src/mcp-server/steps/EnvironmentAuthStep.tsx +19 -19
  489. package/src/mcp-server/steps/IdentityTransportStep.tsx +24 -23
  490. package/src/mcp-server/useMcpServerConnect.ts +1 -1
  491. package/src/mcp-server/useMcpServerDefinitionDrift.ts +95 -0
  492. package/src/models/ModelRegistryContext.ts +7 -1
  493. package/src/models/ModelSelector.tsx +37 -0
  494. package/src/models/__tests__/ModelSelector-visionIndicator.test.tsx +129 -0
  495. package/src/models/__tests__/resolveDefaultModel.test.ts +115 -0
  496. package/src/models/__tests__/useModelRegistry.test.tsx +99 -4
  497. package/src/models/index.ts +2 -2
  498. package/src/models/registry.ts +196 -29
  499. package/src/models/useModelRegistry.ts +10 -2
  500. package/src/oauth-app/CreateOAuthAppForm.tsx +16 -31
  501. package/src/oauth-app/OAuthAppDetailPanel.tsx +16 -31
  502. package/src/organization/CreateOrganizationForm.tsx +10 -29
  503. package/src/organization/OrgProfilePanel.tsx +13 -44
  504. package/src/platform-client/CreatePlatformClientForm.tsx +9 -29
  505. package/src/platform-client/PlatformClientDetailPanel.tsx +10 -30
  506. package/src/platform-client/PlatformClientListPanel.tsx +2 -18
  507. package/src/platform-client/PlatformClientSecretAlert.tsx +26 -55
  508. package/src/provider.tsx +76 -33
  509. package/src/resource-creation/WizardNav.tsx +2 -18
  510. package/src/resource-detail/ConfirmDialog.tsx +1 -1
  511. package/src/resource-detail/useCopyResource.ts +17 -23
  512. package/src/schedule/ScheduleDetailView.tsx +2 -18
  513. package/src/schedule/ScheduleForm.tsx +19 -34
  514. package/src/session/NewSessionViewer.tsx +85 -7
  515. package/src/session/SessionViewer.tsx +120 -17
  516. package/src/session/__tests__/audienceWiring.test.tsx +76 -0
  517. package/src/session/__tests__/panelNegotiation.test.tsx +302 -0
  518. package/src/session/__tests__/useNewSessionFlow.test.tsx +134 -5
  519. package/src/session/__tests__/useSessionPageFlow.autoApprove.test.tsx +74 -0
  520. package/src/session/__tests__/useSessionPageFlow.runConfig.test.tsx +157 -0
  521. package/src/session/__tests__/useSessionPanel.test.ts +114 -0
  522. package/src/session/audience.ts +18 -0
  523. package/src/session/index.ts +2 -1
  524. package/src/session/run-config.ts +59 -0
  525. package/src/session/useNewSessionFlow.ts +39 -2
  526. package/src/session/useSessionConversation.ts +10 -8
  527. package/src/session/useSessionPageFlow.ts +51 -10
  528. package/src/session/useSessionPanel.ts +91 -10
  529. package/src/settings/ApiKeysSection.tsx +4 -3
  530. package/src/settings/ChannelAppsSection.tsx +4 -3
  531. package/src/settings/EnvironmentsSection.tsx +8 -5
  532. package/src/settings/IdentityProvidersSection.tsx +4 -3
  533. package/src/settings/InvitationsSection.tsx +4 -2
  534. package/src/settings/MembersSection.tsx +4 -2
  535. package/src/settings/OAuthAppsSection.tsx +4 -3
  536. package/src/settings/OrgProfileSection.tsx +4 -3
  537. package/src/settings/PlatformClientsSection.tsx +4 -3
  538. package/src/settings/UsageSection.tsx +4 -2
  539. package/src/sharing/ShareAgentDialog.tsx +28 -10
  540. package/src/sidebar/__tests__/WorkspaceSidebar.test.tsx +4 -1
  541. package/src/sidebar/chrome.tsx +6 -6
  542. package/src/skill/SkillDiffDialog.tsx +1 -1
  543. package/src/styles.css +43 -0
  544. package/src/version-history/VersionTimelineEntry.tsx +1 -21
  545. package/src/workflow/FailedRunsWidget.tsx +2 -9
  546. package/src/workflow/PendingApprovalsWidget.tsx +2 -9
  547. package/src/workflow/ViewYamlDialog.tsx +7 -22
  548. package/src/workflow/WorkflowArchitectDialog.tsx +8 -27
  549. package/src/workflow/WorkflowArtifactDocument.tsx +5 -9
  550. package/src/workflow/WorkflowCanvasEditor.tsx +2 -0
  551. package/src/workflow/WorkflowCanvasInner.tsx +14 -1
  552. package/src/workflow/WorkflowDiffGraph.tsx +7 -1
  553. package/src/workflow/WorkflowExecutionViewer.tsx +88 -11
  554. package/src/workflow/WorkflowExplainDialog.tsx +8 -24
  555. package/src/workflow/WorkflowOverviewGraph.tsx +9 -1
  556. package/src/workflow/WorkflowRefinePanel.tsx +2 -18
  557. package/src/workflow/WorkflowRepairCard.tsx +2 -18
  558. package/src/workflow/WorkflowRunDialog.tsx +3 -23
  559. package/src/workflow/WorkflowTaskApprovalSummary.tsx +2 -17
  560. package/src/workflow/WorkflowVersionBadge.tsx +4 -13
  561. package/src/workflow/WorkflowVersionTimeline.tsx +1 -25
  562. package/src/workflow/__tests__/panelNegotiation.test.tsx +230 -0
  563. package/src/workflow/__tests__/useWorkflowCanvas.dirty.test.tsx +178 -0
  564. package/src/workflow/__tests__/useWorkflowCanvas.drag.test.tsx +224 -0
  565. package/src/workflow/__tests__/useWorkflowExecutionPanel.test.ts +100 -0
  566. package/src/workflow/execution-comparison/ExecutionComparisonPicker.tsx +7 -11
  567. package/src/workflow/execution-history/ExecutionHistoryTable.tsx +1 -25
  568. package/src/workflow/index.ts +1 -0
  569. package/src/workflow/instance/CreateWorkflowInstanceDialog.tsx +1 -1
  570. package/src/workflow/instance/WorkflowInstanceDetailPanel.tsx +2 -1
  571. package/src/workflow/picker/BranchAddPopover.tsx +4 -3
  572. package/src/workflow/templates/WorkflowTemplatePreview.tsx +1 -1
  573. package/src/workflow/useApprovalBoundary.ts +1 -1
  574. package/src/workflow/useWorkflowCanvas.ts +114 -11
  575. package/src/workflow/useWorkflowExecutionPanel.ts +95 -13
  576. package/styles.css +1 -1
  577. package/version-history/VersionTimelineEntry.d.ts.map +1 -1
  578. package/version-history/VersionTimelineEntry.js +1 -23
  579. package/version-history/VersionTimelineEntry.js.map +1 -1
  580. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  581. package/workflow/FailedRunsWidget.d.ts.map +1 -1
  582. package/workflow/FailedRunsWidget.js +2 -11
  583. package/workflow/FailedRunsWidget.js.map +1 -1
  584. package/workflow/PendingApprovalsWidget.d.ts.map +1 -1
  585. package/workflow/PendingApprovalsWidget.js +2 -11
  586. package/workflow/PendingApprovalsWidget.js.map +1 -1
  587. package/workflow/ViewYamlDialog.d.ts.map +1 -1
  588. package/workflow/ViewYamlDialog.js +7 -23
  589. package/workflow/ViewYamlDialog.js.map +1 -1
  590. package/workflow/WorkflowArchitectDialog.d.ts.map +1 -1
  591. package/workflow/WorkflowArchitectDialog.js +7 -11
  592. package/workflow/WorkflowArchitectDialog.js.map +1 -1
  593. package/workflow/WorkflowArtifactDocument.d.ts.map +1 -1
  594. package/workflow/WorkflowArtifactDocument.js +5 -8
  595. package/workflow/WorkflowArtifactDocument.js.map +1 -1
  596. package/workflow/WorkflowCanvasEditor.d.ts.map +1 -1
  597. package/workflow/WorkflowCanvasEditor.js +1 -1
  598. package/workflow/WorkflowCanvasEditor.js.map +1 -1
  599. package/workflow/WorkflowCanvasInner.d.ts +4 -2
  600. package/workflow/WorkflowCanvasInner.d.ts.map +1 -1
  601. package/workflow/WorkflowCanvasInner.js +7 -3
  602. package/workflow/WorkflowCanvasInner.js.map +1 -1
  603. package/workflow/WorkflowDiffGraph.js +6 -2
  604. package/workflow/WorkflowDiffGraph.js.map +1 -1
  605. package/workflow/WorkflowExecutionViewer.d.ts +51 -0
  606. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  607. package/workflow/WorkflowExecutionViewer.js +23 -6
  608. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  609. package/workflow/WorkflowExplainDialog.d.ts.map +1 -1
  610. package/workflow/WorkflowExplainDialog.js +6 -8
  611. package/workflow/WorkflowExplainDialog.js.map +1 -1
  612. package/workflow/WorkflowOverviewGraph.js +8 -2
  613. package/workflow/WorkflowOverviewGraph.js.map +1 -1
  614. package/workflow/WorkflowRefinePanel.d.ts.map +1 -1
  615. package/workflow/WorkflowRefinePanel.js +2 -4
  616. package/workflow/WorkflowRefinePanel.js.map +1 -1
  617. package/workflow/WorkflowRepairCard.d.ts.map +1 -1
  618. package/workflow/WorkflowRepairCard.js +2 -4
  619. package/workflow/WorkflowRepairCard.js.map +1 -1
  620. package/workflow/WorkflowRunDialog.d.ts.map +1 -1
  621. package/workflow/WorkflowRunDialog.js +2 -7
  622. package/workflow/WorkflowRunDialog.js.map +1 -1
  623. package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
  624. package/workflow/WorkflowTaskApprovalSummary.js +2 -4
  625. package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
  626. package/workflow/WorkflowVersionBadge.d.ts.map +1 -1
  627. package/workflow/WorkflowVersionBadge.js +4 -13
  628. package/workflow/WorkflowVersionBadge.js.map +1 -1
  629. package/workflow/WorkflowVersionTimeline.d.ts.map +1 -1
  630. package/workflow/WorkflowVersionTimeline.js +1 -26
  631. package/workflow/WorkflowVersionTimeline.js.map +1 -1
  632. package/workflow/execution-comparison/ExecutionComparisonPicker.d.ts.map +1 -1
  633. package/workflow/execution-comparison/ExecutionComparisonPicker.js +7 -15
  634. package/workflow/execution-comparison/ExecutionComparisonPicker.js.map +1 -1
  635. package/workflow/execution-history/ExecutionHistoryTable.d.ts.map +1 -1
  636. package/workflow/execution-history/ExecutionHistoryTable.js +1 -24
  637. package/workflow/execution-history/ExecutionHistoryTable.js.map +1 -1
  638. package/workflow/index.d.ts +1 -1
  639. package/workflow/index.d.ts.map +1 -1
  640. package/workflow/index.js.map +1 -1
  641. package/workflow/instance/CreateWorkflowInstanceDialog.js +1 -1
  642. package/workflow/instance/WorkflowInstanceDetailPanel.d.ts.map +1 -1
  643. package/workflow/instance/WorkflowInstanceDetailPanel.js +1 -1
  644. package/workflow/instance/WorkflowInstanceDetailPanel.js.map +1 -1
  645. package/workflow/picker/BranchAddPopover.d.ts.map +1 -1
  646. package/workflow/picker/BranchAddPopover.js +3 -2
  647. package/workflow/picker/BranchAddPopover.js.map +1 -1
  648. package/workflow/templates/WorkflowTemplatePreview.js +1 -1
  649. package/workflow/useApprovalBoundary.d.ts +1 -1
  650. package/workflow/useApprovalBoundary.js +1 -1
  651. package/workflow/useWorkflowCanvas.d.ts +5 -1
  652. package/workflow/useWorkflowCanvas.d.ts.map +1 -1
  653. package/workflow/useWorkflowCanvas.js +99 -13
  654. package/workflow/useWorkflowCanvas.js.map +1 -1
  655. package/workflow/useWorkflowExecutionPanel.d.ts +38 -2
  656. package/workflow/useWorkflowExecutionPanel.d.ts.map +1 -1
  657. package/workflow/useWorkflowExecutionPanel.js +46 -13
  658. package/workflow/useWorkflowExecutionPanel.js.map +1 -1
@@ -16,6 +16,7 @@ import {
16
16
  import {
17
17
  useWorkflowExecutionPanel,
18
18
  workflowArtifactTabPath,
19
+ type UseWorkflowExecutionPanelOptions,
19
20
  } from "../useWorkflowExecutionPanel";
20
21
 
21
22
  function artifact(id: string, displayName: string) {
@@ -238,3 +239,102 @@ describe("useWorkflowExecutionPanel openDiagnosis", () => {
238
239
  );
239
240
  });
240
241
  });
242
+
243
+ // ---------------------------------------------------------------------------
244
+ // The controlled/observable open-state seam — the #651 contract mirrored from
245
+ // useSessionPanel (#654). The panel opens ITSELF (Diagnose, artifact/change
246
+ // opens), so onOpenChange fires in BOTH modes; controlled mode surfaces
247
+ // requests without applying them, and a declined request stays re-fireable.
248
+ // ---------------------------------------------------------------------------
249
+
250
+ function renderSeamPanel(initial?: UseWorkflowExecutionPanelOptions) {
251
+ return renderHook(
252
+ (opts: UseWorkflowExecutionPanelOptions) => useWorkflowExecutionPanel(opts),
253
+ { initialProps: { ...initial } as UseWorkflowExecutionPanelOptions },
254
+ );
255
+ }
256
+
257
+ describe("useWorkflowExecutionPanel — observed open state (uncontrolled + onOpenChange)", () => {
258
+ it("reports the chip toggle without taking control", () => {
259
+ const seen: boolean[] = [];
260
+ const { result } = renderSeamPanel({ onOpenChange: (o) => seen.push(o) });
261
+ act(() => result.current.openPanel());
262
+ expect(result.current.isOpen).toBe(true);
263
+ act(() => result.current.closePanel());
264
+ expect(result.current.isOpen).toBe(false);
265
+ expect(seen).toEqual([true, false]);
266
+ });
267
+
268
+ it("reports internal open intents (openDiagnosis, openArtifact), once per actual transition", () => {
269
+ const seen: boolean[] = [];
270
+ const { result } = renderSeamPanel({ onOpenChange: (o) => seen.push(o) });
271
+ act(() => result.current.openDiagnosis());
272
+ // Already open — further open intents are not transitions.
273
+ act(() => result.current.openArtifact(artifact("art_1", "report.json")));
274
+ act(() => result.current.openPanel());
275
+ expect(seen).toEqual([true]);
276
+ });
277
+
278
+ it("starts open when defaultOpen is set, without a spurious notification", () => {
279
+ const seen: boolean[] = [];
280
+ const { result } = renderSeamPanel({
281
+ defaultOpen: true,
282
+ onOpenChange: (o) => seen.push(o),
283
+ });
284
+ expect(result.current.isOpen).toBe(true);
285
+ expect(seen).toEqual([]);
286
+ });
287
+ });
288
+
289
+ describe("useWorkflowExecutionPanel — controlled open state", () => {
290
+ it("follows the host's open value and ignores defaultOpen", () => {
291
+ const { result, rerender } = renderSeamPanel({ open: false, defaultOpen: true });
292
+ expect(result.current.isOpen).toBe(false);
293
+ rerender({ open: true, defaultOpen: true });
294
+ expect(result.current.isOpen).toBe(true);
295
+ });
296
+
297
+ it("surfaces intents through onOpenChange without flipping state itself", () => {
298
+ const seen: boolean[] = [];
299
+ const onOpenChange = (o: boolean) => seen.push(o);
300
+ const { result, rerender } = renderSeamPanel({ open: false, onOpenChange });
301
+ act(() => result.current.openPanel());
302
+ expect(seen).toEqual([true]);
303
+ expect(result.current.isOpen).toBe(false);
304
+ // The host grants the request.
305
+ rerender({ open: true, onOpenChange });
306
+ expect(result.current.isOpen).toBe(true);
307
+ act(() => result.current.closePanel());
308
+ expect(seen).toEqual([true, false]);
309
+ expect(result.current.isOpen).toBe(true);
310
+ });
311
+
312
+ it("re-fires a declined request (once per request, not per transition)", () => {
313
+ const seen: boolean[] = [];
314
+ const onOpenChange = (o: boolean) => seen.push(o);
315
+ const { result } = renderSeamPanel({ open: false, onOpenChange });
316
+ act(() => result.current.openArtifact(artifact("art_1", "a.json")));
317
+ // The host declined (open stayed false) — a later intent must re-fire,
318
+ // not be swallowed by a stale "already requested" memory.
319
+ act(() => result.current.openFileChange(fileChange("src/a.ts")));
320
+ expect(seen).toEqual([true, true]);
321
+ });
322
+
323
+ it("Diagnose is reported, not applied — but the tab is pinned and ready", () => {
324
+ const seen: boolean[] = [];
325
+ const onOpenChange = (o: boolean) => seen.push(o);
326
+ const { result } = renderSeamPanel({ open: false, onOpenChange });
327
+ act(() => result.current.openDiagnosis());
328
+ expect(seen).toEqual([true]);
329
+ expect(result.current.isOpen).toBe(false);
330
+ // Tab state stays SDK-owned: the diagnosis tab is pinned regardless, so
331
+ // the moment the host opens the panel the conversation greets the user.
332
+ expect(result.current.editorsStore.getSnapshot().editors).toEqual([
333
+ {
334
+ entryId: DIAGNOSIS_DOCUMENT_ENTRY_ID,
335
+ path: DIAGNOSIS_DOCUMENT_PATH,
336
+ preview: false,
337
+ },
338
+ ]);
339
+ });
340
+ });
@@ -6,6 +6,7 @@ import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/workflowexecu
6
6
  import { useWorkflowExecutionList } from "../useWorkflowExecutionList.js";
7
7
  import { WorkflowExecutionPhaseBadge } from "../WorkflowExecutionPhaseBadge.js";
8
8
  import { formatDuration } from "../format-utils.js";
9
+ import { formatRelativeTime } from "../../activity/format-relative-time.js";
9
10
 
10
11
  /** Props for {@link ExecutionComparisonPicker}. */
11
12
  export interface ExecutionComparisonPickerProps {
@@ -119,7 +120,7 @@ export const ExecutionComparisonPicker = memo(function ExecutionComparisonPicker
119
120
  ref={dialogRef}
120
121
  className={cn(
121
122
  "stgm stg:m-auto stg:max-h-[70vh] stg:w-full stg:max-w-md stg:rounded-lg stg:border stg:border-[var(--stgm-border,#e5e5e5)] stg:bg-[var(--stgm-background,#fff)] stg:p-0 stg:shadow-xl",
122
- "stg:backdrop:bg-black/40",
123
+ "stg:backdrop:bg-backdrop",
123
124
  )}
124
125
  onClick={handleBackdropClick}
125
126
  aria-label="Select execution to compare"
@@ -183,7 +184,7 @@ export const ExecutionComparisonPicker = memo(function ExecutionComparisonPicker
183
184
  {name}
184
185
  </span>
185
186
  <span className="stg:text-[10px] stg:text-[var(--stgm-muted-foreground,#737373)]">
186
- {startedAt ? formatRelative(startedAt) : "—"}
187
+ {startedAt ? formatStartedAt(startedAt) : "—"}
187
188
  {durationMs != null && ` · ${formatDuration(durationMs)}`}
188
189
  </span>
189
190
  </div>
@@ -228,13 +229,8 @@ function getDurationMs(startedAt: string | undefined, completedAt: string | unde
228
229
  return e - s;
229
230
  }
230
231
 
231
- function formatRelative(iso: string): string {
232
- const d = new Date(iso);
233
- if (Number.isNaN(d.getTime())) return iso;
234
- const now = Date.now();
235
- const diff = now - d.getTime();
236
- if (diff < 60_000) return "just now";
237
- if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;
238
- if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`;
239
- return d.toLocaleDateString(undefined, { month: "short", day: "numeric" });
232
+ /** ISO wire value → the shared compact stamp; unparseable renders as absent. */
233
+ function formatStartedAt(iso: string): string {
234
+ const date = new Date(iso);
235
+ return Number.isNaN(date.getTime()) ? "—" : formatRelativeTime(date);
240
236
  }
@@ -12,6 +12,7 @@ import {
12
12
  } from "./derive-execution-row.js";
13
13
  import { Tooltip, TooltipContent, TooltipTrigger } from "../../internal/tooltip.js";
14
14
  import { TruncatedText } from "../../internal/truncated-text.js";
15
+ import { formatRelativeTime } from "../../activity/format-relative-time.js";
15
16
 
16
17
  // ---------------------------------------------------------------------------
17
18
  // Column definitions
@@ -436,28 +437,3 @@ function LoadingSkeleton({
436
437
  </div>
437
438
  );
438
439
  }
439
-
440
- // ---------------------------------------------------------------------------
441
- // Relative time formatter
442
- // ---------------------------------------------------------------------------
443
-
444
- function formatRelativeTime(date: Date): string {
445
- const now = Date.now();
446
- const diff = now - date.getTime();
447
-
448
- if (diff < 0) return date.toLocaleString();
449
- if (diff < 60_000) return "just now";
450
- if (diff < 3_600_000) {
451
- const mins = Math.floor(diff / 60_000);
452
- return `${mins}m ago`;
453
- }
454
- if (diff < 86_400_000) {
455
- const hours = Math.floor(diff / 3_600_000);
456
- return `${hours}h ago`;
457
- }
458
- if (diff < 604_800_000) {
459
- const days = Math.floor(diff / 86_400_000);
460
- return `${days}d ago`;
461
- }
462
- return date.toLocaleDateString();
463
- }
@@ -177,6 +177,7 @@ export {
177
177
  export {
178
178
  WorkflowExecutionViewer,
179
179
  type WorkflowExecutionViewerProps,
180
+ type WorkflowExecutionPanelMode,
180
181
  } from "./WorkflowExecutionViewer.js";
181
182
 
182
183
  export {
@@ -115,7 +115,7 @@ export function CreateWorkflowInstanceDialog({
115
115
  onClose={handleClose}
116
116
  className={cn(
117
117
  "stg:fixed stg:inset-0 stg:m-auto stg:w-full stg:max-w-lg stg:rounded-xl stg:border stg:border-border stg:bg-popover stg:p-0 stg:shadow-xl",
118
- "stg:backdrop:bg-black/50",
118
+ "stg:backdrop:bg-backdrop",
119
119
  )}
120
120
  aria-labelledby={titleId}
121
121
  >
@@ -296,7 +296,8 @@ export function WorkflowInstanceDetailPanel({
296
296
  ) : (
297
297
  <div className="stg:space-y-2 stg:rounded-md stg:border stg:border-destructive/30 stg:p-3 stg:bg-destructive/5">
298
298
  <p className="stg:text-xs stg:text-destructive stg:font-medium">
299
- This will permanently delete this instance and all its execution history.
299
+ This permanently removes the instance and its environment bindings. Executions
300
+ already run against it are preserved in the workflow&apos;s execution history.
300
301
  This action cannot be undone.
301
302
  </p>
302
303
  {deleteError && (
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { memo, useState, useCallback, useRef, useEffect } from "react";
3
+ import { memo, useState, useCallback, useId, useRef, useEffect } from "react";
4
4
  import { Popover } from "@base-ui/react/popover";
5
5
  import { cn } from "@stigmer/theme";
6
6
  import { useStigmerPortalContainer } from "../../portal-container.js";
@@ -76,6 +76,7 @@ export const BranchAddPopover = memo(function BranchAddPopover({
76
76
  side = "bottom",
77
77
  align = "start",
78
78
  }: BranchAddPopoverProps) {
79
+ const errorId = useId();
79
80
  const portalContainer = useStigmerPortalContainer();
80
81
  const config = MODE_CONFIG[mode];
81
82
  const nameRef = useRef<HTMLInputElement>(null);
@@ -175,11 +176,11 @@ export const BranchAddPopover = memo(function BranchAddPopover({
175
176
  nameError ? "stg:border-[var(--stgm-destructive,#ef4444)]" : "stg:border-border",
176
177
  )}
177
178
  aria-invalid={!!nameError}
178
- aria-describedby={nameError ? "branch-name-error" : undefined}
179
+ aria-describedby={nameError ? errorId : undefined}
179
180
  />
180
181
  {nameError && (
181
182
  <p
182
- id="branch-name-error"
183
+ id={errorId}
183
184
  className="stg:mt-0.5 stg:text-[10px] stg:text-[var(--stgm-destructive,#ef4444)]"
184
185
  >
185
186
  {nameError}
@@ -83,7 +83,7 @@ export function WorkflowTemplatePreview({
83
83
  ref={dialogRef}
84
84
  className={cn(
85
85
  "stgm stg:m-auto stg:max-h-[85vh] stg:w-full stg:max-w-3xl stg:rounded-lg stg:border stg:border-border stg:bg-background stg:p-0 stg:shadow-lg",
86
- "stg:backdrop:bg-black/50",
86
+ "stg:backdrop:bg-backdrop",
87
87
  )}
88
88
  >
89
89
  <div className="stg:flex stg:flex-col">
@@ -29,7 +29,7 @@ export interface ApprovalBoundaryCrossing {
29
29
  * the decision surface (the panel's Inspect Approval tab) is never hidden
30
30
  * while the run is blocked.
31
31
  *
32
- * Same diffing shape as {@link useExecutionAnnouncements} (prev-map ref,
32
+ * Same diffing shape as `useExecutionAnnouncements` (prev-map ref,
33
33
  * diff on each map commit). A task first observed already in
34
34
  * `waiting_approval` counts as entered — with rAF-coalesced commits the
35
35
  * running→waiting transition can collapse into the task's first appearance.
@@ -7,6 +7,7 @@ import type {
7
7
  Edge,
8
8
  OnNodesChange,
9
9
  OnEdgesChange,
10
+ OnNodeDrag,
10
11
  Connection,
11
12
  IsValidConnection,
12
13
  } from "@xyflow/react";
@@ -67,6 +68,20 @@ import type { LayoutEngine } from "./layout/index.js";
67
68
  import { serializeSelection, pasteClipboard } from "./clipboard.js";
68
69
  import type { ClipboardEntry } from "./clipboard.js";
69
70
 
71
+ /**
72
+ * Serializes a graph model to canonical YAML, or `null` if serialization
73
+ * fails. graphToYaml is total on models produced by yamlToGraph (its sort is
74
+ * cycle-protected and unknown kinds fall back to `unknown_N`), so `null` is
75
+ * a defensive outcome, not an expected one.
76
+ */
77
+ function serializeGraphOrNull(model: WorkflowGraphModel): string | null {
78
+ try {
79
+ return graphToYaml(model);
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+
70
85
  /** Selection state for the canvas inspector. */
71
86
  export interface CanvasSelection {
72
87
  readonly type: "node" | "edge";
@@ -90,6 +105,10 @@ export interface UseWorkflowCanvasReturn {
90
105
  readonly edges: Edge[];
91
106
  readonly onNodesChange: OnNodesChange;
92
107
  readonly onEdgesChange: OnEdgesChange;
108
+ /** Marks the model snapshot an in-flight drag started from. */
109
+ readonly onNodeDragStart: OnNodeDrag;
110
+ /** Records a completed node drag into the command history (oss#602). */
111
+ readonly onNodeDragStop: OnNodeDrag;
93
112
  readonly onConnect: (connection: Connection) => void;
94
113
  readonly isValidConnection: IsValidConnection;
95
114
  readonly onDrop: (event: React.DragEvent) => void;
@@ -175,6 +194,10 @@ export function useWorkflowCanvas(
175
194
  const [error, setError] = useState<string | null>(null);
176
195
  const [selection, setSelection] = useState<CanvasSelection | null>(null);
177
196
  const initialModelRef = useRef<WorkflowGraphModel | null>(null);
197
+ // Serialized form of the baseline model, kept in lockstep with
198
+ // initialModelRef. Dirty tracking compares serializations, not references —
199
+ // see the "Dirty tracking" section below for why.
200
+ const initialYamlRef = useRef<string | null>(null);
178
201
 
179
202
  const [nodes, setNodes, onNodesChangeRaw] = useNodesState([] as Node[]);
180
203
  const [edges, setEdges, onEdgesChangeRaw] = useEdgesState([] as Edge[]);
@@ -201,6 +224,7 @@ export function useWorkflowCanvas(
201
224
  setNodes([]);
202
225
  setEdges([]);
203
226
  initialModelRef.current = null;
227
+ initialYamlRef.current = null;
204
228
  return;
205
229
  }
206
230
 
@@ -209,6 +233,10 @@ export function useWorkflowCanvas(
209
233
  const laidOut = applyDagreLayout(parsed);
210
234
  history.reset(laidOut);
211
235
  initialModelRef.current = laidOut;
236
+ // Baseline is the canonical re-serialization, not the incoming string:
237
+ // dirty comparisons must be canonical-vs-canonical, immune to cosmetic
238
+ // formatting differences in host-provided YAML.
239
+ initialYamlRef.current = serializeGraphOrNull(laidOut);
212
240
  setError(null);
213
241
 
214
242
  const elements = toReactFlowElements(laidOut);
@@ -219,6 +247,7 @@ export function useWorkflowCanvas(
219
247
  setNodes([]);
220
248
  setEdges([]);
221
249
  initialModelRef.current = null;
250
+ initialYamlRef.current = null;
222
251
  }
223
252
  }, [yaml]);
224
253
 
@@ -252,6 +281,63 @@ export function useWorkflowCanvas(
252
281
  [onNodesChangeRaw],
253
282
  );
254
283
 
284
+ // During a drag, React Flow streams position changes into RF state only
285
+ // (via onNodesChange above); the model still holds the pre-drag
286
+ // positions. At drag stop, the completed gesture is recorded as ONE
287
+ // MoveNodesCommand — the auto-layout precedent — so drags survive
288
+ // later syncFromModel calls and are undoable (oss#602).
289
+ //
290
+ // The ref detects mid-drag model mutations: the keyboard undo listener
291
+ // and the host's YAML prop are both reachable while the mouse is down,
292
+ // and either one rebuilds the canvas from a model this drag never saw —
293
+ // recording the drag on top of that would fight the mutation.
294
+ const dragStartModelRef = useRef<WorkflowGraphModel | null>(null);
295
+
296
+ const onNodeDragStart: OnNodeDrag = useCallback(() => {
297
+ dragStartModelRef.current = history.currentModel;
298
+ }, [history.currentModel]);
299
+
300
+ const onNodeDragStop: OnNodeDrag = useCallback(
301
+ (_event, _node, draggedNodes) => {
302
+ const model = history.currentModel;
303
+ const startModel = dragStartModelRef.current;
304
+ dragStartModelRef.current = null;
305
+ if (!startModel || model !== startModel) return;
306
+
307
+ const oldPositions: { id: string; x: number; y: number }[] = [];
308
+ const newPositions: { id: string; x: number; y: number }[] = [];
309
+ for (const dragged of draggedNodes) {
310
+ const modelNode = model.nodes.find((n) => n.id === dragged.id);
311
+ if (!modelNode) continue;
312
+ oldPositions.push({
313
+ id: modelNode.id,
314
+ x: modelNode.position.x,
315
+ y: modelNode.position.y,
316
+ });
317
+ newPositions.push({
318
+ id: dragged.id,
319
+ x: dragged.position.x,
320
+ y: dragged.position.y,
321
+ });
322
+ }
323
+
324
+ const hasChanges = newPositions.some((np, i) => {
325
+ const op = oldPositions[i];
326
+ return Math.abs(op.x - np.x) > 0.5 || Math.abs(op.y - np.y) > 0.5;
327
+ });
328
+ if (!hasChanges) return;
329
+
330
+ // Record-only dispatch — deliberately NOT the syncing dispatch().
331
+ // React Flow already renders the dragged positions, so here the
332
+ // model catches up to the canvas (everywhere else the model leads
333
+ // and syncFromModel makes the canvas follow). Rebuilding the node
334
+ // array would be a visual no-op that wipes React Flow's `selected`
335
+ // flags at the end of every drag, breaking consecutive group drags.
336
+ history.dispatch(new MoveNodesCommand(oldPositions, newPositions));
337
+ },
338
+ [history.currentModel, history.dispatch],
339
+ );
340
+
255
341
  const onEdgesChange: OnEdgesChange = useCallback(
256
342
  (changes) => {
257
343
  onEdgesChangeRaw(changes);
@@ -387,6 +473,7 @@ export function useWorkflowCanvas(
387
473
  };
388
474
  history.reset(bootstrapModel);
389
475
  initialModelRef.current = bootstrapModel;
476
+ initialYamlRef.current = serializeGraphOrNull(bootstrapModel);
390
477
 
391
478
  const autoEdge = {
392
479
  id: generateEdgeId(),
@@ -1096,20 +1183,33 @@ export function useWorkflowCanvas(
1096
1183
  }, [history.redo, syncFromModel]);
1097
1184
 
1098
1185
  // ---------------------------------------------------------------------------
1099
- // Dirty tracking: model reference comparison
1186
+ // Dirty tracking: serialization comparison (oss#609)
1187
+ //
1188
+ // Dirty means "saving would change the document". Node positions are not
1189
+ // part of the serialized YAML (dagre recomputes them on every load), so a
1190
+ // position-only edit session (drags, auto-layout) must NOT read as dirty:
1191
+ // its save would round-trip byte-identical YAML, and because hosts reset
1192
+ // the baseline by feeding saved YAML back through the `yaml` prop (whose
1193
+ // re-parse effect is string-change gated), a reference-based flag could
1194
+ // never clear afterwards — an armed Save button that saving cannot disarm.
1195
+ // graphToYaml is total on parsed models (cycle-protected sort, unknown-kind
1196
+ // fallback) and O(nodes+edges), cheap enough to compare per model change.
1100
1197
  // ---------------------------------------------------------------------------
1101
1198
 
1102
1199
  const graph = history.currentModel.nodes.length > 0 ? history.currentModel : null;
1103
- const isDirty = initialModelRef.current !== null && graph !== initialModelRef.current;
1200
+ const currentYaml = useMemo(
1201
+ () => (graph ? serializeGraphOrNull(graph) : null),
1202
+ [graph],
1203
+ );
1204
+ // Reference comparison remains as the fallback for the defensive case where
1205
+ // serialization failed (null); failing dirty-side keeps Save reachable.
1206
+ const isDirty =
1207
+ initialModelRef.current !== null &&
1208
+ (currentYaml !== null && initialYamlRef.current !== null
1209
+ ? currentYaml !== initialYamlRef.current
1210
+ : graph !== initialModelRef.current);
1104
1211
 
1105
- const serializeToYaml = useCallback((): string | null => {
1106
- if (!graph) return null;
1107
- try {
1108
- return graphToYaml(graph);
1109
- } catch {
1110
- return null;
1111
- }
1112
- }, [graph]);
1212
+ const serializeToYaml = useCallback((): string | null => currentYaml, [currentYaml]);
1113
1213
 
1114
1214
  return useMemo(
1115
1215
  () => ({
@@ -1117,6 +1217,8 @@ export function useWorkflowCanvas(
1117
1217
  edges,
1118
1218
  onNodesChange,
1119
1219
  onEdgesChange,
1220
+ onNodeDragStart,
1221
+ onNodeDragStop,
1120
1222
  onConnect,
1121
1223
  isValidConnection,
1122
1224
  onDrop,
@@ -1174,7 +1276,8 @@ export function useWorkflowCanvas(
1174
1276
  getSelectedNodeIds,
1175
1277
  }),
1176
1278
  [
1177
- nodes, edges, onNodesChange, onEdgesChange, onConnect,
1279
+ nodes, edges, onNodesChange, onEdgesChange, onNodeDragStart,
1280
+ onNodeDragStop, onConnect,
1178
1281
  isValidConnection, onDrop, onDragOver, onNodesDelete, onEdgesDelete,
1179
1282
  selection, selectNode, selectEdge, clearSelection, autoLayout,
1180
1283
  undo, redo, history.canUndo, history.canRedo, isDirty, graph, error,
@@ -3,7 +3,7 @@
3
3
  // State + actions for the workflow execution viewer's WorkspaceSurface panel.
4
4
  // Domain: workflow (the lean analog of session/useSessionPanel).
5
5
 
6
- import { useCallback, useMemo, useState } from "react";
6
+ import { useCallback, useMemo, useRef, useState } from "react";
7
7
  import type { Artifact } from "@stigmer/protos/ai/stigmer/agentic/artifact/v1/api_pb";
8
8
  import type { FileChange } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
9
9
  import {
@@ -50,7 +50,11 @@ export function workflowArtifactTabPath(artifact: Artifact): string {
50
50
  export interface WorkflowExecutionPanelController {
51
51
  /** The open-editor group store; subscribe with `useWorkspaceEditors`. */
52
52
  readonly editorsStore: WorkspaceEditorsStore;
53
- /** Whether the panel is expanded or collapsed to the chip. */
53
+ /**
54
+ * Whether the panel is expanded or collapsed to the chip. In controlled
55
+ * mode ({@link UseWorkflowExecutionPanelOptions.open}) this mirrors the
56
+ * host's value.
57
+ */
54
58
  readonly isOpen: boolean;
55
59
  /** The active rail view id (an injected facet — `"artifacts"` today). */
56
60
  readonly view: string;
@@ -119,6 +123,38 @@ export interface UseWorkflowExecutionPanelOptions {
119
123
  * @default "artifacts"
120
124
  */
121
125
  readonly defaultView?: string;
126
+ /**
127
+ * Controlled open state. When provided, the host owns whether the panel is
128
+ * expanded: internal open intents (the chip toggle, Diagnose, an
129
+ * artifact/file-change/file open) no longer flip state themselves — they
130
+ * surface through {@link UseWorkflowExecutionPanelOptions.onOpenChange}
131
+ * and the panel follows this value. Leave `undefined` for the
132
+ * self-managing default. The same seam `useSessionPanel` carries (#651);
133
+ * kept domain-local, like the controllers themselves.
134
+ */
135
+ readonly open?: boolean;
136
+ /**
137
+ * Initial open state in uncontrolled mode. Ignored when
138
+ * {@link UseWorkflowExecutionPanelOptions.open} is provided.
139
+ *
140
+ * @default false
141
+ */
142
+ readonly defaultOpen?: boolean;
143
+ /**
144
+ * Called on every effective open/close transition — in BOTH modes,
145
+ * matching `useSessionPanel`'s convention (and departing from
146
+ * `useDetailTabs`'s DD-T05A-001 for the same principled reason): this
147
+ * panel opens ITSELF (`openDiagnosis`, `openArtifact`, `openFileChange`,
148
+ * `openFile` all expand a collapsed panel), and an embedding host that
149
+ * must react to those moments — widen a dock, make room for a diagnosis
150
+ * conversation — has no other seam. Passing only this callback observes
151
+ * the panel without controlling it.
152
+ *
153
+ * In controlled mode this fires once per open/close REQUEST (the host may
154
+ * decline by not updating `open` — a later identical request re-fires); in
155
+ * uncontrolled mode it fires once per actual transition.
156
+ */
157
+ readonly onOpenChange?: (open: boolean) => void;
122
158
  }
123
159
 
124
160
  /**
@@ -126,13 +162,59 @@ export interface UseWorkflowExecutionPanelOptions {
126
162
  */
127
163
  export function useWorkflowExecutionPanel({
128
164
  defaultView = "artifacts",
165
+ open,
166
+ defaultOpen = false,
167
+ onOpenChange,
129
168
  }: UseWorkflowExecutionPanelOptions = {}): WorkflowExecutionPanelController {
130
169
  const editorsStore = useWorkspaceEditorsStoreRef();
131
- const [isOpen, setIsOpen] = useState(false);
170
+
171
+ // Uncontrolled-by-default / controlled-when-`open`-is-provided (React's own
172
+ // value/defaultValue convention — presence of the value prop decides, so an
173
+ // observe-only host can pass just `onOpenChange`). Same shape as
174
+ // `useSessionPanel`; re-transcribed rather than extracted because the
175
+ // controllers are deliberately not shared (see the interface doc above).
176
+ const isControlled = open !== undefined;
177
+ const [internalIsOpen, setInternalIsOpen] = useState(defaultOpen);
178
+ const isOpen = isControlled ? open : internalIsOpen;
179
+
180
+ // Latest-ref idiom: the host's callback and the mode/value mirrors live in
181
+ // refs so `requestOpenChange` — and every action callback built on it —
182
+ // stays referentially stable regardless of how the host authored
183
+ // `onOpenChange` (DD-010: an inline lambda must not churn the memoized
184
+ // controller and re-render the panel subtree).
185
+ const onOpenChangeRef = useRef(onOpenChange);
186
+ onOpenChangeRef.current = onOpenChange;
187
+ const isControlledRef = useRef(isControlled);
188
+ isControlledRef.current = isControlled;
189
+ const isOpenRef = useRef(isOpen);
190
+ isOpenRef.current = isOpen;
191
+
192
+ // The single seam every open/close intent routes through — the chip
193
+ // toggle, Diagnose, artifact/file-change/file opens, and the surface's
194
+ // collapse affordance. Uncontrolled: apply + notify (the ref is updated
195
+ // eagerly so two same-tick intents produce one notification). Controlled:
196
+ // notify only — the host owns the state, and the panel follows the `open`
197
+ // prop; the ref is NOT updated, so a declined request stays re-fireable.
198
+ const requestOpenChange = useCallback((next: boolean) => {
199
+ if (isOpenRef.current === next) return;
200
+ if (!isControlledRef.current) {
201
+ isOpenRef.current = next;
202
+ setInternalIsOpen(next);
203
+ }
204
+ onOpenChangeRef.current?.(next);
205
+ }, []);
206
+
132
207
  const [view, setViewState] = useState(defaultView);
133
208
 
134
- const openPanel = useCallback(() => setIsOpen(true), []);
135
- const closePanel = useCallback(() => setIsOpen(false), []);
209
+ const openPanel = useCallback(
210
+ () => requestOpenChange(true),
211
+ [requestOpenChange],
212
+ );
213
+
214
+ const closePanel = useCallback(
215
+ () => requestOpenChange(false),
216
+ [requestOpenChange],
217
+ );
136
218
 
137
219
  const setView = useCallback((viewId: string) => setViewState(viewId), []);
138
220
 
@@ -141,15 +223,15 @@ export function useWorkflowExecutionPanel({
141
223
  DIAGNOSIS_DOCUMENT_ENTRY_ID,
142
224
  DIAGNOSIS_DOCUMENT_PATH,
143
225
  );
144
- setIsOpen(true);
145
- }, [editorsStore]);
226
+ requestOpenChange(true);
227
+ }, [editorsStore, requestOpenChange]);
146
228
 
147
229
  const openFile = useCallback(
148
230
  (entryId: string, path: string, options?: OpenFileOptions) => {
149
231
  editorsStore.openPreview(entryId, path, options);
150
- setIsOpen(true);
232
+ requestOpenChange(true);
151
233
  },
152
- [editorsStore],
234
+ [editorsStore, requestOpenChange],
153
235
  );
154
236
 
155
237
  const openArtifact = useCallback(
@@ -158,9 +240,9 @@ export function useWorkflowExecutionPanel({
158
240
  ARTIFACT_DOCUMENT_ENTRY_ID,
159
241
  workflowArtifactTabPath(artifact),
160
242
  );
161
- setIsOpen(true);
243
+ requestOpenChange(true);
162
244
  },
163
- [editorsStore],
245
+ [editorsStore, requestOpenChange],
164
246
  );
165
247
 
166
248
  const pinArtifact = useCallback(
@@ -179,9 +261,9 @@ export function useWorkflowExecutionPanel({
179
261
  FILE_CHANGE_DOCUMENT_ENTRY_ID,
180
262
  fileChangeTabPath(change),
181
263
  );
182
- setIsOpen(true);
264
+ requestOpenChange(true);
183
265
  },
184
- [editorsStore],
266
+ [editorsStore, requestOpenChange],
185
267
  );
186
268
 
187
269
  const pinFileChange = useCallback(