@8wave/ai-elements 0.99.0-beta.1 → 0.99.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 (156) hide show
  1. package/{dist-vue/_chunks/PkStreamingMarkdown-DEhbK-3c.js → dist/_chunks/PkStreamingMarkdown-6Xx9n1ue.js} +379 -362
  2. package/dist/_chunks/PkStreamingMarkdown-6Xx9n1ue.js.map +1 -0
  3. package/dist/_chunks/{PkToolRequestGeolocation-BJ9NJZIg.js → PkToolRequestGeolocation-B73evGBg.js} +2 -2
  4. package/dist/_chunks/{PkToolRequestGeolocation-BJ9NJZIg.js.map → PkToolRequestGeolocation-B73evGBg.js.map} +1 -1
  5. package/dist/_chunks/{PkToolRequestOAuthConnection-DdvJ6n1K.js → PkToolRequestOAuthConnection-BWP5dsK_.js} +3 -3
  6. package/dist/_chunks/{PkToolRequestOAuthConnection-DdvJ6n1K.js.map → PkToolRequestOAuthConnection-BWP5dsK_.js.map} +1 -1
  7. package/dist/_chunks/{PkToolShowArtifact-BaGEr7O9.js → PkToolShowArtifact-bYYaMGxq.js} +7 -7
  8. package/dist/_chunks/{PkToolShowArtifact-BaGEr7O9.js.map → PkToolShowArtifact-bYYaMGxq.js.map} +1 -1
  9. package/dist/_chunks/{PkToolShowCalendarEvent-BYnhl2er.js → PkToolShowCalendarEvent-DdEWaTj-.js} +4 -4
  10. package/dist/_chunks/{PkToolShowCalendarEvent-BYnhl2er.js.map → PkToolShowCalendarEvent-DdEWaTj-.js.map} +1 -1
  11. package/dist/_chunks/{PkToolShowComparison-DahL5vHr.js → PkToolShowComparison-Dcar7HPW.js} +4 -4
  12. package/dist/_chunks/{PkToolShowComparison-DahL5vHr.js.map → PkToolShowComparison-Dcar7HPW.js.map} +1 -1
  13. package/dist/_chunks/{PkToolShowContactForm-upUNZtId.js → PkToolShowContactForm-DtjVW-n6.js} +13 -13
  14. package/dist/_chunks/{PkToolShowContactForm-upUNZtId.js.map → PkToolShowContactForm-DtjVW-n6.js.map} +1 -1
  15. package/dist/_chunks/{PkToolShowDiagram-Jq_4KWiK.js → PkToolShowDiagram-X35nsoIY.js} +8 -8
  16. package/dist/_chunks/{PkToolShowDiagram-Jq_4KWiK.js.map → PkToolShowDiagram-X35nsoIY.js.map} +1 -1
  17. package/dist/_chunks/{PkToolShowEmail-CtmpDS1B.js → PkToolShowEmail-jVoK8qEh.js} +4 -4
  18. package/dist/_chunks/{PkToolShowEmail-CtmpDS1B.js.map → PkToolShowEmail-jVoK8qEh.js.map} +1 -1
  19. package/dist/_chunks/{PkToolShowForm-dFuoqTPs.js → PkToolShowForm-BP8asXtz.js} +101 -79
  20. package/dist/_chunks/PkToolShowForm-BP8asXtz.js.map +1 -0
  21. package/dist/_chunks/{PkToolShowImageGallery-mLq2p3aH.js → PkToolShowImageGallery-WQL3T4Hr.js} +2 -2
  22. package/dist/_chunks/{PkToolShowImageGallery-mLq2p3aH.js.map → PkToolShowImageGallery-WQL3T4Hr.js.map} +1 -1
  23. package/dist/_chunks/{PkToolShowLocation-SbgTbuGu.js → PkToolShowLocation-w2t7lKpb.js} +4 -4
  24. package/dist/_chunks/{PkToolShowLocation-SbgTbuGu.js.map → PkToolShowLocation-w2t7lKpb.js.map} +1 -1
  25. package/dist/_chunks/{PkToolShowMessage-CAVpDTzd.js → PkToolShowMessage-BPo7WPim.js} +4 -4
  26. package/dist/_chunks/{PkToolShowMessage-CAVpDTzd.js.map → PkToolShowMessage-BPo7WPim.js.map} +1 -1
  27. package/dist/_chunks/{PkToolShowProductList-puiPFItN.js → PkToolShowProductList-BbY4ni7Y.js} +2 -2
  28. package/dist/_chunks/{PkToolShowProductList-puiPFItN.js.map → PkToolShowProductList-BbY4ni7Y.js.map} +1 -1
  29. package/dist/_chunks/{PkToolShowQrCode-CctXvRyG.js → PkToolShowQrCode-CN0ms27N.js} +4 -4
  30. package/dist/_chunks/{PkToolShowQrCode-CctXvRyG.js.map → PkToolShowQrCode-CN0ms27N.js.map} +1 -1
  31. package/dist/_chunks/{PkToolShowSources-DwB6VXrK.js → PkToolShowSources-D2tBcx7n.js} +18 -18
  32. package/dist/_chunks/{PkToolShowSources-DwB6VXrK.js.map → PkToolShowSources-D2tBcx7n.js.map} +1 -1
  33. package/dist/_chunks/{PkToolShowSuggestedReply-QEcIhSxa.js → PkToolShowSuggestedReply-Cdh_elSh.js} +2 -2
  34. package/dist/_chunks/{PkToolShowSuggestedReply-QEcIhSxa.js.map → PkToolShowSuggestedReply-Cdh_elSh.js.map} +1 -1
  35. package/dist/_chunks/{PkToolShowVideo-DoLoI8_N.js → PkToolShowVideo-D3aU5FMO.js} +2 -2
  36. package/dist/_chunks/{PkToolShowVideo-DoLoI8_N.js.map → PkToolShowVideo-D3aU5FMO.js.map} +1 -1
  37. package/dist/_chunks/{PkToolShowWeather-C2rPCQ_K.js → PkToolShowWeather-CzanXIJp.js} +3 -3
  38. package/dist/_chunks/{PkToolShowWeather-C2rPCQ_K.js.map → PkToolShowWeather-CzanXIJp.js.map} +1 -1
  39. package/dist/_chunks/{PkToolShowWebPages-BBJYzF8V.js → PkToolShowWebPages-DkMJrWmT.js} +2 -2
  40. package/dist/_chunks/{PkToolShowWebPages-BBJYzF8V.js.map → PkToolShowWebPages-DkMJrWmT.js.map} +1 -1
  41. package/dist/_chunks/{VvCheckbox.es-D5d8k9yP.js → VvCheckbox.es-CRhIKQNR.js} +2 -2
  42. package/dist/_chunks/{VvCheckbox.es-D5d8k9yP.js.map → VvCheckbox.es-CRhIKQNR.js.map} +1 -1
  43. package/dist/_chunks/{VvCheckboxGroup.es-DVnsOjX0.js → VvCheckboxGroup.es-gOy2kM1Y.js} +5 -5
  44. package/dist/_chunks/{VvCheckboxGroup.es-DVnsOjX0.js.map → VvCheckboxGroup.es-gOy2kM1Y.js.map} +1 -1
  45. package/dist/_chunks/{VvCombobox.es-CFA-K-cQ.js → VvCombobox.es-BOwH3LmO.js} +9 -9
  46. package/dist/_chunks/VvCombobox.es-BOwH3LmO.js.map +1 -0
  47. package/dist/_chunks/{VvInputText.es-csEQ-bSG.js → VvInputText.es-D8nXroKO.js} +536 -513
  48. package/dist/_chunks/VvInputText.es-D8nXroKO.js.map +1 -0
  49. package/dist/_chunks/{VvRadio.es-BpymhC73.js → VvRadio.es-Djy5J33A.js} +2 -2
  50. package/dist/_chunks/{VvRadio.es-BpymhC73.js.map → VvRadio.es-Djy5J33A.js.map} +1 -1
  51. package/dist/_chunks/{VvRadioGroup.es-CSNzOJKx.js → VvRadioGroup.es-DQq3JYCR.js} +5 -5
  52. package/dist/_chunks/VvRadioGroup.es-DQq3JYCR.js.map +1 -0
  53. package/dist/_chunks/{VvSelect.es-CjKMd0nH.js → VvSelect.es-CE4x1ww0.js} +4 -4
  54. package/dist/_chunks/{VvSelect.es-CjKMd0nH.js.map → VvSelect.es-CE4x1ww0.js.map} +1 -1
  55. package/dist/_chunks/VvTextarea.es-BU2vqdEQ.js +1129 -0
  56. package/dist/_chunks/VvTextarea.es-BU2vqdEQ.js.map +1 -0
  57. package/dist/_chunks/{dist-BNET2z7b.js → dist-CvMCBce7.js} +39 -21
  58. package/dist/_chunks/dist-CvMCBce7.js.map +1 -0
  59. package/dist/_chunks/dot-prop-CObyt75F.js +141 -0
  60. package/dist/_chunks/dot-prop-CObyt75F.js.map +1 -0
  61. package/dist/_chunks/{floating-ui.vue-CIKvCpTA.js → floating-ui.vue-BacoFpVq.js} +278 -305
  62. package/dist/_chunks/floating-ui.vue-BacoFpVq.js.map +1 -0
  63. package/dist/_chunks/{index.es-u1dF1xg2.js → index.es-DpqfagWZ.js} +12 -12
  64. package/dist/_chunks/{index.es-u1dF1xg2.js.map → index.es-DpqfagWZ.js.map} +1 -1
  65. package/dist/_chunks/{index.es-BYny0uhz.js → index.es-_oXVRjHy.js} +2352 -2329
  66. package/dist/_chunks/index.es-_oXVRjHy.js.map +1 -0
  67. package/dist/ai-elements.es.js +4087 -5205
  68. package/dist/ai-elements.es.js.map +1 -1
  69. package/dist-vue/PkChatbot.js +1 -1
  70. package/dist-vue/PkChatbotAuth.js +1 -1
  71. package/dist-vue/PkChatbotEmptyState.js +1 -1
  72. package/dist-vue/PkChatbotFeedbackForm.js +1 -1
  73. package/dist-vue/PkChatbotInput.js +1 -1
  74. package/dist-vue/PkChatbotMessages.js +1 -1
  75. package/dist-vue/PkChatbotSteps.js +1 -1
  76. package/dist-vue/PkChatbotViewChat.js +1 -1
  77. package/dist-vue/PkChatbotViewConversations.js +1 -1
  78. package/dist-vue/PkChatbotViewFiles.js +1 -1
  79. package/dist-vue/PkChatbotViewProfile.js +1 -1
  80. package/dist-vue/_chunks/PkChatbot-Bf5uY3cO.js +236 -0
  81. package/dist-vue/_chunks/{PkChatbot-BlG1WlAO.js.map → PkChatbot-Bf5uY3cO.js.map} +1 -1
  82. package/dist-vue/_chunks/{PkChatbotAuth-C_L2xWuD.js → PkChatbotAuth-BGn2MDYD.js} +2 -2
  83. package/dist-vue/_chunks/{PkChatbotAuth-C_L2xWuD.js.map → PkChatbotAuth-BGn2MDYD.js.map} +1 -1
  84. package/dist-vue/_chunks/{PkChatbotEmptyState-BGOC6vxr.js → PkChatbotEmptyState-CPqLqXek.js} +2 -2
  85. package/dist-vue/_chunks/{PkChatbotEmptyState-BGOC6vxr.js.map → PkChatbotEmptyState-CPqLqXek.js.map} +1 -1
  86. package/dist-vue/_chunks/{PkChatbotFeedbackForm-BSe40qlc.js → PkChatbotFeedbackForm-C_y__RH8.js} +2 -2
  87. package/dist-vue/_chunks/{PkChatbotFeedbackForm-BSe40qlc.js.map → PkChatbotFeedbackForm-C_y__RH8.js.map} +1 -1
  88. package/dist-vue/_chunks/{PkChatbotInput-DTazYlPd.js → PkChatbotInput-jvb0vuak.js} +2 -2
  89. package/dist-vue/_chunks/{PkChatbotInput-DTazYlPd.js.map → PkChatbotInput-jvb0vuak.js.map} +1 -1
  90. package/dist-vue/_chunks/{PkChatbotMessages-BrufA7o1.js → PkChatbotMessages-B3G12zah.js} +246 -246
  91. package/dist-vue/_chunks/{PkChatbotMessages-BrufA7o1.js.map → PkChatbotMessages-B3G12zah.js.map} +1 -1
  92. package/dist-vue/_chunks/PkChatbotSteps-BdU6YC_N.js +172 -0
  93. package/dist-vue/_chunks/{PkChatbotSteps-Dv9NkYER.js.map → PkChatbotSteps-BdU6YC_N.js.map} +1 -1
  94. package/dist-vue/_chunks/{PkChatbotViewChat-CAqvbbfN.js → PkChatbotViewChat-c0Ecpzoc.js} +6 -6
  95. package/dist-vue/_chunks/{PkChatbotViewChat-CAqvbbfN.js.map → PkChatbotViewChat-c0Ecpzoc.js.map} +1 -1
  96. package/dist-vue/_chunks/{PkChatbotViewConversations-Cq41H-tc.js → PkChatbotViewConversations-BfhRCA_1.js} +2 -2
  97. package/dist-vue/_chunks/{PkChatbotViewConversations-Cq41H-tc.js.map → PkChatbotViewConversations-BfhRCA_1.js.map} +1 -1
  98. package/dist-vue/_chunks/{PkChatbotViewFiles-DNuzmBJc.js → PkChatbotViewFiles-BipRoidH.js} +2 -2
  99. package/dist-vue/_chunks/{PkChatbotViewFiles-DNuzmBJc.js.map → PkChatbotViewFiles-BipRoidH.js.map} +1 -1
  100. package/dist-vue/_chunks/{PkChatbotViewProfile-C0BXIY2N.js → PkChatbotViewProfile-DuLwYpGZ.js} +2 -2
  101. package/dist-vue/_chunks/{PkChatbotViewProfile-C0BXIY2N.js.map → PkChatbotViewProfile-DuLwYpGZ.js.map} +1 -1
  102. package/{dist/_chunks/PkStreamingMarkdown-Djw604Ny.js → dist-vue/_chunks/PkStreamingMarkdown-CjBMQ18U.js} +344 -347
  103. package/dist-vue/_chunks/PkStreamingMarkdown-CjBMQ18U.js.map +1 -0
  104. package/dist-vue/_chunks/{PkToolShowArtifact-CTBwt4DN.js → PkToolShowArtifact-COwSXmF4.js} +2 -2
  105. package/dist-vue/_chunks/{PkToolShowArtifact-CTBwt4DN.js.map → PkToolShowArtifact-COwSXmF4.js.map} +1 -1
  106. package/dist-vue/_chunks/{PkToolShowContactForm-B6-MsExL.js → PkToolShowContactForm-DRRtCCxB.js} +10 -10
  107. package/dist-vue/_chunks/{PkToolShowContactForm-B6-MsExL.js.map → PkToolShowContactForm-DRRtCCxB.js.map} +1 -1
  108. package/dist-vue/_chunks/{PkToolShowForm-CQuX08lk.js → PkToolShowForm-j7Ha-0X3.js} +109 -87
  109. package/dist-vue/_chunks/PkToolShowForm-j7Ha-0X3.js.map +1 -0
  110. package/dist-vue/_chunks/{PkToolShowSources-CFh-i60o.js → PkToolShowSources-BVLw4W5l.js} +43 -43
  111. package/dist-vue/_chunks/{PkToolShowSources-CFh-i60o.js.map → PkToolShowSources-BVLw4W5l.js.map} +1 -1
  112. package/dist-vue/_chunks/{createChatbotApiClient-BMZltBLh.js → createChatbotApiClient-IH6wBh4s.js} +365 -381
  113. package/dist-vue/_chunks/createChatbotApiClient-IH6wBh4s.js.map +1 -0
  114. package/dist-vue/_chunks/{index.es-XfWQ82pb.js → index.es-Bk1O0p8N.js} +166 -156
  115. package/dist-vue/_chunks/index.es-Bk1O0p8N.js.map +1 -0
  116. package/dist-vue/_chunks/{useChatbotStore-DZiorgLW.js → useChatbotStore-C3uKi2FS.js} +3 -5
  117. package/dist-vue/_chunks/useChatbotStore-C3uKi2FS.js.map +1 -0
  118. package/dist-vue/api.js +1 -1
  119. package/dist-vue/composables.js +2 -2
  120. package/dist-vue/index.js +4430 -4221
  121. package/dist-vue/index.js.map +1 -1
  122. package/dist-vue/locales.js +27 -7
  123. package/dist-vue/packages/components/src/PkCheckboxField.d.ts +1 -1
  124. package/dist-vue/packages/components/src/PkOfflineScreen.d.ts +18 -0
  125. package/dist-vue/packages/components/src/PkPwaNotices.d.ts +19 -0
  126. package/dist-vue/packages/components/src/chat/PkAgentSettingsPanel.d.ts +9 -3
  127. package/dist-vue/packages/components/src/index.d.ts +3 -3
  128. package/dist-vue/packages/composable/src/chatbot/useChatbotStore.d.ts +36 -0
  129. package/dist-vue/packages/composable/src/index.d.ts +1 -0
  130. package/dist-vue/packages/composable/src/useConnectivity.d.ts +28 -0
  131. package/dist-vue/packages/models/src/schema/Agent.d.ts +81 -0
  132. package/dist-vue/packages/models/src/schema/ReasoningChat.d.ts +24 -0
  133. package/dist-vue/packages/models/src/schema/SubAgent.d.ts +24 -0
  134. package/dist-vue/style.css +1 -1
  135. package/package.json +3 -3
  136. package/dist/_chunks/PkStreamingMarkdown-Djw604Ny.js.map +0 -1
  137. package/dist/_chunks/PkToolShowForm-dFuoqTPs.js.map +0 -1
  138. package/dist/_chunks/VvCombobox.es-CFA-K-cQ.js.map +0 -1
  139. package/dist/_chunks/VvInputText.es-csEQ-bSG.js.map +0 -1
  140. package/dist/_chunks/VvRadioGroup.es-CSNzOJKx.js.map +0 -1
  141. package/dist/_chunks/VvTextarea.es-eEyRRpuT.js +0 -1109
  142. package/dist/_chunks/VvTextarea.es-eEyRRpuT.js.map +0 -1
  143. package/dist/_chunks/dist-BNET2z7b.js.map +0 -1
  144. package/dist/_chunks/dot-prop-BXrC9bAX.js +0 -131
  145. package/dist/_chunks/dot-prop-BXrC9bAX.js.map +0 -1
  146. package/dist/_chunks/floating-ui.vue-CIKvCpTA.js.map +0 -1
  147. package/dist/_chunks/index.es-BYny0uhz.js.map +0 -1
  148. package/dist-vue/_chunks/PkChatbot-BlG1WlAO.js +0 -236
  149. package/dist-vue/_chunks/PkChatbotSteps-Dv9NkYER.js +0 -172
  150. package/dist-vue/_chunks/PkStreamingMarkdown-DEhbK-3c.js.map +0 -1
  151. package/dist-vue/_chunks/PkToolShowForm-CQuX08lk.js.map +0 -1
  152. package/dist-vue/_chunks/createChatbotApiClient-BMZltBLh.js.map +0 -1
  153. package/dist-vue/_chunks/index.es-XfWQ82pb.js.map +0 -1
  154. package/dist-vue/_chunks/useChatbotStore-DZiorgLW.js.map +0 -1
  155. package/dist-vue/packages/components/src/PkPwaInstallPrompt.d.ts +0 -4
  156. package/dist-vue/packages/components/src/PkPwaOfflineNotice.d.ts +0 -4
@@ -1,6 +1,6 @@
1
1
  import { A as e, C as t, D as n, S as r, T as i, Ut as a, _ as o, at as s, b as c, et as l, g as u, kt as d, qt as f, xt as p, z as m } from "./vue.runtime.esm-bundler-DbhD_IvR.js";
2
- import { i as h } from "./dist-BNET2z7b.js";
3
- import { d as g, l as _, n as v, p as y, u as b } from "./index.es-BYny0uhz.js";
2
+ import { i as h } from "./dist-CvMCBce7.js";
3
+ import { d as g, f as _, i as v, l as y, t as b } from "./index.es-_oXVRjHy.js";
4
4
  import { n as x } from "./useShortUrlResolver-B3FkPQpo.js";
5
5
  e(), d(), s();
6
6
  var S = { class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-surface" }, C = { class: "px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8" }, w = { class: "font-bold" }, T = { class: "p-sm" }, E = { class: "text-12 text-word-4 mb-4" }, D = { class: "text-word-2 whitespace-pre-wrap break-words" }, O = /* @__PURE__ */ i({
@@ -21,7 +21,7 @@ var S = { class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-s
21
21
  window.open(e);
22
22
  };
23
23
  return (e, i) => {
24
- let u = _, h = y, x = b, O = g, k = v;
24
+ let u = _, h = g, x = b, O = y, k = v;
25
25
  return m(), c("div", S, [o("div", C, [
26
26
  t(u, {
27
27
  name: "ri:chat-1-line",
@@ -74,4 +74,4 @@ var S = { class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-s
74
74
  //#endregion
75
75
  export { O as default };
76
76
 
77
- //# sourceMappingURL=PkToolShowMessage-CAVpDTzd.js.map
77
+ //# sourceMappingURL=PkToolShowMessage-BPo7WPim.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowMessage-CAVpDTzd.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkToolShowMessage.vue","../../../../packages/components/src/chat/PkToolShowMessage.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useShortUrlResolver } from 'composables'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n body: string\n }\n }\n return part\n })\n\n // Messages leave the app (WhatsApp/Telegram/SMS/clipboard), so expand short\n // urls to their real target rather than keeping the fragile `/api/r/` link.\n const { resolveText } = useShortUrlResolver()\n const body = resolveText(() => toolPart.value.input?.body)\n\n const openInWhatsApp = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://wa.me/?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInTelegram = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://t.me/share/url?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInSms = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `sms:?body=${encodeURIComponent(body.value)}`\n window.open(url)\n }\n</script>\n\n<template>\n <div\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:chat-1-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.message') }}\n </strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(body)\" />\n <VvDropdown\n v-bind=\"{\n placement: 'bottom-end',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n strategy: 'fixed',\n }\">\n <VvButton\n icon=\"ri:send-plane-line\"\n modifiers=\"action-quiet-small\"\n :label=\"$t('action.send')\" />\n <template #items>\n <VvDropdownAction @click=\"openInWhatsApp\">\n <VvIcon name=\"ri:whatsapp-line\" />\n {{ $t('action.openInWhatsApp') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInTelegram\">\n <VvIcon name=\"ri:telegram-line\" />\n {{ $t('action.openInTelegram') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInSms\">\n <VvIcon name=\"ri:message-2-line\" />\n {{ $t('action.openInSms') }}\n </VvDropdownAction>\n </template>\n </VvDropdown>\n </VvButtonGroup>\n </div>\n <div class=\"p-sm\">\n <div class=\"text-12 text-word-4 mb-4\">\n {{ $t('label.body') }}\n </div>\n <pre class=\"text-word-2 whitespace-pre-wrap break-words\">{{\n body\n }}</pre>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useShortUrlResolver } from 'composables'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n body: string\n }\n }\n return part\n })\n\n // Messages leave the app (WhatsApp/Telegram/SMS/clipboard), so expand short\n // urls to their real target rather than keeping the fragile `/api/r/` link.\n const { resolveText } = useShortUrlResolver()\n const body = resolveText(() => toolPart.value.input?.body)\n\n const openInWhatsApp = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://wa.me/?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInTelegram = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://t.me/share/url?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInSms = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `sms:?body=${encodeURIComponent(body.value)}`\n window.open(url)\n }\n</script>\n\n<template>\n <div\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:chat-1-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.message') }}\n </strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(body)\" />\n <VvDropdown\n v-bind=\"{\n placement: 'bottom-end',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n strategy: 'fixed',\n }\">\n <VvButton\n icon=\"ri:send-plane-line\"\n modifiers=\"action-quiet-small\"\n :label=\"$t('action.send')\" />\n <template #items>\n <VvDropdownAction @click=\"openInWhatsApp\">\n <VvIcon name=\"ri:whatsapp-line\" />\n {{ $t('action.openInWhatsApp') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInTelegram\">\n <VvIcon name=\"ri:telegram-line\" />\n {{ $t('action.openInTelegram') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInSms\">\n <VvIcon name=\"ri:message-2-line\" />\n {{ $t('action.openInSms') }}\n </VvDropdownAction>\n </template>\n </VvDropdown>\n </VvButtonGroup>\n </div>\n <div class=\"p-sm\">\n <div class=\"text-12 text-word-4 mb-4\">\n {{ $t('label.body') }}\n </div>\n <pre class=\"text-word-2 whitespace-pre-wrap break-words\">{{\n body\n }}</pre>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;EAKI,IAAM,IAAQ,GAIR,EAAE,SAAM,cAAW,EAAa,GAEhC,IAAW,QACA,EAAM,IAMtB,GAIK,EAAE,mBAAgB,EAAoB,GACtC,IAAO,QAAkB,EAAS,MAAM,OAAO,IAAI,GAEnD,UAAuB;GACzB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,uBAAuB,mBAAmB,EAAK,KAAK;GAChE,OAAO,KAAK,GAAK,QAAQ;EAC7B,GAEM,UAAuB;GACzB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,+BAA+B,mBAAmB,EAAK,KAAK;GACxE,OAAO,KAAK,GAAK,QAAQ;EAC7B,GAEM,UAAkB;GACpB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,aAAa,mBAAmB,EAAK,KAAK;GACtD,OAAO,KAAK,CAAG;EACnB;;;eAIA,EAmDM,OAnDN,GAmDM,CAjDF,EAwCM,OAxCN,GAwCM;IAtCF,EAAgD,GAAA;KAAxC,MAAK;KAAiB,OAAM;;IACpC,EAES,UAFT,GAES,EADFA,EAAAA,GAAE,eAAA,CAAA,GAAA,CAAA;IAET,EAiCgB,GAAA;KAjCD,WAAU;KAAU,OAAM;;sBAKX,CAJ1B,EAI0B,GAAA;MAHtB,WAAU;MACT,MAAM,EAAA,CAAA,IAAM,kBAAA;MACZ,OAAO,EAAA,CAAA,IAASA,EAAAA,GAAE,eAAA,IAAoBA,EAAAA,GAAE,aAAA;MACxC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAI,CAAC,EAAA,CAAA,CAAI;qCACrB,EA0Ba,GAAA,EAAA,EAzBD;;;;;;MAMP,CAAA,GAAA;MAKU,OAAK,QAIO;OAHnB,EAGmB,GAAA,EAHA,SAAO,EAAc,GAAA;yBACF,CAAlC,EAAkC,GAAA,EAA1B,MAAK,mBAAkB,CAAA,GAAA,EAAG,MAClC,EAAGA,EAAAA,GAAE,uBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EAGmB,GAAA,EAHA,SAAO,EAAc,GAAA;yBACF,CAAlC,EAAkC,GAAA,EAA1B,MAAK,mBAAkB,CAAA,GAAA,EAAG,MAClC,EAAGA,EAAAA,GAAE,uBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EAGmB,GAAA,EAHA,SAAO,EAAS,GAAA;yBACI,CAAnC,EAAmC,GAAA,EAA3B,MAAK,oBAAmB,CAAA,GAAA,EAAG,MACnC,EAAGA,EAAAA,GAAE,kBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;;uBAZoB,CAHjC,EAGiC,GAAA;OAF7B,MAAK;OACL,WAAU;OACT,OAAOA,EAAAA,GAAE,aAAA;;;;;;OAkB1B,EAOM,OAPN,GAOM,CANF,EAEM,OAFN,GAEM,EADCA,EAAAA,GAAE,YAAA,CAAA,GAAA,CAAA,GAET,EAEQ,OAFR,GAEQ,EADJ,EAAA,CAAA,CAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"PkToolShowMessage-BPo7WPim.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkToolShowMessage.vue","../../../../packages/components/src/chat/PkToolShowMessage.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useShortUrlResolver } from 'composables'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n body: string\n }\n }\n return part\n })\n\n // Messages leave the app (WhatsApp/Telegram/SMS/clipboard), so expand short\n // urls to their real target rather than keeping the fragile `/api/r/` link.\n const { resolveText } = useShortUrlResolver()\n const body = resolveText(() => toolPart.value.input?.body)\n\n const openInWhatsApp = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://wa.me/?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInTelegram = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://t.me/share/url?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInSms = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `sms:?body=${encodeURIComponent(body.value)}`\n window.open(url)\n }\n</script>\n\n<template>\n <div\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:chat-1-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.message') }}\n </strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(body)\" />\n <VvDropdown\n v-bind=\"{\n placement: 'bottom-end',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n strategy: 'fixed',\n }\">\n <VvButton\n icon=\"ri:send-plane-line\"\n modifiers=\"action-quiet-small\"\n :label=\"$t('action.send')\" />\n <template #items>\n <VvDropdownAction @click=\"openInWhatsApp\">\n <VvIcon name=\"ri:whatsapp-line\" />\n {{ $t('action.openInWhatsApp') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInTelegram\">\n <VvIcon name=\"ri:telegram-line\" />\n {{ $t('action.openInTelegram') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInSms\">\n <VvIcon name=\"ri:message-2-line\" />\n {{ $t('action.openInSms') }}\n </VvDropdownAction>\n </template>\n </VvDropdown>\n </VvButtonGroup>\n </div>\n <div class=\"p-sm\">\n <div class=\"text-12 text-word-4 mb-4\">\n {{ $t('label.body') }}\n </div>\n <pre class=\"text-word-2 whitespace-pre-wrap break-words\">{{\n body\n }}</pre>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useShortUrlResolver } from 'composables'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n body: string\n }\n }\n return part\n })\n\n // Messages leave the app (WhatsApp/Telegram/SMS/clipboard), so expand short\n // urls to their real target rather than keeping the fragile `/api/r/` link.\n const { resolveText } = useShortUrlResolver()\n const body = resolveText(() => toolPart.value.input?.body)\n\n const openInWhatsApp = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://wa.me/?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInTelegram = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `https://t.me/share/url?text=${encodeURIComponent(body.value)}`\n window.open(url, '_blank')\n }\n\n const openInSms = () => {\n if (!toolPart.value.input) {\n return\n }\n const url = `sms:?body=${encodeURIComponent(body.value)}`\n window.open(url)\n }\n</script>\n\n<template>\n <div\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:chat-1-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.message') }}\n </strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(body)\" />\n <VvDropdown\n v-bind=\"{\n placement: 'bottom-end',\n modifiers: 'menu',\n flip: true,\n offset: 3,\n strategy: 'fixed',\n }\">\n <VvButton\n icon=\"ri:send-plane-line\"\n modifiers=\"action-quiet-small\"\n :label=\"$t('action.send')\" />\n <template #items>\n <VvDropdownAction @click=\"openInWhatsApp\">\n <VvIcon name=\"ri:whatsapp-line\" />\n {{ $t('action.openInWhatsApp') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInTelegram\">\n <VvIcon name=\"ri:telegram-line\" />\n {{ $t('action.openInTelegram') }}\n </VvDropdownAction>\n <VvDropdownAction @click=\"openInSms\">\n <VvIcon name=\"ri:message-2-line\" />\n {{ $t('action.openInSms') }}\n </VvDropdownAction>\n </template>\n </VvDropdown>\n </VvButtonGroup>\n </div>\n <div class=\"p-sm\">\n <div class=\"text-12 text-word-4 mb-4\">\n {{ $t('label.body') }}\n </div>\n <pre class=\"text-word-2 whitespace-pre-wrap break-words\">{{\n body\n }}</pre>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;EAKI,IAAM,IAAQ,GAIR,EAAE,SAAM,cAAW,EAAa,GAEhC,IAAW,QACA,EAAM,IAMtB,GAIK,EAAE,mBAAgB,EAAoB,GACtC,IAAO,QAAkB,EAAS,MAAM,OAAO,IAAI,GAEnD,UAAuB;GACzB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,uBAAuB,mBAAmB,EAAK,KAAK;GAChE,OAAO,KAAK,GAAK,QAAQ;EAC7B,GAEM,UAAuB;GACzB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,+BAA+B,mBAAmB,EAAK,KAAK;GACxE,OAAO,KAAK,GAAK,QAAQ;EAC7B,GAEM,UAAkB;GACpB,IAAI,CAAC,EAAS,MAAM,OAChB;GAEJ,IAAM,IAAM,aAAa,mBAAmB,EAAK,KAAK;GACtD,OAAO,KAAK,CAAG;EACnB;;;eAIA,EAmDM,OAnDN,GAmDM,CAjDF,EAwCM,OAxCN,GAwCM;IAtCF,EAAgD,GAAA;KAAxC,MAAK;KAAiB,OAAM;;IACpC,EAES,UAFT,GAES,EADFA,EAAAA,GAAE,eAAA,CAAA,GAAA,CAAA;IAET,EAiCgB,GAAA;KAjCD,WAAU;KAAU,OAAM;;sBAKX,CAJ1B,EAI0B,GAAA;MAHtB,WAAU;MACT,MAAM,EAAA,CAAA,IAAM,kBAAA;MACZ,OAAO,EAAA,CAAA,IAASA,EAAAA,GAAE,eAAA,IAAoBA,EAAAA,GAAE,aAAA;MACxC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAI,CAAC,EAAA,CAAA,CAAI;qCACrB,EA0Ba,GAAA,EAAA,EAzBD;;;;;;MAMP,CAAA,GAAA;MAKU,OAAK,QAIO;OAHnB,EAGmB,GAAA,EAHA,SAAO,EAAc,GAAA;yBACF,CAAlC,EAAkC,GAAA,EAA1B,MAAK,mBAAkB,CAAA,GAAA,EAAG,MAClC,EAAGA,EAAAA,GAAE,uBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EAGmB,GAAA,EAHA,SAAO,EAAc,GAAA;yBACF,CAAlC,EAAkC,GAAA,EAA1B,MAAK,mBAAkB,CAAA,GAAA,EAAG,MAClC,EAAGA,EAAAA,GAAE,uBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;OAET,EAGmB,GAAA,EAHA,SAAO,EAAS,GAAA;yBACI,CAAnC,EAAmC,GAAA,EAA3B,MAAK,oBAAmB,CAAA,GAAA,EAAG,MACnC,EAAGA,EAAAA,GAAE,kBAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;;;uBAZoB,CAHjC,EAGiC,GAAA;OAF7B,MAAK;OACL,WAAU;OACT,OAAOA,EAAAA,GAAE,aAAA;;;;;;OAkB1B,EAOM,OAPN,GAOM,CANF,EAEM,OAFN,GAEM,EADCA,EAAAA,GAAE,YAAA,CAAA,GAAA,CAAA,GAET,EAEQ,OAFR,GAEQ,EADJ,EAAA,CAAA,CAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { A as e, C as t, Ht as n, T as r, V as i, W as a, _ as o, b as s, et as c, g as l, kt as u, p as d, qt as f, v as p, y as m, z as h } from "./vue.runtime.esm-bundler-DbhD_IvR.js";
2
- import { l as g } from "./index.es-BYny0uhz.js";
2
+ import { f as g } from "./index.es-_oXVRjHy.js";
3
3
  import { t as _ } from "./PkUrl-liCemvcx.js";
4
4
  e(), u();
5
5
  var v = {
@@ -63,4 +63,4 @@ var v = {
63
63
  //#endregion
64
64
  export { E as default };
65
65
 
66
- //# sourceMappingURL=PkToolShowProductList-puiPFItN.js.map
66
+ //# sourceMappingURL=PkToolShowProductList-BbY4ni7Y.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowProductList-puiPFItN.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowProductList.vue","../../../../packages/components/src/chat/PkToolShowProductList.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import PkUrl from '../PkUrl.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n products: Array<{\n name: string\n url?: string\n image?: string\n price?: string\n availability?: string\n description?: string\n }>\n }\n }\n return part\n })\n\n const getAvailabilityColor = (availability?: string) => {\n if (!availability) {\n return ''\n }\n const lower = availability.toLowerCase()\n if (\n lower.includes('in stock') ||\n lower.includes('available') ||\n lower.includes('disponibile')\n ) {\n return 'text-success'\n }\n if (\n lower.includes('out of stock') ||\n lower.includes('unavailable') ||\n lower.includes('non disponibile')\n ) {\n return 'text-danger'\n }\n if (\n lower.includes('limited') ||\n lower.includes('low stock') ||\n lower.includes('limitato')\n ) {\n return 'text-warning'\n }\n return 'text-word-3'\n }\n</script>\n\n<template>\n <ul\n v-if=\"toolPart?.input?.products?.length\"\n class=\"flex flex-col gap-xs w-full\">\n <li\n v-for=\"(product, index) in toolPart.input.products\"\n :key=\"index\"\n class=\"border border-surface-3 rounded-xl overflow-hidden hover:border-surface-4 transition-colors\">\n <component\n :is=\"product.url ? 'a' : 'div'\"\n :href=\"product.url\"\n :target=\"product.url ? '_blank' : undefined\"\n :rel=\"product.url ? 'noopener noreferrer' : undefined\"\n class=\"flex gap-8 p-8 hover:bg-surface-1 transition-colors\">\n <img\n v-if=\"product.image\"\n :src=\"product.image\"\n :alt=\"product.name\"\n class=\"w-48 h-48 object-contain rounded shrink-0 border border-surface-3 bg-surface\" />\n <div class=\"flex flex-col gap-4 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate\">\n {{ product.name }}\n </strong>\n <span\n v-if=\"product.url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-12\" />\n <PkUrl :url=\"product.url\" />\n </span>\n <div class=\"flex items-center gap-sm flex-wrap text-12\">\n <span\n v-if=\"product.price\"\n class=\"font-semibold text-word-1\">\n {{ product.price }}\n </span>\n <span\n v-if=\"product.availability\"\n class=\"text-10 font-medium\"\n :class=\"getAvailabilityColor(product.availability)\">\n {{ product.availability }}\n </span>\n </div>\n <p\n v-if=\"product.description\"\n class=\"text-12 text-word-3 line-clamp-2\">\n {{ product.description }}\n </p>\n </div>\n </component>\n </li>\n </ul>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import PkUrl from '../PkUrl.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n products: Array<{\n name: string\n url?: string\n image?: string\n price?: string\n availability?: string\n description?: string\n }>\n }\n }\n return part\n })\n\n const getAvailabilityColor = (availability?: string) => {\n if (!availability) {\n return ''\n }\n const lower = availability.toLowerCase()\n if (\n lower.includes('in stock') ||\n lower.includes('available') ||\n lower.includes('disponibile')\n ) {\n return 'text-success'\n }\n if (\n lower.includes('out of stock') ||\n lower.includes('unavailable') ||\n lower.includes('non disponibile')\n ) {\n return 'text-danger'\n }\n if (\n lower.includes('limited') ||\n lower.includes('low stock') ||\n lower.includes('limitato')\n ) {\n return 'text-warning'\n }\n return 'text-word-3'\n }\n</script>\n\n<template>\n <ul\n v-if=\"toolPart?.input?.products?.length\"\n class=\"flex flex-col gap-xs w-full\">\n <li\n v-for=\"(product, index) in toolPart.input.products\"\n :key=\"index\"\n class=\"border border-surface-3 rounded-xl overflow-hidden hover:border-surface-4 transition-colors\">\n <component\n :is=\"product.url ? 'a' : 'div'\"\n :href=\"product.url\"\n :target=\"product.url ? '_blank' : undefined\"\n :rel=\"product.url ? 'noopener noreferrer' : undefined\"\n class=\"flex gap-8 p-8 hover:bg-surface-1 transition-colors\">\n <img\n v-if=\"product.image\"\n :src=\"product.image\"\n :alt=\"product.name\"\n class=\"w-48 h-48 object-contain rounded shrink-0 border border-surface-3 bg-surface\" />\n <div class=\"flex flex-col gap-4 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate\">\n {{ product.name }}\n </strong>\n <span\n v-if=\"product.url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-12\" />\n <PkUrl :url=\"product.url\" />\n </span>\n <div class=\"flex items-center gap-sm flex-wrap text-12\">\n <span\n v-if=\"product.price\"\n class=\"font-semibold text-word-1\">\n {{ product.price }}\n </span>\n <span\n v-if=\"product.availability\"\n class=\"text-10 font-medium\"\n :class=\"getAvailabilityColor(product.availability)\">\n {{ product.availability }}\n </span>\n </div>\n <p\n v-if=\"product.description\"\n class=\"text-12 text-word-3 line-clamp-2\">\n {{ product.description }}\n </p>\n </div>\n </component>\n </li>\n </ul>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAII,IAAM,IAAQ,GAIR,IAAW,QACA,EAAM,IAatB,GAEK,KAAwB,MAA0B;GACpD,IAAI,CAAC,GACD,OAAO;GAEX,IAAM,IAAQ,EAAa,YAAY;GAsBvC,OApBI,EAAM,SAAS,UAAU,KACzB,EAAM,SAAS,WAAW,KAC1B,EAAM,SAAS,aAAa,IAErB,iBAGP,EAAM,SAAS,cAAc,KAC7B,EAAM,SAAS,aAAa,KAC5B,EAAM,SAAS,iBAAiB,IAEzB,gBAGP,EAAM,SAAS,SAAS,KACxB,EAAM,SAAS,WAAW,KAC1B,EAAM,SAAS,UAAU,IAElB,iBAEJ;EACX;;;UAKU,EAAA,OAAU,OAAO,UAAU,UAAA,EAAA,GADrC,EAiDK,MAjDL,GAiDK,EAAA,EAAA,EAAA,GA9CD,EA6CK,GAAA,MAAA,EA5C0B,EAAA,MAAS,MAAM,WAAlC,GAAS,YADrB,EA6CK,MAAA;IA3CA,KAAK;IACN,OAAM;aACN,EAwCY,EAvCH,EAAQ,MAAG,MAAA,KAAA,GAAA;IACf,MAAM,EAAQ;IACd,QAAQ,EAAQ,MAAG,WAAc,KAAA;IACjC,KAAK,EAAQ,MAAG,wBAA2B,KAAA;IAC5C,OAAM;;qBAKqF,CAHjF,EAAQ,SAAA,EAAA,GADlB,EAI2F,OAAA;;KAFtF,KAAK,EAAQ;KACb,KAAK,EAAQ;KACd,OAAM;iCACV,EA4BM,OA5BN,GA4BM;KA3BF,EAES,UAFT,GAES,EADF,EAAQ,IAAI,GAAA,CAAA;KAGT,EAAQ,OAAA,EAAA,GADlB,EAKO,QALP,GAKO,CAFH,EAAkD,GAAA;MAA1C,MAAK;MAAU,OAAM;SAC7B,EAA4B,GAAA,EAApB,KAAK,EAAQ,IAAA,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAEzB,EAYM,OAZN,GAYM,CAVQ,EAAQ,SAAA,EAAA,GADlB,EAIO,QAJP,GAIO,EADA,EAAQ,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAGV,EAAQ,gBAAA,EAAA,GADlB,EAKO,QAAA;;MAHH,OAAK,EAAA,CAAC,uBACE,EAAqB,EAAQ,YAAY,CAAA,CAAA;UAC9C,EAAQ,YAAY,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;KAIrB,EAAQ,eAAA,EAAA,GADlB,EAII,KAJJ,GAII,EADG,EAAQ,WAAW,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"PkToolShowProductList-BbY4ni7Y.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowProductList.vue","../../../../packages/components/src/chat/PkToolShowProductList.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import PkUrl from '../PkUrl.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n products: Array<{\n name: string\n url?: string\n image?: string\n price?: string\n availability?: string\n description?: string\n }>\n }\n }\n return part\n })\n\n const getAvailabilityColor = (availability?: string) => {\n if (!availability) {\n return ''\n }\n const lower = availability.toLowerCase()\n if (\n lower.includes('in stock') ||\n lower.includes('available') ||\n lower.includes('disponibile')\n ) {\n return 'text-success'\n }\n if (\n lower.includes('out of stock') ||\n lower.includes('unavailable') ||\n lower.includes('non disponibile')\n ) {\n return 'text-danger'\n }\n if (\n lower.includes('limited') ||\n lower.includes('low stock') ||\n lower.includes('limitato')\n ) {\n return 'text-warning'\n }\n return 'text-word-3'\n }\n</script>\n\n<template>\n <ul\n v-if=\"toolPart?.input?.products?.length\"\n class=\"flex flex-col gap-xs w-full\">\n <li\n v-for=\"(product, index) in toolPart.input.products\"\n :key=\"index\"\n class=\"border border-surface-3 rounded-xl overflow-hidden hover:border-surface-4 transition-colors\">\n <component\n :is=\"product.url ? 'a' : 'div'\"\n :href=\"product.url\"\n :target=\"product.url ? '_blank' : undefined\"\n :rel=\"product.url ? 'noopener noreferrer' : undefined\"\n class=\"flex gap-8 p-8 hover:bg-surface-1 transition-colors\">\n <img\n v-if=\"product.image\"\n :src=\"product.image\"\n :alt=\"product.name\"\n class=\"w-48 h-48 object-contain rounded shrink-0 border border-surface-3 bg-surface\" />\n <div class=\"flex flex-col gap-4 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate\">\n {{ product.name }}\n </strong>\n <span\n v-if=\"product.url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-12\" />\n <PkUrl :url=\"product.url\" />\n </span>\n <div class=\"flex items-center gap-sm flex-wrap text-12\">\n <span\n v-if=\"product.price\"\n class=\"font-semibold text-word-1\">\n {{ product.price }}\n </span>\n <span\n v-if=\"product.availability\"\n class=\"text-10 font-medium\"\n :class=\"getAvailabilityColor(product.availability)\">\n {{ product.availability }}\n </span>\n </div>\n <p\n v-if=\"product.description\"\n class=\"text-12 text-word-3 line-clamp-2\">\n {{ product.description }}\n </p>\n </div>\n </component>\n </li>\n </ul>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import PkUrl from '../PkUrl.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n products: Array<{\n name: string\n url?: string\n image?: string\n price?: string\n availability?: string\n description?: string\n }>\n }\n }\n return part\n })\n\n const getAvailabilityColor = (availability?: string) => {\n if (!availability) {\n return ''\n }\n const lower = availability.toLowerCase()\n if (\n lower.includes('in stock') ||\n lower.includes('available') ||\n lower.includes('disponibile')\n ) {\n return 'text-success'\n }\n if (\n lower.includes('out of stock') ||\n lower.includes('unavailable') ||\n lower.includes('non disponibile')\n ) {\n return 'text-danger'\n }\n if (\n lower.includes('limited') ||\n lower.includes('low stock') ||\n lower.includes('limitato')\n ) {\n return 'text-warning'\n }\n return 'text-word-3'\n }\n</script>\n\n<template>\n <ul\n v-if=\"toolPart?.input?.products?.length\"\n class=\"flex flex-col gap-xs w-full\">\n <li\n v-for=\"(product, index) in toolPart.input.products\"\n :key=\"index\"\n class=\"border border-surface-3 rounded-xl overflow-hidden hover:border-surface-4 transition-colors\">\n <component\n :is=\"product.url ? 'a' : 'div'\"\n :href=\"product.url\"\n :target=\"product.url ? '_blank' : undefined\"\n :rel=\"product.url ? 'noopener noreferrer' : undefined\"\n class=\"flex gap-8 p-8 hover:bg-surface-1 transition-colors\">\n <img\n v-if=\"product.image\"\n :src=\"product.image\"\n :alt=\"product.name\"\n class=\"w-48 h-48 object-contain rounded shrink-0 border border-surface-3 bg-surface\" />\n <div class=\"flex flex-col gap-4 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate\">\n {{ product.name }}\n </strong>\n <span\n v-if=\"product.url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-12\" />\n <PkUrl :url=\"product.url\" />\n </span>\n <div class=\"flex items-center gap-sm flex-wrap text-12\">\n <span\n v-if=\"product.price\"\n class=\"font-semibold text-word-1\">\n {{ product.price }}\n </span>\n <span\n v-if=\"product.availability\"\n class=\"text-10 font-medium\"\n :class=\"getAvailabilityColor(product.availability)\">\n {{ product.availability }}\n </span>\n </div>\n <p\n v-if=\"product.description\"\n class=\"text-12 text-word-3 line-clamp-2\">\n {{ product.description }}\n </p>\n </div>\n </component>\n </li>\n </ul>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAII,IAAM,IAAQ,GAIR,IAAW,QACA,EAAM,IAatB,GAEK,KAAwB,MAA0B;GACpD,IAAI,CAAC,GACD,OAAO;GAEX,IAAM,IAAQ,EAAa,YAAY;GAsBvC,OApBI,EAAM,SAAS,UAAU,KACzB,EAAM,SAAS,WAAW,KAC1B,EAAM,SAAS,aAAa,IAErB,iBAGP,EAAM,SAAS,cAAc,KAC7B,EAAM,SAAS,aAAa,KAC5B,EAAM,SAAS,iBAAiB,IAEzB,gBAGP,EAAM,SAAS,SAAS,KACxB,EAAM,SAAS,WAAW,KAC1B,EAAM,SAAS,UAAU,IAElB,iBAEJ;EACX;;;UAKU,EAAA,OAAU,OAAO,UAAU,UAAA,EAAA,GADrC,EAiDK,MAjDL,GAiDK,EAAA,EAAA,EAAA,GA9CD,EA6CK,GAAA,MAAA,EA5C0B,EAAA,MAAS,MAAM,WAAlC,GAAS,YADrB,EA6CK,MAAA;IA3CA,KAAK;IACN,OAAM;aACN,EAwCY,EAvCH,EAAQ,MAAG,MAAA,KAAA,GAAA;IACf,MAAM,EAAQ;IACd,QAAQ,EAAQ,MAAG,WAAc,KAAA;IACjC,KAAK,EAAQ,MAAG,wBAA2B,KAAA;IAC5C,OAAM;;qBAKqF,CAHjF,EAAQ,SAAA,EAAA,GADlB,EAI2F,OAAA;;KAFtF,KAAK,EAAQ;KACb,KAAK,EAAQ;KACd,OAAM;iCACV,EA4BM,OA5BN,GA4BM;KA3BF,EAES,UAFT,GAES,EADF,EAAQ,IAAI,GAAA,CAAA;KAGT,EAAQ,OAAA,EAAA,GADlB,EAKO,QALP,GAKO,CAFH,EAAkD,GAAA;MAA1C,MAAK;MAAU,OAAM;SAC7B,EAA4B,GAAA,EAApB,KAAK,EAAQ,IAAA,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAEzB,EAYM,OAZN,GAYM,CAVQ,EAAQ,SAAA,EAAA,GADlB,EAIO,QAJP,GAIO,EADA,EAAQ,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAGV,EAAQ,gBAAA,EAAA,GADlB,EAKO,QAAA;;MAHH,OAAK,EAAA,CAAC,uBACE,EAAqB,EAAQ,YAAY,CAAA,CAAA;UAC9C,EAAQ,YAAY,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA;KAIrB,EAAQ,eAAA,EAAA,GADlB,EAII,KAJJ,GAII,EADG,EAAQ,WAAW,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
@@ -1,6 +1,6 @@
1
1
  import { A as e, C as t, L as n, T as r, _ as i, at as a, b as o, et as s, g as c, kt as l, mt as u, qt as d, xt as f, y as p, z as m } from "./vue.runtime.esm-bundler-DbhD_IvR.js";
2
- import { i as h } from "./dist-BNET2z7b.js";
3
- import { l as g, n as _, p as v } from "./index.es-BYny0uhz.js";
2
+ import { i as h } from "./dist-CvMCBce7.js";
3
+ import { d as g, f as _, i as v } from "./index.es-_oXVRjHy.js";
4
4
  e(), l(), a();
5
5
  var y = {
6
6
  key: 0,
@@ -32,7 +32,7 @@ var y = {
32
32
  }, o.src = r;
33
33
  };
34
34
  return (e, n) => {
35
- let r = g, c = v, u = _;
35
+ let r = _, c = g, u = v;
36
36
  return T.value?.input ? (m(), o("div", y, [i("div", b, [
37
37
  t(r, {
38
38
  name: "ri:qr-code-line",
@@ -68,4 +68,4 @@ var y = {
68
68
  //#endregion
69
69
  export { T as default };
70
70
 
71
- //# sourceMappingURL=PkToolShowQrCode-CctXvRyG.js.map
71
+ //# sourceMappingURL=PkToolShowQrCode-CN0ms27N.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowQrCode-CctXvRyG.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkToolShowQrCode.vue","../../../../packages/components/src/chat/PkToolShowQrCode.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref, onMounted } from 'vue'\n import { useClipboard } from '@vueuse/core'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n content: string\n label?: string\n }\n }\n return part\n })\n\n const svgContent = ref('')\n const qrContainerRef = ref<HTMLElement>()\n\n onMounted(async () => {\n const content = toolPart.value.input?.content\n if (!content) {\n return\n }\n const { default: QRCode } = await import('qrcode')\n svgContent.value = await QRCode.toString(content, { type: 'svg' })\n })\n\n const downloadQr = async () => {\n const svgEl = qrContainerRef.value?.querySelector('svg')\n if (!svgEl) {\n return\n }\n const svgData = new XMLSerializer().serializeToString(svgEl)\n const svgBlob = new Blob([svgData], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const svgUrl = URL.createObjectURL(svgBlob)\n\n const canvas = document.createElement('canvas')\n canvas.width = 512\n canvas.height = 512\n const ctx = canvas.getContext('2d')\n const img = new Image()\n img.onload = () => {\n ctx?.drawImage(img, 0, 0, 512, 512)\n URL.revokeObjectURL(svgUrl)\n const a = document.createElement('a')\n a.href = canvas.toDataURL('image/png')\n a.download = 'qrcode.png'\n a.click()\n }\n img.src = svgUrl\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:qr-code-line\" class=\"text-16\" />\n <strong class=\"font-bold\">{{ $t('label.qrCode') }}</strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(toolPart?.input?.content ?? '')\" />\n <VvButton\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadQr\" />\n </VvButtonGroup>\n </div>\n <div class=\"p-sm flex flex-col items-center\">\n <div ref=\"qrContainerRef\" class=\"w-144 h-144\" v-html=\"svgContent\" />\n <p\n v-if=\"toolPart.input.label\"\n class=\"text-12 text-word-3 text-center\">\n {{ toolPart.input.label }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, onMounted } from 'vue'\n import { useClipboard } from '@vueuse/core'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n content: string\n label?: string\n }\n }\n return part\n })\n\n const svgContent = ref('')\n const qrContainerRef = ref<HTMLElement>()\n\n onMounted(async () => {\n const content = toolPart.value.input?.content\n if (!content) {\n return\n }\n const { default: QRCode } = await import('qrcode')\n svgContent.value = await QRCode.toString(content, { type: 'svg' })\n })\n\n const downloadQr = async () => {\n const svgEl = qrContainerRef.value?.querySelector('svg')\n if (!svgEl) {\n return\n }\n const svgData = new XMLSerializer().serializeToString(svgEl)\n const svgBlob = new Blob([svgData], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const svgUrl = URL.createObjectURL(svgBlob)\n\n const canvas = document.createElement('canvas')\n canvas.width = 512\n canvas.height = 512\n const ctx = canvas.getContext('2d')\n const img = new Image()\n img.onload = () => {\n ctx?.drawImage(img, 0, 0, 512, 512)\n URL.revokeObjectURL(svgUrl)\n const a = document.createElement('a')\n a.href = canvas.toDataURL('image/png')\n a.download = 'qrcode.png'\n a.click()\n }\n img.src = svgUrl\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:qr-code-line\" class=\"text-16\" />\n <strong class=\"font-bold\">{{ $t('label.qrCode') }}</strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(toolPart?.input?.content ?? '')\" />\n <VvButton\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadQr\" />\n </VvButtonGroup>\n </div>\n <div class=\"p-sm flex flex-col items-center\">\n <div ref=\"qrContainerRef\" class=\"w-144 h-144\" v-html=\"svgContent\" />\n <p\n v-if=\"toolPart.input.label\"\n class=\"text-12 text-word-3 text-center\">\n {{ toolPart.input.label }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAII,IAAM,IAAQ,GAIR,EAAE,SAAM,cAAW,EAAa,GAEhC,IAAW,QACA,EAAM,IAOtB,GAEK,IAAa,EAAI,EAAE,GACnB,IAAiB,EAAiB;EAExC,EAAU,YAAY;GAClB,IAAM,IAAU,EAAS,MAAM,OAAO;GACtC,IAAI,CAAC,GACD;GAEJ,IAAM,EAAE,SAAS,MAAW,MAAM,OAAO;GACzC,EAAW,QAAQ,MAAM,EAAO,SAAS,GAAS,EAAE,MAAM,MAAM,CAAC;EACrE,CAAC;EAED,IAAM,IAAa,YAAY;GAC3B,IAAM,IAAQ,EAAe,OAAO,cAAc,KAAK;GACvD,IAAI,CAAC,GACD;GAEJ,IAAM,IAAU,IAAI,cAAc,CAAC,CAAC,kBAAkB,CAAK,GACrD,IAAU,IAAI,KAAK,CAAC,CAAO,GAAG,EAChC,MAAM,8BACV,CAAC,GACK,IAAS,IAAI,gBAAgB,CAAO,GAEpC,IAAS,SAAS,cAAc,QAAQ;GAE9C,AADA,EAAO,QAAQ,KACf,EAAO,SAAS;GAChB,IAAM,IAAM,EAAO,WAAW,IAAI,GAC5B,IAAM,IAAI,MAAM;GAStB,AARA,EAAI,eAAe;IAEf,AADA,GAAK,UAAU,GAAK,GAAG,GAAG,KAAK,GAAG,GAClC,IAAI,gBAAgB,CAAM;IAC1B,IAAM,IAAI,SAAS,cAAc,GAAG;IAGpC,AAFA,EAAE,OAAO,EAAO,UAAU,WAAW,GACrC,EAAE,WAAW,cACb,EAAE,MAAM;GACZ,GACA,EAAI,MAAM;EACd;;;UAKU,EAAA,OAAU,SAAA,EAAA,GADpB,EA4BM,OA5BN,GA4BM,CAzBF,EAgBM,OAhBN,GAgBM;IAdF,EAAiD,GAAA;KAAzC,MAAK;KAAkB,OAAM;;IACrC,EAA2D,UAA3D,GAA2D,EAA9BA,EAAAA,GAAE,cAAA,CAAA,GAAA,CAAA;IAC/B,EAWgB,GAAA;KAXD,WAAU;KAAU,OAAM;;sBAKe,CAJpD,EAIoD,GAAA;MAHhD,WAAU;MACT,MAAM,EAAA,CAAA,IAAM,kBAAA;MACZ,OAAO,EAAA,CAAA,IAASA,EAAAA,GAAE,eAAA,IAAoBA,EAAAA,GAAE,aAAA;MACxC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAI,CAAC,EAAA,OAAU,OAAO,WAAO,EAAA;qCACzC,EAI0B,GAAA;MAHtB,WAAU;MACV,MAAK;MACJ,OAAOA,EAAAA,GAAE,iBAAA;MACT,SAAO;;;;OAGpB,EAOM,OAPN,GAOM,CANF,EAAoE,OAAA;aAA3D;IAAJ,KAAI;IAAiB,OAAM;IAAc,WAAQ,EAAA;mBAE5C,EAAA,MAAS,MAAM,SAAA,EAAA,GADzB,EAII,KAJJ,GAII,EADG,EAAA,MAAS,MAAM,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"PkToolShowQrCode-CN0ms27N.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkToolShowQrCode.vue","../../../../packages/components/src/chat/PkToolShowQrCode.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref, onMounted } from 'vue'\n import { useClipboard } from '@vueuse/core'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n content: string\n label?: string\n }\n }\n return part\n })\n\n const svgContent = ref('')\n const qrContainerRef = ref<HTMLElement>()\n\n onMounted(async () => {\n const content = toolPart.value.input?.content\n if (!content) {\n return\n }\n const { default: QRCode } = await import('qrcode')\n svgContent.value = await QRCode.toString(content, { type: 'svg' })\n })\n\n const downloadQr = async () => {\n const svgEl = qrContainerRef.value?.querySelector('svg')\n if (!svgEl) {\n return\n }\n const svgData = new XMLSerializer().serializeToString(svgEl)\n const svgBlob = new Blob([svgData], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const svgUrl = URL.createObjectURL(svgBlob)\n\n const canvas = document.createElement('canvas')\n canvas.width = 512\n canvas.height = 512\n const ctx = canvas.getContext('2d')\n const img = new Image()\n img.onload = () => {\n ctx?.drawImage(img, 0, 0, 512, 512)\n URL.revokeObjectURL(svgUrl)\n const a = document.createElement('a')\n a.href = canvas.toDataURL('image/png')\n a.download = 'qrcode.png'\n a.click()\n }\n img.src = svgUrl\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:qr-code-line\" class=\"text-16\" />\n <strong class=\"font-bold\">{{ $t('label.qrCode') }}</strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(toolPart?.input?.content ?? '')\" />\n <VvButton\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadQr\" />\n </VvButtonGroup>\n </div>\n <div class=\"p-sm flex flex-col items-center\">\n <div ref=\"qrContainerRef\" class=\"w-144 h-144\" v-html=\"svgContent\" />\n <p\n v-if=\"toolPart.input.label\"\n class=\"text-12 text-word-3 text-center\">\n {{ toolPart.input.label }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, onMounted } from 'vue'\n import { useClipboard } from '@vueuse/core'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n content: string\n label?: string\n }\n }\n return part\n })\n\n const svgContent = ref('')\n const qrContainerRef = ref<HTMLElement>()\n\n onMounted(async () => {\n const content = toolPart.value.input?.content\n if (!content) {\n return\n }\n const { default: QRCode } = await import('qrcode')\n svgContent.value = await QRCode.toString(content, { type: 'svg' })\n })\n\n const downloadQr = async () => {\n const svgEl = qrContainerRef.value?.querySelector('svg')\n if (!svgEl) {\n return\n }\n const svgData = new XMLSerializer().serializeToString(svgEl)\n const svgBlob = new Blob([svgData], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const svgUrl = URL.createObjectURL(svgBlob)\n\n const canvas = document.createElement('canvas')\n canvas.width = 512\n canvas.height = 512\n const ctx = canvas.getContext('2d')\n const img = new Image()\n img.onload = () => {\n ctx?.drawImage(img, 0, 0, 512, 512)\n URL.revokeObjectURL(svgUrl)\n const a = document.createElement('a')\n a.href = canvas.toDataURL('image/png')\n a.download = 'qrcode.png'\n a.click()\n }\n img.src = svgUrl\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden bg-surface\">\n <div\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8\">\n <VvIcon name=\"ri:qr-code-line\" class=\"text-16\" />\n <strong class=\"font-bold\">{{ $t('label.qrCode') }}</strong>\n <VvButtonGroup modifiers=\"compact\" class=\"ml-auto shrink-0\">\n <VvButton\n modifiers=\"action-quiet-small\"\n :icon=\"copied ? 'ri:check-line' : 'ri:file-copy-line'\"\n :label=\"copied ? $t('action.copied') : $t('action.copy')\"\n @click=\"copy(toolPart?.input?.content ?? '')\" />\n <VvButton\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadQr\" />\n </VvButtonGroup>\n </div>\n <div class=\"p-sm flex flex-col items-center\">\n <div ref=\"qrContainerRef\" class=\"w-144 h-144\" v-html=\"svgContent\" />\n <p\n v-if=\"toolPart.input.label\"\n class=\"text-12 text-word-3 text-center\">\n {{ toolPart.input.label }}\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAII,IAAM,IAAQ,GAIR,EAAE,SAAM,cAAW,EAAa,GAEhC,IAAW,QACA,EAAM,IAOtB,GAEK,IAAa,EAAI,EAAE,GACnB,IAAiB,EAAiB;EAExC,EAAU,YAAY;GAClB,IAAM,IAAU,EAAS,MAAM,OAAO;GACtC,IAAI,CAAC,GACD;GAEJ,IAAM,EAAE,SAAS,MAAW,MAAM,OAAO;GACzC,EAAW,QAAQ,MAAM,EAAO,SAAS,GAAS,EAAE,MAAM,MAAM,CAAC;EACrE,CAAC;EAED,IAAM,IAAa,YAAY;GAC3B,IAAM,IAAQ,EAAe,OAAO,cAAc,KAAK;GACvD,IAAI,CAAC,GACD;GAEJ,IAAM,IAAU,IAAI,cAAc,CAAC,CAAC,kBAAkB,CAAK,GACrD,IAAU,IAAI,KAAK,CAAC,CAAO,GAAG,EAChC,MAAM,8BACV,CAAC,GACK,IAAS,IAAI,gBAAgB,CAAO,GAEpC,IAAS,SAAS,cAAc,QAAQ;GAE9C,AADA,EAAO,QAAQ,KACf,EAAO,SAAS;GAChB,IAAM,IAAM,EAAO,WAAW,IAAI,GAC5B,IAAM,IAAI,MAAM;GAStB,AARA,EAAI,eAAe;IAEf,AADA,GAAK,UAAU,GAAK,GAAG,GAAG,KAAK,GAAG,GAClC,IAAI,gBAAgB,CAAM;IAC1B,IAAM,IAAI,SAAS,cAAc,GAAG;IAGpC,AAFA,EAAE,OAAO,EAAO,UAAU,WAAW,GACrC,EAAE,WAAW,cACb,EAAE,MAAM;GACZ,GACA,EAAI,MAAM;EACd;;;UAKU,EAAA,OAAU,SAAA,EAAA,GADpB,EA4BM,OA5BN,GA4BM,CAzBF,EAgBM,OAhBN,GAgBM;IAdF,EAAiD,GAAA;KAAzC,MAAK;KAAkB,OAAM;;IACrC,EAA2D,UAA3D,GAA2D,EAA9BA,EAAAA,GAAE,cAAA,CAAA,GAAA,CAAA;IAC/B,EAWgB,GAAA;KAXD,WAAU;KAAU,OAAM;;sBAKe,CAJpD,EAIoD,GAAA;MAHhD,WAAU;MACT,MAAM,EAAA,CAAA,IAAM,kBAAA;MACZ,OAAO,EAAA,CAAA,IAASA,EAAAA,GAAE,eAAA,IAAoBA,EAAAA,GAAE,aAAA;MACxC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAI,CAAC,EAAA,OAAU,OAAO,WAAO,EAAA;qCACzC,EAI0B,GAAA;MAHtB,WAAU;MACV,MAAK;MACJ,OAAOA,EAAAA,GAAE,iBAAA;MACT,SAAO;;;;OAGpB,EAOM,OAPN,GAOM,CANF,EAAoE,OAAA;aAA3D;IAAJ,KAAI;IAAiB,OAAM;IAAc,WAAQ,EAAA;mBAE5C,EAAA,MAAS,MAAM,SAAA,EAAA,GADzB,EAII,KAJJ,GAII,EADG,EAAA,MAAS,MAAM,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
@@ -1,8 +1,8 @@
1
1
  import { A as e, C as t, Ht as n, S as r, T as i, V as a, _ as o, at as s, b as c, et as l, ft as u, g as d, i as f, kt as p, mt as m, n as h, p as g, qt as _, v, xt as y, y as b, z as x } from "./vue.runtime.esm-bundler-DbhD_IvR.js";
2
+ import { t as S } from "./PkStreamingMarkdown-6Xx9n1ue.js";
2
3
  import "./src-BGqVtumX.js";
3
- import { f as S, n as C } from "./Document-DtFcn7Mq.js";
4
- import { l as w } from "./index.es-BYny0uhz.js";
5
- import { t as T } from "./PkStreamingMarkdown-Djw604Ny.js";
4
+ import { f as C, n as w } from "./Document-DtFcn7Mq.js";
5
+ import { f as T } from "./index.es-_oXVRjHy.js";
6
6
  import { t as E } from "./PkUrl-liCemvcx.js";
7
7
  e(), s(), p();
8
8
  var D = ["title"], O = {
@@ -23,7 +23,7 @@ var D = ["title"], O = {
23
23
  return Math.round(n.similarity / e * 100);
24
24
  });
25
25
  return (n, i) => {
26
- let a = w;
26
+ let a = T;
27
27
  return x(), c(g, null, [
28
28
  t(a, {
29
29
  name: "ri:text-snippet",
@@ -32,7 +32,7 @@ var D = ["title"], O = {
32
32
  o("span", {
33
33
  class: "text-10 text-word-2 truncate flex-1",
34
34
  title: e.content
35
- }, _(y(S)(e.content)), 9, D),
35
+ }, _(y(C)(e.content)), 9, D),
36
36
  r.value == null ? b("", !0) : (x(), c("span", O, _(r.value) + "% ", 1)),
37
37
  t(a, {
38
38
  name: e.expanded ? "ri:arrow-up-s-line" : "ri:arrow-down-s-line",
@@ -59,9 +59,9 @@ var A = { class: "flex flex-col gap-2 min-w-0 flex-1" }, j = { class: "font-bold
59
59
  },
60
60
  setup(e) {
61
61
  return (n, r) => {
62
- let i = w;
62
+ let i = T;
63
63
  return x(), c(g, null, [t(i, {
64
- name: y(C)(e.type),
64
+ name: y(w)(e.type),
65
65
  class: "shrink-0 text-14 text-word-3"
66
66
  }, null, 8, ["name"]), o("div", A, [
67
67
  o("strong", j, _(e.name), 1),
@@ -105,10 +105,10 @@ var F = {
105
105
  });
106
106
  }
107
107
  return [...e.values()];
108
- }), y = d(() => Math.max(...f.value.map((e) => e.similarity ?? 0), 0)), S = u(/* @__PURE__ */ new Set()), C = u(/* @__PURE__ */ new Set()), E = u(/* @__PURE__ */ new Map()), D = u(/* @__PURE__ */ new Set()), O = (e) => {
109
- S.has(e) ? S.delete(e) : S.add(e);
110
- }, A = (e) => {
108
+ }), y = d(() => Math.max(...f.value.map((e) => e.similarity ?? 0), 0)), C = u(/* @__PURE__ */ new Set()), w = u(/* @__PURE__ */ new Set()), E = u(/* @__PURE__ */ new Map()), D = u(/* @__PURE__ */ new Set()), O = (e) => {
111
109
  C.has(e) ? C.delete(e) : C.add(e);
110
+ }, A = (e) => {
111
+ w.has(e) ? w.delete(e) : w.add(e);
112
112
  }, j = async (e) => {
113
113
  if (!(e.chunkIndex == null || !i.onExpandContext)) {
114
114
  D.add(e.chunkId);
@@ -126,7 +126,7 @@ var F = {
126
126
  E.delete(e);
127
127
  }, N = m(!1), Q = d(() => N.value ? p.value : p.value.slice(0, 3)), $ = d(() => p.value.length > 3);
128
128
  return (i, s) => {
129
- let u = w;
129
+ let u = T;
130
130
  return f.value.length ? (x(), c("div", F, [
131
131
  o("div", I, [
132
132
  t(u, {
@@ -156,10 +156,10 @@ var F = {
156
156
  s.chunks.length > 1 ? (x(), c("span", V, _(s.chunks.length), 1)) : b("", !0),
157
157
  o("span", H, _(s.document.language), 1),
158
158
  t(u, {
159
- name: S.has(s.document.documentId) ? "ri:arrow-up-s-line" : "ri:arrow-down-s-line",
159
+ name: C.has(s.document.documentId) ? "ri:arrow-up-s-line" : "ri:arrow-down-s-line",
160
160
  class: "text-16 text-word-3"
161
161
  }, null, 8, ["name"])
162
- ])], 8, z), S.has(s.document.documentId) ? (x(), c("div", U, [s.document.sourceDescription ? (x(), v(T, {
162
+ ])], 8, z), C.has(s.document.documentId) ? (x(), c("div", U, [s.document.sourceDescription ? (x(), v(S, {
163
163
  key: 0,
164
164
  markdown: s.document.sourceDescription,
165
165
  class: "px-8 py-4 text-10 text-word-3 bg-surface-1 border-b border-surface-3"
@@ -173,18 +173,18 @@ var F = {
173
173
  content: a.content,
174
174
  similarity: a.similarity,
175
175
  "max-similarity": y.value,
176
- expanded: C.has(a.chunkId)
176
+ expanded: w.has(a.chunkId)
177
177
  }, null, 8, [
178
178
  "content",
179
179
  "similarity",
180
180
  "max-similarity",
181
181
  "expanded"
182
- ])], 8, W), C.has(a.chunkId) ? (x(), c("div", G, [o("div", K, [t(h, { mode: "out-in" }, {
183
- default: l(() => [E.has(a.chunkId) ? (x(), v(T, {
182
+ ])], 8, W), w.has(a.chunkId) ? (x(), c("div", G, [o("div", K, [t(h, { mode: "out-in" }, {
183
+ default: l(() => [E.has(a.chunkId) ? (x(), v(S, {
184
184
  key: 0,
185
185
  markdown: E.get(a.chunkId),
186
186
  class: "wysiwyg"
187
- }, null, 8, ["markdown"])) : (x(), v(T, {
187
+ }, null, 8, ["markdown"])) : (x(), v(S, {
188
188
  key: 1,
189
189
  markdown: a.content,
190
190
  class: "wysiwyg"
@@ -241,4 +241,4 @@ var F = {
241
241
  //#endregion
242
242
  export { Q as default };
243
243
 
244
- //# sourceMappingURL=PkToolShowSources-DwB6VXrK.js.map
244
+ //# sourceMappingURL=PkToolShowSources-D2tBcx7n.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowSources-DwB6VXrK.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkChunkPreview.vue","../../../../packages/components/src/chat/PkChunkPreview.vue","../../../../packages/components/src/chat/PkDocumentHeader.vue","../../../../packages/components/src/chat/PkDocumentHeader.vue","../../../../packages/components/src/chat/PkToolShowSources.vue","../../../../packages/components/src/chat/PkToolShowSources.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { stripMarkdown } from 'utils'\n\n const props = defineProps<{\n content: string\n similarity?: number\n maxSimilarity?: number\n expanded: boolean\n }>()\n\n const similarityPercent = computed(() => {\n if (props.similarity == null) {\n return null\n }\n const max =\n props.maxSimilarity && props.maxSimilarity > 0\n ? props.maxSimilarity\n : 1\n return Math.round((props.similarity / max) * 100)\n })\n</script>\n\n<template>\n <VvIcon name=\"ri:text-snippet\" class=\"shrink-0 text-12 text-word-4\" />\n <span class=\"text-10 text-word-2 truncate flex-1\" :title=\"content\">\n {{ stripMarkdown(content) }}\n </span>\n <span v-if=\"similarityPercent != null\" class=\"text-10 text-word-4 shrink-0\">\n {{ similarityPercent }}%\n </span>\n <VvIcon\n :name=\"expanded ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-14 text-word-4 shrink-0\" />\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { stripMarkdown } from 'utils'\n\n const props = defineProps<{\n content: string\n similarity?: number\n maxSimilarity?: number\n expanded: boolean\n }>()\n\n const similarityPercent = computed(() => {\n if (props.similarity == null) {\n return null\n }\n const max =\n props.maxSimilarity && props.maxSimilarity > 0\n ? props.maxSimilarity\n : 1\n return Math.round((props.similarity / max) * 100)\n })\n</script>\n\n<template>\n <VvIcon name=\"ri:text-snippet\" class=\"shrink-0 text-12 text-word-4\" />\n <span class=\"text-10 text-word-2 truncate flex-1\" :title=\"content\">\n {{ stripMarkdown(content) }}\n </span>\n <span v-if=\"similarityPercent != null\" class=\"text-10 text-word-4 shrink-0\">\n {{ similarityPercent }}%\n </span>\n <VvIcon\n :name=\"expanded ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-14 text-word-4 shrink-0\" />\n</template>\n","<script setup lang=\"ts\">\n import type { DocumentType } from 'models'\n import { getTypeIcon } from 'models'\n import PkUrl from '../PkUrl.vue'\n\n defineProps<{\n type: string\n name: string\n url?: string\n filename?: string\n }>()\n</script>\n\n<template>\n <VvIcon\n :name=\"getTypeIcon(type as DocumentType)\"\n class=\"shrink-0 text-14 text-word-3\" />\n <div class=\"flex flex-col gap-2 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate block\">\n {{ name }}\n </strong>\n <span v-if=\"filename\" class=\"text-10 text-word-4 truncate\">\n {{ filename }}\n </span>\n <span\n v-if=\"url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-10\" />\n <PkUrl :url=\"url\" />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import type { DocumentType } from 'models'\n import { getTypeIcon } from 'models'\n import PkUrl from '../PkUrl.vue'\n\n defineProps<{\n type: string\n name: string\n url?: string\n filename?: string\n }>()\n</script>\n\n<template>\n <VvIcon\n :name=\"getTypeIcon(type as DocumentType)\"\n class=\"shrink-0 text-14 text-word-3\" />\n <div class=\"flex flex-col gap-2 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate block\">\n {{ name }}\n </strong>\n <span v-if=\"filename\" class=\"text-10 text-word-4 truncate\">\n {{ filename }}\n </span>\n <span\n v-if=\"url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-10\" />\n <PkUrl :url=\"url\" />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive } from 'vue'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChunkPreview from './PkChunkPreview.vue'\n import PkDocumentHeader from './PkDocumentHeader.vue'\n\n interface SourceItem {\n chunkId: string\n documentId: string\n documentName: string\n documentType: string\n language: string\n content: string\n chunkIndex?: number | null\n similarity?: number\n sourceUrl?: string\n sourceFilename?: string\n sourceDescription?: string\n sourceImageUrl?: string\n }\n\n const props = defineProps<{\n part: unknown\n onExpandContext?: (payload: {\n documentId: string\n chunkIndex: number\n }) => Promise<string>\n onDownload?: (documentId: string) => void\n }>()\n\n const toolPart = computed(() => {\n return props.part as {\n input?: {\n sources: SourceItem[]\n }\n }\n })\n\n const sources = computed(() => toolPart.value.input?.sources || [])\n\n const groupedSources = computed(() => {\n const groups = new Map<\n string,\n { document: SourceItem; chunks: SourceItem[] }\n >()\n for (const source of sources.value) {\n const existing = groups.get(source.documentId)\n if (existing) {\n existing.chunks.push(source)\n } else {\n groups.set(source.documentId, {\n document: source,\n chunks: [source],\n })\n }\n }\n return [...groups.values()]\n })\n\n const maxSimilarity = computed(() => {\n return Math.max(...sources.value.map((s) => s.similarity ?? 0), 0)\n })\n\n const expandedDocuments = reactive(new Set<string>())\n const expandedChunks = reactive(new Set<string>())\n const contextData = reactive(new Map<string, string>())\n const loadingContext = reactive(new Set<string>())\n\n const toggleDocument = (documentId: string) => {\n if (expandedDocuments.has(documentId)) {\n expandedDocuments.delete(documentId)\n } else {\n expandedDocuments.add(documentId)\n }\n }\n\n const toggleChunk = (chunkId: string) => {\n if (expandedChunks.has(chunkId)) {\n expandedChunks.delete(chunkId)\n } else {\n expandedChunks.add(chunkId)\n }\n }\n\n const handleExpandContext = async (source: SourceItem) => {\n if (source.chunkIndex == null || !props.onExpandContext) {\n return\n }\n loadingContext.add(source.chunkId)\n try {\n const content = await props.onExpandContext({\n documentId: source.documentId,\n chunkIndex: source.chunkIndex,\n })\n contextData.set(source.chunkId, content)\n } finally {\n loadingContext.delete(source.chunkId)\n }\n }\n\n const clearContext = (chunkId: string) => {\n contextData.delete(chunkId)\n }\n\n const showMore = ref(false)\n const visibleGroups = computed(() => {\n if (showMore.value) {\n return groupedSources.value\n }\n return groupedSources.value.slice(0, 3)\n })\n const hasMore = computed(() => groupedSources.value.length > 3)\n</script>\n\n<template>\n <div v-if=\"sources.length\" class=\"flex flex-col gap-xs w-full\">\n <div class=\"flex items-center gap-4 text-12 text-word-3 font-semibold\">\n <VvIcon name=\"ri:article-line\" class=\"text-14\" />\n {{ $t('label.sources') }}\n <span class=\"text-word-4 font-normal\">\n ({{ groupedSources.length }})\n </span>\n </div>\n\n <ul class=\"flex flex-col gap-xs\">\n <li\n v-for=\"group in visibleGroups\"\n :key=\"group.document.documentId\"\n class=\"border border-surface-3 rounded-xl overflow-hidden\">\n <!-- Document header -->\n <button\n class=\"flex items-center gap-8 p-8 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleDocument(group.document.documentId)\">\n <PkDocumentHeader\n :type=\"group.document.documentType\"\n :name=\"group.document.documentName\"\n :url=\"group.document.sourceUrl\"\n :filename=\"group.document.sourceFilename\" />\n <div class=\"flex items-center gap-4 shrink-0\">\n <span\n v-if=\"group.chunks.length > 1\"\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2\">\n {{ group.chunks.length }}\n </span>\n <span\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2 uppercase\">\n {{ group.document.language }}\n </span>\n <VvIcon\n :name=\"\n expandedDocuments.has(group.document.documentId)\n ? 'ri:arrow-up-s-line'\n : 'ri:arrow-down-s-line'\n \"\n class=\"text-16 text-word-3\" />\n </div>\n </button>\n\n <!-- Expanded content -->\n <div\n v-if=\"expandedDocuments.has(group.document.documentId)\"\n class=\"border-t border-surface-3\">\n <PkStreamingMarkdown\n v-if=\"group.document.sourceDescription\"\n :markdown=\"group.document.sourceDescription\"\n class=\"px-8 py-4 text-10 text-word-3 bg-surface-1 border-b border-surface-3\" />\n\n <!-- Chunk excerpts -->\n <div\n v-for=\"chunk in group.chunks\"\n :key=\"chunk.chunkId\"\n class=\"border-b border-surface-3 last:border-b-0\">\n <button\n class=\"flex items-center gap-8 px-8 py-6 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleChunk(chunk.chunkId)\">\n <PkChunkPreview\n :content=\"chunk.content\"\n :similarity=\"chunk.similarity\"\n :max-similarity=\"maxSimilarity\"\n :expanded=\"expandedChunks.has(chunk.chunkId)\" />\n </button>\n\n <!-- Expanded chunk content -->\n <div\n v-if=\"expandedChunks.has(chunk.chunkId)\"\n class=\"bg-surface-1 border-t border-surface-3\">\n <div class=\"p-8 text-10 text-word-3\">\n <transition mode=\"out-in\">\n <!-- Context expansion -->\n <PkStreamingMarkdown\n v-if=\"contextData.has(chunk.chunkId)\"\n :markdown=\"\n contextData.get(chunk.chunkId)!\n \"\n class=\"wysiwyg\" />\n\n <!-- Chunk content -->\n <PkStreamingMarkdown\n v-else\n :markdown=\"chunk.content\"\n class=\"wysiwyg\" />\n </transition>\n </div>\n\n <!-- Actions bar -->\n <div\n class=\"flex items-center gap-8 px-8 py-6 border-t border-surface-3 bg-surface\">\n <!-- Expand / collapse context -->\n <button\n v-if=\"\n onExpandContext &&\n chunk.chunkIndex != null &&\n !contextData.has(chunk.chunkId)\n \"\n class=\"text-10 text-word-3 hover:text-word flex items-center gap-4 cursor-pointer\"\n :disabled=\"\n loadingContext.has(chunk.chunkId)\n \"\n @click=\"handleExpandContext(chunk)\">\n <VvIcon\n :name=\"\n loadingContext.has(chunk.chunkId)\n ? 'line-md:loading-loop'\n : 'ri:expand-up-down-line'\n \"\n class=\"text-12\" />\n {{ $t('label.expandContext') }}\n </button>\n <button\n v-else-if=\"contextData.has(chunk.chunkId)\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n @click=\"clearContext(chunk.chunkId)\">\n <VvIcon\n name=\"ri:collapse-vertical-line\"\n class=\"text-12\" />\n {{ $t('label.collapseContext') }}\n </button>\n\n <!-- Open source URL -->\n <a\n v-if=\"chunk.sourceUrl\"\n :href=\"chunk.sourceUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 ml-auto\">\n <VvIcon\n name=\"ri:external-link-line\"\n class=\"text-12\" />\n {{ $t('label.openSource') }}\n </a>\n\n <!-- Download file -->\n <button\n v-if=\"\n onDownload &&\n chunk.documentType === 'file'\n \"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n :class=\"{\n 'ml-auto': !chunk.sourceUrl,\n }\"\n @click=\"onDownload(chunk.documentId)\">\n <VvIcon\n name=\"ri:download-line\"\n class=\"text-12\" />\n {{ $t('label.downloadFile') }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- Show more -->\n <button\n v-if=\"hasMore\"\n class=\"text-12 text-word-3 cursor-pointer hover:underline flex items-center gap-4 mx-auto\"\n @click=\"showMore = !showMore\">\n <VvIcon\n :name=\"showMore ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-16\" />\n {{\n showMore\n ? $t('action.showLess')\n : $t('action.showMore', {\n count: groupedSources.length - 3,\n })\n }}\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive } from 'vue'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChunkPreview from './PkChunkPreview.vue'\n import PkDocumentHeader from './PkDocumentHeader.vue'\n\n interface SourceItem {\n chunkId: string\n documentId: string\n documentName: string\n documentType: string\n language: string\n content: string\n chunkIndex?: number | null\n similarity?: number\n sourceUrl?: string\n sourceFilename?: string\n sourceDescription?: string\n sourceImageUrl?: string\n }\n\n const props = defineProps<{\n part: unknown\n onExpandContext?: (payload: {\n documentId: string\n chunkIndex: number\n }) => Promise<string>\n onDownload?: (documentId: string) => void\n }>()\n\n const toolPart = computed(() => {\n return props.part as {\n input?: {\n sources: SourceItem[]\n }\n }\n })\n\n const sources = computed(() => toolPart.value.input?.sources || [])\n\n const groupedSources = computed(() => {\n const groups = new Map<\n string,\n { document: SourceItem; chunks: SourceItem[] }\n >()\n for (const source of sources.value) {\n const existing = groups.get(source.documentId)\n if (existing) {\n existing.chunks.push(source)\n } else {\n groups.set(source.documentId, {\n document: source,\n chunks: [source],\n })\n }\n }\n return [...groups.values()]\n })\n\n const maxSimilarity = computed(() => {\n return Math.max(...sources.value.map((s) => s.similarity ?? 0), 0)\n })\n\n const expandedDocuments = reactive(new Set<string>())\n const expandedChunks = reactive(new Set<string>())\n const contextData = reactive(new Map<string, string>())\n const loadingContext = reactive(new Set<string>())\n\n const toggleDocument = (documentId: string) => {\n if (expandedDocuments.has(documentId)) {\n expandedDocuments.delete(documentId)\n } else {\n expandedDocuments.add(documentId)\n }\n }\n\n const toggleChunk = (chunkId: string) => {\n if (expandedChunks.has(chunkId)) {\n expandedChunks.delete(chunkId)\n } else {\n expandedChunks.add(chunkId)\n }\n }\n\n const handleExpandContext = async (source: SourceItem) => {\n if (source.chunkIndex == null || !props.onExpandContext) {\n return\n }\n loadingContext.add(source.chunkId)\n try {\n const content = await props.onExpandContext({\n documentId: source.documentId,\n chunkIndex: source.chunkIndex,\n })\n contextData.set(source.chunkId, content)\n } finally {\n loadingContext.delete(source.chunkId)\n }\n }\n\n const clearContext = (chunkId: string) => {\n contextData.delete(chunkId)\n }\n\n const showMore = ref(false)\n const visibleGroups = computed(() => {\n if (showMore.value) {\n return groupedSources.value\n }\n return groupedSources.value.slice(0, 3)\n })\n const hasMore = computed(() => groupedSources.value.length > 3)\n</script>\n\n<template>\n <div v-if=\"sources.length\" class=\"flex flex-col gap-xs w-full\">\n <div class=\"flex items-center gap-4 text-12 text-word-3 font-semibold\">\n <VvIcon name=\"ri:article-line\" class=\"text-14\" />\n {{ $t('label.sources') }}\n <span class=\"text-word-4 font-normal\">\n ({{ groupedSources.length }})\n </span>\n </div>\n\n <ul class=\"flex flex-col gap-xs\">\n <li\n v-for=\"group in visibleGroups\"\n :key=\"group.document.documentId\"\n class=\"border border-surface-3 rounded-xl overflow-hidden\">\n <!-- Document header -->\n <button\n class=\"flex items-center gap-8 p-8 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleDocument(group.document.documentId)\">\n <PkDocumentHeader\n :type=\"group.document.documentType\"\n :name=\"group.document.documentName\"\n :url=\"group.document.sourceUrl\"\n :filename=\"group.document.sourceFilename\" />\n <div class=\"flex items-center gap-4 shrink-0\">\n <span\n v-if=\"group.chunks.length > 1\"\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2\">\n {{ group.chunks.length }}\n </span>\n <span\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2 uppercase\">\n {{ group.document.language }}\n </span>\n <VvIcon\n :name=\"\n expandedDocuments.has(group.document.documentId)\n ? 'ri:arrow-up-s-line'\n : 'ri:arrow-down-s-line'\n \"\n class=\"text-16 text-word-3\" />\n </div>\n </button>\n\n <!-- Expanded content -->\n <div\n v-if=\"expandedDocuments.has(group.document.documentId)\"\n class=\"border-t border-surface-3\">\n <PkStreamingMarkdown\n v-if=\"group.document.sourceDescription\"\n :markdown=\"group.document.sourceDescription\"\n class=\"px-8 py-4 text-10 text-word-3 bg-surface-1 border-b border-surface-3\" />\n\n <!-- Chunk excerpts -->\n <div\n v-for=\"chunk in group.chunks\"\n :key=\"chunk.chunkId\"\n class=\"border-b border-surface-3 last:border-b-0\">\n <button\n class=\"flex items-center gap-8 px-8 py-6 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleChunk(chunk.chunkId)\">\n <PkChunkPreview\n :content=\"chunk.content\"\n :similarity=\"chunk.similarity\"\n :max-similarity=\"maxSimilarity\"\n :expanded=\"expandedChunks.has(chunk.chunkId)\" />\n </button>\n\n <!-- Expanded chunk content -->\n <div\n v-if=\"expandedChunks.has(chunk.chunkId)\"\n class=\"bg-surface-1 border-t border-surface-3\">\n <div class=\"p-8 text-10 text-word-3\">\n <transition mode=\"out-in\">\n <!-- Context expansion -->\n <PkStreamingMarkdown\n v-if=\"contextData.has(chunk.chunkId)\"\n :markdown=\"\n contextData.get(chunk.chunkId)!\n \"\n class=\"wysiwyg\" />\n\n <!-- Chunk content -->\n <PkStreamingMarkdown\n v-else\n :markdown=\"chunk.content\"\n class=\"wysiwyg\" />\n </transition>\n </div>\n\n <!-- Actions bar -->\n <div\n class=\"flex items-center gap-8 px-8 py-6 border-t border-surface-3 bg-surface\">\n <!-- Expand / collapse context -->\n <button\n v-if=\"\n onExpandContext &&\n chunk.chunkIndex != null &&\n !contextData.has(chunk.chunkId)\n \"\n class=\"text-10 text-word-3 hover:text-word flex items-center gap-4 cursor-pointer\"\n :disabled=\"\n loadingContext.has(chunk.chunkId)\n \"\n @click=\"handleExpandContext(chunk)\">\n <VvIcon\n :name=\"\n loadingContext.has(chunk.chunkId)\n ? 'line-md:loading-loop'\n : 'ri:expand-up-down-line'\n \"\n class=\"text-12\" />\n {{ $t('label.expandContext') }}\n </button>\n <button\n v-else-if=\"contextData.has(chunk.chunkId)\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n @click=\"clearContext(chunk.chunkId)\">\n <VvIcon\n name=\"ri:collapse-vertical-line\"\n class=\"text-12\" />\n {{ $t('label.collapseContext') }}\n </button>\n\n <!-- Open source URL -->\n <a\n v-if=\"chunk.sourceUrl\"\n :href=\"chunk.sourceUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 ml-auto\">\n <VvIcon\n name=\"ri:external-link-line\"\n class=\"text-12\" />\n {{ $t('label.openSource') }}\n </a>\n\n <!-- Download file -->\n <button\n v-if=\"\n onDownload &&\n chunk.documentType === 'file'\n \"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n :class=\"{\n 'ml-auto': !chunk.sourceUrl,\n }\"\n @click=\"onDownload(chunk.documentId)\">\n <VvIcon\n name=\"ri:download-line\"\n class=\"text-12\" />\n {{ $t('label.downloadFile') }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- Show more -->\n <button\n v-if=\"hasMore\"\n class=\"text-12 text-word-3 cursor-pointer hover:underline flex items-center gap-4 mx-auto\"\n @click=\"showMore = !showMore\">\n <VvIcon\n :name=\"showMore ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-16\" />\n {{\n showMore\n ? $t('action.showLess')\n : $t('action.showMore', {\n count: groupedSources.length - 3,\n })\n }}\n </button>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAII,IAAM,IAAQ,GAOR,IAAoB,QAAe;GACrC,IAAI,EAAM,cAAc,MACpB,OAAO;GAEX,IAAM,IACF,EAAM,iBAAiB,EAAM,gBAAgB,IACvC,EAAM,gBACN;GACV,OAAO,KAAK,MAAO,EAAM,aAAa,IAAO,GAAG;EACpD,CAAC;;;;IAID,EAAsE,GAAA;KAA9D,MAAK;KAAkB,OAAM;;IACrC,EAEO,QAAA;KAFD,OAAM;KAAuC,OAAO,EAAA;SACnD,EAAA,CAAA,CAAa,CAAC,EAAA,OAAO,CAAA,GAAA,GAAA,CAAA;IAEhB,EAAA,SAAiB,OAE7B,EAAA,IAAA,EAAA,KAF6B,EAAA,GAA7B,EAEO,QAFP,GAEO,EADA,EAAA,KAAiB,IAAG,MAC3B,CAAA;IACA,EAE2C,GAAA;KADtC,MAAM,EAAA,WAAQ,uBAAA;KACf,OAAM;;;;;;;;;;;;;;;;;;;;;;;;2BEnBV,EAE2C,GAAA;IADtC,MAAM,EAAA,CAAA,CAAW,CAAC,EAAA,IAAI;IACvB,OAAM;0BACV,EAaM,OAbN,GAaM;IAZF,EAES,UAFT,GAES,EADF,EAAA,IAAI,GAAA,CAAA;IAEC,EAAA,YAAA,EAAA,GAAZ,EAEO,QAFP,GAEO,EADA,EAAA,QAAQ,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;IAGL,EAAA,OAAA,EAAA,GADV,EAKO,QALP,GAKO,CAFH,EAAkD,GAAA;KAA1C,MAAK;KAAU,OAAM;QAC7B,EAAoB,GAAA,EAAZ,KAAK,EAAA,IAAG,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;EEPxB,IAAM,IAAQ,GASR,IAAW,QACN,EAAM,IAKhB,GAEK,IAAU,QAAe,EAAS,MAAM,OAAO,WAAW,CAAC,CAAC,GAE5D,IAAiB,QAAe;GAClC,IAAM,oBAAS,IAAI,IAGjB;GACF,KAAK,IAAM,KAAU,EAAQ,OAAO;IAChC,IAAM,IAAW,EAAO,IAAI,EAAO,UAAU;IAC7C,AAAI,IACA,EAAS,OAAO,KAAK,CAAM,IAE3B,EAAO,IAAI,EAAO,YAAY;KAC1B,UAAU;KACV,QAAQ,CAAC,CAAM;IACnB,CAAC;GAET;GACA,OAAO,CAAC,GAAG,EAAO,OAAO,CAAC;EAC9B,CAAC,GAEK,IAAgB,QACX,KAAK,IAAI,GAAG,EAAQ,MAAM,KAAK,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,CACpE,GAEK,IAAoB,kBAAS,IAAI,IAAY,CAAC,GAC9C,IAAiB,kBAAS,IAAI,IAAY,CAAC,GAC3C,IAAc,kBAAS,IAAI,IAAoB,CAAC,GAChD,IAAiB,kBAAS,IAAI,IAAY,CAAC,GAE3C,KAAkB,MAAuB;GAC3C,AAAI,EAAkB,IAAI,CAAU,IAChC,EAAkB,OAAO,CAAU,IAEnC,EAAkB,IAAI,CAAU;EAExC,GAEM,KAAe,MAAoB;GACrC,AAAI,EAAe,IAAI,CAAO,IAC1B,EAAe,OAAO,CAAO,IAE7B,EAAe,IAAI,CAAO;EAElC,GAEM,IAAsB,OAAO,MAAuB;GAClD,QAAO,cAAc,QAAQ,CAAC,EAAM,kBAGxC;MAAe,IAAI,EAAO,OAAO;IACjC,IAAI;KACA,IAAM,IAAU,MAAM,EAAM,gBAAgB;MACxC,YAAY,EAAO;MACnB,YAAY,EAAO;KACvB,CAAC;KACD,EAAY,IAAI,EAAO,SAAS,CAAO;IAC3C,UAAU;KACN,EAAe,OAAO,EAAO,OAAO;IACxC;GATiC;EAUrC,GAEM,KAAgB,MAAoB;GACtC,EAAY,OAAO,CAAO;EAC9B,GAEM,IAAW,EAAI,EAAK,GACpB,IAAgB,QACd,EAAS,QACF,EAAe,QAEnB,EAAe,MAAM,MAAM,GAAG,CAAC,CACzC,GACK,IAAU,QAAe,EAAe,MAAM,SAAS,CAAC;;;UAInD,EAAA,MAAQ,UAAA,EAAA,GAAnB,EA+KM,OA/KN,GA+KM;IA9KF,EAMM,OANN,GAMM;KALF,EAAiD,GAAA;MAAzC,MAAK;MAAkB,OAAM;;OAAY,MACjD,EAAGA,EAAAA,GAAE,eAAA,CAAA,IAAoB,KACzB,CAAA;KAAA,EAEO,QAFP,GAAsC,OACjC,EAAG,EAAA,MAAe,MAAM,IAAG,MAChC,CAAA;;IAGJ,EAoJK,MApJL,GAoJK,EAAA,EAAA,EAAA,GAnJD,EAkJK,GAAA,MAAA,EAjJe,EAAA,QAAT,YADX,EAkJK,MAAA;KAhJA,KAAK,EAAM,SAAS;KACrB,OAAM;QAEN,EA0BS,UAAA;KAzBL,OAAM;KACL,UAAK,MAAE,EAAe,EAAM,SAAS,UAAU;QAChD,EAIgD,GAAA;KAH3C,MAAM,EAAM,SAAS;KACrB,MAAM,EAAM,SAAS;KACrB,KAAK,EAAM,SAAS;KACpB,UAAU,EAAM,SAAS;;;;;;QAC9B,EAiBM,OAjBN,GAiBM;KAfQ,EAAM,OAAO,SAAM,KAAA,EAAA,GAD7B,EAIO,QAJP,GAIO,EADA,EAAM,OAAO,MAAM,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAE1B,EAGO,QAHP,GAGO,EADA,EAAM,SAAS,QAAQ,GAAA,CAAA;KAE9B,EAMkC,GAAA;MAL7B,MAAuC,EAAkB,IAAI,EAAM,SAAS,UAAU,IAAA,uBAAA;MAKvF,OAAM;;gBAMR,EAAkB,IAAI,EAAM,SAAS,UAAU,KAAA,EAAA,GADzD,EA+GM,OA/GN,GA+GM,CA3GQ,EAAM,SAAS,qBAAA,EAAA,GADzB,EAGmF,GAAA;;KAD9E,UAAU,EAAM,SAAS;KAC1B,OAAM;oDAGV,EAqGM,GAAA,MAAA,EApGc,EAAM,SAAf,YADX,EAqGM,OAAA;KAnGD,KAAK,EAAM;KACZ,OAAM;QACN,EAQS,UAAA;KAPL,OAAM;KACL,UAAK,MAAE,EAAY,EAAM,OAAO;QACjC,EAIoD,GAAA;KAH/C,SAAS,EAAM;KACf,YAAY,EAAM;KAClB,kBAAgB,EAAA;KAChB,UAAU,EAAe,IAAI,EAAM,OAAO;;;;;;gBAKzC,EAAe,IAAI,EAAM,OAAO,KAAA,EAAA,GAD1C,EAqFM,OArFN,GAqFM,CAlFF,EAgBM,OAhBN,GAgBM,CAfF,EAca,GAAA,EAdD,MAAK,SAAQ,GAAA;sBAOC,CAJZ,EAAY,IAAI,EAAM,OAAO,KAAA,EAAA,GADvC,EAKsB,GAAA;;MAHjB,UAAuD,EAAY,IAAI,EAAM,OAAO;MAGrF,OAAM;wCAGV,EAGsB,GAAA;;MADjB,UAAU,EAAM;MACjB,OAAM;;;gBAKlB,EA8DM,OA9DN,GA8DM;KA1DiD,EAAA,mBAA2D,EAAM,cAAU,QAAA,CAAqD,EAAY,IAAI,EAAM,OAAO,KAAA,EAAA,GADhN,EAmBS,UAAA;;MAbL,OAAM;MACL,UAAmD,EAAe,IAAI,EAAM,OAAO;MAGnF,UAAK,MAAE,EAAoB,CAAK;SACjC,EAMsB,GAAA;MALjB,MAAmD,EAAe,IAAI,EAAM,OAAO,IAAA,yBAAA;MAKpF,OAAM;8BAAY,MACtB,EAAGA,EAAAA,GAAE,qBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,KAGM,EAAY,IAAI,EAAM,OAAO,KAAA,EAAA,GAD5C,EAQS,UAAA;;MANL,OAAM;MACL,UAAK,MAAE,EAAa,EAAM,OAAO;SAClC,EAEsB,GAAA;MADlB,MAAK;MACL,OAAM;WAAY,MACtB,EAAGA,EAAAA,GAAE,uBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAKC,EAAM,aAAA,EAAA,GADhB,EAUI,KAAA;;MARC,MAAM,EAAM;MACb,QAAO;MACP,KAAI;MACJ,OAAM;SACN,EAEsB,GAAA;MADlB,MAAK;MACL,OAAM;WAAY,MACtB,EAAGA,EAAAA,GAAE,kBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAK0C,EAAA,cAAsD,EAAM,iBAAY,UAAA,EAAA,GAD3H,EAcS,UAAA;;MATL,OAAK,EAAA,CAAC,gFAA8E,EAAA,WAAA,CACtB,EAAM,UAAA,CAAA,CAAA;MAGnE,UAAK,MAAE,EAAA,WAAW,EAAM,UAAU;SACnC,EAEsB,GAAA;MADlB,MAAK;MACL,OAAM;WAAY,MACtB,EAAGA,EAAAA,GAAE,oBAAA,CAAA,GAAA,CAAA,CAAA,GAAA,IAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;IAWvB,EAAA,SAAA,EAAA,GADV,EAcS,UAAA;;KAZL,OAAM;KACL,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,QAAQ,CAAI,EAAA;QACpB,EAEsB,GAAA;KADjB,MAAM,EAAA,QAAQ,uBAAA;KACf,OAAM;6BAAY,MACtB,EACI,EAAA,QAA+BA,EAAAA,GAAE,iBAAA,IAA0CA,EAAAA,GAAE,mBAAA,EAAA,OAAuD,EAAA,MAAe,SAAM,EAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"PkToolShowSources-D2tBcx7n.js","names":["$t"],"sources":["../../../../packages/components/src/chat/PkChunkPreview.vue","../../../../packages/components/src/chat/PkChunkPreview.vue","../../../../packages/components/src/chat/PkDocumentHeader.vue","../../../../packages/components/src/chat/PkDocumentHeader.vue","../../../../packages/components/src/chat/PkToolShowSources.vue","../../../../packages/components/src/chat/PkToolShowSources.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { stripMarkdown } from 'utils'\n\n const props = defineProps<{\n content: string\n similarity?: number\n maxSimilarity?: number\n expanded: boolean\n }>()\n\n const similarityPercent = computed(() => {\n if (props.similarity == null) {\n return null\n }\n const max =\n props.maxSimilarity && props.maxSimilarity > 0\n ? props.maxSimilarity\n : 1\n return Math.round((props.similarity / max) * 100)\n })\n</script>\n\n<template>\n <VvIcon name=\"ri:text-snippet\" class=\"shrink-0 text-12 text-word-4\" />\n <span class=\"text-10 text-word-2 truncate flex-1\" :title=\"content\">\n {{ stripMarkdown(content) }}\n </span>\n <span v-if=\"similarityPercent != null\" class=\"text-10 text-word-4 shrink-0\">\n {{ similarityPercent }}%\n </span>\n <VvIcon\n :name=\"expanded ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-14 text-word-4 shrink-0\" />\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { stripMarkdown } from 'utils'\n\n const props = defineProps<{\n content: string\n similarity?: number\n maxSimilarity?: number\n expanded: boolean\n }>()\n\n const similarityPercent = computed(() => {\n if (props.similarity == null) {\n return null\n }\n const max =\n props.maxSimilarity && props.maxSimilarity > 0\n ? props.maxSimilarity\n : 1\n return Math.round((props.similarity / max) * 100)\n })\n</script>\n\n<template>\n <VvIcon name=\"ri:text-snippet\" class=\"shrink-0 text-12 text-word-4\" />\n <span class=\"text-10 text-word-2 truncate flex-1\" :title=\"content\">\n {{ stripMarkdown(content) }}\n </span>\n <span v-if=\"similarityPercent != null\" class=\"text-10 text-word-4 shrink-0\">\n {{ similarityPercent }}%\n </span>\n <VvIcon\n :name=\"expanded ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-14 text-word-4 shrink-0\" />\n</template>\n","<script setup lang=\"ts\">\n import type { DocumentType } from 'models'\n import { getTypeIcon } from 'models'\n import PkUrl from '../PkUrl.vue'\n\n defineProps<{\n type: string\n name: string\n url?: string\n filename?: string\n }>()\n</script>\n\n<template>\n <VvIcon\n :name=\"getTypeIcon(type as DocumentType)\"\n class=\"shrink-0 text-14 text-word-3\" />\n <div class=\"flex flex-col gap-2 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate block\">\n {{ name }}\n </strong>\n <span v-if=\"filename\" class=\"text-10 text-word-4 truncate\">\n {{ filename }}\n </span>\n <span\n v-if=\"url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-10\" />\n <PkUrl :url=\"url\" />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import type { DocumentType } from 'models'\n import { getTypeIcon } from 'models'\n import PkUrl from '../PkUrl.vue'\n\n defineProps<{\n type: string\n name: string\n url?: string\n filename?: string\n }>()\n</script>\n\n<template>\n <VvIcon\n :name=\"getTypeIcon(type as DocumentType)\"\n class=\"shrink-0 text-14 text-word-3\" />\n <div class=\"flex flex-col gap-2 min-w-0 flex-1\">\n <strong class=\"font-bold text-12 text-word-1 truncate block\">\n {{ name }}\n </strong>\n <span v-if=\"filename\" class=\"text-10 text-word-4 truncate\">\n {{ filename }}\n </span>\n <span\n v-if=\"url\"\n class=\"text-10 text-word-4 truncate flex items-center gap-4\">\n <VvIcon name=\"ri:link\" class=\"shrink-0 text-10\" />\n <PkUrl :url=\"url\" />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive } from 'vue'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChunkPreview from './PkChunkPreview.vue'\n import PkDocumentHeader from './PkDocumentHeader.vue'\n\n interface SourceItem {\n chunkId: string\n documentId: string\n documentName: string\n documentType: string\n language: string\n content: string\n chunkIndex?: number | null\n similarity?: number\n sourceUrl?: string\n sourceFilename?: string\n sourceDescription?: string\n sourceImageUrl?: string\n }\n\n const props = defineProps<{\n part: unknown\n onExpandContext?: (payload: {\n documentId: string\n chunkIndex: number\n }) => Promise<string>\n onDownload?: (documentId: string) => void\n }>()\n\n const toolPart = computed(() => {\n return props.part as {\n input?: {\n sources: SourceItem[]\n }\n }\n })\n\n const sources = computed(() => toolPart.value.input?.sources || [])\n\n const groupedSources = computed(() => {\n const groups = new Map<\n string,\n { document: SourceItem; chunks: SourceItem[] }\n >()\n for (const source of sources.value) {\n const existing = groups.get(source.documentId)\n if (existing) {\n existing.chunks.push(source)\n } else {\n groups.set(source.documentId, {\n document: source,\n chunks: [source],\n })\n }\n }\n return [...groups.values()]\n })\n\n const maxSimilarity = computed(() => {\n return Math.max(...sources.value.map((s) => s.similarity ?? 0), 0)\n })\n\n const expandedDocuments = reactive(new Set<string>())\n const expandedChunks = reactive(new Set<string>())\n const contextData = reactive(new Map<string, string>())\n const loadingContext = reactive(new Set<string>())\n\n const toggleDocument = (documentId: string) => {\n if (expandedDocuments.has(documentId)) {\n expandedDocuments.delete(documentId)\n } else {\n expandedDocuments.add(documentId)\n }\n }\n\n const toggleChunk = (chunkId: string) => {\n if (expandedChunks.has(chunkId)) {\n expandedChunks.delete(chunkId)\n } else {\n expandedChunks.add(chunkId)\n }\n }\n\n const handleExpandContext = async (source: SourceItem) => {\n if (source.chunkIndex == null || !props.onExpandContext) {\n return\n }\n loadingContext.add(source.chunkId)\n try {\n const content = await props.onExpandContext({\n documentId: source.documentId,\n chunkIndex: source.chunkIndex,\n })\n contextData.set(source.chunkId, content)\n } finally {\n loadingContext.delete(source.chunkId)\n }\n }\n\n const clearContext = (chunkId: string) => {\n contextData.delete(chunkId)\n }\n\n const showMore = ref(false)\n const visibleGroups = computed(() => {\n if (showMore.value) {\n return groupedSources.value\n }\n return groupedSources.value.slice(0, 3)\n })\n const hasMore = computed(() => groupedSources.value.length > 3)\n</script>\n\n<template>\n <div v-if=\"sources.length\" class=\"flex flex-col gap-xs w-full\">\n <div class=\"flex items-center gap-4 text-12 text-word-3 font-semibold\">\n <VvIcon name=\"ri:article-line\" class=\"text-14\" />\n {{ $t('label.sources') }}\n <span class=\"text-word-4 font-normal\">\n ({{ groupedSources.length }})\n </span>\n </div>\n\n <ul class=\"flex flex-col gap-xs\">\n <li\n v-for=\"group in visibleGroups\"\n :key=\"group.document.documentId\"\n class=\"border border-surface-3 rounded-xl overflow-hidden\">\n <!-- Document header -->\n <button\n class=\"flex items-center gap-8 p-8 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleDocument(group.document.documentId)\">\n <PkDocumentHeader\n :type=\"group.document.documentType\"\n :name=\"group.document.documentName\"\n :url=\"group.document.sourceUrl\"\n :filename=\"group.document.sourceFilename\" />\n <div class=\"flex items-center gap-4 shrink-0\">\n <span\n v-if=\"group.chunks.length > 1\"\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2\">\n {{ group.chunks.length }}\n </span>\n <span\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2 uppercase\">\n {{ group.document.language }}\n </span>\n <VvIcon\n :name=\"\n expandedDocuments.has(group.document.documentId)\n ? 'ri:arrow-up-s-line'\n : 'ri:arrow-down-s-line'\n \"\n class=\"text-16 text-word-3\" />\n </div>\n </button>\n\n <!-- Expanded content -->\n <div\n v-if=\"expandedDocuments.has(group.document.documentId)\"\n class=\"border-t border-surface-3\">\n <PkStreamingMarkdown\n v-if=\"group.document.sourceDescription\"\n :markdown=\"group.document.sourceDescription\"\n class=\"px-8 py-4 text-10 text-word-3 bg-surface-1 border-b border-surface-3\" />\n\n <!-- Chunk excerpts -->\n <div\n v-for=\"chunk in group.chunks\"\n :key=\"chunk.chunkId\"\n class=\"border-b border-surface-3 last:border-b-0\">\n <button\n class=\"flex items-center gap-8 px-8 py-6 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleChunk(chunk.chunkId)\">\n <PkChunkPreview\n :content=\"chunk.content\"\n :similarity=\"chunk.similarity\"\n :max-similarity=\"maxSimilarity\"\n :expanded=\"expandedChunks.has(chunk.chunkId)\" />\n </button>\n\n <!-- Expanded chunk content -->\n <div\n v-if=\"expandedChunks.has(chunk.chunkId)\"\n class=\"bg-surface-1 border-t border-surface-3\">\n <div class=\"p-8 text-10 text-word-3\">\n <transition mode=\"out-in\">\n <!-- Context expansion -->\n <PkStreamingMarkdown\n v-if=\"contextData.has(chunk.chunkId)\"\n :markdown=\"\n contextData.get(chunk.chunkId)!\n \"\n class=\"wysiwyg\" />\n\n <!-- Chunk content -->\n <PkStreamingMarkdown\n v-else\n :markdown=\"chunk.content\"\n class=\"wysiwyg\" />\n </transition>\n </div>\n\n <!-- Actions bar -->\n <div\n class=\"flex items-center gap-8 px-8 py-6 border-t border-surface-3 bg-surface\">\n <!-- Expand / collapse context -->\n <button\n v-if=\"\n onExpandContext &&\n chunk.chunkIndex != null &&\n !contextData.has(chunk.chunkId)\n \"\n class=\"text-10 text-word-3 hover:text-word flex items-center gap-4 cursor-pointer\"\n :disabled=\"\n loadingContext.has(chunk.chunkId)\n \"\n @click=\"handleExpandContext(chunk)\">\n <VvIcon\n :name=\"\n loadingContext.has(chunk.chunkId)\n ? 'line-md:loading-loop'\n : 'ri:expand-up-down-line'\n \"\n class=\"text-12\" />\n {{ $t('label.expandContext') }}\n </button>\n <button\n v-else-if=\"contextData.has(chunk.chunkId)\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n @click=\"clearContext(chunk.chunkId)\">\n <VvIcon\n name=\"ri:collapse-vertical-line\"\n class=\"text-12\" />\n {{ $t('label.collapseContext') }}\n </button>\n\n <!-- Open source URL -->\n <a\n v-if=\"chunk.sourceUrl\"\n :href=\"chunk.sourceUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 ml-auto\">\n <VvIcon\n name=\"ri:external-link-line\"\n class=\"text-12\" />\n {{ $t('label.openSource') }}\n </a>\n\n <!-- Download file -->\n <button\n v-if=\"\n onDownload &&\n chunk.documentType === 'file'\n \"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n :class=\"{\n 'ml-auto': !chunk.sourceUrl,\n }\"\n @click=\"onDownload(chunk.documentId)\">\n <VvIcon\n name=\"ri:download-line\"\n class=\"text-12\" />\n {{ $t('label.downloadFile') }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- Show more -->\n <button\n v-if=\"hasMore\"\n class=\"text-12 text-word-3 cursor-pointer hover:underline flex items-center gap-4 mx-auto\"\n @click=\"showMore = !showMore\">\n <VvIcon\n :name=\"showMore ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-16\" />\n {{\n showMore\n ? $t('action.showLess')\n : $t('action.showMore', {\n count: groupedSources.length - 3,\n })\n }}\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive } from 'vue'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkChunkPreview from './PkChunkPreview.vue'\n import PkDocumentHeader from './PkDocumentHeader.vue'\n\n interface SourceItem {\n chunkId: string\n documentId: string\n documentName: string\n documentType: string\n language: string\n content: string\n chunkIndex?: number | null\n similarity?: number\n sourceUrl?: string\n sourceFilename?: string\n sourceDescription?: string\n sourceImageUrl?: string\n }\n\n const props = defineProps<{\n part: unknown\n onExpandContext?: (payload: {\n documentId: string\n chunkIndex: number\n }) => Promise<string>\n onDownload?: (documentId: string) => void\n }>()\n\n const toolPart = computed(() => {\n return props.part as {\n input?: {\n sources: SourceItem[]\n }\n }\n })\n\n const sources = computed(() => toolPart.value.input?.sources || [])\n\n const groupedSources = computed(() => {\n const groups = new Map<\n string,\n { document: SourceItem; chunks: SourceItem[] }\n >()\n for (const source of sources.value) {\n const existing = groups.get(source.documentId)\n if (existing) {\n existing.chunks.push(source)\n } else {\n groups.set(source.documentId, {\n document: source,\n chunks: [source],\n })\n }\n }\n return [...groups.values()]\n })\n\n const maxSimilarity = computed(() => {\n return Math.max(...sources.value.map((s) => s.similarity ?? 0), 0)\n })\n\n const expandedDocuments = reactive(new Set<string>())\n const expandedChunks = reactive(new Set<string>())\n const contextData = reactive(new Map<string, string>())\n const loadingContext = reactive(new Set<string>())\n\n const toggleDocument = (documentId: string) => {\n if (expandedDocuments.has(documentId)) {\n expandedDocuments.delete(documentId)\n } else {\n expandedDocuments.add(documentId)\n }\n }\n\n const toggleChunk = (chunkId: string) => {\n if (expandedChunks.has(chunkId)) {\n expandedChunks.delete(chunkId)\n } else {\n expandedChunks.add(chunkId)\n }\n }\n\n const handleExpandContext = async (source: SourceItem) => {\n if (source.chunkIndex == null || !props.onExpandContext) {\n return\n }\n loadingContext.add(source.chunkId)\n try {\n const content = await props.onExpandContext({\n documentId: source.documentId,\n chunkIndex: source.chunkIndex,\n })\n contextData.set(source.chunkId, content)\n } finally {\n loadingContext.delete(source.chunkId)\n }\n }\n\n const clearContext = (chunkId: string) => {\n contextData.delete(chunkId)\n }\n\n const showMore = ref(false)\n const visibleGroups = computed(() => {\n if (showMore.value) {\n return groupedSources.value\n }\n return groupedSources.value.slice(0, 3)\n })\n const hasMore = computed(() => groupedSources.value.length > 3)\n</script>\n\n<template>\n <div v-if=\"sources.length\" class=\"flex flex-col gap-xs w-full\">\n <div class=\"flex items-center gap-4 text-12 text-word-3 font-semibold\">\n <VvIcon name=\"ri:article-line\" class=\"text-14\" />\n {{ $t('label.sources') }}\n <span class=\"text-word-4 font-normal\">\n ({{ groupedSources.length }})\n </span>\n </div>\n\n <ul class=\"flex flex-col gap-xs\">\n <li\n v-for=\"group in visibleGroups\"\n :key=\"group.document.documentId\"\n class=\"border border-surface-3 rounded-xl overflow-hidden\">\n <!-- Document header -->\n <button\n class=\"flex items-center gap-8 p-8 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleDocument(group.document.documentId)\">\n <PkDocumentHeader\n :type=\"group.document.documentType\"\n :name=\"group.document.documentName\"\n :url=\"group.document.sourceUrl\"\n :filename=\"group.document.sourceFilename\" />\n <div class=\"flex items-center gap-4 shrink-0\">\n <span\n v-if=\"group.chunks.length > 1\"\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2\">\n {{ group.chunks.length }}\n </span>\n <span\n class=\"text-10 text-word-4 bg-surface-2 rounded px-4 py-2 uppercase\">\n {{ group.document.language }}\n </span>\n <VvIcon\n :name=\"\n expandedDocuments.has(group.document.documentId)\n ? 'ri:arrow-up-s-line'\n : 'ri:arrow-down-s-line'\n \"\n class=\"text-16 text-word-3\" />\n </div>\n </button>\n\n <!-- Expanded content -->\n <div\n v-if=\"expandedDocuments.has(group.document.documentId)\"\n class=\"border-t border-surface-3\">\n <PkStreamingMarkdown\n v-if=\"group.document.sourceDescription\"\n :markdown=\"group.document.sourceDescription\"\n class=\"px-8 py-4 text-10 text-word-3 bg-surface-1 border-b border-surface-3\" />\n\n <!-- Chunk excerpts -->\n <div\n v-for=\"chunk in group.chunks\"\n :key=\"chunk.chunkId\"\n class=\"border-b border-surface-3 last:border-b-0\">\n <button\n class=\"flex items-center gap-8 px-8 py-6 w-full text-left hover:bg-surface-1 transition-colors cursor-pointer\"\n @click=\"toggleChunk(chunk.chunkId)\">\n <PkChunkPreview\n :content=\"chunk.content\"\n :similarity=\"chunk.similarity\"\n :max-similarity=\"maxSimilarity\"\n :expanded=\"expandedChunks.has(chunk.chunkId)\" />\n </button>\n\n <!-- Expanded chunk content -->\n <div\n v-if=\"expandedChunks.has(chunk.chunkId)\"\n class=\"bg-surface-1 border-t border-surface-3\">\n <div class=\"p-8 text-10 text-word-3\">\n <transition mode=\"out-in\">\n <!-- Context expansion -->\n <PkStreamingMarkdown\n v-if=\"contextData.has(chunk.chunkId)\"\n :markdown=\"\n contextData.get(chunk.chunkId)!\n \"\n class=\"wysiwyg\" />\n\n <!-- Chunk content -->\n <PkStreamingMarkdown\n v-else\n :markdown=\"chunk.content\"\n class=\"wysiwyg\" />\n </transition>\n </div>\n\n <!-- Actions bar -->\n <div\n class=\"flex items-center gap-8 px-8 py-6 border-t border-surface-3 bg-surface\">\n <!-- Expand / collapse context -->\n <button\n v-if=\"\n onExpandContext &&\n chunk.chunkIndex != null &&\n !contextData.has(chunk.chunkId)\n \"\n class=\"text-10 text-word-3 hover:text-word flex items-center gap-4 cursor-pointer\"\n :disabled=\"\n loadingContext.has(chunk.chunkId)\n \"\n @click=\"handleExpandContext(chunk)\">\n <VvIcon\n :name=\"\n loadingContext.has(chunk.chunkId)\n ? 'line-md:loading-loop'\n : 'ri:expand-up-down-line'\n \"\n class=\"text-12\" />\n {{ $t('label.expandContext') }}\n </button>\n <button\n v-else-if=\"contextData.has(chunk.chunkId)\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n @click=\"clearContext(chunk.chunkId)\">\n <VvIcon\n name=\"ri:collapse-vertical-line\"\n class=\"text-12\" />\n {{ $t('label.collapseContext') }}\n </button>\n\n <!-- Open source URL -->\n <a\n v-if=\"chunk.sourceUrl\"\n :href=\"chunk.sourceUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 ml-auto\">\n <VvIcon\n name=\"ri:external-link-line\"\n class=\"text-12\" />\n {{ $t('label.openSource') }}\n </a>\n\n <!-- Download file -->\n <button\n v-if=\"\n onDownload &&\n chunk.documentType === 'file'\n \"\n class=\"text-10 text-word-3 hover:text-word-1 flex items-center gap-4 cursor-pointer\"\n :class=\"{\n 'ml-auto': !chunk.sourceUrl,\n }\"\n @click=\"onDownload(chunk.documentId)\">\n <VvIcon\n name=\"ri:download-line\"\n class=\"text-12\" />\n {{ $t('label.downloadFile') }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </li>\n </ul>\n\n <!-- Show more -->\n <button\n v-if=\"hasMore\"\n class=\"text-12 text-word-3 cursor-pointer hover:underline flex items-center gap-4 mx-auto\"\n @click=\"showMore = !showMore\">\n <VvIcon\n :name=\"showMore ? 'ri:arrow-up-s-line' : 'ri:arrow-down-s-line'\"\n class=\"text-16\" />\n {{\n showMore\n ? $t('action.showLess')\n : $t('action.showMore', {\n count: groupedSources.length - 3,\n })\n }}\n </button>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { A as e, C as t, Ht as n, T as r, V as i, _ as a, at as o, b as s, f as c, g as l, i as u, kt as d, mt as f, p, qt as m, y as h, z as g } from "./vue.runtime.esm-bundler-DbhD_IvR.js";
2
- import { l as _ } from "./index.es-BYny0uhz.js";
2
+ import { f as _ } from "./index.es-_oXVRjHy.js";
3
3
  import { t as v } from "./_plugin-vue_export-helper-B3ysoDQm.js";
4
4
  e(), d(), u(), o();
5
5
  var y = {
@@ -44,4 +44,4 @@ var y = {
44
44
  //#endregion
45
45
  export { x as default };
46
46
 
47
- //# sourceMappingURL=PkToolShowSuggestedReply-QEcIhSxa.js.map
47
+ //# sourceMappingURL=PkToolShowSuggestedReply-Cdh_elSh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowSuggestedReply-QEcIhSxa.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n"],"mappings":";;;;;;;;;;;;EAKI,IAAM,IAAQ,GAIR,IAAO,GAIP,IAAW,QACN,KAAK,MAAM,KAAK,UAAU,EAAM,IAAI,CAAC,CAY/C,GAGK,IAAc,QAA6B;GAC7C,IAAM,IAAQ,EAAS,OAAO;GAW9B,OAVK,IAGD,EAAM,aAAa,SACZ,EAAM,cAGb,EAAM,QACC,CAAC;IAAE,OAAO,EAAM;IAAO,QAAQ,EAAM,UAAU,EAAM;GAAM,CAAC,IAEhE,CAAC,IATG,CAAC;EAUhB,CAAC,GAEK,IAAe,EAAmB,IAAI,GAEtC,IAAgB,QAEd,EAAS,OAAO,UAAU,qBAC1B,EAAa,UAAU,IAE9B;EAED,SAAS,EAAY,GAAe;GAChC,IAAI,CAAC,EAAc,OACf;GAEJ,EAAa,QAAQ;GACrB,IAAM,IAAa,EAAY,MAAM,IAC/B,IAAQ,GAAY,UAAU,GAAY;GAChD,AAAI,KACA,EAAK,UAAU,CAAK;EAE5B;;;UAIW,EAAA,MAAY,UAAA,EAAA,GAAvB,EAiBM,OAjBN,GAiBM,EAAA,EAAA,EAAA,GAhBF,EAeS,GAAA,MAAA,EAdyB,EAAA,QAAtB,GAAY,YADxB,EAeS,UAAA;IAbJ,KAAK;IACN,MAAK;IACL,OAAK,EAAA,CAAC,iCAA+B;mBACG,EAAA,UAAiB;qBAAuC,EAAA;;IAI/F,UAAQ,CAAG,EAAA;IACX,SAAK,GAAA,MAAO,EAAY,CAAK,GAAA,CAAA,MAAA,CAAA;OAC9B,EAE4C,GAAA;IADxC,MAAK;IACL,OAAM;OACV,EAAmC,QAAA,MAAA,EAA1B,EAAW,KAAK,GAAA,CAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"PkToolShowSuggestedReply-Cdh_elSh.js","names":[],"sources":["../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue","../../../../packages/components/src/chat/PkToolShowSuggestedReply.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, ref } from 'vue'\n\n type Suggestion = { label: string; prompt?: string }\n\n const props = defineProps<{\n part: unknown\n }>()\n\n const emit = defineEmits<{\n select: [value: string]\n }>()\n\n const toolPart = computed(() => {\n return JSON.parse(JSON.stringify(props.part)) as {\n state?: string\n toolCallId?: string\n input?: {\n /** New schema: array of suggestions */\n suggestions?: Suggestion[]\n /** Legacy schema: single suggestion */\n label?: string\n prompt?: string\n }\n output?: string\n }\n })\n\n /** Normalize to always work with an array of suggestions */\n const suggestions = computed<Suggestion[]>(() => {\n const input = toolPart.value?.input\n if (!input) {\n return []\n }\n if (input.suggestions?.length) {\n return input.suggestions\n }\n // Legacy single-suggestion format (client-side fallback)\n if (input.label) {\n return [{ label: input.label, prompt: input.prompt ?? input.label }]\n }\n return []\n })\n\n const clickedIndex = ref<number | null>(null)\n\n const isInteractive = computed(() => {\n return (\n toolPart.value?.state === 'input-available' &&\n clickedIndex.value === null\n )\n })\n\n function handleClick(index: number) {\n if (!isInteractive.value) {\n return\n }\n clickedIndex.value = index\n const suggestion = suggestions.value[index]\n const value = suggestion?.prompt ?? suggestion?.label\n if (value) {\n emit('select', value)\n }\n }\n</script>\n\n<template>\n <div v-if=\"suggestions.length\" class=\"pk-tool-suggested-reply\">\n <button\n v-for=\"(suggestion, index) in suggestions\"\n :key=\"index\"\n type=\"button\"\n class=\"pk-tool-suggested-reply__link\"\n :class=\"{\n 'is-clicked': clickedIndex === index,\n 'is-disabled': !isInteractive,\n }\"\n :disabled=\"!isInteractive\"\n @click.stop=\"handleClick(index)\">\n <VvIcon\n name=\"ri:corner-down-right-line\"\n class=\"pk-tool-suggested-reply__icon\" />\n <span>{{ suggestion.label }}</span>\n </button>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-suggested-reply {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-4);\n\n &__link {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-4);\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n font-size: var(--text-12);\n text-decoration: underline;\n text-underline-offset: 2px;\n cursor: pointer;\n color: var(--color-word-3);\n transition: var(--transition-colors);\n\n &:hover:not(:disabled) {\n color: var(--color-word);\n }\n\n &.is-disabled {\n cursor: default;\n pointer-events: none;\n color: var(--color-word-5);\n }\n\n &.is-clicked {\n color: var(--color-word-5);\n text-decoration: none;\n }\n }\n\n &__icon {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n }\n }\n</style>\n"],"mappings":";;;;;;;;;;;;EAKI,IAAM,IAAQ,GAIR,IAAO,GAIP,IAAW,QACN,KAAK,MAAM,KAAK,UAAU,EAAM,IAAI,CAAC,CAY/C,GAGK,IAAc,QAA6B;GAC7C,IAAM,IAAQ,EAAS,OAAO;GAW9B,OAVK,IAGD,EAAM,aAAa,SACZ,EAAM,cAGb,EAAM,QACC,CAAC;IAAE,OAAO,EAAM;IAAO,QAAQ,EAAM,UAAU,EAAM;GAAM,CAAC,IAEhE,CAAC,IATG,CAAC;EAUhB,CAAC,GAEK,IAAe,EAAmB,IAAI,GAEtC,IAAgB,QAEd,EAAS,OAAO,UAAU,qBAC1B,EAAa,UAAU,IAE9B;EAED,SAAS,EAAY,GAAe;GAChC,IAAI,CAAC,EAAc,OACf;GAEJ,EAAa,QAAQ;GACrB,IAAM,IAAa,EAAY,MAAM,IAC/B,IAAQ,GAAY,UAAU,GAAY;GAChD,AAAI,KACA,EAAK,UAAU,CAAK;EAE5B;;;UAIW,EAAA,MAAY,UAAA,EAAA,GAAvB,EAiBM,OAjBN,GAiBM,EAAA,EAAA,EAAA,GAhBF,EAeS,GAAA,MAAA,EAdyB,EAAA,QAAtB,GAAY,YADxB,EAeS,UAAA;IAbJ,KAAK;IACN,MAAK;IACL,OAAK,EAAA,CAAC,iCAA+B;mBACG,EAAA,UAAiB;qBAAuC,EAAA;;IAI/F,UAAQ,CAAG,EAAA;IACX,SAAK,GAAA,MAAO,EAAY,CAAK,GAAA,CAAA,MAAA,CAAA;OAC9B,EAE4C,GAAA;IADxC,MAAK;IACL,OAAM;OACV,EAAmC,QAAA,MAAA,EAA1B,EAAW,KAAK,GAAA,CAAA,CAAA,GAAA,IAAA,CAAA"}