@flanksource/clicky-ui 0.3.43 → 0.3.45

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 (483) hide show
  1. package/README.md +2 -0
  2. package/dist/ai.cjs +4 -2
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.js +3 -1
  5. package/dist/components/MdxEditorField.cjs +40 -22
  6. package/dist/components/MdxEditorField.cjs.map +1 -1
  7. package/dist/components/MdxEditorField.d.ts.map +1 -1
  8. package/dist/components/MdxEditorField.js +41 -23
  9. package/dist/components/MdxEditorField.js.map +1 -1
  10. package/dist/components/json-schema-form-item-summary.cjs +6 -1
  11. package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
  12. package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
  13. package/dist/components/json-schema-form-item-summary.js +6 -1
  14. package/dist/components/json-schema-form-item-summary.js.map +1 -1
  15. package/dist/data/CodeBlock.cjs +3 -2
  16. package/dist/data/CodeBlock.cjs.map +1 -1
  17. package/dist/data/CodeBlock.d.ts +3 -1
  18. package/dist/data/CodeBlock.d.ts.map +1 -1
  19. package/dist/data/CodeBlock.js +3 -2
  20. package/dist/data/CodeBlock.js.map +1 -1
  21. package/dist/data/CodeLine.cjs +22 -0
  22. package/dist/data/CodeLine.cjs.map +1 -0
  23. package/dist/data/CodeLine.d.ts +8 -0
  24. package/dist/data/CodeLine.d.ts.map +1 -0
  25. package/dist/data/CodeLine.js +22 -0
  26. package/dist/data/CodeLine.js.map +1 -0
  27. package/dist/data/GraphDiagram.cjs +18 -6
  28. package/dist/data/GraphDiagram.cjs.map +1 -1
  29. package/dist/data/GraphDiagram.d.ts +9 -1
  30. package/dist/data/GraphDiagram.d.ts.map +1 -1
  31. package/dist/data/GraphDiagram.js +18 -6
  32. package/dist/data/GraphDiagram.js.map +1 -1
  33. package/dist/data/GraphDiagramNodes.cjs +38 -29
  34. package/dist/data/GraphDiagramNodes.cjs.map +1 -1
  35. package/dist/data/GraphDiagramNodes.d.ts +8 -2
  36. package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
  37. package/dist/data/GraphDiagramNodes.js +38 -29
  38. package/dist/data/GraphDiagramNodes.js.map +1 -1
  39. package/dist/data/JsonView.cjs +118 -49
  40. package/dist/data/JsonView.cjs.map +1 -1
  41. package/dist/data/JsonView.d.ts +13 -10
  42. package/dist/data/JsonView.d.ts.map +1 -1
  43. package/dist/data/JsonView.js +118 -49
  44. package/dist/data/JsonView.js.map +1 -1
  45. package/dist/data/MarkdownEditor.cjs +2 -2
  46. package/dist/data/MarkdownEditor.cjs.map +1 -1
  47. package/dist/data/MarkdownEditor.js +2 -2
  48. package/dist/data/MarkdownEditor.js.map +1 -1
  49. package/dist/data/ai/AdvancedChatConfig.cjs +90 -249
  50. package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
  51. package/dist/data/ai/AdvancedChatConfig.d.ts +2 -5
  52. package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
  53. package/dist/data/ai/AdvancedChatConfig.js +91 -250
  54. package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
  55. package/dist/data/ai/ChatButton.cjs +2 -0
  56. package/dist/data/ai/ChatButton.cjs.map +1 -1
  57. package/dist/data/ai/ChatButton.d.ts +1 -1
  58. package/dist/data/ai/ChatButton.d.ts.map +1 -1
  59. package/dist/data/ai/ChatButton.js +2 -0
  60. package/dist/data/ai/ChatButton.js.map +1 -1
  61. package/dist/data/ai/ChatFab.cjs +5 -1
  62. package/dist/data/ai/ChatFab.cjs.map +1 -1
  63. package/dist/data/ai/ChatFab.d.ts +5 -1
  64. package/dist/data/ai/ChatFab.d.ts.map +1 -1
  65. package/dist/data/ai/ChatFab.js +5 -1
  66. package/dist/data/ai/ChatFab.js.map +1 -1
  67. package/dist/data/ai/ChatWindow.cjs +2 -8
  68. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  69. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  70. package/dist/data/ai/ChatWindow.js +2 -8
  71. package/dist/data/ai/ChatWindow.js.map +1 -1
  72. package/dist/data/ai/ChatWindow.runtime.cjs +0 -5
  73. package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
  74. package/dist/data/ai/ChatWindow.runtime.d.ts +0 -2
  75. package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
  76. package/dist/data/ai/ChatWindow.runtime.js +0 -5
  77. package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
  78. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +2 -2
  79. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
  80. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
  81. package/dist/data/ai/PromptRunEditor/runtimeActions.js +2 -2
  82. package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
  83. package/dist/data/ai/SessionInspector.approvals.cjs +3 -6
  84. package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
  85. package/dist/data/ai/SessionInspector.approvals.js +3 -6
  86. package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
  87. package/dist/data/ai/SessionViewer.cjs +13 -4
  88. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  89. package/dist/data/ai/SessionViewer.d.ts +5 -1
  90. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  91. package/dist/data/ai/SessionViewer.header.cjs +1 -1
  92. package/dist/data/ai/SessionViewer.header.cjs.map +1 -1
  93. package/dist/data/ai/SessionViewer.header.js +1 -1
  94. package/dist/data/ai/SessionViewer.header.js.map +1 -1
  95. package/dist/data/ai/SessionViewer.js +13 -4
  96. package/dist/data/ai/SessionViewer.js.map +1 -1
  97. package/dist/data/ai/SessionViewer.model.cjs +2 -0
  98. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  99. package/dist/data/ai/SessionViewer.model.d.ts +1 -0
  100. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  101. package/dist/data/ai/SessionViewer.model.js +2 -0
  102. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  103. package/dist/data/ai/SessionViewer.rows.cjs +41 -27
  104. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  105. package/dist/data/ai/SessionViewer.rows.d.ts +4 -2
  106. package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
  107. package/dist/data/ai/SessionViewer.rows.js +41 -27
  108. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  109. package/dist/data/ai/SessionViewer.tokens.cjs +35 -0
  110. package/dist/data/ai/SessionViewer.tokens.cjs.map +1 -0
  111. package/dist/data/ai/SessionViewer.tokens.d.ts +5 -0
  112. package/dist/data/ai/SessionViewer.tokens.d.ts.map +1 -0
  113. package/dist/data/ai/SessionViewer.tokens.js +35 -0
  114. package/dist/data/ai/SessionViewer.tokens.js.map +1 -0
  115. package/dist/data/ai/SessionViewer.tool-cost.cjs +128 -0
  116. package/dist/data/ai/SessionViewer.tool-cost.cjs.map +1 -0
  117. package/dist/data/ai/SessionViewer.tool-cost.d.ts +6 -0
  118. package/dist/data/ai/SessionViewer.tool-cost.d.ts.map +1 -0
  119. package/dist/data/ai/SessionViewer.tool-cost.js +128 -0
  120. package/dist/data/ai/SessionViewer.tool-cost.js.map +1 -0
  121. package/dist/data/ai/SessionViewer.tool-details.cjs +3 -1
  122. package/dist/data/ai/SessionViewer.tool-details.cjs.map +1 -1
  123. package/dist/data/ai/SessionViewer.tool-details.d.ts.map +1 -1
  124. package/dist/data/ai/SessionViewer.tool-details.js +3 -1
  125. package/dist/data/ai/SessionViewer.tool-details.js.map +1 -1
  126. package/dist/data/ai/SessionViewer.tool-row.cjs +55 -35
  127. package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
  128. package/dist/data/ai/SessionViewer.tool-row.d.ts +2 -1
  129. package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
  130. package/dist/data/ai/SessionViewer.tool-row.js +55 -35
  131. package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
  132. package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
  133. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  134. package/dist/data/ai/SessionViewerMenu.cjs +18 -1
  135. package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
  136. package/dist/data/ai/SessionViewerMenu.d.ts +6 -1
  137. package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
  138. package/dist/data/ai/SessionViewerMenu.js +18 -1
  139. package/dist/data/ai/SessionViewerMenu.js.map +1 -1
  140. package/dist/data/ai/ToolPreferences.cjs +149 -143
  141. package/dist/data/ai/ToolPreferences.cjs.map +1 -1
  142. package/dist/data/ai/ToolPreferences.d.ts +20 -6
  143. package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
  144. package/dist/data/ai/ToolPreferences.js +151 -146
  145. package/dist/data/ai/ToolPreferences.js.map +1 -1
  146. package/dist/data/ai/ToolPreferences.model.cjs +14 -10
  147. package/dist/data/ai/ToolPreferences.model.cjs.map +1 -1
  148. package/dist/data/ai/ToolPreferences.model.d.ts +1 -0
  149. package/dist/data/ai/ToolPreferences.model.d.ts.map +1 -1
  150. package/dist/data/ai/ToolPreferences.model.js +15 -11
  151. package/dist/data/ai/ToolPreferences.model.js.map +1 -1
  152. package/dist/data/ai/ToolPreferencesList.cjs +1 -0
  153. package/dist/data/ai/ToolPreferencesList.cjs.map +1 -1
  154. package/dist/data/ai/ToolPreferencesList.d.ts +4 -1
  155. package/dist/data/ai/ToolPreferencesList.d.ts.map +1 -1
  156. package/dist/data/ai/ToolPreferencesList.js +2 -1
  157. package/dist/data/ai/ToolPreferencesList.js.map +1 -1
  158. package/dist/data/ai/ToolSchemaBrowser.cjs +52 -53
  159. package/dist/data/ai/ToolSchemaBrowser.cjs.map +1 -1
  160. package/dist/data/ai/ToolSchemaBrowser.d.ts +6 -3
  161. package/dist/data/ai/ToolSchemaBrowser.d.ts.map +1 -1
  162. package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs +9 -13
  163. package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs.map +1 -1
  164. package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts +5 -2
  165. package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts.map +1 -1
  166. package/dist/data/ai/ToolSchemaBrowser.directory-header.js +9 -13
  167. package/dist/data/ai/ToolSchemaBrowser.directory-header.js.map +1 -1
  168. package/dist/data/ai/ToolSchemaBrowser.js +53 -54
  169. package/dist/data/ai/ToolSchemaBrowser.js.map +1 -1
  170. package/dist/data/ai/ToolSchemaBrowser.model.cjs +19 -27
  171. package/dist/data/ai/ToolSchemaBrowser.model.cjs.map +1 -1
  172. package/dist/data/ai/ToolSchemaBrowser.model.d.ts +9 -6
  173. package/dist/data/ai/ToolSchemaBrowser.model.d.ts.map +1 -1
  174. package/dist/data/ai/ToolSchemaBrowser.model.js +20 -28
  175. package/dist/data/ai/ToolSchemaBrowser.model.js.map +1 -1
  176. package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs +12 -213
  177. package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs.map +1 -1
  178. package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts +1 -3
  179. package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts.map +1 -1
  180. package/dist/data/ai/ToolSchemaBrowser.sidebar.js +13 -214
  181. package/dist/data/ai/ToolSchemaBrowser.sidebar.js.map +1 -1
  182. package/dist/data/ai/ToolSchemaBrowser.strategies.cjs +54 -0
  183. package/dist/data/ai/ToolSchemaBrowser.strategies.cjs.map +1 -0
  184. package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts +9 -0
  185. package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts.map +1 -0
  186. package/dist/data/ai/ToolSchemaBrowser.strategies.js +54 -0
  187. package/dist/data/ai/ToolSchemaBrowser.strategies.js.map +1 -0
  188. package/dist/data/ai/ToolSchemaBrowser.tree.cjs +179 -0
  189. package/dist/data/ai/ToolSchemaBrowser.tree.cjs.map +1 -0
  190. package/dist/data/ai/ToolSchemaBrowser.tree.d.ts +20 -0
  191. package/dist/data/ai/ToolSchemaBrowser.tree.d.ts.map +1 -0
  192. package/dist/data/ai/ToolSchemaBrowser.tree.js +179 -0
  193. package/dist/data/ai/ToolSchemaBrowser.tree.js.map +1 -0
  194. package/dist/data/ai/index.d.ts +2 -2
  195. package/dist/data/ai/index.d.ts.map +1 -1
  196. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +8 -28
  197. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -1
  198. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -1
  199. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +9 -29
  200. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -1
  201. package/dist/data/ai/session-token-sizing.d.ts +32 -0
  202. package/dist/data/ai/session-token-sizing.d.ts.map +1 -0
  203. package/dist/data/ai/use-session-token-sizing.cjs +73 -0
  204. package/dist/data/ai/use-session-token-sizing.cjs.map +1 -0
  205. package/dist/data/ai/use-session-token-sizing.d.ts +21 -0
  206. package/dist/data/ai/use-session-token-sizing.d.ts.map +1 -0
  207. package/dist/data/ai/use-session-token-sizing.js +73 -0
  208. package/dist/data/ai/use-session-token-sizing.js.map +1 -0
  209. package/dist/data/call-graph/CallGraph.cjs +250 -0
  210. package/dist/data/call-graph/CallGraph.cjs.map +1 -0
  211. package/dist/data/call-graph/CallGraph.d.ts +69 -0
  212. package/dist/data/call-graph/CallGraph.d.ts.map +1 -0
  213. package/dist/data/call-graph/CallGraph.js +250 -0
  214. package/dist/data/call-graph/CallGraph.js.map +1 -0
  215. package/dist/data/call-graph/CallGraphGlyphs.cjs +39 -0
  216. package/dist/data/call-graph/CallGraphGlyphs.cjs.map +1 -0
  217. package/dist/data/call-graph/CallGraphGlyphs.d.ts +19 -0
  218. package/dist/data/call-graph/CallGraphGlyphs.d.ts.map +1 -0
  219. package/dist/data/call-graph/CallGraphGlyphs.js +39 -0
  220. package/dist/data/call-graph/CallGraphGlyphs.js.map +1 -0
  221. package/dist/data/call-graph/CallGraphMembers.cjs +50 -0
  222. package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -0
  223. package/dist/data/call-graph/CallGraphMembers.d.ts +22 -0
  224. package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -0
  225. package/dist/data/call-graph/CallGraphMembers.js +50 -0
  226. package/dist/data/call-graph/CallGraphMembers.js.map +1 -0
  227. package/dist/data/call-graph/CallGraphParts.cjs +204 -0
  228. package/dist/data/call-graph/CallGraphParts.cjs.map +1 -0
  229. package/dist/data/call-graph/CallGraphParts.d.ts +44 -0
  230. package/dist/data/call-graph/CallGraphParts.d.ts.map +1 -0
  231. package/dist/data/call-graph/CallGraphParts.js +204 -0
  232. package/dist/data/call-graph/CallGraphParts.js.map +1 -0
  233. package/dist/data/call-graph/CallGraphToolbar.cjs +186 -0
  234. package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -0
  235. package/dist/data/call-graph/CallGraphToolbar.d.ts +45 -0
  236. package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -0
  237. package/dist/data/call-graph/CallGraphToolbar.js +186 -0
  238. package/dist/data/call-graph/CallGraphToolbar.js.map +1 -0
  239. package/dist/data/call-graph/call-graph-exclude.cjs +75 -0
  240. package/dist/data/call-graph/call-graph-exclude.cjs.map +1 -0
  241. package/dist/data/call-graph/call-graph-exclude.d.ts +31 -0
  242. package/dist/data/call-graph/call-graph-exclude.d.ts.map +1 -0
  243. package/dist/data/call-graph/call-graph-exclude.js +75 -0
  244. package/dist/data/call-graph/call-graph-exclude.js.map +1 -0
  245. package/dist/data/call-graph/call-graph-labels.cjs +96 -0
  246. package/dist/data/call-graph/call-graph-labels.cjs.map +1 -0
  247. package/dist/data/call-graph/call-graph-labels.d.ts +53 -0
  248. package/dist/data/call-graph/call-graph-labels.d.ts.map +1 -0
  249. package/dist/data/call-graph/call-graph-labels.js +96 -0
  250. package/dist/data/call-graph/call-graph-labels.js.map +1 -0
  251. package/dist/data/call-graph/call-graph-model.cjs +161 -0
  252. package/dist/data/call-graph/call-graph-model.cjs.map +1 -0
  253. package/dist/data/call-graph/call-graph-model.d.ts +102 -0
  254. package/dist/data/call-graph/call-graph-model.d.ts.map +1 -0
  255. package/dist/data/call-graph/call-graph-model.js +161 -0
  256. package/dist/data/call-graph/call-graph-model.js.map +1 -0
  257. package/dist/data/call-graph/call-graph-vocabulary.cjs +177 -0
  258. package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -0
  259. package/dist/data/call-graph/call-graph-vocabulary.d.ts +72 -0
  260. package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -0
  261. package/dist/data/call-graph/call-graph-vocabulary.js +177 -0
  262. package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -0
  263. package/dist/data/call-graph/call-graph.fixtures.d.ts +63 -0
  264. package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -0
  265. package/dist/data/call-graph/index.d.ts +7 -0
  266. package/dist/data/call-graph/index.d.ts.map +1 -0
  267. package/dist/data/call-graph/types.cjs +5 -0
  268. package/dist/data/call-graph/types.cjs.map +1 -0
  269. package/dist/data/call-graph/types.d.ts +135 -0
  270. package/dist/data/call-graph/types.d.ts.map +1 -0
  271. package/dist/data/call-graph/types.js +5 -0
  272. package/dist/data/call-graph/types.js.map +1 -0
  273. package/dist/data/call-graph/use-call-graph.cjs +93 -0
  274. package/dist/data/call-graph/use-call-graph.cjs.map +1 -0
  275. package/dist/data/call-graph/use-call-graph.d.ts +24 -0
  276. package/dist/data/call-graph/use-call-graph.d.ts.map +1 -0
  277. package/dist/data/call-graph/use-call-graph.js +93 -0
  278. package/dist/data/call-graph/use-call-graph.js.map +1 -0
  279. package/dist/data/chat/Chat.cjs +39 -15
  280. package/dist/data/chat/Chat.cjs.map +1 -1
  281. package/dist/data/chat/Chat.d.ts.map +1 -1
  282. package/dist/data/chat/Chat.fixtures.cjs +2 -2
  283. package/dist/data/chat/Chat.fixtures.cjs.map +1 -1
  284. package/dist/data/chat/Chat.fixtures.js +2 -2
  285. package/dist/data/chat/Chat.fixtures.js.map +1 -1
  286. package/dist/data/chat/Chat.js +40 -16
  287. package/dist/data/chat/Chat.js.map +1 -1
  288. package/dist/data/chat/ChatRuntimeToolbar.cjs +3 -6
  289. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  290. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  291. package/dist/data/chat/ChatRuntimeToolbar.js +3 -6
  292. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  293. package/dist/data/chat/ContextMeter.bar.cjs +5 -8
  294. package/dist/data/chat/ContextMeter.bar.cjs.map +1 -1
  295. package/dist/data/chat/ContextMeter.bar.d.ts +1 -1
  296. package/dist/data/chat/ContextMeter.bar.d.ts.map +1 -1
  297. package/dist/data/chat/ContextMeter.bar.js +5 -8
  298. package/dist/data/chat/ContextMeter.bar.js.map +1 -1
  299. package/dist/data/chat/ContextMeter.cjs +18 -19
  300. package/dist/data/chat/ContextMeter.cjs.map +1 -1
  301. package/dist/data/chat/ContextMeter.d.ts +1 -1
  302. package/dist/data/chat/ContextMeter.d.ts.map +1 -1
  303. package/dist/data/chat/ContextMeter.js +18 -19
  304. package/dist/data/chat/ContextMeter.js.map +1 -1
  305. package/dist/data/chat/Conversation.cjs +2 -1
  306. package/dist/data/chat/Conversation.cjs.map +1 -1
  307. package/dist/data/chat/Conversation.d.ts +4 -1
  308. package/dist/data/chat/Conversation.d.ts.map +1 -1
  309. package/dist/data/chat/Conversation.js +2 -1
  310. package/dist/data/chat/Conversation.js.map +1 -1
  311. package/dist/data/chat/Message.cjs +39 -12
  312. package/dist/data/chat/Message.cjs.map +1 -1
  313. package/dist/data/chat/Message.d.ts +1 -1
  314. package/dist/data/chat/Message.d.ts.map +1 -1
  315. package/dist/data/chat/Message.js +40 -13
  316. package/dist/data/chat/Message.js.map +1 -1
  317. package/dist/data/chat/ToolCall.cjs +60 -5
  318. package/dist/data/chat/ToolCall.cjs.map +1 -1
  319. package/dist/data/chat/ToolCall.d.ts +7 -2
  320. package/dist/data/chat/ToolCall.d.ts.map +1 -1
  321. package/dist/data/chat/ToolCall.js +60 -5
  322. package/dist/data/chat/ToolCall.js.map +1 -1
  323. package/dist/data/chat/approval.cjs.map +1 -1
  324. package/dist/data/chat/approval.d.ts +2 -2
  325. package/dist/data/chat/approval.d.ts.map +1 -1
  326. package/dist/data/chat/approval.js.map +1 -1
  327. package/dist/data/chat/tool-policy.cjs +59 -2
  328. package/dist/data/chat/tool-policy.cjs.map +1 -1
  329. package/dist/data/chat/tool-policy.d.ts +9 -0
  330. package/dist/data/chat/tool-policy.d.ts.map +1 -1
  331. package/dist/data/chat/tool-policy.js +59 -2
  332. package/dist/data/chat/tool-policy.js.map +1 -1
  333. package/dist/data/chat/types.cjs +6 -0
  334. package/dist/data/chat/types.cjs.map +1 -1
  335. package/dist/data/chat/types.d.ts +13 -4
  336. package/dist/data/chat/types.d.ts.map +1 -1
  337. package/dist/data/chat/types.js +7 -1
  338. package/dist/data/chat/types.js.map +1 -1
  339. package/dist/data/chat/usage-snapshot.cjs +11 -6
  340. package/dist/data/chat/usage-snapshot.cjs.map +1 -1
  341. package/dist/data/chat/usage-snapshot.d.ts +0 -1
  342. package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
  343. package/dist/data/chat/usage-snapshot.js +11 -6
  344. package/dist/data/chat/usage-snapshot.js.map +1 -1
  345. package/dist/data/diagnostics/RenderedStackTrace.cjs +2 -1
  346. package/dist/data/diagnostics/RenderedStackTrace.cjs.map +1 -1
  347. package/dist/data/diagnostics/RenderedStackTrace.d.ts +3 -1
  348. package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -1
  349. package/dist/data/diagnostics/RenderedStackTrace.js +2 -1
  350. package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -1
  351. package/dist/data/diagnostics/StackFrameRow.cjs +3 -3
  352. package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -1
  353. package/dist/data/diagnostics/StackFrameRow.js +3 -3
  354. package/dist/data/diagnostics/StackFrameRow.js.map +1 -1
  355. package/dist/data/graph-columns-layout.cjs +26 -10
  356. package/dist/data/graph-columns-layout.cjs.map +1 -1
  357. package/dist/data/graph-columns-layout.d.ts +8 -0
  358. package/dist/data/graph-columns-layout.d.ts.map +1 -1
  359. package/dist/data/graph-columns-layout.js +26 -10
  360. package/dist/data/graph-columns-layout.js.map +1 -1
  361. package/dist/data/graph-diagram-model.cjs.map +1 -1
  362. package/dist/data/graph-diagram-model.d.ts +5 -0
  363. package/dist/data/graph-diagram-model.d.ts.map +1 -1
  364. package/dist/data/graph-diagram-model.js.map +1 -1
  365. package/dist/data/graph-edge-routing.cjs +9 -3
  366. package/dist/data/graph-edge-routing.cjs.map +1 -1
  367. package/dist/data/graph-edge-routing.d.ts +2 -0
  368. package/dist/data/graph-edge-routing.d.ts.map +1 -1
  369. package/dist/data/graph-edge-routing.js +9 -3
  370. package/dist/data/graph-edge-routing.js.map +1 -1
  371. package/dist/data/json-view/JsonSource.cjs +84 -0
  372. package/dist/data/json-view/JsonSource.cjs.map +1 -0
  373. package/dist/data/json-view/JsonSource.d.ts +7 -0
  374. package/dist/data/json-view/JsonSource.d.ts.map +1 -0
  375. package/dist/data/json-view/JsonSource.js +84 -0
  376. package/dist/data/json-view/JsonSource.js.map +1 -0
  377. package/dist/data/json-view/parse-prefix.cjs +132 -0
  378. package/dist/data/json-view/parse-prefix.cjs.map +1 -0
  379. package/dist/data/json-view/parse-prefix.d.ts +11 -0
  380. package/dist/data/json-view/parse-prefix.d.ts.map +1 -0
  381. package/dist/data/json-view/parse-prefix.js +132 -0
  382. package/dist/data/json-view/parse-prefix.js.map +1 -0
  383. package/dist/data/json-view/parse-source.cjs +62 -0
  384. package/dist/data/json-view/parse-source.cjs.map +1 -0
  385. package/dist/data/json-view/parse-source.d.ts +16 -0
  386. package/dist/data/json-view/parse-source.d.ts.map +1 -0
  387. package/dist/data/json-view/parse-source.js +62 -0
  388. package/dist/data/json-view/parse-source.js.map +1 -0
  389. package/dist/data/json-view/story-fixtures.d.ts +6 -0
  390. package/dist/data/json-view/story-fixtures.d.ts.map +1 -0
  391. package/dist/data/json-view/types.d.ts +14 -0
  392. package/dist/data/json-view/types.d.ts.map +1 -0
  393. package/dist/data/runtime/RuntimeBar.cjs +2 -5
  394. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  395. package/dist/data/runtime/RuntimeBar.d.ts +2 -4
  396. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  397. package/dist/data/runtime/RuntimeBar.fields.cjs +2 -2
  398. package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -1
  399. package/dist/data/runtime/RuntimeBar.fields.js +2 -2
  400. package/dist/data/runtime/RuntimeBar.fields.js.map +1 -1
  401. package/dist/data/runtime/RuntimeBar.js +2 -5
  402. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  403. package/dist/data/runtime/RuntimeBar.selection.cjs +4 -1
  404. package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -1
  405. package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -1
  406. package/dist/data/runtime/RuntimeBar.selection.js +5 -2
  407. package/dist/data/runtime/RuntimeBar.selection.js.map +1 -1
  408. package/dist/data/runtime/RuntimeBarActions.cjs +1 -5
  409. package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
  410. package/dist/data/runtime/RuntimeBarActions.d.ts +1 -1
  411. package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
  412. package/dist/data/runtime/RuntimeBarActions.js +1 -5
  413. package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
  414. package/dist/data/runtime/RuntimeBarIdentity.cjs +6 -14
  415. package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -1
  416. package/dist/data/runtime/RuntimeBarIdentity.d.ts +0 -1
  417. package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -1
  418. package/dist/data/runtime/RuntimeBarIdentity.js +6 -14
  419. package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -1
  420. package/dist/data/runtime/RuntimeBarLayout.cjs +8 -27
  421. package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -1
  422. package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -1
  423. package/dist/data/runtime/RuntimeBarLayout.js +8 -27
  424. package/dist/data/runtime/RuntimeBarLayout.js.map +1 -1
  425. package/dist/data/runtime/RuntimeBarSegment.cjs +1 -5
  426. package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
  427. package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
  428. package/dist/data/runtime/RuntimeBarSegment.js +1 -5
  429. package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
  430. package/dist/data/runtime/use-runtime-bar-overflow.cjs +4 -10
  431. package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -1
  432. package/dist/data/runtime/use-runtime-bar-overflow.d.ts +1 -2
  433. package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -1
  434. package/dist/data/runtime/use-runtime-bar-overflow.js +4 -10
  435. package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -1
  436. package/dist/data/test-runner/TestRunner.fixtures.d.ts +0 -20
  437. package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
  438. package/dist/data/test-runner/TestRunner.large-fixtures.d.ts +22 -0
  439. package/dist/data/test-runner/TestRunner.large-fixtures.d.ts.map +1 -0
  440. package/dist/data/use-pan-zoom.cjs +23 -10
  441. package/dist/data/use-pan-zoom.cjs.map +1 -1
  442. package/dist/data/use-pan-zoom.d.ts +16 -2
  443. package/dist/data/use-pan-zoom.d.ts.map +1 -1
  444. package/dist/data/use-pan-zoom.js +23 -10
  445. package/dist/data/use-pan-zoom.js.map +1 -1
  446. package/dist/data/version-info.cjs +3 -3
  447. package/dist/data/version-info.js +3 -3
  448. package/dist/data.cjs +28 -2
  449. package/dist/data.cjs.map +1 -1
  450. package/dist/data.d.ts +2 -0
  451. package/dist/data.d.ts.map +1 -1
  452. package/dist/data.js +26 -0
  453. package/dist/data.js.map +1 -1
  454. package/dist/index.cjs +30 -4
  455. package/dist/index.cjs.map +1 -1
  456. package/dist/index.js +26 -0
  457. package/dist/index.js.map +1 -1
  458. package/dist/layout/Workspace.cjs +13 -4
  459. package/dist/layout/Workspace.cjs.map +1 -1
  460. package/dist/layout/Workspace.d.ts +7 -2
  461. package/dist/layout/Workspace.d.ts.map +1 -1
  462. package/dist/layout/Workspace.js +13 -4
  463. package/dist/layout/Workspace.js.map +1 -1
  464. package/dist/lib/permission-strategies.cjs +71 -11
  465. package/dist/lib/permission-strategies.cjs.map +1 -1
  466. package/dist/lib/permission-strategies.d.ts +3 -0
  467. package/dist/lib/permission-strategies.d.ts.map +1 -1
  468. package/dist/lib/permission-strategies.js +71 -11
  469. package/dist/lib/permission-strategies.js.map +1 -1
  470. package/dist/styles.css +1 -1
  471. package/package.json +5 -3
  472. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs +0 -57
  473. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs.map +0 -1
  474. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts +0 -7
  475. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts.map +0 -1
  476. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js +0 -57
  477. package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js.map +0 -1
  478. package/dist/data/runtime/RuntimeBar.context.cjs +0 -8
  479. package/dist/data/runtime/RuntimeBar.context.cjs.map +0 -1
  480. package/dist/data/runtime/RuntimeBar.context.d.ts +0 -2
  481. package/dist/data/runtime/RuntimeBar.context.d.ts.map +0 -1
  482. package/dist/data/runtime/RuntimeBar.context.js +0 -8
  483. package/dist/data/runtime/RuntimeBar.context.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Workspace.cjs","sources":["../../src/layout/Workspace.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { UiSidebar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport {\n createWorkspaceLayoutState,\n readWorkspaceLayoutState,\n validateWorkspacePanes,\n writeWorkspaceLayoutState,\n type WorkspaceLayoutDefaults,\n type WorkspaceLayoutState,\n type WorkspacePaneSpec,\n} from \"./Workspace.model\";\nimport {\n WorkspaceSideRegion,\n WorkspaceSingleRegion,\n type WorkspaceUpdate,\n} from \"./Workspace.regions\";\n\nexport type {\n WorkspaceLayoutDefaults,\n WorkspaceLayoutState,\n WorkspacePaneLocation,\n WorkspacePaneSlots,\n WorkspacePaneSpec,\n WorkspaceSideLocation,\n} from \"./Workspace.model\";\n\nexport type WorkspaceSlots = {\n topRightActions?: ReactNode;\n};\n\nexport type WorkspaceProps = {\n panes: WorkspacePaneSpec[];\n value?: WorkspaceLayoutState;\n defaultValue?: WorkspaceLayoutDefaults;\n onValueChange?: (value: WorkspaceLayoutState) => void;\n storageKey?: string;\n slots?: WorkspaceSlots;\n className?: string;\n};\n\ntype WorkspaceTopRightProps = {\n hasLeft: boolean;\n hasRight: boolean;\n slots?: WorkspaceSlots;\n state: WorkspaceLayoutState;\n update: WorkspaceUpdate;\n};\n\nfunction WorkspaceTopRight({\n hasLeft,\n hasRight,\n slots,\n state,\n update,\n}: WorkspaceTopRightProps) {\n if (!hasLeft && !hasRight && !slots?.topRightActions) return null;\n const toggleSide = (location: \"left\" | \"right\") =>\n update((current) => ({\n ...current,\n sideCollapsed: {\n ...current.sideCollapsed,\n [location]: !current.sideCollapsed[location],\n },\n }));\n return (\n <div\n data-testid=\"workspace-top-right\"\n className=\"absolute right-1 top-1 z-30 flex h-7 items-center gap-1 rounded bg-muted/90 px-1 shadow-sm backdrop-blur\"\n >\n {slots?.topRightActions}\n {hasLeft && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.left}\n aria-label={`${state.sideCollapsed.left ? \"Expand\" : \"Collapse\"} left side`}\n onClick={() => toggleSide(\"left\")}\n >\n <UiSidebar className=\"size-4\" />\n </button>\n )}\n {hasRight && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.right}\n aria-label={`${state.sideCollapsed.right ? \"Expand\" : \"Collapse\"} right side`}\n onClick={() => toggleSide(\"right\")}\n >\n <UiSidebar className=\"size-4 -scale-x-100\" />\n </button>\n )}\n </div>\n );\n}\n\nexport function Workspace({\n panes,\n value,\n defaultValue = {},\n onValueChange,\n storageKey,\n slots,\n className,\n}: WorkspaceProps) {\n validateWorkspacePanes(panes);\n if (value !== undefined && storageKey !== undefined) {\n throw new Error(\"Workspace cannot combine value with storageKey\");\n }\n const [internal, setInternal] = useState(() =>\n storageKey\n ? readWorkspaceLayoutState(storageKey, panes, defaultValue)\n : createWorkspaceLayoutState(panes, defaultValue),\n );\n const seenLocations = useRef(new Set(panes.map((pane) => pane.location)));\n const seenPaneIds = useRef(new Set(panes.map((pane) => pane.id)));\n const state = value ?? internal;\n const groups = useMemo(\n () => ({\n left: panes.filter((pane) => pane.location === \"left\"),\n center: panes.find(\n (pane) => pane.location === \"center\",\n ) as WorkspacePaneSpec,\n right: panes.filter((pane) => pane.location === \"right\"),\n bottom: panes.find((pane) => pane.location === \"bottom\"),\n }),\n [panes],\n );\n\n useLayoutEffect(() => {\n const addedLocations = new Set(\n panes\n .map((pane) => pane.location)\n .filter((location) => !seenLocations.current.has(location)),\n );\n const addedPanes = panes.filter(\n (pane) => !seenPaneIds.current.has(pane.id),\n );\n panes.forEach((pane) => {\n seenLocations.current.add(pane.location);\n seenPaneIds.current.add(pane.id);\n });\n if (\n value !== undefined ||\n (addedLocations.size === 0 && addedPanes.length === 0)\n )\n return;\n const defaults = createWorkspaceLayoutState(panes, defaultValue);\n const addedStackHeights = addedPanes.reduce<Record<string, number>>(\n (heights, pane) => {\n if (pane.height !== undefined) heights[pane.id] = pane.height;\n return heights;\n },\n {},\n );\n setInternal((current) => ({\n ...current,\n ...(addedLocations.has(\"left\") ? { leftWidth: defaults.leftWidth } : {}),\n ...(addedLocations.has(\"right\")\n ? { rightWidth: defaults.rightWidth }\n : {}),\n ...(addedLocations.has(\"bottom\")\n ? { bottomHeight: defaults.bottomHeight }\n : {}),\n stackHeights: { ...current.stackHeights, ...addedStackHeights },\n collapsed: {\n ...current.collapsed,\n ...Object.fromEntries(\n addedPanes.map((pane) => [pane.id, pane.defaultCollapsed ?? false]),\n ),\n },\n }));\n }, [defaultValue, panes, value]);\n\n const update = useCallback<WorkspaceUpdate>(\n (change) => {\n const next = change(state);\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n },\n [onValueChange, state, value],\n );\n\n useEffect(() => {\n if (storageKey && value === undefined)\n writeWorkspaceLayoutState(storageKey, internal);\n }, [internal, storageKey, value]);\n\n return (\n <div\n className={cn(\n \"relative grid min-h-0 w-full grid-cols-1 overflow-auto bg-background md:h-full md:grid-cols-[auto_minmax(0,1fr)_auto] md:grid-rows-[minmax(0,1fr)_auto] md:overflow-hidden\",\n className,\n )}\n >\n <WorkspaceTopRight\n hasLeft={groups.left.length > 0}\n hasRight={groups.right.length > 0}\n {...(slots ? { slots } : {})}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"left\"\n panes={groups.left}\n state={state}\n update={update}\n />\n <WorkspaceSingleRegion\n pane={groups.center}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"right\"\n panes={groups.right}\n state={state}\n update={update}\n />\n {groups.bottom && (\n <WorkspaceSingleRegion\n pane={groups.bottom}\n state={state}\n update={update}\n />\n )}\n </div>\n );\n}\n"],"names":["jsxs","jsx","UiSidebar","validateWorkspacePanes","useState","readWorkspaceLayoutState","createWorkspaceLayoutState","useRef","useMemo","useLayoutEffect","useCallback","useEffect","writeWorkspaceLayoutState","cn","WorkspaceSideRegion","WorkspaceSingleRegion"],"mappings":"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"}
1
+ {"version":3,"file":"Workspace.cjs","sources":["../../src/layout/Workspace.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { UiSidebar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport {\n createWorkspaceLayoutState,\n readWorkspaceLayoutState,\n validateWorkspacePanes,\n writeWorkspaceLayoutState,\n type WorkspaceLayoutDefaults,\n type WorkspaceLayoutState,\n type WorkspacePaneSpec,\n type WorkspaceSideLocation,\n} from \"./Workspace.model\";\nimport {\n WorkspaceSideRegion,\n WorkspaceSingleRegion,\n type WorkspaceUpdate,\n} from \"./Workspace.regions\";\n\nexport type {\n WorkspaceLayoutDefaults,\n WorkspaceLayoutState,\n WorkspacePaneLocation,\n WorkspacePaneSlots,\n WorkspacePaneSpec,\n WorkspaceSideLocation,\n} from \"./Workspace.model\";\n\nexport type WorkspaceSlots = {\n topRightActions?: ReactNode;\n};\n\nexport type WorkspaceProps = {\n panes: WorkspacePaneSpec[];\n value?: WorkspaceLayoutState;\n defaultValue?: WorkspaceLayoutDefaults;\n onValueChange?: (value: WorkspaceLayoutState) => void;\n storageKey?: string;\n slots?: WorkspaceSlots;\n /**\n * Sides the host holds collapsed for now, such as while the center shows something that needs the\n * full width: they render collapsed and lose their toggle, and the layout state keeps how they were.\n */\n collapsedSides?: WorkspaceSideLocation[];\n className?: string;\n};\n\ntype WorkspaceTopRightProps = {\n hasLeft: boolean;\n hasRight: boolean;\n slots?: WorkspaceSlots;\n state: WorkspaceLayoutState;\n update: WorkspaceUpdate;\n};\n\nfunction WorkspaceTopRight({\n hasLeft,\n hasRight,\n slots,\n state,\n update,\n}: WorkspaceTopRightProps) {\n if (!hasLeft && !hasRight && !slots?.topRightActions) return null;\n const toggleSide = (location: \"left\" | \"right\") =>\n update((current) => ({\n ...current,\n sideCollapsed: {\n ...current.sideCollapsed,\n [location]: !current.sideCollapsed[location],\n },\n }));\n return (\n <div\n data-testid=\"workspace-top-right\"\n className=\"absolute right-1 top-1 z-30 flex h-7 items-center gap-1 rounded bg-muted/90 px-1 shadow-sm backdrop-blur\"\n >\n {slots?.topRightActions}\n {hasLeft && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.left}\n aria-label={`${state.sideCollapsed.left ? \"Expand\" : \"Collapse\"} left side`}\n onClick={() => toggleSide(\"left\")}\n >\n <UiSidebar className=\"size-4\" />\n </button>\n )}\n {hasRight && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.right}\n aria-label={`${state.sideCollapsed.right ? \"Expand\" : \"Collapse\"} right side`}\n onClick={() => toggleSide(\"right\")}\n >\n <UiSidebar className=\"size-4 -scale-x-100\" />\n </button>\n )}\n </div>\n );\n}\n\nexport function Workspace({\n panes,\n value,\n defaultValue = {},\n onValueChange,\n storageKey,\n slots,\n collapsedSides,\n className,\n}: WorkspaceProps) {\n validateWorkspacePanes(panes);\n if (value !== undefined && storageKey !== undefined) {\n throw new Error(\"Workspace cannot combine value with storageKey\");\n }\n const [internal, setInternal] = useState(() =>\n storageKey\n ? readWorkspaceLayoutState(storageKey, panes, defaultValue)\n : createWorkspaceLayoutState(panes, defaultValue),\n );\n const seenLocations = useRef(new Set(panes.map((pane) => pane.location)));\n const seenPaneIds = useRef(new Set(panes.map((pane) => pane.id)));\n const state = value ?? internal;\n const groups = useMemo(\n () => ({\n left: panes.filter((pane) => pane.location === \"left\"),\n center: panes.find(\n (pane) => pane.location === \"center\",\n ) as WorkspacePaneSpec,\n right: panes.filter((pane) => pane.location === \"right\"),\n bottom: panes.find((pane) => pane.location === \"bottom\"),\n }),\n [panes],\n );\n\n useLayoutEffect(() => {\n const addedLocations = new Set(\n panes\n .map((pane) => pane.location)\n .filter((location) => !seenLocations.current.has(location)),\n );\n const addedPanes = panes.filter(\n (pane) => !seenPaneIds.current.has(pane.id),\n );\n panes.forEach((pane) => {\n seenLocations.current.add(pane.location);\n seenPaneIds.current.add(pane.id);\n });\n if (\n value !== undefined ||\n (addedLocations.size === 0 && addedPanes.length === 0)\n )\n return;\n const defaults = createWorkspaceLayoutState(panes, defaultValue);\n const addedStackHeights = addedPanes.reduce<Record<string, number>>(\n (heights, pane) => {\n if (pane.height !== undefined) heights[pane.id] = pane.height;\n return heights;\n },\n {},\n );\n setInternal((current) => ({\n ...current,\n ...(addedLocations.has(\"left\") ? { leftWidth: defaults.leftWidth } : {}),\n ...(addedLocations.has(\"right\")\n ? { rightWidth: defaults.rightWidth }\n : {}),\n ...(addedLocations.has(\"bottom\")\n ? { bottomHeight: defaults.bottomHeight }\n : {}),\n stackHeights: { ...current.stackHeights, ...addedStackHeights },\n collapsed: {\n ...current.collapsed,\n ...Object.fromEntries(\n addedPanes.map((pane) => [pane.id, pane.defaultCollapsed ?? false]),\n ),\n },\n }));\n }, [defaultValue, panes, value]);\n\n const update = useCallback<WorkspaceUpdate>(\n (change) => {\n const next = change(state);\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n },\n [onValueChange, state, value],\n );\n\n useEffect(() => {\n if (storageKey && value === undefined)\n writeWorkspaceLayoutState(storageKey, internal);\n }, [internal, storageKey, value]);\n\n const held = (location: WorkspaceSideLocation) =>\n collapsedSides?.includes(location) ?? false;\n const shown: WorkspaceLayoutState = collapsedSides?.length\n ? {\n ...state,\n sideCollapsed: {\n left: held(\"left\") || state.sideCollapsed.left,\n right: held(\"right\") || state.sideCollapsed.right,\n },\n }\n : state;\n\n return (\n <div\n className={cn(\n \"relative grid min-h-0 w-full grid-cols-1 overflow-auto bg-background md:h-full md:grid-cols-[auto_minmax(0,1fr)_auto] md:grid-rows-[minmax(0,1fr)_auto] md:overflow-hidden\",\n className,\n )}\n >\n <WorkspaceTopRight\n hasLeft={groups.left.length > 0 && !held(\"left\")}\n hasRight={groups.right.length > 0 && !held(\"right\")}\n {...(slots ? { slots } : {})}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"left\"\n panes={groups.left}\n state={shown}\n update={update}\n />\n <WorkspaceSingleRegion\n pane={groups.center}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"right\"\n panes={groups.right}\n state={shown}\n update={update}\n />\n {groups.bottom && (\n <WorkspaceSingleRegion\n pane={groups.bottom}\n state={state}\n update={update}\n />\n )}\n </div>\n );\n}\n"],"names":["jsxs","jsx","UiSidebar","validateWorkspacePanes","useState","readWorkspaceLayoutState","createWorkspaceLayoutState","useRef","useMemo","useLayoutEffect","useCallback","useEffect","writeWorkspaceLayoutState","cn","WorkspaceSideRegion","WorkspaceSingleRegion"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { WorkspaceLayoutDefaults, WorkspaceLayoutState, WorkspacePaneSpec } from './Workspace.model.js';
2
+ import { WorkspaceLayoutDefaults, WorkspaceLayoutState, WorkspacePaneSpec, WorkspaceSideLocation } from './Workspace.model.js';
3
3
  export type { WorkspaceLayoutDefaults, WorkspaceLayoutState, WorkspacePaneLocation, WorkspacePaneSlots, WorkspacePaneSpec, WorkspaceSideLocation, } from './Workspace.model.js';
4
4
  export type WorkspaceSlots = {
5
5
  topRightActions?: ReactNode;
@@ -11,7 +11,12 @@ export type WorkspaceProps = {
11
11
  onValueChange?: (value: WorkspaceLayoutState) => void;
12
12
  storageKey?: string;
13
13
  slots?: WorkspaceSlots;
14
+ /**
15
+ * Sides the host holds collapsed for now, such as while the center shows something that needs the
16
+ * full width: they render collapsed and lose their toggle, and the layout state keeps how they were.
17
+ */
18
+ collapsedSides?: WorkspaceSideLocation[];
14
19
  className?: string;
15
20
  };
16
- export declare function Workspace({ panes, value, defaultValue, onValueChange, storageKey, slots, className, }: WorkspaceProps): import("react").JSX.Element;
21
+ export declare function Workspace({ panes, value, defaultValue, onValueChange, storageKey, slots, collapsedSides, className, }: WorkspaceProps): import("react").JSX.Element;
17
22
  //# sourceMappingURL=Workspace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Workspace.d.ts","sourceRoot":"","sources":["../../src/layout/Workspace.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAO3B,YAAY,EACV,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,cAAc,GAAG;IAC3B,eAAe,CAAC,EAAE,SAAS,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA0DF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,YAAiB,EACjB,aAAa,EACb,UAAU,EACV,KAAK,EACL,SAAS,GACV,EAAE,cAAc,+BA4HhB"}
1
+ {"version":3,"file":"Workspace.d.ts","sourceRoot":"","sources":["../../src/layout/Workspace.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAKL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAO3B,YAAY,EACV,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,cAAc,GAAG;IAC3B,eAAe,CAAC,EAAE,SAAS,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA0DF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,YAAiB,EACjB,aAAa,EACb,UAAU,EACV,KAAK,EACL,cAAc,EACd,SAAS,GACV,EAAE,cAAc,+BAwIhB"}
@@ -59,6 +59,7 @@ function Workspace({
59
59
  onValueChange,
60
60
  storageKey,
61
61
  slots,
62
+ collapsedSides,
62
63
  className
63
64
  }) {
64
65
  validateWorkspacePanes(panes);
@@ -129,6 +130,14 @@ function Workspace({
129
130
  if (storageKey && value === void 0)
130
131
  writeWorkspaceLayoutState(storageKey, internal);
131
132
  }, [internal, storageKey, value]);
133
+ const held = (location) => (collapsedSides == null ? void 0 : collapsedSides.includes(location)) ?? false;
134
+ const shown = (collapsedSides == null ? void 0 : collapsedSides.length) ? {
135
+ ...state,
136
+ sideCollapsed: {
137
+ left: held("left") || state.sideCollapsed.left,
138
+ right: held("right") || state.sideCollapsed.right
139
+ }
140
+ } : state;
132
141
  return /* @__PURE__ */ jsxs(
133
142
  "div",
134
143
  {
@@ -140,8 +149,8 @@ function Workspace({
140
149
  /* @__PURE__ */ jsx(
141
150
  WorkspaceTopRight,
142
151
  {
143
- hasLeft: groups.left.length > 0,
144
- hasRight: groups.right.length > 0,
152
+ hasLeft: groups.left.length > 0 && !held("left"),
153
+ hasRight: groups.right.length > 0 && !held("right"),
145
154
  ...slots ? { slots } : {},
146
155
  state,
147
156
  update
@@ -152,7 +161,7 @@ function Workspace({
152
161
  {
153
162
  location: "left",
154
163
  panes: groups.left,
155
- state,
164
+ state: shown,
156
165
  update
157
166
  }
158
167
  ),
@@ -169,7 +178,7 @@ function Workspace({
169
178
  {
170
179
  location: "right",
171
180
  panes: groups.right,
172
- state,
181
+ state: shown,
173
182
  update
174
183
  }
175
184
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"Workspace.js","sources":["../../src/layout/Workspace.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { UiSidebar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport {\n createWorkspaceLayoutState,\n readWorkspaceLayoutState,\n validateWorkspacePanes,\n writeWorkspaceLayoutState,\n type WorkspaceLayoutDefaults,\n type WorkspaceLayoutState,\n type WorkspacePaneSpec,\n} from \"./Workspace.model\";\nimport {\n WorkspaceSideRegion,\n WorkspaceSingleRegion,\n type WorkspaceUpdate,\n} from \"./Workspace.regions\";\n\nexport type {\n WorkspaceLayoutDefaults,\n WorkspaceLayoutState,\n WorkspacePaneLocation,\n WorkspacePaneSlots,\n WorkspacePaneSpec,\n WorkspaceSideLocation,\n} from \"./Workspace.model\";\n\nexport type WorkspaceSlots = {\n topRightActions?: ReactNode;\n};\n\nexport type WorkspaceProps = {\n panes: WorkspacePaneSpec[];\n value?: WorkspaceLayoutState;\n defaultValue?: WorkspaceLayoutDefaults;\n onValueChange?: (value: WorkspaceLayoutState) => void;\n storageKey?: string;\n slots?: WorkspaceSlots;\n className?: string;\n};\n\ntype WorkspaceTopRightProps = {\n hasLeft: boolean;\n hasRight: boolean;\n slots?: WorkspaceSlots;\n state: WorkspaceLayoutState;\n update: WorkspaceUpdate;\n};\n\nfunction WorkspaceTopRight({\n hasLeft,\n hasRight,\n slots,\n state,\n update,\n}: WorkspaceTopRightProps) {\n if (!hasLeft && !hasRight && !slots?.topRightActions) return null;\n const toggleSide = (location: \"left\" | \"right\") =>\n update((current) => ({\n ...current,\n sideCollapsed: {\n ...current.sideCollapsed,\n [location]: !current.sideCollapsed[location],\n },\n }));\n return (\n <div\n data-testid=\"workspace-top-right\"\n className=\"absolute right-1 top-1 z-30 flex h-7 items-center gap-1 rounded bg-muted/90 px-1 shadow-sm backdrop-blur\"\n >\n {slots?.topRightActions}\n {hasLeft && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.left}\n aria-label={`${state.sideCollapsed.left ? \"Expand\" : \"Collapse\"} left side`}\n onClick={() => toggleSide(\"left\")}\n >\n <UiSidebar className=\"size-4\" />\n </button>\n )}\n {hasRight && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.right}\n aria-label={`${state.sideCollapsed.right ? \"Expand\" : \"Collapse\"} right side`}\n onClick={() => toggleSide(\"right\")}\n >\n <UiSidebar className=\"size-4 -scale-x-100\" />\n </button>\n )}\n </div>\n );\n}\n\nexport function Workspace({\n panes,\n value,\n defaultValue = {},\n onValueChange,\n storageKey,\n slots,\n className,\n}: WorkspaceProps) {\n validateWorkspacePanes(panes);\n if (value !== undefined && storageKey !== undefined) {\n throw new Error(\"Workspace cannot combine value with storageKey\");\n }\n const [internal, setInternal] = useState(() =>\n storageKey\n ? readWorkspaceLayoutState(storageKey, panes, defaultValue)\n : createWorkspaceLayoutState(panes, defaultValue),\n );\n const seenLocations = useRef(new Set(panes.map((pane) => pane.location)));\n const seenPaneIds = useRef(new Set(panes.map((pane) => pane.id)));\n const state = value ?? internal;\n const groups = useMemo(\n () => ({\n left: panes.filter((pane) => pane.location === \"left\"),\n center: panes.find(\n (pane) => pane.location === \"center\",\n ) as WorkspacePaneSpec,\n right: panes.filter((pane) => pane.location === \"right\"),\n bottom: panes.find((pane) => pane.location === \"bottom\"),\n }),\n [panes],\n );\n\n useLayoutEffect(() => {\n const addedLocations = new Set(\n panes\n .map((pane) => pane.location)\n .filter((location) => !seenLocations.current.has(location)),\n );\n const addedPanes = panes.filter(\n (pane) => !seenPaneIds.current.has(pane.id),\n );\n panes.forEach((pane) => {\n seenLocations.current.add(pane.location);\n seenPaneIds.current.add(pane.id);\n });\n if (\n value !== undefined ||\n (addedLocations.size === 0 && addedPanes.length === 0)\n )\n return;\n const defaults = createWorkspaceLayoutState(panes, defaultValue);\n const addedStackHeights = addedPanes.reduce<Record<string, number>>(\n (heights, pane) => {\n if (pane.height !== undefined) heights[pane.id] = pane.height;\n return heights;\n },\n {},\n );\n setInternal((current) => ({\n ...current,\n ...(addedLocations.has(\"left\") ? { leftWidth: defaults.leftWidth } : {}),\n ...(addedLocations.has(\"right\")\n ? { rightWidth: defaults.rightWidth }\n : {}),\n ...(addedLocations.has(\"bottom\")\n ? { bottomHeight: defaults.bottomHeight }\n : {}),\n stackHeights: { ...current.stackHeights, ...addedStackHeights },\n collapsed: {\n ...current.collapsed,\n ...Object.fromEntries(\n addedPanes.map((pane) => [pane.id, pane.defaultCollapsed ?? false]),\n ),\n },\n }));\n }, [defaultValue, panes, value]);\n\n const update = useCallback<WorkspaceUpdate>(\n (change) => {\n const next = change(state);\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n },\n [onValueChange, state, value],\n );\n\n useEffect(() => {\n if (storageKey && value === undefined)\n writeWorkspaceLayoutState(storageKey, internal);\n }, [internal, storageKey, value]);\n\n return (\n <div\n className={cn(\n \"relative grid min-h-0 w-full grid-cols-1 overflow-auto bg-background md:h-full md:grid-cols-[auto_minmax(0,1fr)_auto] md:grid-rows-[minmax(0,1fr)_auto] md:overflow-hidden\",\n className,\n )}\n >\n <WorkspaceTopRight\n hasLeft={groups.left.length > 0}\n hasRight={groups.right.length > 0}\n {...(slots ? { slots } : {})}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"left\"\n panes={groups.left}\n state={state}\n update={update}\n />\n <WorkspaceSingleRegion\n pane={groups.center}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"right\"\n panes={groups.right}\n state={state}\n update={update}\n />\n {groups.bottom && (\n <WorkspaceSingleRegion\n pane={groups.bottom}\n state={state}\n update={update}\n />\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Workspace.js","sources":["../../src/layout/Workspace.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { UiSidebar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport {\n createWorkspaceLayoutState,\n readWorkspaceLayoutState,\n validateWorkspacePanes,\n writeWorkspaceLayoutState,\n type WorkspaceLayoutDefaults,\n type WorkspaceLayoutState,\n type WorkspacePaneSpec,\n type WorkspaceSideLocation,\n} from \"./Workspace.model\";\nimport {\n WorkspaceSideRegion,\n WorkspaceSingleRegion,\n type WorkspaceUpdate,\n} from \"./Workspace.regions\";\n\nexport type {\n WorkspaceLayoutDefaults,\n WorkspaceLayoutState,\n WorkspacePaneLocation,\n WorkspacePaneSlots,\n WorkspacePaneSpec,\n WorkspaceSideLocation,\n} from \"./Workspace.model\";\n\nexport type WorkspaceSlots = {\n topRightActions?: ReactNode;\n};\n\nexport type WorkspaceProps = {\n panes: WorkspacePaneSpec[];\n value?: WorkspaceLayoutState;\n defaultValue?: WorkspaceLayoutDefaults;\n onValueChange?: (value: WorkspaceLayoutState) => void;\n storageKey?: string;\n slots?: WorkspaceSlots;\n /**\n * Sides the host holds collapsed for now, such as while the center shows something that needs the\n * full width: they render collapsed and lose their toggle, and the layout state keeps how they were.\n */\n collapsedSides?: WorkspaceSideLocation[];\n className?: string;\n};\n\ntype WorkspaceTopRightProps = {\n hasLeft: boolean;\n hasRight: boolean;\n slots?: WorkspaceSlots;\n state: WorkspaceLayoutState;\n update: WorkspaceUpdate;\n};\n\nfunction WorkspaceTopRight({\n hasLeft,\n hasRight,\n slots,\n state,\n update,\n}: WorkspaceTopRightProps) {\n if (!hasLeft && !hasRight && !slots?.topRightActions) return null;\n const toggleSide = (location: \"left\" | \"right\") =>\n update((current) => ({\n ...current,\n sideCollapsed: {\n ...current.sideCollapsed,\n [location]: !current.sideCollapsed[location],\n },\n }));\n return (\n <div\n data-testid=\"workspace-top-right\"\n className=\"absolute right-1 top-1 z-30 flex h-7 items-center gap-1 rounded bg-muted/90 px-1 shadow-sm backdrop-blur\"\n >\n {slots?.topRightActions}\n {hasLeft && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.left}\n aria-label={`${state.sideCollapsed.left ? \"Expand\" : \"Collapse\"} left side`}\n onClick={() => toggleSide(\"left\")}\n >\n <UiSidebar className=\"size-4\" />\n </button>\n )}\n {hasRight && (\n <button\n type=\"button\"\n className=\"inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n aria-expanded={!state.sideCollapsed.right}\n aria-label={`${state.sideCollapsed.right ? \"Expand\" : \"Collapse\"} right side`}\n onClick={() => toggleSide(\"right\")}\n >\n <UiSidebar className=\"size-4 -scale-x-100\" />\n </button>\n )}\n </div>\n );\n}\n\nexport function Workspace({\n panes,\n value,\n defaultValue = {},\n onValueChange,\n storageKey,\n slots,\n collapsedSides,\n className,\n}: WorkspaceProps) {\n validateWorkspacePanes(panes);\n if (value !== undefined && storageKey !== undefined) {\n throw new Error(\"Workspace cannot combine value with storageKey\");\n }\n const [internal, setInternal] = useState(() =>\n storageKey\n ? readWorkspaceLayoutState(storageKey, panes, defaultValue)\n : createWorkspaceLayoutState(panes, defaultValue),\n );\n const seenLocations = useRef(new Set(panes.map((pane) => pane.location)));\n const seenPaneIds = useRef(new Set(panes.map((pane) => pane.id)));\n const state = value ?? internal;\n const groups = useMemo(\n () => ({\n left: panes.filter((pane) => pane.location === \"left\"),\n center: panes.find(\n (pane) => pane.location === \"center\",\n ) as WorkspacePaneSpec,\n right: panes.filter((pane) => pane.location === \"right\"),\n bottom: panes.find((pane) => pane.location === \"bottom\"),\n }),\n [panes],\n );\n\n useLayoutEffect(() => {\n const addedLocations = new Set(\n panes\n .map((pane) => pane.location)\n .filter((location) => !seenLocations.current.has(location)),\n );\n const addedPanes = panes.filter(\n (pane) => !seenPaneIds.current.has(pane.id),\n );\n panes.forEach((pane) => {\n seenLocations.current.add(pane.location);\n seenPaneIds.current.add(pane.id);\n });\n if (\n value !== undefined ||\n (addedLocations.size === 0 && addedPanes.length === 0)\n )\n return;\n const defaults = createWorkspaceLayoutState(panes, defaultValue);\n const addedStackHeights = addedPanes.reduce<Record<string, number>>(\n (heights, pane) => {\n if (pane.height !== undefined) heights[pane.id] = pane.height;\n return heights;\n },\n {},\n );\n setInternal((current) => ({\n ...current,\n ...(addedLocations.has(\"left\") ? { leftWidth: defaults.leftWidth } : {}),\n ...(addedLocations.has(\"right\")\n ? { rightWidth: defaults.rightWidth }\n : {}),\n ...(addedLocations.has(\"bottom\")\n ? { bottomHeight: defaults.bottomHeight }\n : {}),\n stackHeights: { ...current.stackHeights, ...addedStackHeights },\n collapsed: {\n ...current.collapsed,\n ...Object.fromEntries(\n addedPanes.map((pane) => [pane.id, pane.defaultCollapsed ?? false]),\n ),\n },\n }));\n }, [defaultValue, panes, value]);\n\n const update = useCallback<WorkspaceUpdate>(\n (change) => {\n const next = change(state);\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n },\n [onValueChange, state, value],\n );\n\n useEffect(() => {\n if (storageKey && value === undefined)\n writeWorkspaceLayoutState(storageKey, internal);\n }, [internal, storageKey, value]);\n\n const held = (location: WorkspaceSideLocation) =>\n collapsedSides?.includes(location) ?? false;\n const shown: WorkspaceLayoutState = collapsedSides?.length\n ? {\n ...state,\n sideCollapsed: {\n left: held(\"left\") || state.sideCollapsed.left,\n right: held(\"right\") || state.sideCollapsed.right,\n },\n }\n : state;\n\n return (\n <div\n className={cn(\n \"relative grid min-h-0 w-full grid-cols-1 overflow-auto bg-background md:h-full md:grid-cols-[auto_minmax(0,1fr)_auto] md:grid-rows-[minmax(0,1fr)_auto] md:overflow-hidden\",\n className,\n )}\n >\n <WorkspaceTopRight\n hasLeft={groups.left.length > 0 && !held(\"left\")}\n hasRight={groups.right.length > 0 && !held(\"right\")}\n {...(slots ? { slots } : {})}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"left\"\n panes={groups.left}\n state={shown}\n update={update}\n />\n <WorkspaceSingleRegion\n pane={groups.center}\n state={state}\n update={update}\n />\n <WorkspaceSideRegion\n location=\"right\"\n panes={groups.right}\n state={shown}\n update={update}\n />\n {groups.bottom && (\n <WorkspaceSingleRegion\n pane={groups.bottom}\n state={state}\n update={update}\n />\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -41,18 +41,77 @@ const STRATEGY_PRESETS = [
41
41
  }
42
42
  ];
43
43
  const MATCH_FIELD_OPTIONS = [
44
- { value: "name", label: "Tool name" },
45
- { value: "group", label: "Group" },
46
- { value: "parent", label: "Parent" },
47
- { value: "entity", label: "Entity" },
48
- { value: "action", label: "Action" },
49
- { value: "verb", label: "Verb" },
50
- { value: "method", label: "HTTP method" },
51
- { value: "scope", label: "Scope" },
52
- { value: "readOnly", label: "Read only" },
53
- { value: "destructive", label: "Destructive" },
54
- { value: "idempotent", label: "Idempotent" }
44
+ {
45
+ value: "name",
46
+ label: "Tool name",
47
+ description: "The operation's unique id, e.g. todo_create."
48
+ },
49
+ {
50
+ value: "group",
51
+ label: "Group",
52
+ description: "The permission category a tool is filed under."
53
+ },
54
+ {
55
+ value: "parent",
56
+ label: "Parent",
57
+ description: "The surface a tool belongs to, e.g. Contacts."
58
+ },
59
+ {
60
+ value: "entity",
61
+ label: "Entity",
62
+ description: "The resource type the operation acts on."
63
+ },
64
+ {
65
+ value: "action",
66
+ label: "Action",
67
+ description: "The operation's action name within its entity."
68
+ },
69
+ {
70
+ value: "verb",
71
+ label: "Verb",
72
+ description: "What the operation does: get, list, create, delete…"
73
+ },
74
+ {
75
+ value: "method",
76
+ label: "HTTP method",
77
+ description: "GET, POST, PATCH or DELETE for HTTP-backed tools."
78
+ },
79
+ {
80
+ value: "scope",
81
+ label: "Scope",
82
+ description: "Whether it acts on one item or a whole collection."
83
+ },
84
+ {
85
+ value: "readOnly",
86
+ label: "Read only",
87
+ description: "Tools that declare they never change anything."
88
+ },
89
+ {
90
+ value: "destructive",
91
+ label: "Destructive",
92
+ description: "Tools that declare they may delete or overwrite data."
93
+ },
94
+ {
95
+ value: "idempotent",
96
+ label: "Idempotent",
97
+ description: "Tools that declare repeating a call is safe."
98
+ }
55
99
  ];
100
+ function strategySummary(rule) {
101
+ const preset = strategyPreset(rule);
102
+ if (preset !== "custom") {
103
+ return STRATEGY_PRESETS.find((option) => option.value === preset).label;
104
+ }
105
+ return activeMatchFields(rule).map((field) => {
106
+ var _a;
107
+ const label = ((_a = MATCH_FIELD_OPTIONS.find((option) => option.value === field)) == null ? void 0 : _a.label) ?? field;
108
+ if (isHintField(field)) {
109
+ return `${label} is ${rule[field] ? "Yes" : "No"}`;
110
+ }
111
+ const values = patternValues(rule[field]);
112
+ return `${label} ${values.length > 1 ? "in" : "is"} ${values.join(", ")}`;
113
+ }).join(" · ");
114
+ }
56
115
  function strategyPreset(rule) {
57
116
  const fields = activeMatchFields(rule);
58
117
  if (fields.length !== 1) return "custom";
@@ -149,6 +208,7 @@ exports.patternsText = patternsText;
149
208
  exports.removeCondition = removeCondition;
150
209
  exports.replaceMatchField = replaceMatchField;
151
210
  exports.strategyPreset = strategyPreset;
211
+ exports.strategySummary = strategySummary;
152
212
  exports.toolFieldSuggestions = toolFieldSuggestions;
153
213
  exports.updateCondition = updateCondition;
154
214
  exports.updatePatternCondition = updatePatternCondition;
@@ -1 +1 @@
1
- {"version":3,"file":"permission-strategies.cjs","sources":["../../src/lib/permission-strategies.ts"],"sourcesContent":["import {\n matchesTool,\n type MatchPatterns,\n type PermissionRule,\n} from \"../data/chat/tool-policy\";\nimport type { ToolMeta } from \"../data/chat/types\";\n\nexport const PATTERN_FIELDS = [\n \"name\",\n \"group\",\n \"parent\",\n \"entity\",\n \"action\",\n \"verb\",\n \"method\",\n \"scope\",\n] as const;\nexport const HINT_FIELDS = [\"readOnly\", \"destructive\", \"idempotent\"] as const;\nexport const MATCH_FIELDS = [...PATTERN_FIELDS, ...HINT_FIELDS] as const;\n\nexport type MatchField = (typeof MATCH_FIELDS)[number];\nexport type StrategyPreset =\n | \"all\"\n | \"read-only\"\n | \"destructive\"\n | \"idempotent\"\n | \"custom\";\n\nexport const STRATEGY_PRESETS: Array<{\n value: StrategyPreset;\n label: string;\n description: string;\n}> = [\n {\n value: \"all\",\n label: \"All tools\",\n description: \"Match every tool in the catalog.\",\n },\n {\n value: \"read-only\",\n label: \"Read-only tools\",\n description: \"Match tools explicitly marked read-only.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive tools\",\n description: \"Match tools explicitly marked destructive.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent tools\",\n description: \"Match tools safe to repeat.\",\n },\n {\n value: \"custom\",\n label: \"Custom conditions\",\n description: \"Combine tool metadata and safety annotations.\",\n },\n];\n\nexport const MATCH_FIELD_OPTIONS: Array<{ value: MatchField; label: string }> =\n [\n { value: \"name\", label: \"Tool name\" },\n { value: \"group\", label: \"Group\" },\n { value: \"parent\", label: \"Parent\" },\n { value: \"entity\", label: \"Entity\" },\n { value: \"action\", label: \"Action\" },\n { value: \"verb\", label: \"Verb\" },\n { value: \"method\", label: \"HTTP method\" },\n { value: \"scope\", label: \"Scope\" },\n { value: \"readOnly\", label: \"Read only\" },\n { value: \"destructive\", label: \"Destructive\" },\n { value: \"idempotent\", label: \"Idempotent\" },\n ];\n\nexport function strategyPreset(rule: PermissionRule): StrategyPreset {\n const fields = activeMatchFields(rule);\n if (fields.length !== 1) return \"custom\";\n if (fields[0] === \"name\" && patternsText(rule.name) === \"*\") return \"all\";\n if (fields[0] === \"readOnly\" && rule.readOnly === true) return \"read-only\";\n if (fields[0] === \"destructive\" && rule.destructive === true) {\n return \"destructive\";\n }\n if (fields[0] === \"idempotent\" && rule.idempotent === true) {\n return \"idempotent\";\n }\n return \"custom\";\n}\n\nexport function applyStrategyPreset(\n rule: PermissionRule,\n preset: Exclude<StrategyPreset, \"custom\">,\n): PermissionRule {\n if (preset === \"all\") return { name: \"*\", policy: rule.policy };\n if (preset === \"read-only\") return { readOnly: true, policy: rule.policy };\n if (preset === \"destructive\")\n return { destructive: true, policy: rule.policy };\n return { idempotent: true, policy: rule.policy };\n}\n\nexport function activeMatchFields(rule: PermissionRule): MatchField[] {\n return MATCH_FIELDS.filter((field) => rule[field] !== undefined);\n}\n\nexport function patternsText(value: MatchPatterns | undefined): string {\n return typeof value === \"string\" ? value : (value ?? []).join(\", \");\n}\n\nexport function patternValues(value: MatchPatterns | undefined): string[] {\n return typeof value === \"string\" ? (value ? [value] : []) : (value ?? []);\n}\n\nexport function updatePatternCondition({\n rule,\n field,\n value,\n}: {\n rule: PermissionRule;\n field: (typeof PATTERN_FIELDS)[number];\n value: MatchPatterns;\n}): PermissionRule {\n return { ...rule, [field]: value };\n}\n\nexport function conditionText(rule: PermissionRule, field: MatchField): string {\n if (isHintField(field)) return String(rule[field]);\n return patternsText(rule[field]);\n}\n\nexport function replaceMatchField(\n rule: PermissionRule,\n current: MatchField,\n next: MatchField,\n): PermissionRule {\n if (current === next) return rule;\n const match = { ...rule } as Record<string, unknown>;\n const previous = match[current];\n delete match[current];\n match[next] = isHintField(next)\n ? typeof previous === \"boolean\"\n ? previous\n : true\n : typeof previous === \"string\" || Array.isArray(previous)\n ? previous\n : \"*\";\n return match as PermissionRule;\n}\n\nexport function updateCondition(\n rule: PermissionRule,\n field: MatchField,\n value: string,\n): PermissionRule {\n if (isHintField(field)) return { ...rule, [field]: value === \"true\" };\n const patterns = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return {\n ...rule,\n [field]: patterns.length <= 1 ? (patterns[0] ?? \"\") : patterns,\n };\n}\n\nexport function removeCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n const next = { ...rule } as Record<string, unknown>;\n delete next[field];\n if (activeMatchFields(next as PermissionRule).length === 0) next.name = \"*\";\n return next as PermissionRule;\n}\n\nexport function addCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n if (rule[field] !== undefined) return rule;\n return { ...rule, [field]: isHintField(field) ? true : \"*\" };\n}\n\nexport function isHintField(\n field: MatchField,\n): field is (typeof HINT_FIELDS)[number] {\n return (HINT_FIELDS as readonly MatchField[]).includes(field);\n}\n\nexport function matchingTools(rule: PermissionRule, tools: ToolMeta[]) {\n return tools.filter((tool) => matchesTool(rule, tool));\n}\n\nexport function toolFieldSuggestions(\n tools: ToolMeta[],\n field: Exclude<MatchField, (typeof HINT_FIELDS)[number]>,\n) {\n const values = new Set<string>();\n for (const tool of tools) {\n const value = tool[field === \"name\" ? \"name\" : field];\n if (typeof value === \"string\" && value.trim()) values.add(value);\n }\n return Array.from(values).sort((left, right) => left.localeCompare(right));\n}\n"],"names":["matchesTool"],"mappings":";;;AAOO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,MAAM,cAAc,CAAC,YAAY,eAAe,YAAY;AAC5D,MAAM,eAAe,CAAC,GAAG,gBAAgB,GAAG,WAAW;AAUvD,MAAM,mBAIR;AAAA,EACH;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EAAA;AAAA,EAEf;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EAAA;AAAA,EAEf;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EAAA;AAAA,EAEf;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EAAA;AAAA,EAEf;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,EAAA;AAEjB;AAEO,MAAM,sBACX;AAAA,EACE,EAAE,OAAO,QAAQ,OAAO,YAAA;AAAA,EACxB,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,EACzB,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,EAC1B,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,EAC1B,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,EAC1B,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,UAAU,OAAO,cAAA;AAAA,EAC1B,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,EACzB,EAAE,OAAO,YAAY,OAAO,YAAA;AAAA,EAC5B,EAAE,OAAO,eAAe,OAAO,cAAA;AAAA,EAC/B,EAAE,OAAO,cAAc,OAAO,aAAA;AAChC;AAEK,SAAS,eAAe,MAAsC;AACnE,QAAM,SAAS,kBAAkB,IAAI;AACrC,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,MAAI,OAAO,CAAC,MAAM,UAAU,aAAa,KAAK,IAAI,MAAM,IAAK,QAAO;AACpE,MAAI,OAAO,CAAC,MAAM,cAAc,KAAK,aAAa,KAAM,QAAO;AAC/D,MAAI,OAAO,CAAC,MAAM,iBAAiB,KAAK,gBAAgB,MAAM;AAC5D,WAAO;AAAA,EACT;AACA,MAAI,OAAO,CAAC,MAAM,gBAAgB,KAAK,eAAe,MAAM;AAC1D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,oBACd,MACA,QACgB;AAChB,MAAI,WAAW,MAAO,QAAO,EAAE,MAAM,KAAK,QAAQ,KAAK,OAAA;AACvD,MAAI,WAAW,YAAa,QAAO,EAAE,UAAU,MAAM,QAAQ,KAAK,OAAA;AAClE,MAAI,WAAW;AACb,WAAO,EAAE,aAAa,MAAM,QAAQ,KAAK,OAAA;AAC3C,SAAO,EAAE,YAAY,MAAM,QAAQ,KAAK,OAAA;AAC1C;AAEO,SAAS,kBAAkB,MAAoC;AACpE,SAAO,aAAa,OAAO,CAAC,UAAU,KAAK,KAAK,MAAM,MAAS;AACjE;AAEO,SAAS,aAAa,OAA0C;AACrE,SAAO,OAAO,UAAU,WAAW,SAAS,SAAS,CAAA,GAAI,KAAK,IAAI;AACpE;AAEO,SAAS,cAAc,OAA4C;AACxE,SAAO,OAAO,UAAU,WAAY,QAAQ,CAAC,KAAK,IAAI,CAAA,IAAO,SAAS,CAAA;AACxE;AAEO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAImB;AACjB,SAAO,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,MAAA;AAC7B;AAEO,SAAS,cAAc,MAAsB,OAA2B;AAC7E,MAAI,YAAY,KAAK,UAAU,OAAO,KAAK,KAAK,CAAC;AACjD,SAAO,aAAa,KAAK,KAAK,CAAC;AACjC;AAEO,SAAS,kBACd,MACA,SACA,MACgB;AAChB,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAM,QAAQ,EAAE,GAAG,KAAA;AACnB,QAAM,WAAW,MAAM,OAAO;AAC9B,SAAO,MAAM,OAAO;AACpB,QAAM,IAAI,IAAI,YAAY,IAAI,IAC1B,OAAO,aAAa,YAClB,WACA,OACF,OAAO,aAAa,YAAY,MAAM,QAAQ,QAAQ,IACpD,WACA;AACN,SAAO;AACT;AAEO,SAAS,gBACd,MACA,OACA,OACgB;AAChB,MAAI,YAAY,KAAK,EAAG,QAAO,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,UAAU,OAAA;AAC7D,QAAM,WAAW,MACd,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAA,CAAM,EACzB,OAAO,OAAO;AACjB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,KAAK,GAAG,SAAS,UAAU,IAAK,SAAS,CAAC,KAAK,KAAM;AAAA,EAAA;AAE1D;AAEO,SAAS,gBACd,MACA,OACgB;AAChB,QAAM,OAAO,EAAE,GAAG,KAAA;AAClB,SAAO,KAAK,KAAK;AACjB,MAAI,kBAAkB,IAAsB,EAAE,WAAW,QAAQ,OAAO;AACxE,SAAO;AACT;AAEO,SAAS,aACd,MACA,OACgB;AAChB,MAAI,KAAK,KAAK,MAAM,OAAW,QAAO;AACtC,SAAO,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,YAAY,KAAK,IAAI,OAAO,IAAA;AACzD;AAEO,SAAS,YACd,OACuC;AACvC,SAAQ,YAAsC,SAAS,KAAK;AAC9D;AAEO,SAAS,cAAc,MAAsB,OAAmB;AACrE,SAAO,MAAM,OAAO,CAAC,SAASA,WAAAA,YAAY,MAAM,IAAI,CAAC;AACvD;AAEO,SAAS,qBACd,OACA,OACA;AACA,QAAM,6BAAa,IAAA;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,UAAU,SAAS,SAAS,KAAK;AACpD,QAAI,OAAO,UAAU,YAAY,MAAM,OAAQ,QAAO,IAAI,KAAK;AAAA,EACjE;AACA,SAAO,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC;AAC3E;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"permission-strategies.cjs","sources":["../../src/lib/permission-strategies.ts"],"sourcesContent":["import {\n matchesTool,\n type MatchPatterns,\n type PermissionRule,\n} from \"../data/chat/tool-policy\";\nimport type { ToolMeta } from \"../data/chat/types\";\n\nexport const PATTERN_FIELDS = [\n \"name\",\n \"group\",\n \"parent\",\n \"entity\",\n \"action\",\n \"verb\",\n \"method\",\n \"scope\",\n] as const;\nexport const HINT_FIELDS = [\"readOnly\", \"destructive\", \"idempotent\"] as const;\nexport const MATCH_FIELDS = [...PATTERN_FIELDS, ...HINT_FIELDS] as const;\n\nexport type MatchField = (typeof MATCH_FIELDS)[number];\nexport type StrategyPreset =\n | \"all\"\n | \"read-only\"\n | \"destructive\"\n | \"idempotent\"\n | \"custom\";\n\nexport const STRATEGY_PRESETS: Array<{\n value: StrategyPreset;\n label: string;\n description: string;\n}> = [\n {\n value: \"all\",\n label: \"All tools\",\n description: \"Match every tool in the catalog.\",\n },\n {\n value: \"read-only\",\n label: \"Read-only tools\",\n description: \"Match tools explicitly marked read-only.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive tools\",\n description: \"Match tools explicitly marked destructive.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent tools\",\n description: \"Match tools safe to repeat.\",\n },\n {\n value: \"custom\",\n label: \"Custom conditions\",\n description: \"Combine tool metadata and safety annotations.\",\n },\n];\n\nexport const MATCH_FIELD_OPTIONS: Array<{\n value: MatchField;\n label: string;\n description: string;\n}> = [\n {\n value: \"name\",\n label: \"Tool name\",\n description: \"The operation's unique id, e.g. todo_create.\",\n },\n {\n value: \"group\",\n label: \"Group\",\n description: \"The permission category a tool is filed under.\",\n },\n {\n value: \"parent\",\n label: \"Parent\",\n description: \"The surface a tool belongs to, e.g. Contacts.\",\n },\n {\n value: \"entity\",\n label: \"Entity\",\n description: \"The resource type the operation acts on.\",\n },\n {\n value: \"action\",\n label: \"Action\",\n description: \"The operation's action name within its entity.\",\n },\n {\n value: \"verb\",\n label: \"Verb\",\n description: \"What the operation does: get, list, create, delete…\",\n },\n {\n value: \"method\",\n label: \"HTTP method\",\n description: \"GET, POST, PATCH or DELETE for HTTP-backed tools.\",\n },\n {\n value: \"scope\",\n label: \"Scope\",\n description: \"Whether it acts on one item or a whole collection.\",\n },\n {\n value: \"readOnly\",\n label: \"Read only\",\n description: \"Tools that declare they never change anything.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive\",\n description: \"Tools that declare they may delete or overwrite data.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent\",\n description: \"Tools that declare repeating a call is safe.\",\n },\n];\n\n/** A strategy's actual match, e.g. \"Tool name in a, b · Destructive is No\". */\nexport function strategySummary(rule: PermissionRule): string {\n const preset = strategyPreset(rule);\n if (preset !== \"custom\") {\n return STRATEGY_PRESETS.find((option) => option.value === preset)!.label;\n }\n return activeMatchFields(rule)\n .map((field) => {\n const label =\n MATCH_FIELD_OPTIONS.find((option) => option.value === field)?.label ??\n field;\n if (isHintField(field)) {\n return `${label} is ${rule[field] ? \"Yes\" : \"No\"}`;\n }\n const values = patternValues(rule[field]);\n return `${label} ${values.length > 1 ? \"in\" : \"is\"} ${values.join(\", \")}`;\n })\n .join(\" · \");\n}\n\nexport function strategyPreset(rule: PermissionRule): StrategyPreset {\n const fields = activeMatchFields(rule);\n if (fields.length !== 1) return \"custom\";\n if (fields[0] === \"name\" && patternsText(rule.name) === \"*\") return \"all\";\n if (fields[0] === \"readOnly\" && rule.readOnly === true) return \"read-only\";\n if (fields[0] === \"destructive\" && rule.destructive === true) {\n return \"destructive\";\n }\n if (fields[0] === \"idempotent\" && rule.idempotent === true) {\n return \"idempotent\";\n }\n return \"custom\";\n}\n\nexport function applyStrategyPreset(\n rule: PermissionRule,\n preset: Exclude<StrategyPreset, \"custom\">,\n): PermissionRule {\n if (preset === \"all\") return { name: \"*\", policy: rule.policy };\n if (preset === \"read-only\") return { readOnly: true, policy: rule.policy };\n if (preset === \"destructive\")\n return { destructive: true, policy: rule.policy };\n return { idempotent: true, policy: rule.policy };\n}\n\nexport function activeMatchFields(rule: PermissionRule): MatchField[] {\n return MATCH_FIELDS.filter((field) => rule[field] !== undefined);\n}\n\nexport function patternsText(value: MatchPatterns | undefined): string {\n return typeof value === \"string\" ? value : (value ?? []).join(\", \");\n}\n\nexport function patternValues(value: MatchPatterns | undefined): string[] {\n return typeof value === \"string\" ? (value ? [value] : []) : (value ?? []);\n}\n\nexport function updatePatternCondition({\n rule,\n field,\n value,\n}: {\n rule: PermissionRule;\n field: (typeof PATTERN_FIELDS)[number];\n value: MatchPatterns;\n}): PermissionRule {\n return { ...rule, [field]: value };\n}\n\nexport function conditionText(rule: PermissionRule, field: MatchField): string {\n if (isHintField(field)) return String(rule[field]);\n return patternsText(rule[field]);\n}\n\nexport function replaceMatchField(\n rule: PermissionRule,\n current: MatchField,\n next: MatchField,\n): PermissionRule {\n if (current === next) return rule;\n const match = { ...rule } as Record<string, unknown>;\n const previous = match[current];\n delete match[current];\n match[next] = isHintField(next)\n ? typeof previous === \"boolean\"\n ? previous\n : true\n : typeof previous === \"string\" || Array.isArray(previous)\n ? previous\n : \"*\";\n return match as PermissionRule;\n}\n\nexport function updateCondition(\n rule: PermissionRule,\n field: MatchField,\n value: string,\n): PermissionRule {\n if (isHintField(field)) return { ...rule, [field]: value === \"true\" };\n const patterns = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return {\n ...rule,\n [field]: patterns.length <= 1 ? (patterns[0] ?? \"\") : patterns,\n };\n}\n\nexport function removeCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n const next = { ...rule } as Record<string, unknown>;\n delete next[field];\n if (activeMatchFields(next as PermissionRule).length === 0) next.name = \"*\";\n return next as PermissionRule;\n}\n\nexport function addCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n if (rule[field] !== undefined) return rule;\n return { ...rule, [field]: isHintField(field) ? true : \"*\" };\n}\n\nexport function isHintField(\n field: MatchField,\n): field is (typeof HINT_FIELDS)[number] {\n return (HINT_FIELDS as readonly MatchField[]).includes(field);\n}\n\nexport function matchingTools(rule: PermissionRule, tools: ToolMeta[]) {\n return tools.filter((tool) => matchesTool(rule, tool));\n}\n\nexport function toolFieldSuggestions(\n tools: ToolMeta[],\n field: Exclude<MatchField, (typeof HINT_FIELDS)[number]>,\n) {\n const values = new Set<string>();\n for (const tool of tools) {\n const value = tool[field === \"name\" ? \"name\" : field];\n if (typeof value === \"string\" && value.trim()) values.add(value);\n }\n return Array.from(values).sort((left, right) => left.localeCompare(right));\n}\n"],"names":["matchesTool"],"mappings":"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"}
@@ -13,7 +13,10 @@ export declare const STRATEGY_PRESETS: Array<{
13
13
  export declare const MATCH_FIELD_OPTIONS: Array<{
14
14
  value: MatchField;
15
15
  label: string;
16
+ description: string;
16
17
  }>;
18
+ /** A strategy's actual match, e.g. "Tool name in a, b · Destructive is No". */
19
+ export declare function strategySummary(rule: PermissionRule): string;
17
20
  export declare function strategyPreset(rule: PermissionRule): StrategyPreset;
18
21
  export declare function applyStrategyPreset(rule: PermissionRule, preset: Exclude<StrategyPreset, "custom">): PermissionRule;
19
22
  export declare function activeMatchFields(rule: PermissionRule): MatchField[];
@@ -1 +1 @@
1
- {"version":3,"file":"permission-strategies.d.ts","sourceRoot":"","sources":["../../src/lib/permission-strategies.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,cAAc,qFASjB,CAAC;AACX,eAAO,MAAM,WAAW,oDAAqD,CAAC;AAC9E,eAAO,MAAM,YAAY,8HAA+C,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,WAAW,GACX,aAAa,GACb,YAAY,GACZ,QAAQ,CAAC;AAEb,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC;IACnC,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CA0BA,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAazE,CAAC;AAEJ,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAYnE;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,GACxC,cAAc,CAMhB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,EAAE,CAEpE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,CAErE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,EAAE,CAExE;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,KAAK,EACL,KAAK,GACN,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,EAAE,aAAa,CAAC;CACtB,GAAG,cAAc,CAEjB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAG7E;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,UAAU,GACf,cAAc,CAahB;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,GACZ,cAAc,CAUhB;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,GAChB,cAAc,CAKhB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,GAChB,cAAc,CAGhB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,GAChB,KAAK,IAAI,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAEvC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,cAEpE;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,YAQzD"}
1
+ {"version":3,"file":"permission-strategies.d.ts","sourceRoot":"","sources":["../../src/lib/permission-strategies.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,cAAc,qFASjB,CAAC;AACX,eAAO,MAAM,WAAW,oDAAqD,CAAC;AAC9E,eAAO,MAAM,YAAY,8HAA+C,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,WAAW,GACX,aAAa,GACb,YAAY,GACZ,QAAQ,CAAC;AAEb,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC;IACnC,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CA0BA,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC;IACtC,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAwDA,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAiB5D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAYnE;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,GACxC,cAAc,CAMhB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,EAAE,CAEpE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,CAErE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,EAAE,CAExE;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,KAAK,EACL,KAAK,GACN,EAAE;IACD,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,EAAE,aAAa,CAAC;CACtB,GAAG,cAAc,CAEjB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAG7E;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,UAAU,GACf,cAAc,CAahB;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,GACZ,cAAc,CAUhB;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,GAChB,cAAc,CAKhB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,UAAU,GAChB,cAAc,CAGhB;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,GAChB,KAAK,IAAI,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAEvC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,cAEpE;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,YAQzD"}
@@ -39,18 +39,77 @@ const STRATEGY_PRESETS = [
39
39
  }
40
40
  ];
41
41
  const MATCH_FIELD_OPTIONS = [
42
- { value: "name", label: "Tool name" },
43
- { value: "group", label: "Group" },
44
- { value: "parent", label: "Parent" },
45
- { value: "entity", label: "Entity" },
46
- { value: "action", label: "Action" },
47
- { value: "verb", label: "Verb" },
48
- { value: "method", label: "HTTP method" },
49
- { value: "scope", label: "Scope" },
50
- { value: "readOnly", label: "Read only" },
51
- { value: "destructive", label: "Destructive" },
52
- { value: "idempotent", label: "Idempotent" }
42
+ {
43
+ value: "name",
44
+ label: "Tool name",
45
+ description: "The operation's unique id, e.g. todo_create."
46
+ },
47
+ {
48
+ value: "group",
49
+ label: "Group",
50
+ description: "The permission category a tool is filed under."
51
+ },
52
+ {
53
+ value: "parent",
54
+ label: "Parent",
55
+ description: "The surface a tool belongs to, e.g. Contacts."
56
+ },
57
+ {
58
+ value: "entity",
59
+ label: "Entity",
60
+ description: "The resource type the operation acts on."
61
+ },
62
+ {
63
+ value: "action",
64
+ label: "Action",
65
+ description: "The operation's action name within its entity."
66
+ },
67
+ {
68
+ value: "verb",
69
+ label: "Verb",
70
+ description: "What the operation does: get, list, create, delete…"
71
+ },
72
+ {
73
+ value: "method",
74
+ label: "HTTP method",
75
+ description: "GET, POST, PATCH or DELETE for HTTP-backed tools."
76
+ },
77
+ {
78
+ value: "scope",
79
+ label: "Scope",
80
+ description: "Whether it acts on one item or a whole collection."
81
+ },
82
+ {
83
+ value: "readOnly",
84
+ label: "Read only",
85
+ description: "Tools that declare they never change anything."
86
+ },
87
+ {
88
+ value: "destructive",
89
+ label: "Destructive",
90
+ description: "Tools that declare they may delete or overwrite data."
91
+ },
92
+ {
93
+ value: "idempotent",
94
+ label: "Idempotent",
95
+ description: "Tools that declare repeating a call is safe."
96
+ }
53
97
  ];
98
+ function strategySummary(rule) {
99
+ const preset = strategyPreset(rule);
100
+ if (preset !== "custom") {
101
+ return STRATEGY_PRESETS.find((option) => option.value === preset).label;
102
+ }
103
+ return activeMatchFields(rule).map((field) => {
104
+ var _a;
105
+ const label = ((_a = MATCH_FIELD_OPTIONS.find((option) => option.value === field)) == null ? void 0 : _a.label) ?? field;
106
+ if (isHintField(field)) {
107
+ return `${label} is ${rule[field] ? "Yes" : "No"}`;
108
+ }
109
+ const values = patternValues(rule[field]);
110
+ return `${label} ${values.length > 1 ? "in" : "is"} ${values.join(", ")}`;
111
+ }).join(" · ");
112
+ }
54
113
  function strategyPreset(rule) {
55
114
  const fields = activeMatchFields(rule);
56
115
  if (fields.length !== 1) return "custom";
@@ -148,6 +207,7 @@ export {
148
207
  removeCondition,
149
208
  replaceMatchField,
150
209
  strategyPreset,
210
+ strategySummary,
151
211
  toolFieldSuggestions,
152
212
  updateCondition,
153
213
  updatePatternCondition
@@ -1 +1 @@
1
- {"version":3,"file":"permission-strategies.js","sources":["../../src/lib/permission-strategies.ts"],"sourcesContent":["import {\n matchesTool,\n type MatchPatterns,\n type PermissionRule,\n} from \"../data/chat/tool-policy\";\nimport type { ToolMeta } from \"../data/chat/types\";\n\nexport const PATTERN_FIELDS = [\n \"name\",\n \"group\",\n \"parent\",\n \"entity\",\n \"action\",\n \"verb\",\n \"method\",\n \"scope\",\n] as const;\nexport const HINT_FIELDS = [\"readOnly\", \"destructive\", \"idempotent\"] as const;\nexport const MATCH_FIELDS = [...PATTERN_FIELDS, ...HINT_FIELDS] as const;\n\nexport type MatchField = (typeof MATCH_FIELDS)[number];\nexport type StrategyPreset =\n | \"all\"\n | \"read-only\"\n | \"destructive\"\n | \"idempotent\"\n | \"custom\";\n\nexport const STRATEGY_PRESETS: Array<{\n value: StrategyPreset;\n label: string;\n description: string;\n}> = [\n {\n value: \"all\",\n label: \"All tools\",\n description: \"Match every tool in the catalog.\",\n },\n {\n value: \"read-only\",\n label: \"Read-only tools\",\n description: \"Match tools explicitly marked read-only.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive tools\",\n description: \"Match tools explicitly marked destructive.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent tools\",\n description: \"Match tools safe to repeat.\",\n },\n {\n value: \"custom\",\n label: \"Custom conditions\",\n description: \"Combine tool metadata and safety annotations.\",\n },\n];\n\nexport const MATCH_FIELD_OPTIONS: Array<{ value: MatchField; label: string }> =\n [\n { value: \"name\", label: \"Tool name\" },\n { value: \"group\", label: \"Group\" },\n { value: \"parent\", label: \"Parent\" },\n { value: \"entity\", label: \"Entity\" },\n { value: \"action\", label: \"Action\" },\n { value: \"verb\", label: \"Verb\" },\n { value: \"method\", label: \"HTTP method\" },\n { value: \"scope\", label: \"Scope\" },\n { value: \"readOnly\", label: \"Read only\" },\n { value: \"destructive\", label: \"Destructive\" },\n { value: \"idempotent\", label: \"Idempotent\" },\n ];\n\nexport function strategyPreset(rule: PermissionRule): StrategyPreset {\n const fields = activeMatchFields(rule);\n if (fields.length !== 1) return \"custom\";\n if (fields[0] === \"name\" && patternsText(rule.name) === \"*\") return \"all\";\n if (fields[0] === \"readOnly\" && rule.readOnly === true) return \"read-only\";\n if (fields[0] === \"destructive\" && rule.destructive === true) {\n return \"destructive\";\n }\n if (fields[0] === \"idempotent\" && rule.idempotent === true) {\n return \"idempotent\";\n }\n return \"custom\";\n}\n\nexport function applyStrategyPreset(\n rule: PermissionRule,\n preset: Exclude<StrategyPreset, \"custom\">,\n): PermissionRule {\n if (preset === \"all\") return { name: \"*\", policy: rule.policy };\n if (preset === \"read-only\") return { readOnly: true, policy: rule.policy };\n if (preset === \"destructive\")\n return { destructive: true, policy: rule.policy };\n return { idempotent: true, policy: rule.policy };\n}\n\nexport function activeMatchFields(rule: PermissionRule): MatchField[] {\n return MATCH_FIELDS.filter((field) => rule[field] !== undefined);\n}\n\nexport function patternsText(value: MatchPatterns | undefined): string {\n return typeof value === \"string\" ? value : (value ?? []).join(\", \");\n}\n\nexport function patternValues(value: MatchPatterns | undefined): string[] {\n return typeof value === \"string\" ? (value ? [value] : []) : (value ?? []);\n}\n\nexport function updatePatternCondition({\n rule,\n field,\n value,\n}: {\n rule: PermissionRule;\n field: (typeof PATTERN_FIELDS)[number];\n value: MatchPatterns;\n}): PermissionRule {\n return { ...rule, [field]: value };\n}\n\nexport function conditionText(rule: PermissionRule, field: MatchField): string {\n if (isHintField(field)) return String(rule[field]);\n return patternsText(rule[field]);\n}\n\nexport function replaceMatchField(\n rule: PermissionRule,\n current: MatchField,\n next: MatchField,\n): PermissionRule {\n if (current === next) return rule;\n const match = { ...rule } as Record<string, unknown>;\n const previous = match[current];\n delete match[current];\n match[next] = isHintField(next)\n ? typeof previous === \"boolean\"\n ? previous\n : true\n : typeof previous === \"string\" || Array.isArray(previous)\n ? previous\n : \"*\";\n return match as PermissionRule;\n}\n\nexport function updateCondition(\n rule: PermissionRule,\n field: MatchField,\n value: string,\n): PermissionRule {\n if (isHintField(field)) return { ...rule, [field]: value === \"true\" };\n const patterns = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return {\n ...rule,\n [field]: patterns.length <= 1 ? (patterns[0] ?? \"\") : patterns,\n };\n}\n\nexport function removeCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n const next = { ...rule } as Record<string, unknown>;\n delete next[field];\n if (activeMatchFields(next as PermissionRule).length === 0) next.name = \"*\";\n return next as PermissionRule;\n}\n\nexport function addCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n if (rule[field] !== undefined) return rule;\n return { ...rule, [field]: isHintField(field) ? true : \"*\" };\n}\n\nexport function isHintField(\n field: MatchField,\n): field is (typeof HINT_FIELDS)[number] {\n return (HINT_FIELDS as readonly MatchField[]).includes(field);\n}\n\nexport function matchingTools(rule: PermissionRule, tools: ToolMeta[]) {\n return tools.filter((tool) => matchesTool(rule, tool));\n}\n\nexport function toolFieldSuggestions(\n tools: ToolMeta[],\n field: Exclude<MatchField, (typeof HINT_FIELDS)[number]>,\n) {\n const values = new Set<string>();\n for (const tool of tools) {\n const value = tool[field === \"name\" ? \"name\" : field];\n if (typeof value === \"string\" && value.trim()) values.add(value);\n }\n return Array.from(values).sort((left, right) => left.localeCompare(right));\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permission-strategies.js","sources":["../../src/lib/permission-strategies.ts"],"sourcesContent":["import {\n matchesTool,\n type MatchPatterns,\n type PermissionRule,\n} from \"../data/chat/tool-policy\";\nimport type { ToolMeta } from \"../data/chat/types\";\n\nexport const PATTERN_FIELDS = [\n \"name\",\n \"group\",\n \"parent\",\n \"entity\",\n \"action\",\n \"verb\",\n \"method\",\n \"scope\",\n] as const;\nexport const HINT_FIELDS = [\"readOnly\", \"destructive\", \"idempotent\"] as const;\nexport const MATCH_FIELDS = [...PATTERN_FIELDS, ...HINT_FIELDS] as const;\n\nexport type MatchField = (typeof MATCH_FIELDS)[number];\nexport type StrategyPreset =\n | \"all\"\n | \"read-only\"\n | \"destructive\"\n | \"idempotent\"\n | \"custom\";\n\nexport const STRATEGY_PRESETS: Array<{\n value: StrategyPreset;\n label: string;\n description: string;\n}> = [\n {\n value: \"all\",\n label: \"All tools\",\n description: \"Match every tool in the catalog.\",\n },\n {\n value: \"read-only\",\n label: \"Read-only tools\",\n description: \"Match tools explicitly marked read-only.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive tools\",\n description: \"Match tools explicitly marked destructive.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent tools\",\n description: \"Match tools safe to repeat.\",\n },\n {\n value: \"custom\",\n label: \"Custom conditions\",\n description: \"Combine tool metadata and safety annotations.\",\n },\n];\n\nexport const MATCH_FIELD_OPTIONS: Array<{\n value: MatchField;\n label: string;\n description: string;\n}> = [\n {\n value: \"name\",\n label: \"Tool name\",\n description: \"The operation's unique id, e.g. todo_create.\",\n },\n {\n value: \"group\",\n label: \"Group\",\n description: \"The permission category a tool is filed under.\",\n },\n {\n value: \"parent\",\n label: \"Parent\",\n description: \"The surface a tool belongs to, e.g. Contacts.\",\n },\n {\n value: \"entity\",\n label: \"Entity\",\n description: \"The resource type the operation acts on.\",\n },\n {\n value: \"action\",\n label: \"Action\",\n description: \"The operation's action name within its entity.\",\n },\n {\n value: \"verb\",\n label: \"Verb\",\n description: \"What the operation does: get, list, create, delete…\",\n },\n {\n value: \"method\",\n label: \"HTTP method\",\n description: \"GET, POST, PATCH or DELETE for HTTP-backed tools.\",\n },\n {\n value: \"scope\",\n label: \"Scope\",\n description: \"Whether it acts on one item or a whole collection.\",\n },\n {\n value: \"readOnly\",\n label: \"Read only\",\n description: \"Tools that declare they never change anything.\",\n },\n {\n value: \"destructive\",\n label: \"Destructive\",\n description: \"Tools that declare they may delete or overwrite data.\",\n },\n {\n value: \"idempotent\",\n label: \"Idempotent\",\n description: \"Tools that declare repeating a call is safe.\",\n },\n];\n\n/** A strategy's actual match, e.g. \"Tool name in a, b · Destructive is No\". */\nexport function strategySummary(rule: PermissionRule): string {\n const preset = strategyPreset(rule);\n if (preset !== \"custom\") {\n return STRATEGY_PRESETS.find((option) => option.value === preset)!.label;\n }\n return activeMatchFields(rule)\n .map((field) => {\n const label =\n MATCH_FIELD_OPTIONS.find((option) => option.value === field)?.label ??\n field;\n if (isHintField(field)) {\n return `${label} is ${rule[field] ? \"Yes\" : \"No\"}`;\n }\n const values = patternValues(rule[field]);\n return `${label} ${values.length > 1 ? \"in\" : \"is\"} ${values.join(\", \")}`;\n })\n .join(\" · \");\n}\n\nexport function strategyPreset(rule: PermissionRule): StrategyPreset {\n const fields = activeMatchFields(rule);\n if (fields.length !== 1) return \"custom\";\n if (fields[0] === \"name\" && patternsText(rule.name) === \"*\") return \"all\";\n if (fields[0] === \"readOnly\" && rule.readOnly === true) return \"read-only\";\n if (fields[0] === \"destructive\" && rule.destructive === true) {\n return \"destructive\";\n }\n if (fields[0] === \"idempotent\" && rule.idempotent === true) {\n return \"idempotent\";\n }\n return \"custom\";\n}\n\nexport function applyStrategyPreset(\n rule: PermissionRule,\n preset: Exclude<StrategyPreset, \"custom\">,\n): PermissionRule {\n if (preset === \"all\") return { name: \"*\", policy: rule.policy };\n if (preset === \"read-only\") return { readOnly: true, policy: rule.policy };\n if (preset === \"destructive\")\n return { destructive: true, policy: rule.policy };\n return { idempotent: true, policy: rule.policy };\n}\n\nexport function activeMatchFields(rule: PermissionRule): MatchField[] {\n return MATCH_FIELDS.filter((field) => rule[field] !== undefined);\n}\n\nexport function patternsText(value: MatchPatterns | undefined): string {\n return typeof value === \"string\" ? value : (value ?? []).join(\", \");\n}\n\nexport function patternValues(value: MatchPatterns | undefined): string[] {\n return typeof value === \"string\" ? (value ? [value] : []) : (value ?? []);\n}\n\nexport function updatePatternCondition({\n rule,\n field,\n value,\n}: {\n rule: PermissionRule;\n field: (typeof PATTERN_FIELDS)[number];\n value: MatchPatterns;\n}): PermissionRule {\n return { ...rule, [field]: value };\n}\n\nexport function conditionText(rule: PermissionRule, field: MatchField): string {\n if (isHintField(field)) return String(rule[field]);\n return patternsText(rule[field]);\n}\n\nexport function replaceMatchField(\n rule: PermissionRule,\n current: MatchField,\n next: MatchField,\n): PermissionRule {\n if (current === next) return rule;\n const match = { ...rule } as Record<string, unknown>;\n const previous = match[current];\n delete match[current];\n match[next] = isHintField(next)\n ? typeof previous === \"boolean\"\n ? previous\n : true\n : typeof previous === \"string\" || Array.isArray(previous)\n ? previous\n : \"*\";\n return match as PermissionRule;\n}\n\nexport function updateCondition(\n rule: PermissionRule,\n field: MatchField,\n value: string,\n): PermissionRule {\n if (isHintField(field)) return { ...rule, [field]: value === \"true\" };\n const patterns = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return {\n ...rule,\n [field]: patterns.length <= 1 ? (patterns[0] ?? \"\") : patterns,\n };\n}\n\nexport function removeCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n const next = { ...rule } as Record<string, unknown>;\n delete next[field];\n if (activeMatchFields(next as PermissionRule).length === 0) next.name = \"*\";\n return next as PermissionRule;\n}\n\nexport function addCondition(\n rule: PermissionRule,\n field: MatchField,\n): PermissionRule {\n if (rule[field] !== undefined) return rule;\n return { ...rule, [field]: isHintField(field) ? true : \"*\" };\n}\n\nexport function isHintField(\n field: MatchField,\n): field is (typeof HINT_FIELDS)[number] {\n return (HINT_FIELDS as readonly MatchField[]).includes(field);\n}\n\nexport function matchingTools(rule: PermissionRule, tools: ToolMeta[]) {\n return tools.filter((tool) => matchesTool(rule, tool));\n}\n\nexport function toolFieldSuggestions(\n tools: ToolMeta[],\n field: Exclude<MatchField, (typeof HINT_FIELDS)[number]>,\n) {\n const values = new Set<string>();\n for (const tool of tools) {\n const value = tool[field === \"name\" ? \"name\" : field];\n if (typeof value === \"string\" && value.trim()) values.add(value);\n }\n return Array.from(values).sort((left, right) => left.localeCompare(right));\n}\n"],"names":[],"mappings":"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"}