@ai-matrx/chat 0.6.6 → 0.7.1

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 (249) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +1 -1
  3. package/dist/agents/components/agent-widgets/AgentChatHistorySidebar.js +16 -55
  4. package/dist/agents/components/chat/chat-door.d.ts +67 -0
  5. package/dist/agents/components/chat/chat-door.js +100 -0
  6. package/dist/agents/components/conversation-history/AgentConversationList.d.ts +83 -0
  7. package/dist/agents/components/conversation-history/AgentConversationList.js +252 -0
  8. package/dist/agents/components/conversation-history/ConversationArchiveSection.d.ts +5 -1
  9. package/dist/agents/components/conversation-history/ConversationArchiveSection.js +22 -4
  10. package/dist/agents/components/conversation-history/ConversationHistorySidebar.js +20 -65
  11. package/dist/agents/components/inputs/input-components/TextareaInput.js +2 -0
  12. package/dist/agents/components/inputs/input-components/VariableInputComponent.js +7 -6
  13. package/dist/agents/components/inputs/smart-input/ConversationCompanionPills.d.ts +3 -0
  14. package/dist/agents/components/inputs/smart-input/ConversationCompanionPills.js +40 -0
  15. package/dist/agents/components/inputs/smart-input/ConversationContextRail.js +6 -29
  16. package/dist/agents/components/inputs/smart-input/DeviceToolsModeRow.d.ts +3 -0
  17. package/dist/agents/components/inputs/smart-input/DeviceToolsModeRow.js +35 -0
  18. package/dist/agents/components/inputs/smart-input/InboxQueueStrip.js +0 -8
  19. package/dist/agents/components/inputs/smart-input/RunToolPicker.js +15 -11
  20. package/dist/agents/components/inputs/smart-input/composer/ComposerPlusMenu.js +22 -0
  21. package/dist/agents/components/inputs/smart-input/rail-pill.d.ts +35 -0
  22. package/dist/agents/components/inputs/smart-input/rail-pill.js +30 -0
  23. package/dist/agents/components/inputs/variable-input-variations/AgentVariableForm.js +52 -48
  24. package/dist/agents/components/run-controls/panels/shared.d.ts +1 -1
  25. package/dist/agents/components/shared/AgentModeController.js +3 -2
  26. package/dist/agents/components/shell/AgentRunSidebarMenu.js +15 -54
  27. package/dist/agents/components/working-document/documents-workspace/DocumentsListRail.js +1 -2
  28. package/dist/agents/engine.d.ts +15 -0
  29. package/dist/agents/engine.js +17 -0
  30. package/dist/agents/hooks/useModelControls.js +3 -175
  31. package/dist/agents/redux/agent-definition/selectors.d.ts +237 -237
  32. package/dist/agents/redux/agent-shortcut-categories/selectors.d.ts +50 -50
  33. package/dist/agents/redux/agent-shortcuts/selectors.d.ts +147 -147
  34. package/dist/agents/redux/conversation-history/thunks.js +6 -18
  35. package/dist/agents/redux/conversation-list/conversation-list.selectors.d.ts +1 -73
  36. package/dist/agents/redux/conversation-list/conversation-list.selectors.js +2 -36
  37. package/dist/agents/redux/conversation-list/conversation-list.slice.d.ts +7 -22
  38. package/dist/agents/redux/conversation-list/conversation-list.slice.js +7 -62
  39. package/dist/agents/redux/conversation-list/conversation-list.thunks.d.ts +0 -25
  40. package/dist/agents/redux/conversation-list/conversation-list.thunks.js +2 -58
  41. package/dist/agents/redux/conversation-list/conversation-list.types.d.ts +0 -5
  42. package/dist/agents/redux/conversation-list/conversation-rows.d.ts +16 -0
  43. package/dist/agents/redux/conversation-list/conversation-rows.js +24 -0
  44. package/dist/agents/redux/conversation-list/conversation-trash.thunks.d.ts +1 -0
  45. package/dist/agents/redux/conversation-list/conversation-trash.thunks.js +13 -18
  46. package/dist/agents/redux/execution-system/active-requests/active-requests.selectors.d.ts +54 -54
  47. package/dist/agents/redux/execution-system/context-state/context-state.selectors.d.ts +14 -14
  48. package/dist/agents/redux/execution-system/conversations/conversations.selectors.d.ts +5 -5
  49. package/dist/agents/redux/execution-system/instance-context/instance-context.selectors.d.ts +3 -3
  50. package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.d.ts +8 -8
  51. package/dist/agents/redux/execution-system/instance-ui-state/instance-ui-state.selectors.d.ts +5 -5
  52. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.selectors.d.ts +7 -7
  53. package/dist/agents/redux/execution-system/messages/messages.selectors.d.ts +1 -1
  54. package/dist/agents/redux/execution-system/observability/observability.selectors.d.ts +7 -7
  55. package/dist/agents/redux/execution-system/observational-memory/observational-memory.selectors.d.ts +1 -1
  56. package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +14 -14
  57. package/dist/agents/redux/execution-system/thunks/create-instance.thunk.d.ts +10 -1
  58. package/dist/agents/redux/execution-system/thunks/create-instance.thunk.js +114 -265
  59. package/dist/agents/redux/execution-system/thunks/dispatch-matrx-extend-tool.thunk.js +18 -2
  60. package/dist/agents/redux/execution-system/thunks/dispatch-surface-client-tool.thunk.js +10 -28
  61. package/dist/agents/redux/execution-system/thunks/dispatch-surface-write.thunk.js +10 -25
  62. package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +20 -0
  63. package/dist/agents/redux/execution-system/thunks/execute-manual-instance.thunk.js +6 -1
  64. package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.d.ts +58 -0
  65. package/dist/agents/redux/execution-system/thunks/notify-and-play-dispatcher.js +62 -0
  66. package/dist/agents/redux/execution-system/thunks/post-delegated-tool-outcome.d.ts +23 -0
  67. package/dist/agents/redux/execution-system/thunks/post-delegated-tool-outcome.js +37 -0
  68. package/dist/agents/redux/execution-system/thunks/resume-instance.thunk.js +10 -2
  69. package/dist/agents/redux/execution-system/utils/build-tool-injection.d.ts +7 -0
  70. package/dist/agents/redux/execution-system/utils/build-tool-injection.js +18 -6
  71. package/dist/agents/redux/execution-system/utils/host-turn.d.ts +45 -0
  72. package/dist/agents/redux/execution-system/utils/host-turn.js +119 -0
  73. package/dist/agents/redux/proposed-directives/proposedDirectivesSlice.d.ts +1 -1
  74. package/dist/agents/scribe-tools/dispatcher/dispatch-scribe-tool.thunk.d.ts +50 -20
  75. package/dist/agents/scribe-tools/dispatcher/dispatch-scribe-tool.thunk.js +9 -101
  76. package/dist/agents/types/tool-injection.types.d.ts +18 -2
  77. package/dist/agents/ui-first-tools/redux/agent-lists.selectors.d.ts +2 -2
  78. package/dist/agents/ui-first-tools/redux/pending-asks.slice.d.ts +2 -1
  79. package/dist/agents/ui-first-tools/redux/resolve-asks-with-input.thunk.js +1 -1
  80. package/dist/agents/ui-first-tools/tools/ask-response.d.ts +29 -0
  81. package/dist/agents/ui-first-tools/tools/ask-response.js +15 -0
  82. package/dist/agents/ui-first-tools/tools/schemas.d.ts +3 -25
  83. package/dist/agents/ui-first-tools/tools/schemas.js +1 -12
  84. package/dist/agents/ui-first-tools/ui/ApprovalCard.js +1 -1
  85. package/dist/agents/ui-first-tools/ui/AskWizard.d.ts +1 -1
  86. package/dist/agents/ui-first-tools/ui/AskWizard.js +1 -1
  87. package/dist/cx-chat/_legacy-stubs.d.ts +5 -5
  88. package/dist/cx-chat/components/SsrSidebarChats.js +13 -15
  89. package/dist/cx-chat/components/messages/UserMessage.d.ts +2 -2
  90. package/dist/cx-chat/types/conversation.d.ts +6 -6
  91. package/dist/cx-chat/utils/buildContentBlocksForSave.d.ts +1 -1
  92. package/dist/cx-chat/utils/cx-content-converter.d.ts +1 -1
  93. package/dist/host/bare-host-chrome.js +9 -3
  94. package/dist/host/composer-extensions.d.ts +75 -0
  95. package/dist/host/composer-extensions.js +92 -0
  96. package/dist/host/configure.js +1 -0
  97. package/dist/host/contract.d.ts +105 -13
  98. package/dist/host/defaults/confirm.d.ts +15 -0
  99. package/dist/host/defaults/confirm.js +25 -0
  100. package/dist/host/defaults/files-ui.d.ts +85 -0
  101. package/dist/host/defaults/files-ui.js +158 -0
  102. package/dist/host/defaults/gates.d.ts +27 -0
  103. package/dist/host/defaults/gates.js +72 -0
  104. package/dist/host/defaults/media-client.d.ts +15 -0
  105. package/dist/host/defaults/media-client.js +40 -0
  106. package/dist/host/defaults/voice.d.ts +81 -0
  107. package/dist/host/defaults/voice.js +239 -0
  108. package/dist/host/device-tool-handoff.d.ts +26 -0
  109. package/dist/host/device-tool-handoff.js +45 -0
  110. package/dist/host/index.d.ts +1 -0
  111. package/dist/host/index.js +4 -1
  112. package/dist/host/microphone.d.ts +11 -0
  113. package/dist/host/microphone.js +17 -0
  114. package/dist/host/ui-slots.d.ts +29 -74
  115. package/dist/host/ui-slots.js +40 -42
  116. package/dist/store/create-chat-store.d.ts +2 -2
  117. package/dist/store/middlewares.d.ts +5 -5
  118. package/dist/store/slices.d.ts +1 -1
  119. package/dist/surfaces/redux/selectors.d.ts +2 -2
  120. package/dist/tool-call-visualization/components/ToolCallVisualization.js +3 -2
  121. package/dist/tool-call-visualization/configured-rows/ConfiguredRowRenderer.d.ts +15 -0
  122. package/dist/tool-call-visualization/configured-rows/ConfiguredRowRenderer.js +36 -0
  123. package/dist/tool-call-visualization/configured-rows/ConfiguredToolRow.d.ts +40 -0
  124. package/dist/tool-call-visualization/configured-rows/ConfiguredToolRow.js +296 -0
  125. package/dist/tool-call-visualization/configured-rows/CopyToolButton.d.ts +23 -0
  126. package/dist/tool-call-visualization/configured-rows/CopyToolButton.js +62 -0
  127. package/dist/tool-call-visualization/configured-rows/ToolProgressView.d.ts +23 -0
  128. package/dist/tool-call-visualization/configured-rows/ToolProgressView.js +147 -0
  129. package/dist/tool-call-visualization/configured-rows/field-components.d.ts +15 -0
  130. package/dist/tool-call-visualization/configured-rows/field-components.js +244 -0
  131. package/dist/tool-call-visualization/configured-rows/helpers.d.ts +39 -0
  132. package/dist/tool-call-visualization/configured-rows/helpers.js +110 -0
  133. package/dist/tool-call-visualization/configured-rows/register.d.ts +25 -0
  134. package/dist/tool-call-visualization/configured-rows/register.js +51 -0
  135. package/dist/tool-call-visualization/configured-rows/registries.d.ts +27 -0
  136. package/dist/tool-call-visualization/configured-rows/registries.js +14 -0
  137. package/dist/tool-call-visualization/configured-rows/to-row-entry.d.ts +8 -0
  138. package/dist/tool-call-visualization/configured-rows/to-row-entry.js +38 -0
  139. package/dist/tool-call-visualization/configured-rows/transforms.d.ts +14 -0
  140. package/dist/tool-call-visualization/configured-rows/transforms.js +30 -0
  141. package/dist/tool-call-visualization/configured-rows/types.d.ts +140 -0
  142. package/dist/tool-call-visualization/redux/selectors.d.ts +1 -1
  143. package/dist/tool-call-visualization/registry/registry.d.ts +1 -1
  144. package/dist/tool-call-visualization/registry/registry.js +8 -1
  145. package/dist/tool-call-visualization/types.d.ts +1 -1
  146. package/dist/ui/chat-protocol-types.d.ts +0 -1
  147. package/dist/ui/ownership.d.ts +25 -0
  148. package/dist/ui/ownership.js +18 -0
  149. package/dist/voice-agent/audio/audioCapture.js +11 -6
  150. package/dist/window-panels/windows/agents/AgentRunHistoryWindow.d.ts +1 -2
  151. package/dist/window-panels/windows/agents/AgentRunHistoryWindow.js +21 -181
  152. package/dist/window-panels/windows/agents/AgentRunWindow.js +26 -13
  153. package/package.json +4627 -125
  154. package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.d.ts +0 -7
  155. package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.js +0 -33
  156. package/dist/agents/components/agent-widgets/chat-assistant/StatusCard.d.ts +0 -6
  157. package/dist/agents/components/agent-widgets/chat-assistant/StatusCard.js +0 -21
  158. package/dist/agents/components/agent-widgets/chat-assistant/UserMessageCard.d.ts +0 -6
  159. package/dist/agents/components/agent-widgets/chat-assistant/UserMessageCard.js +0 -11
  160. package/dist/agents/components/agent-widgets/chat-assistant/VariableInputCard.d.ts +0 -12
  161. package/dist/agents/components/agent-widgets/chat-assistant/VariableInputCard.js +0 -7
  162. package/dist/agents/components/agent-widgets/execution-gates/PreExecutionCard.d.ts +0 -4
  163. package/dist/agents/components/agent-widgets/execution-gates/PreExecutionCard.js +0 -81
  164. package/dist/agents/components/run/run-sidebar/SidebarHeader.d.ts +0 -21
  165. package/dist/agents/components/run/run-sidebar/SidebarHeader.js +0 -50
  166. package/dist/agents/components/run-controls/AdvancedRunSettings/index.d.ts +0 -6
  167. package/dist/agents/components/run-controls/AdvancedRunSettings/index.js +0 -32
  168. package/dist/agents/components/run-controls/RunSettingsModal.d.ts +0 -5
  169. package/dist/agents/components/run-controls/RunSettingsModal.js +0 -22
  170. package/dist/agents/components/shell/AgentBuildSidebarExtras.d.ts +0 -6
  171. package/dist/agents/components/shell/AgentBuildSidebarExtras.js +0 -30
  172. package/dist/agents/constants/agent-system-competitors.d.ts +0 -9
  173. package/dist/agents/constants/agent-system-competitors.js +0 -125
  174. package/dist/agents/hooks/message-crud/useMessageActions.d.ts +0 -29
  175. package/dist/agents/hooks/message-crud/useMessageActions.js +0 -119
  176. package/dist/agents/hooks/useConversationPendingCalls.d.ts +0 -30
  177. package/dist/agents/hooks/useConversationPendingCalls.js +0 -42
  178. package/dist/agents/model-registry/model-classes.d.ts +0 -1
  179. package/dist/agents/model-registry/model-classes.js +0 -1
  180. package/dist/agents/redux/conversation-history/index.d.ts +0 -18
  181. package/dist/agents/redux/conversation-history/index.js +0 -4
  182. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.thunks.d.ts +0 -38
  183. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.thunks.js +0 -42
  184. package/dist/agents/redux/execution-system/message-crud/server/compact-turns.thunk.d.ts +0 -58
  185. package/dist/agents/redux/execution-system/message-crud/server/compact-turns.thunk.js +0 -50
  186. package/dist/agents/redux/execution-system/message-crud/server/fork-and-run-server.thunk.d.ts +0 -76
  187. package/dist/agents/redux/execution-system/message-crud/server/fork-and-run-server.thunk.js +0 -101
  188. package/dist/agents/redux/execution-system/thunks/attach-workflow-run.d.ts +0 -38
  189. package/dist/agents/redux/execution-system/thunks/attach-workflow-run.js +0 -25
  190. package/dist/agents/redux/execution-system/utils/source-slice-helpers.d.ts +0 -45
  191. package/dist/agents/redux/execution-system/utils/source-slice-helpers.js +0 -50
  192. package/dist/agents/runtime/realtime/launchRealtimeSession.thunk.d.ts +0 -25
  193. package/dist/agents/runtime/realtime/launchRealtimeSession.thunk.js +0 -15
  194. package/dist/agents/services/agentService.d.ts +0 -12
  195. package/dist/agents/services/agentService.js +0 -92
  196. package/dist/agents/utils/escape-code-fences.d.ts +0 -15
  197. package/dist/agents/utils/escape-code-fences.js +0 -9
  198. package/dist/agents/utils/normalize-managed-options.d.ts +0 -30
  199. package/dist/agents/utils/normalize-managed-options.js +0 -29
  200. package/dist/agents/utils/processedDocumentContext.d.ts +0 -51
  201. package/dist/agents/utils/processedDocumentContext.js +0 -51
  202. package/dist/agents/utils/variable-validation.d.ts +0 -28
  203. package/dist/agents/utils/variable-validation.js +0 -54
  204. package/dist/cx-chat/components/ChatConversationSkeleton.d.ts +0 -9
  205. package/dist/cx-chat/components/ChatConversationSkeleton.js +0 -45
  206. package/dist/cx-chat/components/ChatPanelBackButton.d.ts +0 -1
  207. package/dist/cx-chat/components/ChatPanelBackButton.js +0 -26
  208. package/dist/cx-chat/components/messages/MessageErrorBoundary.d.ts +0 -20
  209. package/dist/cx-chat/components/messages/MessageErrorBoundary.js +0 -40
  210. package/dist/cx-chat/components/variable-inputs/CheckboxGroupInput.d.ts +0 -14
  211. package/dist/cx-chat/components/variable-inputs/CheckboxGroupInput.js +0 -160
  212. package/dist/cx-chat/components/variable-inputs/NumberInput.d.ts +0 -15
  213. package/dist/cx-chat/components/variable-inputs/NumberInput.js +0 -79
  214. package/dist/cx-chat/components/variable-inputs/RadioGroupInput.d.ts +0 -14
  215. package/dist/cx-chat/components/variable-inputs/RadioGroupInput.js +0 -125
  216. package/dist/cx-chat/components/variable-inputs/SelectInput.d.ts +0 -14
  217. package/dist/cx-chat/components/variable-inputs/SelectInput.js +0 -92
  218. package/dist/cx-chat/components/variable-inputs/TextareaInput.d.ts +0 -14
  219. package/dist/cx-chat/components/variable-inputs/TextareaInput.js +0 -46
  220. package/dist/cx-chat/components/variable-inputs/ToggleInput.d.ts +0 -14
  221. package/dist/cx-chat/components/variable-inputs/ToggleInput.js +0 -46
  222. package/dist/cx-chat/hooks/useChatPersistence.d.ts +0 -28
  223. package/dist/cx-chat/hooks/useChatPersistence.js +0 -180
  224. package/dist/cx-chat/hooks/useInstanceBootstrap.d.ts +0 -1
  225. package/dist/cx-chat/hooks/useInstanceBootstrap.js +0 -115
  226. package/dist/cx-chat/types/content.d.ts +0 -184
  227. package/dist/cx-chat/types/content.js +0 -91
  228. package/dist/cx-chat/types/cx-tables.d.ts +0 -176
  229. package/dist/cx-chat/utils/settings-diff.d.ts +0 -13
  230. package/dist/cx-chat/utils/settings-diff.js +0 -25
  231. package/dist/public-chat/components/AgentSelector.d.ts +0 -22
  232. package/dist/public-chat/components/AgentSelector.js +0 -80
  233. package/dist/public-chat/components/GuidedVariableInputs.d.ts +0 -25
  234. package/dist/public-chat/components/GuidedVariableInputs.js +0 -623
  235. package/dist/public-chat/components/PublicVariableInputs.d.ts +0 -29
  236. package/dist/public-chat/components/PublicVariableInputs.js +0 -172
  237. package/dist/public-chat/types/content.d.ts +0 -184
  238. package/dist/public-chat/types/content.js +0 -91
  239. package/dist/tool-call-visualization/renderers/_shared-entity/EntityOpenActions.d.ts +0 -15
  240. package/dist/tool-call-visualization/renderers/_shared-entity/EntityOpenActions.js +0 -31
  241. package/dist/tool-call-visualization/utils/toolCallBlockToLifecycleEntry.d.ts +0 -24
  242. package/dist/tool-call-visualization/utils/toolCallBlockToLifecycleEntry.js +0 -26
  243. package/dist/ui/AudioOutputBlockSkeleton.d.ts +0 -17
  244. package/dist/ui/AudioOutputBlockSkeleton.js +0 -78
  245. package/dist/ui/lazy/PublicChatVariableInputs.d.ts +0 -2
  246. package/dist/ui/lazy/PublicChatVariableInputs.js +0 -16
  247. package/dist/utils/xml/readXmlTag.d.ts +0 -12
  248. package/dist/utils/xml/readXmlTag.js +0 -66
  249. /package/dist/{cx-chat/types/cx-tables.js → tool-call-visualization/configured-rows/types.js} +0 -0
@@ -0,0 +1,244 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "@ai-matrx/design-system";
3
+ import { MarkdownStream } from "../../ui/markdown-stream/MarkdownStream.js";
4
+ import { formatFileSize } from "@ai-matrx/kit/format";
5
+ import { Globe } from "lucide-react";
6
+ import { useState } from "react";
7
+ function safeJson(value) {
8
+ if (value == null) return "";
9
+ if (typeof value === "string") return value;
10
+ try {
11
+ return JSON.stringify(value, null, 2);
12
+ } catch {
13
+ return String(value);
14
+ }
15
+ }
16
+ const BoldLabel = ({ value, className }) => /* @__PURE__ */ jsx("div", { className: cn("text-[12px] font-semibold", className), children: String(value ?? "") });
17
+ const TextDisplay = ({ value, className }) => /* @__PURE__ */ jsx("div", { className: cn("text-[12px]", className), children: String(value ?? "") });
18
+ const Markdown = ({ value, className }) => {
19
+ if (value != null && typeof value === "object") {
20
+ return /* @__PURE__ */ jsx(
21
+ "pre",
22
+ {
23
+ className: cn(
24
+ "max-h-96 overflow-auto rounded-md bg-background/60 p-1.5 text-[11px] leading-snug whitespace-pre-wrap",
25
+ className
26
+ ),
27
+ children: safeJson(value)
28
+ }
29
+ );
30
+ }
31
+ return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(MarkdownStream, { content: String(value ?? "") }) });
32
+ };
33
+ const Code = ({ value, className }) => /* @__PURE__ */ jsx(
34
+ "pre",
35
+ {
36
+ className: cn(
37
+ "max-h-48 overflow-auto rounded-md bg-background/60 p-1.5 text-[11px] leading-snug",
38
+ className
39
+ ),
40
+ children: String(value ?? "")
41
+ }
42
+ );
43
+ const Json = ({ value, className }) => /* @__PURE__ */ jsx(
44
+ "pre",
45
+ {
46
+ className: cn(
47
+ "max-h-48 overflow-auto rounded-md bg-background/60 p-1.5 text-[11px] leading-snug",
48
+ className
49
+ ),
50
+ children: safeJson(value)
51
+ }
52
+ );
53
+ const Image = ({ value, className }) => {
54
+ const src = typeof value === "string" ? value : "";
55
+ if (!src) return null;
56
+ return /* @__PURE__ */ jsx("img", { src, className: cn("max-w-full rounded-md", className), alt: "" });
57
+ };
58
+ const Base64Image = ({ value, className }) => {
59
+ const src = toDataUri(value);
60
+ if (!src) return null;
61
+ const meta = imageMeta(value);
62
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), children: [
63
+ /* @__PURE__ */ jsx(
64
+ "img",
65
+ {
66
+ src,
67
+ alt: "",
68
+ className: "max-h-[28rem] w-full rounded-md border border-border/40 object-contain"
69
+ }
70
+ ),
71
+ meta && /* @__PURE__ */ jsx("div", { className: "text-[10px] text-muted-foreground", children: meta })
72
+ ] });
73
+ };
74
+ function toDataUri(value) {
75
+ if (typeof value === "string") {
76
+ if (value.startsWith("http://") || value.startsWith("https://")) return value;
77
+ return value.startsWith("data:") ? value : `data:image/png;base64,${value}`;
78
+ }
79
+ if (value == null || typeof value !== "object") return "";
80
+ const obj = value;
81
+ const hosted = pickString(obj, ["file_url", "url", "image_url"]);
82
+ if (hosted && (hosted.startsWith("http://") || hosted.startsWith("https://"))) {
83
+ return hosted;
84
+ }
85
+ const raw = pickString(obj, ["image_base64", "base64", "data", "image"]);
86
+ if (!raw) return "";
87
+ if (raw.startsWith("data:")) return raw;
88
+ const mediaType = pickString(obj, ["media_type", "mediaType", "mime_type", "mimeType"]) ?? formatToMime(pickString(obj, ["format"])) ?? "image/png";
89
+ return `data:${mediaType};base64,${raw}`;
90
+ }
91
+ function imageMeta(value) {
92
+ if (value == null || typeof value !== "object") return "";
93
+ const obj = value;
94
+ const w = obj.width ?? obj.w;
95
+ const h = obj.height ?? obj.h;
96
+ const bytes = obj.byte_length ?? obj.byteLength ?? obj.size;
97
+ const parts = [];
98
+ if (typeof w === "number" && typeof h === "number") parts.push(`${w}\xD7${h}`);
99
+ if (typeof bytes === "number") parts.push(formatFileSize(bytes));
100
+ return parts.join(" \xB7 ");
101
+ }
102
+ function pickString(obj, keys) {
103
+ for (const k of keys) {
104
+ const v = obj[k];
105
+ if (typeof v === "string" && v) return v;
106
+ }
107
+ return void 0;
108
+ }
109
+ function formatToMime(format) {
110
+ if (!format) return void 0;
111
+ const f = format.toLowerCase();
112
+ if (f === "jpeg" || f === "jpg") return "image/jpeg";
113
+ if (f === "png") return "image/png";
114
+ if (f === "webp") return "image/webp";
115
+ if (f === "gif") return "image/gif";
116
+ return `image/${f}`;
117
+ }
118
+ const Badge = ({ value, className }) => /* @__PURE__ */ jsx(
119
+ "span",
120
+ {
121
+ className: cn(
122
+ "inline-flex rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground",
123
+ className
124
+ ),
125
+ children: String(value ?? "")
126
+ }
127
+ );
128
+ const Chips = ({ value, className }) => {
129
+ const items = Array.isArray(value) ? value.map((v) => v == null ? "" : String(v)).filter(Boolean) : value == null ? [] : [String(value)];
130
+ if (items.length === 0) return null;
131
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1", className), children: items.map((item, i) => /* @__PURE__ */ jsx(
132
+ "span",
133
+ {
134
+ className: "inline-flex rounded-md border border-border/50 bg-muted/40 px-1.5 py-0.5 font-mono text-[10px] text-foreground",
135
+ children: item
136
+ },
137
+ `${item}-${i}`
138
+ )) });
139
+ };
140
+ const TabCard = ({ value, className }) => {
141
+ const [faviconErr, setFaviconErr] = useState(false);
142
+ if (value == null || typeof value !== "object") return null;
143
+ const obj = value;
144
+ const title = pickString(obj, ["title"]) ?? "";
145
+ const url = pickString(obj, ["url"]) ?? "";
146
+ const favicon = pickString(obj, ["fav_icon_url", "favIconUrl", "favicon"]);
147
+ return /* @__PURE__ */ jsxs(
148
+ "div",
149
+ {
150
+ className: cn(
151
+ "flex items-start gap-2 rounded-md border border-border/40 bg-background/40 p-2",
152
+ className
153
+ ),
154
+ children: [
155
+ favicon && !faviconErr ? /* @__PURE__ */ jsx(
156
+ "img",
157
+ {
158
+ src: favicon,
159
+ alt: "",
160
+ className: "size-5 shrink-0 rounded-sm object-contain",
161
+ onError: () => setFaviconErr(true)
162
+ }
163
+ ) : /* @__PURE__ */ jsx(Globe, { className: "size-5 shrink-0 text-muted-foreground" }),
164
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [
165
+ title && /* @__PURE__ */ jsx("div", { className: "truncate text-[12px] font-medium text-foreground", children: title }),
166
+ url && /* @__PURE__ */ jsx(
167
+ "a",
168
+ {
169
+ href: url,
170
+ target: "_blank",
171
+ rel: "noreferrer noopener",
172
+ className: "block truncate text-[10px] text-muted-foreground hover:text-foreground hover:underline",
173
+ onClick: (e) => e.stopPropagation(),
174
+ children: url
175
+ }
176
+ )
177
+ ] })
178
+ ]
179
+ }
180
+ );
181
+ };
182
+ const Table = ({ value, className }) => {
183
+ if (value == null || typeof value !== "object") return null;
184
+ const obj = value;
185
+ const columns = Array.isArray(obj.columns) ? obj.columns : [];
186
+ const rows = Array.isArray(obj.rows) ? obj.rows : [];
187
+ if (columns.length === 0 || rows.length === 0) return null;
188
+ const visibleCols = columns.filter((c) => {
189
+ if (c.path && c.path.length > 0) return true;
190
+ return rows.some((r) => {
191
+ const cell = r.cells?.[c.index];
192
+ const v = cell?.value;
193
+ return typeof v === "string" ? v.trim().length > 0 : v != null;
194
+ });
195
+ });
196
+ if (visibleCols.length === 0) return null;
197
+ return /* @__PURE__ */ jsxs(
198
+ "div",
199
+ {
200
+ className: cn("overflow-auto rounded-md border border-border/40 bg-background/40", className),
201
+ children: [
202
+ /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-[11px]", children: [
203
+ /* @__PURE__ */ jsx("thead", { className: "bg-muted/40", children: /* @__PURE__ */ jsx("tr", { children: visibleCols.map((c) => /* @__PURE__ */ jsx(
204
+ "th",
205
+ {
206
+ className: "border-b border-border/40 px-2 py-1 text-left font-medium text-muted-foreground",
207
+ children: (c.path ?? []).join(" \u203A ")
208
+ },
209
+ c.index
210
+ )) }) }),
211
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((r, ri) => /* @__PURE__ */ jsx("tr", { className: "border-t border-border/20 hover:bg-muted/30", children: visibleCols.map((c) => {
212
+ const cell = r.cells?.[c.index];
213
+ return /* @__PURE__ */ jsx(
214
+ "td",
215
+ {
216
+ className: "max-w-[20rem] truncate px-2 py-1 align-top text-foreground",
217
+ title: typeof cell?.value === "string" ? cell.value : void 0,
218
+ children: typeof cell?.value === "string" ? cell.value : cell?.value == null ? "" : String(cell.value)
219
+ },
220
+ c.index
221
+ );
222
+ }) }, r.index ?? ri)) })
223
+ ] }),
224
+ obj.truncated === true && /* @__PURE__ */ jsx("div", { className: "border-t border-border/30 bg-muted/30 px-2 py-1 text-[10px] text-muted-foreground", children: "Table was truncated" })
225
+ ]
226
+ }
227
+ );
228
+ };
229
+ const fieldComponents = {
230
+ BoldLabel,
231
+ TextDisplay,
232
+ Markdown,
233
+ Code,
234
+ Json,
235
+ Image,
236
+ Base64Image,
237
+ Badge,
238
+ Chips,
239
+ TabCard,
240
+ Table
241
+ };
242
+ export {
243
+ fieldComponents
244
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Resolution helpers for the tool-display registry. Everything here is silent
3
+ * on bad input — invalid paths return undefined, unknown transforms/icons log
4
+ * a console.warn and return a sensible fallback. Nothing throws into a render.
5
+ */
6
+ import { type RowIcon } from './registries.js';
7
+ import type { ColorToken, IconName, Phase, PhaseAware, ToolRowEntry, TransformName } from './types.js';
8
+ /**
9
+ * If `v` is a `PhaseMap` (a plain object whose only keys are phase names),
10
+ * return the entry for the current phase (or undefined). Otherwise return `v`
11
+ * as-is — single-value config applies to every phase.
12
+ */
13
+ export declare function resolvePhase<T>(v: PhaseAware<T> | undefined, phase: Phase): T | undefined;
14
+ /**
15
+ * Resolve a dot-path against a tool entry. Recognized roots: args, output,
16
+ * result (alias of output), message, toolName, callId. Numeric path segments
17
+ * index into arrays. Returns undefined silently on any miss.
18
+ *
19
+ * getByPath(entry, 'args.key') → entry.args.key
20
+ * getByPath(entry, 'output.items.0.title') → entry.output.items[0].title
21
+ * getByPath(entry, 'result.label') → entry.output.label (alias)
22
+ */
23
+ export declare function getByPath(entry: ToolRowEntry, path: string): unknown;
24
+ /**
25
+ * Run a value through one or more named transforms. Unknown names log a
26
+ * warning and pass the value through. A throwing transform logs and returns
27
+ * the last good value.
28
+ */
29
+ export declare function applyTransforms(value: unknown, names?: TransformName | TransformName[] | null): unknown;
30
+ /**
31
+ * Resolve a color token to a tailwind class. Error phase always wins (red),
32
+ * even if the registry tries to override it — keeps error visuals consistent.
33
+ */
34
+ export declare function resolveColor(token: ColorToken | undefined, phase: Phase): string;
35
+ /**
36
+ * Look up a registered icon by name. Unknown name: warn and use the phase default
37
+ * (`Loader2` for started, `CheckCircle2` for completed, `AlertTriangle` for error).
38
+ */
39
+ export declare function resolveIcon(name: IconName | undefined, phase: Phase): RowIcon;
@@ -0,0 +1,110 @@
1
+ import { AlertTriangle, CheckCircle2, Loader2 } from "lucide-react";
2
+ import { ICONS } from "./registries.js";
3
+ import { transforms } from "./transforms.js";
4
+ function resolvePhase(v, phase) {
5
+ if (v == null) return void 0;
6
+ if (isPhaseMap(v)) return v[phase];
7
+ return v;
8
+ }
9
+ function isPhaseMap(v) {
10
+ if (v == null || typeof v !== "object" || Array.isArray(v)) return false;
11
+ const keys = Object.keys(v);
12
+ if (keys.length === 0) return false;
13
+ return keys.every((k) => k === "started" || k === "completed" || k === "error");
14
+ }
15
+ function getByPath(entry, path) {
16
+ if (!path) return void 0;
17
+ const segments = path.split(".");
18
+ const head = segments[0];
19
+ let cursor;
20
+ switch (head) {
21
+ case "args":
22
+ cursor = entry.args;
23
+ break;
24
+ case "output":
25
+ case "result":
26
+ cursor = entry.output;
27
+ break;
28
+ case "message":
29
+ cursor = entry.message;
30
+ break;
31
+ case "toolName":
32
+ cursor = entry.toolName;
33
+ break;
34
+ case "callId":
35
+ cursor = entry.callId;
36
+ break;
37
+ default:
38
+ return void 0;
39
+ }
40
+ for (let i = 1; i < segments.length; i++) {
41
+ if (cursor == null) return void 0;
42
+ const seg = segments[i];
43
+ if (seg === void 0) return void 0;
44
+ if (Array.isArray(cursor)) {
45
+ const idx = Number(seg);
46
+ if (!Number.isInteger(idx)) return void 0;
47
+ cursor = cursor[idx];
48
+ } else if (typeof cursor === "object") {
49
+ cursor = cursor[seg];
50
+ } else {
51
+ return void 0;
52
+ }
53
+ }
54
+ return cursor;
55
+ }
56
+ function applyTransforms(value, names) {
57
+ if (names == null) return value;
58
+ const list = Array.isArray(names) ? names : [names];
59
+ let cursor = value;
60
+ for (const name of list) {
61
+ const fn = transforms[name];
62
+ if (!fn) {
63
+ console.warn(`[configured-row] unknown transform: "${name}"`);
64
+ continue;
65
+ }
66
+ try {
67
+ cursor = fn(cursor);
68
+ } catch (err) {
69
+ console.warn(`[configured-row] transform "${name}" threw:`, err, { value: cursor });
70
+ }
71
+ }
72
+ return cursor;
73
+ }
74
+ const COLOR_CLASSES = {
75
+ blue: "text-blue-600 dark:text-blue-400",
76
+ sky: "text-sky-600 dark:text-sky-400",
77
+ emerald: "text-emerald-600 dark:text-emerald-400",
78
+ amber: "text-amber-600 dark:text-amber-400",
79
+ red: "text-red-600 dark:text-red-400",
80
+ violet: "text-violet-600 dark:text-violet-400",
81
+ slate: "text-slate-600 dark:text-slate-400",
82
+ primary: "text-primary",
83
+ muted: "text-muted-foreground"
84
+ };
85
+ function resolveColor(token, phase) {
86
+ if (phase === "error") return COLOR_CLASSES.red;
87
+ if (token && COLOR_CLASSES[token]) return COLOR_CLASSES[token];
88
+ if (phase === "started") return COLOR_CLASSES.primary;
89
+ if (phase === "completed") return COLOR_CLASSES.emerald;
90
+ return COLOR_CLASSES.muted;
91
+ }
92
+ const PHASE_DEFAULT_ICON = {
93
+ started: Loader2,
94
+ completed: CheckCircle2,
95
+ error: AlertTriangle
96
+ };
97
+ function resolveIcon(name, phase) {
98
+ if (!name) return PHASE_DEFAULT_ICON[phase];
99
+ const found = ICONS[name];
100
+ if (found) return found;
101
+ console.warn(`[configured-row] unregistered icon: "${name}"`);
102
+ return PHASE_DEFAULT_ICON[phase];
103
+ }
104
+ export {
105
+ applyTransforms,
106
+ getByPath,
107
+ resolveColor,
108
+ resolveIcon,
109
+ resolvePhase
110
+ };
@@ -0,0 +1,25 @@
1
+ import type { ToolDisplayEntry } from "./types.js";
2
+ /**
3
+ * Configs the host keeps out of the first screen: the tool names up front (a cheap list), the
4
+ * configs on demand. `load` runs the first time a call to one of the tools is drawn.
5
+ */
6
+ export interface LazyConfigs {
7
+ names: readonly string[];
8
+ load: () => Promise<Record<string, ToolDisplayEntry>>;
9
+ }
10
+ export interface RegisterConfiguredOptions {
11
+ /**
12
+ * Extra names each config is also registered under, as prefixes the server may put in front of
13
+ * the tool name (`["my-host:"]` registers `read_page` and `my-host:read_page`). The bare name is
14
+ * always registered.
15
+ */
16
+ namePrefixes?: readonly string[];
17
+ /** Removed from the call's tool name before the config paths read it (`toolName` paths). */
18
+ stripPrefix?: RegExp;
19
+ }
20
+ /** Register every config as a `row`-chrome renderer. Returns the registered names. */
21
+ export declare function registerConfiguredToolRenderers(configs: Record<string, ToolDisplayEntry> | LazyConfigs, options?: RegisterConfiguredOptions): string[];
22
+ export { registerRowTransforms } from "./transforms.js";
23
+ export { registerRowIcons, registerRowFieldComponents } from "./registries.js";
24
+ export type { RowTransform } from "./transforms.js";
25
+ export type { ToolDisplayEntry, ToolRowEntry, ToolProgressRow } from "./types.js";
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { clientLazy } from "@ai-matrx/kit/client-lazy";
4
+ import { registerToolRenderer } from "../registry/registry.js";
5
+ function RowPlaceholder() {
6
+ return /* @__PURE__ */ jsx("div", { className: "h-5", "aria-hidden": true });
7
+ }
8
+ const ConfiguredRowRenderer = clientLazy(
9
+ () => import("./ConfiguredRowRenderer.js").then((m) => ({ default: m.ConfiguredRowRenderer })),
10
+ { loading: RowPlaceholder }
11
+ );
12
+ function titleCase(name) {
13
+ return name.split(/[_\s-]+/).filter(Boolean).map((p) => p[0] ? p[0].toUpperCase() + p.slice(1) : p).join(" ");
14
+ }
15
+ function registerConfiguredToolRenderers(configs, options = {}) {
16
+ const registered = [];
17
+ const lazy = "load" in configs && typeof configs.load === "function" ? configs : null;
18
+ const names = lazy ? lazy.names : Object.keys(configs);
19
+ for (const bare of names) {
20
+ const cfg = lazy ? null : configs[bare];
21
+ const Inline = (props) => /* @__PURE__ */ jsx(
22
+ ConfiguredRowRenderer,
23
+ {
24
+ props,
25
+ bare,
26
+ ...cfg && { cfg },
27
+ ...lazy && { load: lazy.load },
28
+ ...options.stripPrefix && { stripPrefix: options.stripPrefix }
29
+ }
30
+ );
31
+ for (const toolName of [bare, ...(options.namePrefixes ?? []).map((p) => `${p}${bare}`)]) {
32
+ const renderer = {
33
+ toolName,
34
+ displayName: titleCase(bare),
35
+ chrome: "row",
36
+ InlineComponent: Inline
37
+ };
38
+ registerToolRenderer(toolName, renderer);
39
+ registered.push(toolName);
40
+ }
41
+ }
42
+ return registered;
43
+ }
44
+ import { registerRowTransforms } from "./transforms.js";
45
+ import { registerRowIcons, registerRowFieldComponents } from "./registries.js";
46
+ export {
47
+ registerConfiguredToolRenderers,
48
+ registerRowFieldComponents,
49
+ registerRowIcons,
50
+ registerRowTransforms
51
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * What a host adds to the configured rows: the icons its configs name and its own field
3
+ * components. Kept apart from the row code on purpose: registering costs nothing, and the row
4
+ * (loaded on first sight of a call) reads these when it draws.
5
+ */
6
+ import type { ComponentType } from "react";
7
+ import type { FieldComponentName, IconName } from "./types.js";
8
+ export type RowIcon = ComponentType<{
9
+ className?: string;
10
+ }>;
11
+ export interface RowFieldProps {
12
+ value: unknown;
13
+ className?: string;
14
+ }
15
+ /**
16
+ * The icons a config can name. Deliberately NOT `import * as lucide`: that pulls the whole icon
17
+ * set (~200 kB gzip) into whichever chunk draws a row. A host registers the icons its configs
18
+ * name (`registerRowIcons({ Camera, HandGrab })`) and so pays only for those.
19
+ */
20
+ export declare const ICONS: Record<IconName, RowIcon>;
21
+ export declare function registerRowIcons(icons: Record<IconName, RowIcon>): void;
22
+ export declare const FIELD_OVERRIDES: Partial<Record<FieldComponentName, ComponentType<RowFieldProps>>>;
23
+ /**
24
+ * Replace field components with the host's own (the host's markdown renderer, say). Call once at
25
+ * module load, before a row renders; an override must accept `{ value, className }`.
26
+ */
27
+ export declare function registerRowFieldComponents(overrides: Partial<Record<FieldComponentName, ComponentType<RowFieldProps>>>): void;
@@ -0,0 +1,14 @@
1
+ const ICONS = {};
2
+ function registerRowIcons(icons) {
3
+ Object.assign(ICONS, icons);
4
+ }
5
+ const FIELD_OVERRIDES = {};
6
+ function registerRowFieldComponents(overrides) {
7
+ Object.assign(FIELD_OVERRIDES, overrides);
8
+ }
9
+ export {
10
+ FIELD_OVERRIDES,
11
+ ICONS,
12
+ registerRowFieldComponents,
13
+ registerRowIcons
14
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Fold the package's `ToolLifecycleEntry` into the flat shape a configured row reads
3
+ * (`args.x` / `output.y` / `message` paths). Progress comes from the call's `tool_progress`
4
+ * events: the event message is the line, `data.step` / `data.status` / `data.percent` ride along.
5
+ */
6
+ import type { ToolLifecycleEntry } from "../../agents/types/request.types.js";
7
+ import type { ToolRowEntry } from "./types.js";
8
+ export declare function toRowEntry(entry: ToolLifecycleEntry, stripPrefix?: RegExp): ToolRowEntry;
@@ -0,0 +1,38 @@
1
+ const PROGRESS_STATUSES = /* @__PURE__ */ new Set(["pending", "active", "done", "error"]);
2
+ function progressOf(entry) {
3
+ const rows = [];
4
+ for (const ev of entry.events ?? []) {
5
+ if (ev.event !== "tool_progress") continue;
6
+ const data = ev.data ?? {};
7
+ const status = typeof data.status === "string" && PROGRESS_STATUSES.has(data.status) ? data.status : void 0;
8
+ rows.push({
9
+ at: typeof ev.timestamp === "number" ? ev.timestamp * 1e3 : Date.now(),
10
+ label: ev.message ?? void 0,
11
+ step: typeof data.step === "string" ? data.step : void 0,
12
+ status,
13
+ percent: typeof data.percent === "number" ? data.percent : void 0,
14
+ data: data.metadata ?? data.data
15
+ });
16
+ }
17
+ return rows.length > 0 ? rows : void 0;
18
+ }
19
+ function toRowEntry(entry, stripPrefix) {
20
+ const phase = entry.status === "completed" ? "completed" : entry.status === "error" ? "error" : "started";
21
+ const ended = entry.completedAt ? Date.parse(entry.completedAt) : void 0;
22
+ const message = entry.errorMessage ?? entry.latestMessage ?? void 0;
23
+ const progress = progressOf(entry);
24
+ return {
25
+ callId: entry.callId,
26
+ toolName: stripPrefix ? entry.toolName.replace(stripPrefix, "") : entry.toolName,
27
+ startedAt: Date.parse(entry.startedAt),
28
+ phase,
29
+ args: entry.arguments,
30
+ output: entry.result ?? void 0,
31
+ ...ended !== void 0 && { endedAt: ended },
32
+ ...message !== void 0 && { message },
33
+ ...progress !== void 0 && { progress }
34
+ };
35
+ }
36
+ export {
37
+ toRowEntry
38
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Named value transformers for configured tool rows: used by `inline.info` (header text) and
3
+ * `results.keysInfo` (expanded body fields). The generic ones ship here; a host adds its own
4
+ * (its tools' action verbs, its icon maps) with `registerRowTransforms`, then names them from its
5
+ * row configs.
6
+ *
7
+ * Contract: `(unknown) => unknown`. A transform is a no-op for input it cannot handle (titleCase
8
+ * only acts on strings): it never throws.
9
+ */
10
+ import type { TransformName } from "./types.js";
11
+ export type RowTransform = (value: unknown) => unknown;
12
+ export declare const transforms: Record<TransformName, RowTransform>;
13
+ /** Add (or replace) named transforms; call once at module load, before a row renders. */
14
+ export declare function registerRowTransforms(extra: Record<TransformName, RowTransform>): void;
@@ -0,0 +1,30 @@
1
+ const titleCaseFn = (v) => {
2
+ if (typeof v !== "string") return v;
3
+ return v.split(/[_\-\s]+/).filter(Boolean).map((p) => p[0] ? p[0].toUpperCase() + p.slice(1) : p).join(" ");
4
+ };
5
+ const transforms = {
6
+ titleCase: titleCaseFn,
7
+ snakeToTitle: titleCaseFn,
8
+ kebabToTitle: titleCaseFn,
9
+ textClean: (v) => typeof v === "string" ? v.replace(/\\([_*`])/g, "$1").trim() : v,
10
+ truncate80: (v) => typeof v === "string" && v.length > 80 ? `${v.slice(0, 80)}\u2026` : v,
11
+ truncate200: (v) => typeof v === "string" && v.length > 200 ? `${v.slice(0, 200)}\u2026` : v,
12
+ lowercase: (v) => typeof v === "string" ? v.toLowerCase() : v,
13
+ uppercase: (v) => typeof v === "string" ? v.toUpperCase() : v,
14
+ /** Object with width/height → "WxH" string. Useful when info.path: 'output'. */
15
+ formatImageDimensions: (v) => {
16
+ if (v == null || typeof v !== "object") return v;
17
+ const obj = v;
18
+ const w = obj.width ?? obj.w;
19
+ const h = obj.height ?? obj.h;
20
+ if (typeof w !== "number" || typeof h !== "number") return void 0;
21
+ return `${w}\xD7${h}`;
22
+ }
23
+ };
24
+ function registerRowTransforms(extra) {
25
+ Object.assign(transforms, extra);
26
+ }
27
+ export {
28
+ registerRowTransforms,
29
+ transforms
30
+ };