@wzrhine/agent 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +21 -0
  3. package/README.md +29 -3
  4. package/dist/agent.css +15 -0
  5. package/dist/components/artifact/ArtifactCard.d.ts +56 -0
  6. package/dist/components/artifact/ArtifactCard.d.ts.map +1 -0
  7. package/dist/components/artifact/ArtifactCard.js +78 -0
  8. package/dist/components/artifact/ArtifactCard.js.map +1 -0
  9. package/dist/components/artifact/FilePreview.d.ts +117 -0
  10. package/dist/components/artifact/FilePreview.d.ts.map +1 -0
  11. package/dist/components/artifact/FilePreview.js +207 -0
  12. package/dist/components/artifact/FilePreview.js.map +1 -0
  13. package/dist/components/artifact/FilePreviewTabs.d.ts +51 -0
  14. package/dist/components/artifact/FilePreviewTabs.d.ts.map +1 -0
  15. package/dist/components/artifact/FilePreviewTabs.js +150 -0
  16. package/dist/components/artifact/FilePreviewTabs.js.map +1 -0
  17. package/dist/components/composer/AttachmentList.d.ts +33 -0
  18. package/dist/components/composer/AttachmentList.d.ts.map +1 -0
  19. package/dist/components/composer/AttachmentList.js +56 -0
  20. package/dist/components/composer/AttachmentList.js.map +1 -0
  21. package/dist/components/composer/Composer.d.ts +113 -0
  22. package/dist/components/composer/Composer.d.ts.map +1 -0
  23. package/dist/components/composer/Composer.js +327 -0
  24. package/dist/components/composer/Composer.js.map +1 -0
  25. package/dist/components/composer/ComposerInput.d.ts +101 -0
  26. package/dist/components/composer/ComposerInput.d.ts.map +1 -0
  27. package/dist/components/composer/ComposerInput.js +301 -0
  28. package/dist/components/composer/ComposerInput.js.map +1 -0
  29. package/dist/components/composer/ComposerNotice.d.ts +38 -0
  30. package/dist/components/composer/ComposerNotice.d.ts.map +1 -0
  31. package/dist/components/composer/ComposerNotice.js +16 -0
  32. package/dist/components/composer/ComposerNotice.js.map +1 -0
  33. package/dist/components/composer/MentionMenu.d.ts +37 -0
  34. package/dist/components/composer/MentionMenu.d.ts.map +1 -0
  35. package/dist/components/composer/MentionMenu.js +55 -0
  36. package/dist/components/composer/MentionMenu.js.map +1 -0
  37. package/dist/components/composer/MenuPanel.d.ts +49 -0
  38. package/dist/components/composer/MenuPanel.d.ts.map +1 -0
  39. package/dist/components/composer/MenuPanel.js +50 -0
  40. package/dist/components/composer/MenuPanel.js.map +1 -0
  41. package/dist/components/composer/ModelPicker.d.ts +40 -0
  42. package/dist/components/composer/ModelPicker.d.ts.map +1 -0
  43. package/dist/components/composer/ModelPicker.js +115 -0
  44. package/dist/components/composer/ModelPicker.js.map +1 -0
  45. package/dist/components/composer/PermissionPicker.d.ts +31 -0
  46. package/dist/components/composer/PermissionPicker.d.ts.map +1 -0
  47. package/dist/components/composer/PermissionPicker.js +43 -0
  48. package/dist/components/composer/PermissionPicker.js.map +1 -0
  49. package/dist/components/composer/SendStopButton.d.ts +71 -0
  50. package/dist/components/composer/SendStopButton.d.ts.map +1 -0
  51. package/dist/components/composer/SendStopButton.js +87 -0
  52. package/dist/components/composer/SendStopButton.js.map +1 -0
  53. package/dist/components/composer/SlashCommandMenu.d.ts +33 -0
  54. package/dist/components/composer/SlashCommandMenu.d.ts.map +1 -0
  55. package/dist/components/composer/SlashCommandMenu.js +43 -0
  56. package/dist/components/composer/SlashCommandMenu.js.map +1 -0
  57. package/dist/components/composer/composer-text.d.ts +10 -0
  58. package/dist/components/composer/composer-text.d.ts.map +1 -0
  59. package/dist/components/composer/composer-text.js +26 -0
  60. package/dist/components/composer/composer-text.js.map +1 -0
  61. package/dist/components/composer/composer-utils.d.ts +74 -0
  62. package/dist/components/composer/composer-utils.d.ts.map +1 -0
  63. package/dist/components/composer/composer-utils.js +133 -0
  64. package/dist/components/composer/composer-utils.js.map +1 -0
  65. package/dist/components/conversation/ConversationList.d.ts +88 -0
  66. package/dist/components/conversation/ConversationList.d.ts.map +1 -0
  67. package/dist/components/conversation/ConversationList.js +81 -0
  68. package/dist/components/conversation/ConversationList.js.map +1 -0
  69. package/dist/components/conversation/ConversationRow.d.ts +66 -0
  70. package/dist/components/conversation/ConversationRow.d.ts.map +1 -0
  71. package/dist/components/conversation/ConversationRow.js +65 -0
  72. package/dist/components/conversation/ConversationRow.js.map +1 -0
  73. package/dist/components/conversation/conversation-status.d.ts +21 -0
  74. package/dist/components/conversation/conversation-status.d.ts.map +1 -0
  75. package/dist/components/conversation/conversation-status.js +33 -0
  76. package/dist/components/conversation/conversation-status.js.map +1 -0
  77. package/dist/components/intervention/ApprovalDiff.d.ts +14 -0
  78. package/dist/components/intervention/ApprovalDiff.d.ts.map +1 -0
  79. package/dist/components/intervention/ApprovalDiff.js +25 -0
  80. package/dist/components/intervention/ApprovalDiff.js.map +1 -0
  81. package/dist/components/intervention/ApprovalPanel.d.ts +57 -0
  82. package/dist/components/intervention/ApprovalPanel.d.ts.map +1 -0
  83. package/dist/components/intervention/ApprovalPanel.js +111 -0
  84. package/dist/components/intervention/ApprovalPanel.js.map +1 -0
  85. package/dist/components/intervention/ErrorRecoveryNotice.d.ts +28 -0
  86. package/dist/components/intervention/ErrorRecoveryNotice.d.ts.map +1 -0
  87. package/dist/components/intervention/ErrorRecoveryNotice.js +30 -0
  88. package/dist/components/intervention/ErrorRecoveryNotice.js.map +1 -0
  89. package/dist/components/intervention/GrantList.d.ts +49 -0
  90. package/dist/components/intervention/GrantList.d.ts.map +1 -0
  91. package/dist/components/intervention/GrantList.js +58 -0
  92. package/dist/components/intervention/GrantList.js.map +1 -0
  93. package/dist/components/intervention/InterventionDock.d.ts +24 -0
  94. package/dist/components/intervention/InterventionDock.d.ts.map +1 -0
  95. package/dist/components/intervention/InterventionDock.js +18 -0
  96. package/dist/components/intervention/InterventionDock.js.map +1 -0
  97. package/dist/components/intervention/QuestionnaireCard.d.ts +60 -0
  98. package/dist/components/intervention/QuestionnaireCard.d.ts.map +1 -0
  99. package/dist/components/intervention/QuestionnaireCard.js +322 -0
  100. package/dist/components/intervention/QuestionnaireCard.js.map +1 -0
  101. package/dist/components/intervention/action-lock.d.ts +20 -0
  102. package/dist/components/intervention/action-lock.d.ts.map +1 -0
  103. package/dist/components/intervention/action-lock.js +65 -0
  104. package/dist/components/intervention/action-lock.js.map +1 -0
  105. package/dist/components/intervention/icons.d.ts +8 -0
  106. package/dist/components/intervention/icons.d.ts.map +1 -0
  107. package/dist/components/intervention/icons.js +11 -0
  108. package/dist/components/intervention/icons.js.map +1 -0
  109. package/dist/components/intervention/questionnaire-answers.d.ts +29 -0
  110. package/dist/components/intervention/questionnaire-answers.d.ts.map +1 -0
  111. package/dist/components/intervention/questionnaire-answers.js +81 -0
  112. package/dist/components/intervention/questionnaire-answers.js.map +1 -0
  113. package/dist/components/message/AgentMessage.d.ts +98 -0
  114. package/dist/components/message/AgentMessage.d.ts.map +1 -0
  115. package/dist/components/message/AgentMessage.js +94 -0
  116. package/dist/components/message/AgentMessage.js.map +1 -0
  117. package/dist/components/message/CitationChip.d.ts +34 -0
  118. package/dist/components/message/CitationChip.d.ts.map +1 -0
  119. package/dist/components/message/CitationChip.js +30 -0
  120. package/dist/components/message/CitationChip.js.map +1 -0
  121. package/dist/components/message/CodeBlock.d.ts +45 -0
  122. package/dist/components/message/CodeBlock.d.ts.map +1 -0
  123. package/dist/components/message/CodeBlock.js +21 -0
  124. package/dist/components/message/CodeBlock.js.map +1 -0
  125. package/dist/components/message/JumpToLatest.d.ts +27 -0
  126. package/dist/components/message/JumpToLatest.d.ts.map +1 -0
  127. package/dist/components/message/JumpToLatest.js +17 -0
  128. package/dist/components/message/JumpToLatest.js.map +1 -0
  129. package/dist/components/message/Markdown.d.ts +21 -0
  130. package/dist/components/message/Markdown.d.ts.map +1 -0
  131. package/dist/components/message/Markdown.js +21 -0
  132. package/dist/components/message/Markdown.js.map +1 -0
  133. package/dist/components/message/MessageActions.d.ts +63 -0
  134. package/dist/components/message/MessageActions.d.ts.map +1 -0
  135. package/dist/components/message/MessageActions.js +83 -0
  136. package/dist/components/message/MessageActions.js.map +1 -0
  137. package/dist/components/message/MessageList.d.ts +100 -0
  138. package/dist/components/message/MessageList.d.ts.map +1 -0
  139. package/dist/components/message/MessageList.js +266 -0
  140. package/dist/components/message/MessageList.js.map +1 -0
  141. package/dist/components/message/MessagePart.d.ts +44 -0
  142. package/dist/components/message/MessagePart.d.ts.map +1 -0
  143. package/dist/components/message/MessagePart.js +146 -0
  144. package/dist/components/message/MessagePart.js.map +1 -0
  145. package/dist/components/message/RunDetails.d.ts +26 -0
  146. package/dist/components/message/RunDetails.d.ts.map +1 -0
  147. package/dist/components/message/RunDetails.js +113 -0
  148. package/dist/components/message/RunDetails.js.map +1 -0
  149. package/dist/components/message/SkillUseList.d.ts +22 -0
  150. package/dist/components/message/SkillUseList.d.ts.map +1 -0
  151. package/dist/components/message/SkillUseList.js +20 -0
  152. package/dist/components/message/SkillUseList.js.map +1 -0
  153. package/dist/components/message/ThinkingBlock.d.ts +44 -0
  154. package/dist/components/message/ThinkingBlock.d.ts.map +1 -0
  155. package/dist/components/message/ThinkingBlock.js +34 -0
  156. package/dist/components/message/ThinkingBlock.js.map +1 -0
  157. package/dist/components/message/icons.d.ts +14 -0
  158. package/dist/components/message/icons.d.ts.map +1 -0
  159. package/dist/components/message/icons.js +16 -0
  160. package/dist/components/message/icons.js.map +1 -0
  161. package/dist/components/message/plain-text.d.ts +11 -0
  162. package/dist/components/message/plain-text.d.ts.map +1 -0
  163. package/dist/components/message/plain-text.js +58 -0
  164. package/dist/components/message/plain-text.js.map +1 -0
  165. package/dist/components/message/renderers.d.ts +30 -0
  166. package/dist/components/message/renderers.d.ts.map +1 -0
  167. package/dist/components/message/renderers.js +2 -0
  168. package/dist/components/message/renderers.js.map +1 -0
  169. package/dist/components/message/use-copy.d.ts +18 -0
  170. package/dist/components/message/use-copy.d.ts.map +1 -0
  171. package/dist/components/message/use-copy.js +65 -0
  172. package/dist/components/message/use-copy.js.map +1 -0
  173. package/dist/components/process/AgentProcess.d.ts +47 -0
  174. package/dist/components/process/AgentProcess.d.ts.map +1 -0
  175. package/dist/components/process/AgentProcess.js +78 -0
  176. package/dist/components/process/AgentProcess.js.map +1 -0
  177. package/dist/components/process/RunStatus.d.ts +60 -0
  178. package/dist/components/process/RunStatus.d.ts.map +1 -0
  179. package/dist/components/process/RunStatus.js +34 -0
  180. package/dist/components/process/RunStatus.js.map +1 -0
  181. package/dist/components/shell/AgentEmptyState.d.ts +35 -0
  182. package/dist/components/shell/AgentEmptyState.d.ts.map +1 -0
  183. package/dist/components/shell/AgentEmptyState.js +20 -0
  184. package/dist/components/shell/AgentEmptyState.js.map +1 -0
  185. package/dist/components/shell/AgentHeader.d.ts +84 -0
  186. package/dist/components/shell/AgentHeader.d.ts.map +1 -0
  187. package/dist/components/shell/AgentHeader.js +38 -0
  188. package/dist/components/shell/AgentHeader.js.map +1 -0
  189. package/dist/components/shell/AgentShell.d.ts +138 -0
  190. package/dist/components/shell/AgentShell.d.ts.map +1 -0
  191. package/dist/components/shell/AgentShell.js +206 -0
  192. package/dist/components/shell/AgentShell.js.map +1 -0
  193. package/dist/components/shell/AgentSidePane.d.ts +54 -0
  194. package/dist/components/shell/AgentSidePane.d.ts.map +1 -0
  195. package/dist/components/shell/AgentSidePane.js +26 -0
  196. package/dist/components/shell/AgentSidePane.js.map +1 -0
  197. package/dist/components/shell/ResizeHandle.d.ts +50 -0
  198. package/dist/components/shell/ResizeHandle.d.ts.map +1 -0
  199. package/dist/components/shell/ResizeHandle.js +84 -0
  200. package/dist/components/shell/ResizeHandle.js.map +1 -0
  201. package/dist/components/shell/use-controllable.d.ts +9 -0
  202. package/dist/components/shell/use-controllable.d.ts.map +1 -0
  203. package/dist/components/shell/use-controllable.js +26 -0
  204. package/dist/components/shell/use-controllable.js.map +1 -0
  205. package/dist/components/tools/ChunkPager.d.ts +48 -0
  206. package/dist/components/tools/ChunkPager.d.ts.map +1 -0
  207. package/dist/components/tools/ChunkPager.js +68 -0
  208. package/dist/components/tools/ChunkPager.js.map +1 -0
  209. package/dist/components/tools/CodeModeToolTree.d.ts +64 -0
  210. package/dist/components/tools/CodeModeToolTree.d.ts.map +1 -0
  211. package/dist/components/tools/CodeModeToolTree.js +97 -0
  212. package/dist/components/tools/CodeModeToolTree.js.map +1 -0
  213. package/dist/components/tools/DiffPreview.d.ts +83 -0
  214. package/dist/components/tools/DiffPreview.d.ts.map +1 -0
  215. package/dist/components/tools/DiffPreview.js +95 -0
  216. package/dist/components/tools/DiffPreview.js.map +1 -0
  217. package/dist/components/tools/ToolActivity.d.ts +63 -0
  218. package/dist/components/tools/ToolActivity.d.ts.map +1 -0
  219. package/dist/components/tools/ToolActivity.js +45 -0
  220. package/dist/components/tools/ToolActivity.js.map +1 -0
  221. package/dist/components/tools/ToolDetails.d.ts +106 -0
  222. package/dist/components/tools/ToolDetails.d.ts.map +1 -0
  223. package/dist/components/tools/ToolDetails.js +247 -0
  224. package/dist/components/tools/ToolDetails.js.map +1 -0
  225. package/dist/components/tools/ToolHistory.d.ts +48 -0
  226. package/dist/components/tools/ToolHistory.d.ts.map +1 -0
  227. package/dist/components/tools/ToolHistory.js +37 -0
  228. package/dist/components/tools/ToolHistory.js.map +1 -0
  229. package/dist/components/tools/ToolOutput.d.ts +61 -0
  230. package/dist/components/tools/ToolOutput.d.ts.map +1 -0
  231. package/dist/components/tools/ToolOutput.js +45 -0
  232. package/dist/components/tools/ToolOutput.js.map +1 -0
  233. package/dist/components/tools/ToolRecord.d.ts +54 -0
  234. package/dist/components/tools/ToolRecord.d.ts.map +1 -0
  235. package/dist/components/tools/ToolRecord.js +78 -0
  236. package/dist/components/tools/ToolRecord.js.map +1 -0
  237. package/dist/components/tools/shared.d.ts +93 -0
  238. package/dist/components/tools/shared.d.ts.map +1 -0
  239. package/dist/components/tools/shared.js +160 -0
  240. package/dist/components/tools/shared.js.map +1 -0
  241. package/dist/components/workspace/ActivityLedger.d.ts +44 -0
  242. package/dist/components/workspace/ActivityLedger.d.ts.map +1 -0
  243. package/dist/components/workspace/ActivityLedger.js +63 -0
  244. package/dist/components/workspace/ActivityLedger.js.map +1 -0
  245. package/dist/components/workspace/CompactionNotice.d.ts +63 -0
  246. package/dist/components/workspace/CompactionNotice.d.ts.map +1 -0
  247. package/dist/components/workspace/CompactionNotice.js +36 -0
  248. package/dist/components/workspace/CompactionNotice.js.map +1 -0
  249. package/dist/components/workspace/ContextUsage.d.ts +44 -0
  250. package/dist/components/workspace/ContextUsage.d.ts.map +1 -0
  251. package/dist/components/workspace/ContextUsage.js +106 -0
  252. package/dist/components/workspace/ContextUsage.js.map +1 -0
  253. package/dist/components/workspace/PersistentTerminal.d.ts +86 -0
  254. package/dist/components/workspace/PersistentTerminal.d.ts.map +1 -0
  255. package/dist/components/workspace/PersistentTerminal.js +155 -0
  256. package/dist/components/workspace/PersistentTerminal.js.map +1 -0
  257. package/dist/components/workspace/PinnedSummary.d.ts +43 -0
  258. package/dist/components/workspace/PinnedSummary.d.ts.map +1 -0
  259. package/dist/components/workspace/PinnedSummary.js +33 -0
  260. package/dist/components/workspace/PinnedSummary.js.map +1 -0
  261. package/dist/components/workspace/RunSummary.d.ts +35 -0
  262. package/dist/components/workspace/RunSummary.d.ts.map +1 -0
  263. package/dist/components/workspace/RunSummary.js +46 -0
  264. package/dist/components/workspace/RunSummary.js.map +1 -0
  265. package/dist/components/workspace/SubAgentCard.d.ts +60 -0
  266. package/dist/components/workspace/SubAgentCard.d.ts.map +1 -0
  267. package/dist/components/workspace/SubAgentCard.js +73 -0
  268. package/dist/components/workspace/SubAgentCard.js.map +1 -0
  269. package/dist/components/workspace/TerminalRow.d.ts +51 -0
  270. package/dist/components/workspace/TerminalRow.d.ts.map +1 -0
  271. package/dist/components/workspace/TerminalRow.js +62 -0
  272. package/dist/components/workspace/TerminalRow.js.map +1 -0
  273. package/dist/components/workspace/shared.d.ts +22 -0
  274. package/dist/components/workspace/shared.d.ts.map +1 -0
  275. package/dist/components/workspace/shared.js +36 -0
  276. package/dist/components/workspace/shared.js.map +1 -0
  277. package/dist/index.d.ts +130 -0
  278. package/dist/index.d.ts.map +1 -0
  279. package/dist/index.js +76 -0
  280. package/dist/index.js.map +1 -0
  281. package/dist/motion/agent-motion.d.ts +62 -0
  282. package/dist/motion/agent-motion.d.ts.map +1 -0
  283. package/dist/motion/agent-motion.js +61 -0
  284. package/dist/motion/agent-motion.js.map +1 -0
  285. package/dist/primitives/AgentSpark.d.ts +17 -0
  286. package/dist/primitives/AgentSpark.d.ts.map +1 -0
  287. package/dist/primitives/AgentSpark.js +11 -0
  288. package/dist/primitives/AgentSpark.js.map +1 -0
  289. package/dist/primitives/AgentStatus.d.ts +32 -0
  290. package/dist/primitives/AgentStatus.d.ts.map +1 -0
  291. package/dist/primitives/AgentStatus.js +13 -0
  292. package/dist/primitives/AgentStatus.js.map +1 -0
  293. package/dist/primitives/StatusGlyph.d.ts +10 -0
  294. package/dist/primitives/StatusGlyph.d.ts.map +1 -0
  295. package/dist/primitives/StatusGlyph.js +31 -0
  296. package/dist/primitives/StatusGlyph.js.map +1 -0
  297. package/dist/primitives/icons.d.ts +7 -0
  298. package/dist/primitives/icons.d.ts.map +1 -0
  299. package/dist/primitives/icons.js +55 -0
  300. package/dist/primitives/icons.js.map +1 -0
  301. package/dist/provider/AgentMessages.d.ts +51 -0
  302. package/dist/provider/AgentMessages.d.ts.map +1 -0
  303. package/dist/provider/AgentMessages.js +77 -0
  304. package/dist/provider/AgentMessages.js.map +1 -0
  305. package/dist/provider/messages/composer.d.ts +90 -0
  306. package/dist/provider/messages/composer.d.ts.map +1 -0
  307. package/dist/provider/messages/composer.js +155 -0
  308. package/dist/provider/messages/composer.js.map +1 -0
  309. package/dist/provider/messages/intervention.d.ts +135 -0
  310. package/dist/provider/messages/intervention.d.ts.map +1 -0
  311. package/dist/provider/messages/intervention.js +321 -0
  312. package/dist/provider/messages/intervention.js.map +1 -0
  313. package/dist/provider/messages/message.d.ts +118 -0
  314. package/dist/provider/messages/message.d.ts.map +1 -0
  315. package/dist/provider/messages/message.js +224 -0
  316. package/dist/provider/messages/message.js.map +1 -0
  317. package/dist/provider/messages/shell.d.ts +70 -0
  318. package/dist/provider/messages/shell.d.ts.map +1 -0
  319. package/dist/provider/messages/shell.js +109 -0
  320. package/dist/provider/messages/shell.js.map +1 -0
  321. package/dist/provider/messages/status.d.ts +20 -0
  322. package/dist/provider/messages/status.d.ts.map +1 -0
  323. package/dist/provider/messages/status.js +195 -0
  324. package/dist/provider/messages/status.js.map +1 -0
  325. package/dist/provider/messages/tools.d.ts +210 -0
  326. package/dist/provider/messages/tools.d.ts.map +1 -0
  327. package/dist/provider/messages/tools.js +482 -0
  328. package/dist/provider/messages/tools.js.map +1 -0
  329. package/dist/provider/messages/workspace.d.ts +176 -0
  330. package/dist/provider/messages/workspace.d.ts.map +1 -0
  331. package/dist/provider/messages/workspace.js +325 -0
  332. package/dist/provider/messages/workspace.js.map +1 -0
  333. package/dist/styles/artifact.css +564 -0
  334. package/dist/styles/base.css +220 -0
  335. package/dist/styles/composer.css +1001 -0
  336. package/dist/styles/conversation.css +275 -0
  337. package/dist/styles/intervention.css +929 -0
  338. package/dist/styles/message.css +917 -0
  339. package/dist/styles/process.css +207 -0
  340. package/dist/styles/shell.css +441 -0
  341. package/dist/styles/tools.css +929 -0
  342. package/dist/styles/workspace.css +1294 -0
  343. package/dist/utils/cx.d.ts +3 -0
  344. package/dist/utils/cx.d.ts.map +1 -0
  345. package/dist/utils/cx.js +5 -0
  346. package/dist/utils/cx.js.map +1 -0
  347. package/package.json +64 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog · @wzrhine/agent
2
+
3
+ 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。本包为 **Experimental**,0.x 期间 API 可能调整。
4
+
5
+ ## [Unreleased]
6
+
7
+ (暂无)
8
+
9
+ ## [0.1.0] - 2026-10-12
10
+
11
+ 首次发布。
12
+
13
+ ### Added
14
+ - **M12(ADR-0010 / 0011 / 0012)**:新包。基座:`AgentMessagesProvider`(`agentZhCN` / `agentEnUS`)、`useAgentFormat`、`AgentIcon`、`StatusGlyph`、`AgentStatus`、`AgentSpark`、`AgentEntrance`、`useAgentLoop`。
15
+ - 组件族(图册 46 个组件全覆盖):
16
+ - Shell:AgentShell(自测宽度三档布局)、ResizeHandle、AgentHeader、ConversationList / ConversationRow、AgentSidePane、AgentEmptyState。
17
+ - Message:MessageList(跟随、锚点、`holdFollow`)、JumpToLatest、AgentMessage、MessagePart(13 类,未知类型兜底)、CodeBlock、ThinkingBlock、CitationChip、MessageActions(能力禁用原因、重新编辑本轮输入)、RunDetails、SkillUseList、AgentProcess、RunStatus。
18
+ - Tools:ToolActivity、ToolRecord、CodeModeToolTree、ToolOutput、ToolHistory、ChunkPager、DiffPreview / MultiFileDiff,以及 11 类工具专项详情。
19
+ - Composer:Composer、ComposerInput(token 镜像、IME 防护)、MentionMenu、SlashCommandMenu、AttachmentList、SendStopButton、ModelPicker、PermissionPicker、ComposerNotice。
20
+ - Intervention:ApprovalPanel(材料门禁、未知回执用同一 actionId 重试)、QuestionnaireCard、ErrorRecoveryNotice、InterventionDock、GrantList。
21
+ - Workspace 与产物:PersistentTerminal / TerminalTabs、TerminalRow / TerminalList、SubAgentCard / SubAgentList、ContextUsage、PinnedSummary、ActivityLedger、RunSummary、CompactionNotice、ArtifactCard / ArtifactList、FilePreview、FilePreviewTabs。
22
+ - 动效(ADR-0012):首次出现才入场、折叠高度过渡、Send ↔ Stop 交叉淡入、AgentSpark 分阶段节奏与静态帧;循环只在可见、在视口内且非减动时运行。
23
+ - 文案:`agentZhCN` / `agentEnUS`(英文未经母语审校),按组件族拆分;数字与时间使用最近 `RhineProvider` 的 locale。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WhiteZhi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,29 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @wzrhine/agent
2
+
3
+ WzRhineLab UI 的 **Agent 界面组件**:工作台外壳、会话索引、消息流与思考过程、工具记录(含十类工具专项与 Diff)、Composer(token 镜像、@ 引用、/ 命令、模型与权限选择)、审批与问卷、终端、子任务、上下文用量、产物与文件预览,以及配套的 Agent 动效。
4
+
5
+ 组件只接收 view-model 快照(类型来自 [`@wzrhine/agent-core`](../agent-core/README.md),本包会重新导出)并发出动作回调;不包含任何运行时、请求、缓存、Markdown / 高亮库或桌面 API。
6
+
7
+ > 实验性(0.x 期间 API 可能调整);MIT 许可证。
8
+
9
+ ```sh
10
+ pnpm add @wzrhine/agent @wzrhine/agent-core @wzrhine/react @wzrhine/tokens react react-dom motion
11
+ ```
12
+
13
+ ```tsx
14
+ import '@wzrhine/tokens/styles.css';
15
+ import '@wzrhine/react/styles.css';
16
+ import '@wzrhine/agent/styles.css';
17
+ import { RhineProvider } from '@wzrhine/react';
18
+ import { AgentStatus, runStatusMeta } from '@wzrhine/agent';
19
+
20
+ <RhineProvider>
21
+ <AgentStatus {...runStatusMeta.running} label="运行中" />
22
+ </RhineProvider>;
23
+ ```
24
+
25
+ - 范围与拆包:[ADR-0010](https://github.com/BaiZhi967/WzRhineLab-UI/blob/main/docs/development/adr/0010-m12-agent-ui-plan.md);契约:[ADR-0011](https://github.com/BaiZhi967/WzRhineLab-UI/blob/main/docs/development/adr/0011-agent-contracts.md);动效:[ADR-0012](https://github.com/BaiZhi967/WzRhineLab-UI/blob/main/docs/development/adr/0012-agent-motion.md)
26
+ - 接入指南:[docs/planning/agent-ui-adoption.md](https://github.com/BaiZhi967/WzRhineLab-UI/blob/main/docs/planning/agent-ui-adoption.md)
27
+ - API 参考(自动生成):[docs/api/agent.md](https://github.com/BaiZhi967/WzRhineLab-UI/blob/main/docs/api/agent.md)
28
+ - 变更记录:[CHANGELOG.md](./CHANGELOG.md)
29
+ - 许可证:[MIT](./LICENSE)
package/dist/agent.css ADDED
@@ -0,0 +1,15 @@
1
+ /*
2
+ * @wzrhine/agent · style entry (`@wzrhine/agent/styles.css`). Load after `@wzrhine/tokens/styles.css`
3
+ * and `@wzrhine/react/styles.css`; requires a `.rl-theme` ancestor (RhineProvider).
4
+ * Only `rl-agent-` classes and `--rl-*` tokens; host elements and :root stay untouched.
5
+ */
6
+ @import './styles/base.css';
7
+ @import './styles/shell.css';
8
+ @import './styles/conversation.css';
9
+ @import './styles/message.css';
10
+ @import './styles/process.css';
11
+ @import './styles/tools.css';
12
+ @import './styles/composer.css';
13
+ @import './styles/intervention.css';
14
+ @import './styles/workspace.css';
15
+ @import './styles/artifact.css';
@@ -0,0 +1,56 @@
1
+ import * as React from 'react';
2
+ import type { ArtifactKind, ArtifactView } from '@wzrhine/agent-core';
3
+ import type { AgentIconName } from '../../primitives/icons.js';
4
+ import type { HeadingLevel, WorkspaceMessagesProp } from '../workspace/shared.js';
5
+ export declare const artifactKindIcon: Record<ArtifactKind, AgentIconName>;
6
+ export type ArtifactCardProps = Omit<React.HTMLAttributes<HTMLElement>, 'children'> & {
7
+ artifact: ArtifactView;
8
+ onOpen?: (artifact: ArtifactView) => void;
9
+ onDownload?: (artifact: ArtifactView) => void;
10
+ /** Shows the file in its folder (host file manager). */
11
+ onReveal?: (artifact: ArtifactView) => void;
12
+ /** Retries a failed artifact. */
13
+ onRetry?: (artifact: ArtifactView) => void;
14
+ /** Custom preview (chart, rendered markdown…); default: image thumbnail, text excerpt or kind icon. */
15
+ renderPreview?: (artifact: ArtifactView) => React.ReactNode;
16
+ headingLevel?: HeadingLevel;
17
+ messages?: WorkspaceMessagesProp;
18
+ };
19
+ /**
20
+ * ArtifactCard (atlas 29): one generated file / report / image. 「已保存」 appears only for
21
+ * `status: 'saved'`; `generating` shows a Spinner without a percentage; `partial` and `failed`
22
+ * keep their reason as visible text. Actions render only with their callbacks; deleted or
23
+ * unavailable artifacts cannot be opened or downloaded.
24
+ *
25
+ * Accessibility: an `<article>` named by its title heading; image previews need `alt` (falls
26
+ * back to an empty alt plus the visible title, so nothing is read twice). Motion: none here;
27
+ * `ArtifactList` gives new items one AgentEntrance.
28
+ */
29
+ export declare const ArtifactCard: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLElement>, "children"> & {
30
+ artifact: ArtifactView;
31
+ onOpen?: (artifact: ArtifactView) => void;
32
+ onDownload?: (artifact: ArtifactView) => void;
33
+ /** Shows the file in its folder (host file manager). */
34
+ onReveal?: (artifact: ArtifactView) => void;
35
+ /** Retries a failed artifact. */
36
+ onRetry?: (artifact: ArtifactView) => void;
37
+ /** Custom preview (chart, rendered markdown…); default: image thumbnail, text excerpt or kind icon. */
38
+ renderPreview?: (artifact: ArtifactView) => React.ReactNode;
39
+ headingLevel?: HeadingLevel;
40
+ messages?: WorkspaceMessagesProp;
41
+ } & React.RefAttributes<HTMLElement>>;
42
+ export type ArtifactListProps = Omit<React.HTMLAttributes<HTMLUListElement>, 'children'> & Pick<ArtifactCardProps, 'onOpen' | 'onDownload' | 'onReveal' | 'onRetry' | 'renderPreview' | 'headingLevel' | 'messages'> & {
43
+ artifacts: ArtifactView[];
44
+ /** The host listed only part of the artifacts: adds 「部分产物未列出」. */
45
+ truncated?: boolean;
46
+ /** Opens the full artifact list; drawn next to the truncated note. */
47
+ onShowAll?: () => void;
48
+ };
49
+ /**
50
+ * Artifacts as a list (`<ul>`). Duplicate ids are dropped; items present on first render are
51
+ * static, items added later enter once (AgentEntrance `row`, reduced → no movement).
52
+ * `truncated` adds a plain note after the list (「部分产物未列出」, never a count it does not know)
53
+ * with an optional 「查看全部产物」 button.
54
+ */
55
+ export declare function ArtifactList({ artifacts, onOpen, onDownload, onReveal, onRetry, renderPreview, headingLevel, truncated, onShowAll, messages: override, className, ...rest }: ArtifactListProps): React.JSX.Element;
56
+ //# sourceMappingURL=ArtifactCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactCard.d.ts","sourceRoot":"","sources":["../../../src/components/artifact/ArtifactCard.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAa,YAAY,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAKlG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAElF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,CAShE,CAAC;AAgBF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,GAAG;IACpF,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9C,wDAAwD;IACxD,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC3C,uGAAuG;IACvG,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5D,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY;cAvBb,YAAY;aACb,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI;iBAC5B,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI;IAC7C,wDAAwD;eAC7C,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI;IAC3C,iCAAiC;cACvB,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI;IAC1C,uGAAuG;oBACvF,CAAC,QAAQ,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS;mBAC5C,YAAY;eAChB,qBAAqB;qCAgGhC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,GACtF,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,eAAe,GAAG,cAAc,GAAG,UAAU,CAAC,GAAG;IAC1H,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,kEAAkE;IAClE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEJ;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,MAAM,EACN,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,EACZ,SAAS,EACT,SAAS,EACT,QAAQ,EAAE,QAAQ,EAClB,SAAS,EACT,GAAG,IAAI,EACR,EAAE,iBAAiB,qBA+CnB"}
@@ -0,0 +1,78 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { Button, IconButton, Spinner } from '@wzrhine/react';
5
+ import { useAgentFormat } from '../../provider/AgentMessages.js';
6
+ import { AgentEntrance } from '../../motion/agent-motion.js';
7
+ import { StatusGlyph } from '../../primitives/StatusGlyph.js';
8
+ import { AgentIcon } from '../../primitives/icons.js';
9
+ import { cx } from '../../utils/cx.js';
10
+ import { Heading, useIsNewId, useWorkspaceMessages } from '../workspace/shared.js';
11
+ export const artifactKindIcon = {
12
+ text: 'file',
13
+ markdown: 'file',
14
+ code: 'code',
15
+ image: 'image',
16
+ file: 'file',
17
+ diff: 'layers',
18
+ data: 'database',
19
+ unknown: 'file',
20
+ };
21
+ const statusGlyph = {
22
+ generating: { glyph: 'pending', tone: 'info' },
23
+ partial: { glyph: 'unknown', tone: 'warning' },
24
+ saved: { glyph: 'done', tone: 'success' },
25
+ failed: { glyph: 'failed', tone: 'danger' },
26
+ unavailable: { glyph: 'stopped', tone: 'neutral' },
27
+ stale: { glyph: 'unknown', tone: 'warning' },
28
+ };
29
+ /** Only same-origin / data / blob thumbnails are drawn; anything else falls back to the kind icon. */
30
+ function isSafeThumbnail(src) {
31
+ return /^(data:image\/|blob:|\/|\.\/)/.test(src);
32
+ }
33
+ /**
34
+ * ArtifactCard (atlas 29): one generated file / report / image. 「已保存」 appears only for
35
+ * `status: 'saved'`; `generating` shows a Spinner without a percentage; `partial` and `failed`
36
+ * keep their reason as visible text. Actions render only with their callbacks; deleted or
37
+ * unavailable artifacts cannot be opened or downloaded.
38
+ *
39
+ * Accessibility: an `<article>` named by its title heading; image previews need `alt` (falls
40
+ * back to an empty alt plus the visible title, so nothing is read twice). Motion: none here;
41
+ * `ArtifactList` gives new items one AgentEntrance.
42
+ */
43
+ export const ArtifactCard = React.forwardRef(function ArtifactCard({ artifact, onOpen, onDownload, onReveal, onRetry, renderPreview, headingLevel = 3, messages: override, className, ...rest }, ref) {
44
+ const m = useWorkspaceMessages(override);
45
+ const format = useAgentFormat();
46
+ const id = React.useId();
47
+ const titleId = `${id}-title`;
48
+ const reasonId = `${id}-reason`;
49
+ const glyph = statusGlyph[artifact.status];
50
+ const gone = artifact.status === 'unavailable' || artifact.change === 'deleted';
51
+ const busy = artifact.status === 'generating';
52
+ const preview = renderPreview ? (renderPreview(artifact)) : artifact.kind === 'image' && artifact.preview && isSafeThumbnail(artifact.preview) ? (_jsx("img", { className: "rl-agent-artifact__thumb", src: artifact.preview, alt: artifact.alt ?? '', loading: "lazy" })) : artifact.preview && artifact.kind !== 'image' ? (_jsx("span", { className: "rl-agent-artifact__excerpt", "aria-hidden": "true", children: artifact.preview })) : (_jsx(AgentIcon, { name: artifactKindIcon[artifact.kind], className: "rl-agent-artifact__kind-icon" }));
53
+ return (_jsxs("article", { ...rest, ref: ref, className: cx('rl-agent-artifact', className), "aria-labelledby": titleId, "aria-describedby": artifact.reason ? reasonId : undefined, "aria-busy": busy || undefined, "data-status": artifact.status, "data-kind": artifact.kind, children: [_jsx("div", { className: "rl-agent-artifact__preview", children: preview }), _jsxs("div", { className: "rl-agent-artifact__body", children: [_jsx(Heading, { level: headingLevel, id: titleId, className: "rl-agent-artifact__title", title: artifact.path ?? artifact.title, children: artifact.title }), _jsxs("p", { className: "rl-agent-artifact__meta", children: [_jsx("span", { children: m.artifactKind[artifact.kind] }), artifact.size !== undefined && _jsx("span", { children: format.bytes(artifact.size) }), artifact.version && _jsx("span", { children: m.artifactVersion(artifact.version) }), artifact.change && (_jsx("span", { className: "rl-agent-artifact__change", "data-change": artifact.change, children: m.artifactChange[artifact.change] }))] }), _jsxs("p", { className: "rl-agent-artifact__status", "data-tone": glyph.tone, children: [busy ? _jsx(Spinner, { size: "sm" }) : _jsx(StatusGlyph, { name: glyph.glyph, tone: glyph.tone }), _jsx("span", { children: m.artifactStatus[artifact.status] })] }), artifact.reason && (_jsx("p", { id: reasonId, className: "rl-agent-artifact__reason", children: artifact.reason }))] }), (onOpen || onDownload || onReveal || (onRetry && artifact.status === 'failed')) && (_jsxs("div", { className: "rl-agent-artifact__actions", children: [artifact.status === 'failed' && onRetry && (_jsx(Button, { size: "sm", variant: "secondary", iconStart: _jsx(AgentIcon, { name: "retry" }), "aria-label": m.artifactRetryNamed(artifact.title), onClick: () => onRetry(artifact), children: m.artifactRetry })), onOpen && !gone && artifact.status !== 'failed' && (_jsx(Button, { size: "sm", variant: "secondary", "aria-label": m.artifactOpenNamed(artifact.title), onClick: () => onOpen(artifact), children: m.artifactOpen })), onDownload && !gone && !busy && artifact.status !== 'failed' && (_jsx(IconButton, { size: "sm", variant: "ghost", icon: _jsx(AgentIcon, { name: "download" }), label: m.artifactDownload(artifact.title), onClick: () => onDownload(artifact) })), onReveal && !gone && artifact.path && (_jsx(IconButton, { size: "sm", variant: "ghost", icon: _jsx(AgentIcon, { name: "folder" }), label: m.artifactReveal(artifact.title), onClick: () => onReveal(artifact) }))] }))] }));
54
+ });
55
+ /**
56
+ * Artifacts as a list (`<ul>`). Duplicate ids are dropped; items present on first render are
57
+ * static, items added later enter once (AgentEntrance `row`, reduced → no movement).
58
+ * `truncated` adds a plain note after the list (「部分产物未列出」, never a count it does not know)
59
+ * with an optional 「查看全部产物」 button.
60
+ */
61
+ export function ArtifactList({ artifacts, onOpen, onDownload, onReveal, onRetry, renderPreview, headingLevel, truncated, onShowAll, messages: override, className, ...rest }) {
62
+ const m = useWorkspaceMessages(override);
63
+ const unique = React.useMemo(() => {
64
+ const seen = new Set();
65
+ return artifacts.filter((a) => (seen.has(a.id) ? false : (seen.add(a.id), true)));
66
+ }, [artifacts]);
67
+ const isNew = useIsNewId(unique.map((a) => a.id));
68
+ const note = truncated ? (_jsxs("p", { className: "rl-agent-artifact-list__truncated", children: [_jsx(AgentIcon, { name: "info" }), _jsx("span", { children: m.artifactTruncated }), onShowAll && (_jsx(Button, { size: "sm", variant: "ghost", onClick: onShowAll, children: m.artifactShowAll }))] })) : null;
69
+ if (unique.length === 0) {
70
+ // Nothing listed but more exists: 「暂无产物」 would be false, so only the note is shown.
71
+ return note ?? _jsx("p", { className: "rl-agent-artifact-list__empty", children: m.artifactEmpty });
72
+ }
73
+ const list = (_jsx("ul", { ...rest, className: cx('rl-agent-artifact-list', className), "aria-label": rest['aria-label'] ?? m.artifactList, children: unique.map((artifact) => (_jsx(AgentEntrance, { as: "li", kind: "row", animate: isNew(artifact.id), className: "rl-agent-artifact-list__item", children: _jsx(ArtifactCard, { artifact: artifact, onOpen: onOpen, onDownload: onDownload, onReveal: onReveal, onRetry: onRetry, renderPreview: renderPreview, headingLevel: headingLevel, messages: override }) }, artifact.id))) }));
74
+ if (!note)
75
+ return list;
76
+ return (_jsxs("div", { className: "rl-agent-artifact-list__wrap", children: [list, note] }));
77
+ }
78
+ //# sourceMappingURL=ArtifactCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactCard.js","sourceRoot":"","sources":["../../../src/components/artifact/ArtifactCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import * as React from 'react';
2
+ import type { BreadcrumbItem } from '@wzrhine/react';
3
+ import type { FilePreviewMode, FilePreviewView } from '@wzrhine/agent-core';
4
+ import type { HeadingLevel, WorkspaceMessagesProp } from '../workspace/shared.js';
5
+ /** A zoom percentage of the image's natural width, or `fit` (scale to the preview width). */
6
+ export type FilePreviewZoom = number | 'fit';
7
+ /** One way to open the file, offered by the host (an editor, the system viewer, a folder). */
8
+ export interface FileOpenTarget {
9
+ id: string;
10
+ label: string;
11
+ /** `app` opens the file; `reveal` shows it in a folder. Default `app`. */
12
+ group?: 'app' | 'reveal';
13
+ }
14
+ export type FilePreviewProps = Omit<React.HTMLAttributes<HTMLElement>, 'children'> & {
15
+ file: FilePreviewView;
16
+ /** Active tab (controlled). */
17
+ mode?: FilePreviewMode;
18
+ defaultMode?: FilePreviewMode;
19
+ onModeChange?: (mode: FilePreviewMode) => void;
20
+ /** Markdown renderer for the preview tab; default shows the source. */
21
+ renderMarkdown?: (source: string) => React.ReactNode;
22
+ /** Code renderer (highlighting); default is numbered plain lines. */
23
+ renderCode?: (code: string, language?: string) => React.ReactNode;
24
+ onRetry?: () => void;
25
+ onReload?: () => void;
26
+ /** Loads the next chunk of a partially loaded file. */
27
+ onLoadMore?: () => void;
28
+ onOpenExternal?: (file: FilePreviewView) => void;
29
+ /** Adds the file as a reference to the conversation. */
30
+ onReference?: (file: FilePreviewView) => void;
31
+ onClose?: () => void;
32
+ /** Ways to open the file. With `onOpenWith` they render a split button + menu. */
33
+ openTargets?: FileOpenTarget[];
34
+ /** Target used by the primary half of the split button; default the first `app` target. */
35
+ defaultOpenTarget?: string;
36
+ onOpenWith?: (targetId: string, file: FilePreviewView) => void;
37
+ /** Copies `file.path` (menu item 「复制路径」); default writes it to the clipboard. */
38
+ onCopyPath?: (path: string, file: FilePreviewView) => void | Promise<void>;
39
+ /** Image zoom percentages (of the natural width); a 「适应宽度」 option is always added. */
40
+ zoomLevels?: number[];
41
+ /** Initial image zoom; default `fit`. */
42
+ defaultZoom?: FilePreviewZoom;
43
+ /**
44
+ * Workspace root. Paths under it show as a workspace-relative breadcrumb (root name first);
45
+ * paths outside it get the 「外部」 badge.
46
+ */
47
+ breadcrumbRoot?: string;
48
+ /** Copy the loaded text. Default true for text-like files. */
49
+ copyable?: boolean;
50
+ headingLevel?: HeadingLevel;
51
+ messages?: WorkspaceMessagesProp;
52
+ };
53
+ /**
54
+ * FilePreview (atlas 30): read-only preview of a file the adapter loaded. Tabs (`@wzrhine/react`,
55
+ * arrow keys) switch preview / raw / metadata; text is real, selectable text in its own focusable
56
+ * scroll region, with decorative line numbers that are not copied. Images get their `alt` and a
57
+ * zoom group (`zoomLevels`, default 25–400% of the natural width, plus 「适应宽度」) inside a scroll
58
+ * container. Binary and unknown kinds say 「无法预览此类型」 and offer 「在外部打开」. Partial loads
59
+ * say how much is loaded and offer 「加载更多」; a changed file keeps the old content with
60
+ * 「文件已更新」 + 「重新加载」, and `onReload` is also always offered as 「重新读取」.
61
+ *
62
+ * The path is a `Breadcrumb` (`<nav>` + `<ol>`), workspace-relative under `breadcrumbRoot`.
63
+ * `openTargets` + `onOpenWith` draw a split control: the primary button opens with the default
64
+ * target, the menu button (`Menu`: arrow keys, Escape, focus return) lists every target plus
65
+ * 「复制路径」 and 「在对话中引用」.
66
+ *
67
+ * The component reads nothing itself; the clipboard is the only browser API it touches.
68
+ * Motion: none (tab indicator is the Tabs component's own CSS transition).
69
+ */
70
+ export declare const FilePreview: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLElement>, "children"> & {
71
+ file: FilePreviewView;
72
+ /** Active tab (controlled). */
73
+ mode?: FilePreviewMode;
74
+ defaultMode?: FilePreviewMode;
75
+ onModeChange?: (mode: FilePreviewMode) => void;
76
+ /** Markdown renderer for the preview tab; default shows the source. */
77
+ renderMarkdown?: (source: string) => React.ReactNode;
78
+ /** Code renderer (highlighting); default is numbered plain lines. */
79
+ renderCode?: (code: string, language?: string) => React.ReactNode;
80
+ onRetry?: () => void;
81
+ onReload?: () => void;
82
+ /** Loads the next chunk of a partially loaded file. */
83
+ onLoadMore?: () => void;
84
+ onOpenExternal?: (file: FilePreviewView) => void;
85
+ /** Adds the file as a reference to the conversation. */
86
+ onReference?: (file: FilePreviewView) => void;
87
+ onClose?: () => void;
88
+ /** Ways to open the file. With `onOpenWith` they render a split button + menu. */
89
+ openTargets?: FileOpenTarget[];
90
+ /** Target used by the primary half of the split button; default the first `app` target. */
91
+ defaultOpenTarget?: string;
92
+ onOpenWith?: (targetId: string, file: FilePreviewView) => void;
93
+ /** Copies `file.path` (menu item 「复制路径」); default writes it to the clipboard. */
94
+ onCopyPath?: (path: string, file: FilePreviewView) => void | Promise<void>;
95
+ /** Image zoom percentages (of the natural width); a 「适应宽度」 option is always added. */
96
+ zoomLevels?: number[];
97
+ /** Initial image zoom; default `fit`. */
98
+ defaultZoom?: FilePreviewZoom;
99
+ /**
100
+ * Workspace root. Paths under it show as a workspace-relative breadcrumb (root name first);
101
+ * paths outside it get the 「外部」 badge.
102
+ */
103
+ breadcrumbRoot?: string;
104
+ /** Copy the loaded text. Default true for text-like files. */
105
+ copyable?: boolean;
106
+ headingLevel?: HeadingLevel;
107
+ messages?: WorkspaceMessagesProp;
108
+ } & React.RefAttributes<HTMLElement>>;
109
+ /**
110
+ * Breadcrumb items for a path. Under `root` the path is shown relative to it (root's last segment
111
+ * first); outside it (or for absolute paths without a root match) `outside` is true.
112
+ */
113
+ export declare function pathCrumbs(path: string | undefined, root?: string): {
114
+ items: BreadcrumbItem[];
115
+ outside: boolean;
116
+ } | undefined;
117
+ //# sourceMappingURL=FilePreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../src/components/artifact/FilePreview.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { Alert, Breadcrumb, Button, IconButton, Menu, MenuGroup, MenuItem, MenuSeparator, Skeleton, Tab, TabList, TabPanel, Tabs } from '@wzrhine/react';
5
+ import { useAgentFormat } from '../../provider/AgentMessages.js';
6
+ import { AgentIcon } from '../../primitives/icons.js';
7
+ import { cx } from '../../utils/cx.js';
8
+ import { Heading, useWorkspaceMessages } from '../workspace/shared.js';
9
+ const TEXT_KINDS = ['text', 'markdown', 'code'];
10
+ const DEFAULT_ZOOMS = [25, 50, 100, 200, 400];
11
+ /**
12
+ * FilePreview (atlas 30): read-only preview of a file the adapter loaded. Tabs (`@wzrhine/react`,
13
+ * arrow keys) switch preview / raw / metadata; text is real, selectable text in its own focusable
14
+ * scroll region, with decorative line numbers that are not copied. Images get their `alt` and a
15
+ * zoom group (`zoomLevels`, default 25–400% of the natural width, plus 「适应宽度」) inside a scroll
16
+ * container. Binary and unknown kinds say 「无法预览此类型」 and offer 「在外部打开」. Partial loads
17
+ * say how much is loaded and offer 「加载更多」; a changed file keeps the old content with
18
+ * 「文件已更新」 + 「重新加载」, and `onReload` is also always offered as 「重新读取」.
19
+ *
20
+ * The path is a `Breadcrumb` (`<nav>` + `<ol>`), workspace-relative under `breadcrumbRoot`.
21
+ * `openTargets` + `onOpenWith` draw a split control: the primary button opens with the default
22
+ * target, the menu button (`Menu`: arrow keys, Escape, focus return) lists every target plus
23
+ * 「复制路径」 and 「在对话中引用」.
24
+ *
25
+ * The component reads nothing itself; the clipboard is the only browser API it touches.
26
+ * Motion: none (tab indicator is the Tabs component's own CSS transition).
27
+ */
28
+ export const FilePreview = React.forwardRef(function FilePreview({ file, mode, defaultMode = 'preview', onModeChange, renderMarkdown, renderCode, onRetry, onReload, onLoadMore, onOpenExternal, onReference, onClose, openTargets, defaultOpenTarget, onOpenWith, onCopyPath, zoomLevels, defaultZoom, breadcrumbRoot, copyable, headingLevel = 3, messages: override, className, ...rest }, ref) {
29
+ const m = useWorkspaceMessages(override);
30
+ const format = useAgentFormat();
31
+ const id = React.useId();
32
+ const titleId = `${id}-title`;
33
+ const textual = TEXT_KINDS.includes(file.kind);
34
+ const [innerMode, setInnerMode] = React.useState(defaultMode);
35
+ const modes = textual ? ['preview', 'raw', 'metadata'] : ['preview', 'metadata'];
36
+ const requested = mode ?? innerMode;
37
+ const active = modes.includes(requested) ? requested : 'preview';
38
+ const hasContent = file.content !== undefined && file.status !== 'loading' && file.status !== 'missing' && file.status !== 'unavailable' && file.status !== 'error';
39
+ const canCopy = (copyable ?? true) && textual && hasContent && Boolean(file.content);
40
+ const crumbs = React.useMemo(() => pathCrumbs(file.path, breadcrumbRoot), [file.path, breadcrumbRoot]);
41
+ const external = Boolean(file.external) || crumbs?.outside === true;
42
+ const changeMode = (next) => {
43
+ const key = next;
44
+ if (mode === undefined)
45
+ setInnerMode(key);
46
+ onModeChange?.(key);
47
+ };
48
+ return (_jsxs("section", { ...rest, ref: ref, className: cx('rl-agent-file', className), "aria-labelledby": titleId, "data-kind": file.kind, "data-status": file.status, children: [_jsxs("header", { className: "rl-agent-file__header", children: [_jsx(AgentIcon, { name: file.kind === 'image' ? 'image' : file.kind === 'code' ? 'code' : 'file', className: "rl-agent-file__icon" }), _jsxs("div", { className: "rl-agent-file__identity", children: [_jsx(Heading, { level: headingLevel, id: titleId, className: "rl-agent-file__name", title: file.name, children: file.name }), crumbs && (_jsx(Breadcrumb, { className: "rl-agent-file__crumbs", items: crumbs.items, label: m.fileBreadcrumb(file.name), expandLabel: m.fileBreadcrumbExpand, title: file.path })), (external || file.version) && (_jsxs("p", { className: "rl-agent-file__path", children: [external && _jsx("span", { className: "rl-agent-file__badge", children: m.fileExternal }), file.version && _jsx("span", { className: "rl-agent-file__version", children: m.artifactVersion(file.version) })] }))] }), onClose && _jsx(IconButton, { size: "sm", variant: "ghost", icon: _jsx(AgentIcon, { name: "close" }), label: m.fileClose, onClick: onClose })] }), _jsx(FileActions, { file: file, canCopy: canCopy, onOpenExternal: onOpenExternal, onReference: onReference, onReload: onReload, openTargets: openTargets, defaultOpenTarget: defaultOpenTarget, onOpenWith: onOpenWith, onCopyPath: onCopyPath, m: m }), _jsx(FileNotices, { file: file, onRetry: onRetry, onReload: onReload, onLoadMore: onLoadMore, m: m, format: format }), _jsxs(Tabs, { value: active, onValueChange: changeMode, size: "sm", className: "rl-agent-file__tabs", children: [_jsx(TabList, { "aria-label": m.fileModes, children: modes.map((key) => (_jsx(Tab, { value: key, children: m.fileMode[key] }, key))) }), _jsx(TabPanel, { value: "preview", className: "rl-agent-file__panel", children: _jsx(FileBody, { file: file, raw: false, renderMarkdown: renderMarkdown, renderCode: renderCode, onOpenExternal: onOpenExternal, zoomLevels: zoomLevels, defaultZoom: defaultZoom, m: m }) }), textual && (_jsx(TabPanel, { value: "raw", className: "rl-agent-file__panel", children: _jsx(FileBody, { file: file, raw: true, renderMarkdown: renderMarkdown, renderCode: renderCode, onOpenExternal: onOpenExternal, m: m }) })), _jsx(TabPanel, { value: "metadata", className: "rl-agent-file__panel", children: _jsx(FileMetadata, { file: file, m: m, format: format }) })] })] }));
49
+ });
50
+ async function writeClipboard(text) {
51
+ if (typeof navigator === 'undefined' || !navigator.clipboard)
52
+ throw new Error('clipboard');
53
+ await navigator.clipboard.writeText(text);
54
+ }
55
+ function FileActions({ file, canCopy, onOpenExternal, onReference, onReload, openTargets, defaultOpenTarget, onOpenWith, onCopyPath, m, }) {
56
+ const [copy, setCopy] = React.useState('idle');
57
+ const timer = React.useRef(undefined);
58
+ React.useEffect(() => () => clearTimeout(timer.current), []);
59
+ React.useEffect(() => setCopy('idle'), [file.content, file.path]);
60
+ const targets = onOpenWith ? (openTargets ?? []) : [];
61
+ const split = targets.length > 0;
62
+ if (!canCopy && !onOpenExternal && !onReference && !onReload && !split)
63
+ return null;
64
+ const run = async (write, ok, fail) => {
65
+ clearTimeout(timer.current);
66
+ try {
67
+ await write();
68
+ setCopy(ok);
69
+ }
70
+ catch {
71
+ setCopy(fail);
72
+ }
73
+ timer.current = setTimeout(() => setCopy('idle'), 2000);
74
+ };
75
+ const copyContent = () => run(() => writeClipboard(file.content ?? ''), 'copied', 'failed');
76
+ const copyPath = () => run(() => (onCopyPath ? onCopyPath(file.path, file) : writeClipboard(file.path)), 'path-copied', 'path-failed');
77
+ const announced = { idle: '', copied: m.fileCopied, failed: m.fileCopyFailed, 'path-copied': m.fileCopiedPath, 'path-failed': m.fileCopyPathFailed }[copy];
78
+ return (_jsxs("div", { className: "rl-agent-file__actions", children: [split && (_jsx(OpenWithSplit, { file: file, targets: targets, defaultTarget: defaultOpenTarget, onOpenWith: onOpenWith, onCopyPath: file.path ? () => void copyPath() : undefined, onReference: onReference, m: m })), canCopy && (_jsx(Button, { size: "sm", variant: "ghost", iconStart: _jsx(AgentIcon, { name: copy === 'copied' ? 'check' : 'copy' }), onClick: () => void copyContent(), children: copy === 'copied' ? m.fileCopied : copy === 'failed' ? m.fileCopyFailed : m.fileCopy })), onReference && (_jsx(Button, { size: "sm", variant: "ghost", iconStart: _jsx(AgentIcon, { name: "at" }), onClick: () => onReference(file), children: m.fileReference })), onReload && (_jsx(Button, { size: "sm", variant: "ghost", iconStart: _jsx(AgentIcon, { name: "retry" }), onClick: onReload, children: m.fileReread })), onOpenExternal && (_jsx(Button, { size: "sm", variant: "ghost", iconStart: _jsx(AgentIcon, { name: "external" }), onClick: () => onOpenExternal(file), children: m.fileOpenExternal })), _jsx("span", { className: "rl-agent-sr", role: "status", children: announced })] }));
79
+ }
80
+ /**
81
+ * Local split control: the primary button opens with the default target; the adjoining menu
82
+ * button (its own accessible name) opens a `Menu` with every target grouped by app / reveal,
83
+ * then 「复制路径」 and 「在对话中引用」. Both halves are real buttons in the tab order.
84
+ */
85
+ function OpenWithSplit({ file, targets, defaultTarget, onOpenWith, onCopyPath, onReference, m, }) {
86
+ const apps = targets.filter((t) => (t.group ?? 'app') === 'app');
87
+ const reveals = targets.filter((t) => t.group === 'reveal');
88
+ const primary = targets.find((t) => t.id === defaultTarget) ?? apps[0] ?? targets[0];
89
+ const extras = Boolean(onCopyPath || onReference);
90
+ return (_jsxs("span", { className: "rl-agent-file__split", role: "group", "aria-label": m.fileOpenGroup.app, children: [_jsx(Button, { size: "sm", variant: "secondary", className: "rl-agent-file__split-main", iconStart: _jsx(AgentIcon, { name: primary.group === 'reveal' ? 'folder' : 'external' }), onClick: () => onOpenWith(primary.id, file), children: m.fileOpenWith(primary.label) }), _jsxs(Menu, { align: "end", trigger: _jsx(IconButton, { size: "sm", variant: "secondary", className: "rl-agent-file__split-menu", icon: _jsx(AgentIcon, { name: "chevron-down" }), label: m.fileOpenTargets(file.name) }), children: [apps.length > 0 && (_jsx(MenuGroup, { label: m.fileOpenGroup.app, children: apps.map((t) => (_jsx(MenuItem, { icon: _jsx(AgentIcon, { name: "external" }), onSelect: () => onOpenWith(t.id, file), children: t.label }, t.id))) })), reveals.length > 0 && (_jsx(MenuGroup, { label: m.fileOpenGroup.reveal, children: reveals.map((t) => (_jsx(MenuItem, { icon: _jsx(AgentIcon, { name: "folder" }), onSelect: () => onOpenWith(t.id, file), children: t.label }, t.id))) })), extras && _jsx(MenuSeparator, {}), onCopyPath && (_jsx(MenuItem, { icon: _jsx(AgentIcon, { name: "copy" }), onSelect: onCopyPath, children: m.fileCopyPath })), onReference && (_jsx(MenuItem, { icon: _jsx(AgentIcon, { name: "at" }), onSelect: () => onReference(file), children: m.fileReference }))] })] }));
91
+ }
92
+ /**
93
+ * Breadcrumb items for a path. Under `root` the path is shown relative to it (root's last segment
94
+ * first); outside it (or for absolute paths without a root match) `outside` is true.
95
+ */
96
+ export function pathCrumbs(path, root) {
97
+ if (!path)
98
+ return undefined;
99
+ const norm = (p) => p.replace(/\\/g, '/').replace(/\/+$/, '');
100
+ const full = norm(path);
101
+ let segments;
102
+ let outside = false;
103
+ if (root) {
104
+ const base = norm(root);
105
+ const under = full === base || full.startsWith(`${base}/`) || (/^[a-z]:/i.test(base) && full.toLowerCase().startsWith(`${base.toLowerCase()}/`));
106
+ if (under) {
107
+ const rootName = base.split('/').filter(Boolean).pop() ?? base;
108
+ segments = [rootName, ...full.slice(base.length).split('/').filter(Boolean)];
109
+ }
110
+ else {
111
+ outside = true;
112
+ segments = full.split('/').filter(Boolean);
113
+ }
114
+ }
115
+ else {
116
+ segments = full.split('/').filter(Boolean);
117
+ }
118
+ if (segments.length === 0)
119
+ segments = [full];
120
+ return { items: segments.map((label) => ({ label })), outside };
121
+ }
122
+ function FileNotices({ file, onRetry, onReload, onLoadMore, m, format, }) {
123
+ const notices = [];
124
+ if (file.status === 'error') {
125
+ notices.push(_jsx(Alert, { tone: "danger", title: m.fileError, action: onRetry && _jsx(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: m.fileRetry }), children: file.reason }, "error"));
126
+ }
127
+ if (file.status === 'missing' || file.status === 'unavailable') {
128
+ notices.push(_jsx(Alert, { tone: "warning", title: file.status === 'missing' ? m.fileMissing : m.fileUnavailable, children: file.reason }, "gone"));
129
+ }
130
+ if (file.status === 'changed') {
131
+ notices.push(_jsx(Alert, { tone: "info", title: m.fileChanged, action: onReload && _jsx(Button, { size: "sm", variant: "secondary", onClick: onReload, children: m.fileReload }), children: file.reason }, "changed"));
132
+ }
133
+ if (file.partial || file.status === 'large-file') {
134
+ const loaded = file.partial ? format.bytes(file.partial.loadedBytes) : undefined;
135
+ const total = file.partial?.totalBytes ?? file.size;
136
+ const text = loaded ? (total !== undefined ? m.fileLoaded(loaded, format.bytes(total)) : m.fileLoadedNoTotal(loaded)) : undefined;
137
+ notices.push(_jsx(Alert, { tone: "warning", title: m.fileLargeFile, action: onLoadMore && _jsx(Button, { size: "sm", variant: "secondary", onClick: onLoadMore, children: m.fileLoadMore }), children: text }, "partial"));
138
+ }
139
+ if (notices.length === 0)
140
+ return null;
141
+ return _jsx("div", { className: "rl-agent-file__notices", children: notices });
142
+ }
143
+ function FileBody({ file, raw, renderMarkdown, renderCode, onOpenExternal, zoomLevels, defaultZoom, m, }) {
144
+ if (file.status === 'loading') {
145
+ return (_jsxs("div", { className: "rl-agent-file__loading", "aria-busy": "true", children: [_jsx(Skeleton, { lines: 4 }), _jsx("span", { className: "rl-agent-sr", children: m.fileLoading })] }));
146
+ }
147
+ if (file.status === 'error' || file.status === 'missing' || file.status === 'unavailable') {
148
+ return _jsx("p", { className: "rl-agent-file__empty", children: m.fileNoContent });
149
+ }
150
+ if (file.kind === 'binary' || file.kind === 'unknown') {
151
+ return (_jsxs("div", { className: "rl-agent-file__unsupported", children: [_jsx(AgentIcon, { name: "file" }), _jsx("p", { children: m.fileUnsupported }), onOpenExternal && (_jsx(Button, { size: "sm", variant: "secondary", iconStart: _jsx(AgentIcon, { name: "external" }), onClick: () => onOpenExternal(file), children: m.fileOpenExternal }))] }));
152
+ }
153
+ if (file.content === undefined || file.content === '')
154
+ return _jsx("p", { className: "rl-agent-file__empty", children: m.fileNoContent });
155
+ if (file.kind === 'image')
156
+ return _jsx(ImagePreview, { file: file, levels: zoomLevels, defaultZoom: defaultZoom, m: m });
157
+ const label = m.fileContent(file.name);
158
+ if (!raw && file.kind === 'markdown' && renderMarkdown) {
159
+ return (_jsx("div", { className: "rl-agent-file__scroll rl-agent-file__markdown", role: "region", "aria-label": label, tabIndex: 0, children: renderMarkdown(file.content) }));
160
+ }
161
+ if (!raw && file.kind === 'code' && renderCode) {
162
+ return (_jsx("div", { className: "rl-agent-file__scroll", role: "region", "aria-label": label, tabIndex: 0, children: renderCode(file.content, file.language) }));
163
+ }
164
+ return _jsx(NumberedText, { text: file.content, label: label, numbered: !raw });
165
+ }
166
+ /** Plain text with decorative (not copied, not read) line numbers. */
167
+ function NumberedText({ text, label, numbered }) {
168
+ const lines = React.useMemo(() => text.replace(/\n$/, '').split('\n'), [text]);
169
+ return (_jsx("div", { className: "rl-agent-file__scroll", role: "region", "aria-label": label, tabIndex: 0, children: _jsx("pre", { className: "rl-agent-file__code", "data-numbered": numbered || undefined, children: numbered
170
+ ? lines.map((line, i) => (_jsxs("span", { className: "rl-agent-file__line", children: [_jsx("span", { className: "rl-agent-file__ln", "aria-hidden": "true", children: i + 1 }), _jsx("span", { className: "rl-agent-file__text", children: line }), '\n'] }, i)))
171
+ : text }) }));
172
+ }
173
+ /**
174
+ * Image with a zoom group. Percentages are of the natural width (known after load); before the
175
+ * image has loaded, or when the browser reports no natural size, they fall back to a share of the
176
+ * preview width. `fit` scales the image down to the preview width, never up.
177
+ */
178
+ function ImagePreview({ file, levels, defaultZoom = 'fit', m }) {
179
+ const options = React.useMemo(() => {
180
+ const list = (levels && levels.length > 0 ? levels : DEFAULT_ZOOMS).filter((z) => Number.isFinite(z) && z > 0);
181
+ return [...new Set(list)].sort((a, b) => a - b);
182
+ }, [levels]);
183
+ const [zoom, setZoom] = React.useState(defaultZoom);
184
+ const [natural, setNatural] = React.useState(undefined);
185
+ const style = zoom === 'fit'
186
+ ? {}
187
+ : natural
188
+ ? { width: `${(natural * zoom) / 100}px` }
189
+ : { '--rl-agent-file-zoom': zoom / 100 };
190
+ return (_jsxs("div", { className: "rl-agent-file__image", children: [_jsxs("div", { className: "rl-agent-file__zoom", role: "group", "aria-label": m.fileZoom, children: [_jsx("button", { type: "button", className: "rl-agent-file__zoom-option", "aria-pressed": zoom === 'fit', onClick: () => setZoom('fit'), children: m.fileZoomFit }), options.map((z) => (_jsxs("button", { type: "button", className: "rl-agent-file__zoom-option", "aria-pressed": zoom === z, onClick: () => setZoom(z), children: [z, "%"] }, z)))] }), _jsx("div", { className: "rl-agent-file__scroll rl-agent-file__canvas", role: "region", "aria-label": m.fileContent(file.name), tabIndex: 0, children: _jsx("img", { className: "rl-agent-file__img", src: file.content, alt: file.alt ?? file.name, style: style, "data-zoom": zoom, onLoad: (event) => setNatural(event.currentTarget.naturalWidth || undefined) }) })] }));
191
+ }
192
+ function FileMetadata({ file, m, format }) {
193
+ const rows = [{ label: m.fileMeta.name, value: file.name }];
194
+ if (file.path)
195
+ rows.push({ label: m.fileMeta.path, value: file.path });
196
+ rows.push({ label: m.fileMeta.type, value: file.mimeType ?? m.artifactKind[file.kind === 'binary' ? 'file' : file.kind] });
197
+ if (file.language)
198
+ rows.push({ label: m.fileMeta.language, value: file.language });
199
+ if (file.size !== undefined)
200
+ rows.push({ label: m.fileMeta.size, value: format.bytes(file.size) });
201
+ if (file.version)
202
+ rows.push({ label: m.fileMeta.version, value: file.version });
203
+ for (const extra of file.metadata ?? [])
204
+ rows.push(extra);
205
+ return (_jsx("dl", { className: "rl-agent-file__meta", children: rows.map((row, i) => (_jsxs("div", { className: "rl-agent-file__meta-row", children: [_jsx("dt", { children: row.label }), _jsx("dd", { children: row.value })] }, `${row.label}-${i}`))) }));
206
+ }
207
+ //# sourceMappingURL=FilePreview.js.map