@8wave/ai-elements 0.117.0-beta.29 → 0.117.0-beta.30

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 (23) hide show
  1. package/dist/_chunks/PkToolShowVideo-C5RfIsFU.js +141 -0
  2. package/dist/_chunks/PkToolShowVideo-C5RfIsFU.js.map +1 -0
  3. package/dist/ai-elements.es.js +1 -1
  4. package/dist-vue/PkChatbot.js +1 -1
  5. package/dist-vue/PkChatbotMessages.js +1 -1
  6. package/dist-vue/PkChatbotViewChat.js +1 -1
  7. package/dist-vue/_chunks/{PkChatbot-BsTXbdI2.js → PkChatbot-DP2XuKXf.js} +2 -2
  8. package/dist-vue/_chunks/{PkChatbot-BsTXbdI2.js.map → PkChatbot-DP2XuKXf.js.map} +1 -1
  9. package/dist-vue/_chunks/{PkChatbotMessages-BDh_t2MT.js → PkChatbotMessages-CVefdmkP.js} +3 -3
  10. package/dist-vue/_chunks/{PkChatbotMessages-BDh_t2MT.js.map → PkChatbotMessages-CVefdmkP.js.map} +1 -1
  11. package/dist-vue/_chunks/{PkChatbotViewChat-Cd5t_ESd.js → PkChatbotViewChat-BOankj81.js} +3 -3
  12. package/dist-vue/_chunks/{PkChatbotViewChat-Cd5t_ESd.js.map → PkChatbotViewChat-BOankj81.js.map} +1 -1
  13. package/dist-vue/_chunks/{PkToolShowDiagram-ysQaeMuo.js → PkToolShowDiagram-CjtKqj4N.js} +2 -2
  14. package/dist-vue/_chunks/{PkToolShowDiagram-ysQaeMuo.js.map → PkToolShowDiagram-CjtKqj4N.js.map} +1 -1
  15. package/dist-vue/_chunks/PkToolShowVideo-Cw2QqlRI.js +140 -0
  16. package/dist-vue/_chunks/PkToolShowVideo-Cw2QqlRI.js.map +1 -0
  17. package/dist-vue/index.js +7 -7
  18. package/dist-vue/index.js.map +1 -1
  19. package/package.json +1 -1
  20. package/dist/_chunks/PkToolShowVideo-he5c61Er.js +0 -142
  21. package/dist/_chunks/PkToolShowVideo-he5c61Er.js.map +0 -1
  22. package/dist-vue/_chunks/PkToolShowVideo-DNqbPNq7.js +0 -141
  23. package/dist-vue/_chunks/PkToolShowVideo-DNqbPNq7.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { a as e } from "./PkChatbotMessages-BDh_t2MT.js";
1
+ import { a as e } from "./PkChatbotMessages-CVefdmkP.js";
2
2
  import "./src-DCfvejyT.js";
3
3
  import { t } from "./PkSvgViewer-Ts3gQ1hB.js";
4
4
  import { VvButton as n, VvButtonGroup as r, VvIcon as i } from "@volverjs/ui-vue/components";
@@ -119,4 +119,4 @@ var x = {
119
119
  //#endregion
120
120
  export { k as default };
121
121
 
122
- //# sourceMappingURL=PkToolShowDiagram-ysQaeMuo.js.map
122
+ //# sourceMappingURL=PkToolShowDiagram-CjtKqj4N.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PkToolShowDiagram-ysQaeMuo.js","names":["__unplugin_components_0","__unplugin_components_1","__unplugin_components_2","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_toDisplayString","_unref","_withCtx","_createBlock","_createCommentVNode","PkSvgViewer","_sfc_main","toSnakeCase","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","DiagramType","\"Sequence\"","\"Class\"","\"State\"","\"ER\"","\"XYChart\"","\"Flowchart\"","\"Graph\"","PkToolShowDiagram_default","defineComponent","props","__props","$t","$te","useI18n","useClipboard","toolPart","computed","svgError","ref","svgContent","diagramType","code","diagramTypeLabel","diagramTypeIcon","renderDiagram","theme","THEMES","renderMermaidSVG","watch","onMounted","downloadSvg","blob","url","anchor","copyCode","copy","_component_VvIcon","VvIcon","_component_VvButton","VvButton","_component_VvButtonGroup","VvButtonGroup","openBlock","createElementBlock","createElementVNode","createVNode","toDisplayString","unref","withCtx","copied","createBlock","createCommentVNode","PkSvgViewer_default"],"sources":["../../../../packages/components/src/chat/PkToolShowDiagram.vue","../../../../packages/components/src/chat/PkToolShowDiagram.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, onMounted, ref, watch } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useI18n } from 'vue-i18n'\n import { toSnakeCase } from 'utils'\n import PkSvgViewer from '../PkSvgViewer.vue'\n\n const props = defineProps<{\n part: unknown\n isDark?: boolean\n }>()\n\n const { t: $t, te: $te } = useI18n({\n useScope: 'global',\n })\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n code: string\n title?: string\n caption?: string\n }\n }\n return part\n })\n\n const svgError = ref(false)\n\n // Serialized SVG content\n const svgContent = ref('')\n\n enum DiagramType {\n Sequence = 'sequenceDiagram',\n Class = 'classDiagram',\n State = 'stateDiagram',\n ER = 'erDiagram',\n XYChart = 'xychart',\n Flowchart = 'flowchart',\n Graph = 'graph',\n }\n\n const diagramType = computed<DiagramType | undefined>(() => {\n const code = toolPart.value.input?.code?.trimStart()\n if (!code) {\n return undefined\n }\n const firstWord = code.match(/^[A-Za-z-]+/)?.[0]\n switch (firstWord) {\n case 'sequenceDiagram':\n return DiagramType.Sequence\n case 'classDiagram':\n return DiagramType.Class\n case 'stateDiagram':\n return DiagramType.State\n case 'erDiagram':\n return DiagramType.ER\n case 'xychart-beta':\n return DiagramType.XYChart\n case 'flowchart':\n return DiagramType.Flowchart\n case 'graph':\n return DiagramType.Graph\n default:\n return undefined\n }\n })\n\n const diagramTypeLabel = computed(() => {\n if (!diagramType.value) {\n return ''\n }\n return $te(`diagram.${diagramType.value}`)\n ? $t(`diagram.${diagramType.value}`)\n : diagramType.value\n })\n\n const diagramTypeIcon = computed(() => {\n switch (diagramType.value) {\n case DiagramType.Sequence:\n return 'ri:timeline-view'\n case DiagramType.Class:\n return 'ri:organization-chart'\n case DiagramType.State:\n return 'ri:organization-chart'\n case DiagramType.ER:\n return 'ri:organization-chart'\n case DiagramType.XYChart:\n return 'ri:line-chart-line'\n case DiagramType.Flowchart:\n return 'ri:flow-chart'\n case DiagramType.Graph:\n return 'ri:flow-chart'\n default:\n return 'ri:flow-chart'\n }\n })\n\n async function renderDiagram() {\n const code = toolPart.value.input?.code\n if (!code) {\n return\n }\n\n svgError.value = false\n try {\n const { renderMermaidSVG, THEMES } =\n await import('beautiful-mermaid')\n const theme = props.isDark\n ? THEMES['github-dark']\n : THEMES['github-light']\n svgContent.value = renderMermaidSVG(code, theme)\n } catch {\n svgError.value = true\n }\n }\n\n watch([() => toolPart.value.input?.code, () => props.isDark], renderDiagram)\n onMounted(async () => {\n await renderDiagram()\n })\n\n const downloadSvg = () => {\n if (!svgContent.value) {\n return\n }\n const blob = new Blob([svgContent.value], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const url = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = url\n anchor.download = `${toSnakeCase(toolPart.value.input?.title || 'diagram')}.svg`\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n URL.revokeObjectURL(url)\n }\n\n const copyCode = () => {\n const code = toolPart.value.input?.code\n if (code) {\n copy(code)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input?.code\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden\">\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=\"diagramTypeIcon\" class=\"text-16\" />\n <div class=\"flex flex-col items-start gap-2\">\n <strong class=\"font-bold\">{{\n diagramTypeLabel ?? $t('label.diagram')\n }}</strong>\n </div>\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=\"copyCode\" />\n <VvButton\n v-if=\"svgContent\"\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadSvg\" />\n </VvButtonGroup>\n </div>\n <div v-if=\"svgError\" class=\"text-12 text-danger py-8 px-sm\">\n {{ $t('message.diagramRenderError') }}\n </div>\n <PkSvgViewer\n v-else-if=\"svgContent\"\n class=\"pk-tool-show-diagram__stage\"\n :svg=\"svgContent\"\n :title=\"toolPart.input?.title\" />\n <div\n v-else\n class=\"pk-tool-show-diagram__stage flex justify-center items-center\">\n <VvIcon name=\"loading-loop\" class=\"w-24 h-24 text-word-5\" />\n </div>\n <div\n v-if=\"toolPart.input.caption\"\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-t border-surface-3 text-word-3\">\n {{ toolPart.input.caption }}\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-show-diagram {\n // Fixed stage height: the diagram renders lazily (async chunk +\n // dynamic mermaid import), so the loader and the rendered SVG must\n // occupy the same space or the chat scroll position jumps around.\n // The SVG scales to fit; zoom/pan and the lightbox cover the rest.\n &__stage {\n height: 384px;\n\n .pk-svg-viewer__stage,\n .pk-svg-viewer__content {\n height: 100%;\n }\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, onMounted, ref, watch } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useI18n } from 'vue-i18n'\n import { toSnakeCase } from 'utils'\n import PkSvgViewer from '../PkSvgViewer.vue'\n\n const props = defineProps<{\n part: unknown\n isDark?: boolean\n }>()\n\n const { t: $t, te: $te } = useI18n({\n useScope: 'global',\n })\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n code: string\n title?: string\n caption?: string\n }\n }\n return part\n })\n\n const svgError = ref(false)\n\n // Serialized SVG content\n const svgContent = ref('')\n\n enum DiagramType {\n Sequence = 'sequenceDiagram',\n Class = 'classDiagram',\n State = 'stateDiagram',\n ER = 'erDiagram',\n XYChart = 'xychart',\n Flowchart = 'flowchart',\n Graph = 'graph',\n }\n\n const diagramType = computed<DiagramType | undefined>(() => {\n const code = toolPart.value.input?.code?.trimStart()\n if (!code) {\n return undefined\n }\n const firstWord = code.match(/^[A-Za-z-]+/)?.[0]\n switch (firstWord) {\n case 'sequenceDiagram':\n return DiagramType.Sequence\n case 'classDiagram':\n return DiagramType.Class\n case 'stateDiagram':\n return DiagramType.State\n case 'erDiagram':\n return DiagramType.ER\n case 'xychart-beta':\n return DiagramType.XYChart\n case 'flowchart':\n return DiagramType.Flowchart\n case 'graph':\n return DiagramType.Graph\n default:\n return undefined\n }\n })\n\n const diagramTypeLabel = computed(() => {\n if (!diagramType.value) {\n return ''\n }\n return $te(`diagram.${diagramType.value}`)\n ? $t(`diagram.${diagramType.value}`)\n : diagramType.value\n })\n\n const diagramTypeIcon = computed(() => {\n switch (diagramType.value) {\n case DiagramType.Sequence:\n return 'ri:timeline-view'\n case DiagramType.Class:\n return 'ri:organization-chart'\n case DiagramType.State:\n return 'ri:organization-chart'\n case DiagramType.ER:\n return 'ri:organization-chart'\n case DiagramType.XYChart:\n return 'ri:line-chart-line'\n case DiagramType.Flowchart:\n return 'ri:flow-chart'\n case DiagramType.Graph:\n return 'ri:flow-chart'\n default:\n return 'ri:flow-chart'\n }\n })\n\n async function renderDiagram() {\n const code = toolPart.value.input?.code\n if (!code) {\n return\n }\n\n svgError.value = false\n try {\n const { renderMermaidSVG, THEMES } =\n await import('beautiful-mermaid')\n const theme = props.isDark\n ? THEMES['github-dark']\n : THEMES['github-light']\n svgContent.value = renderMermaidSVG(code, theme)\n } catch {\n svgError.value = true\n }\n }\n\n watch([() => toolPart.value.input?.code, () => props.isDark], renderDiagram)\n onMounted(async () => {\n await renderDiagram()\n })\n\n const downloadSvg = () => {\n if (!svgContent.value) {\n return\n }\n const blob = new Blob([svgContent.value], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const url = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = url\n anchor.download = `${toSnakeCase(toolPart.value.input?.title || 'diagram')}.svg`\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n URL.revokeObjectURL(url)\n }\n\n const copyCode = () => {\n const code = toolPart.value.input?.code\n if (code) {\n copy(code)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input?.code\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden\">\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=\"diagramTypeIcon\" class=\"text-16\" />\n <div class=\"flex flex-col items-start gap-2\">\n <strong class=\"font-bold\">{{\n diagramTypeLabel ?? $t('label.diagram')\n }}</strong>\n </div>\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=\"copyCode\" />\n <VvButton\n v-if=\"svgContent\"\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadSvg\" />\n </VvButtonGroup>\n </div>\n <div v-if=\"svgError\" class=\"text-12 text-danger py-8 px-sm\">\n {{ $t('message.diagramRenderError') }}\n </div>\n <PkSvgViewer\n v-else-if=\"svgContent\"\n class=\"pk-tool-show-diagram__stage\"\n :svg=\"svgContent\"\n :title=\"toolPart.input?.title\" />\n <div\n v-else\n class=\"pk-tool-show-diagram__stage flex justify-center items-center\">\n <VvIcon name=\"loading-loop\" class=\"w-24 h-24 text-word-5\" />\n </div>\n <div\n v-if=\"toolPart.input.caption\"\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-t border-surface-3 text-word-3\">\n {{ toolPart.input.caption }}\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-show-diagram {\n // Fixed stage height: the diagram renders lazily (async chunk +\n // dynamic mermaid import), so the loader and the rendered SVG must\n // occupy the same space or the chat scroll position jumps around.\n // The SVG scales to fit; zoom/pan and the lightbox cover the rest.\n &__stage {\n height: 384px;\n\n .pk-svg-viewer__stage,\n .pk-svg-viewer__content {\n height: 100%;\n }\n }\n }\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"PkToolShowDiagram-CjtKqj4N.js","names":["__unplugin_components_0","__unplugin_components_1","__unplugin_components_2","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_toDisplayString","_unref","_withCtx","_createBlock","_createCommentVNode","PkSvgViewer","_sfc_main","toSnakeCase","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","DiagramType","\"Sequence\"","\"Class\"","\"State\"","\"ER\"","\"XYChart\"","\"Flowchart\"","\"Graph\"","PkToolShowDiagram_default","defineComponent","props","__props","$t","$te","useI18n","useClipboard","toolPart","computed","svgError","ref","svgContent","diagramType","code","diagramTypeLabel","diagramTypeIcon","renderDiagram","theme","THEMES","renderMermaidSVG","watch","onMounted","downloadSvg","blob","url","anchor","copyCode","copy","_component_VvIcon","VvIcon","_component_VvButton","VvButton","_component_VvButtonGroup","VvButtonGroup","openBlock","createElementBlock","createElementVNode","createVNode","toDisplayString","unref","withCtx","copied","createBlock","createCommentVNode","PkSvgViewer_default"],"sources":["../../../../packages/components/src/chat/PkToolShowDiagram.vue","../../../../packages/components/src/chat/PkToolShowDiagram.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed, onMounted, ref, watch } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useI18n } from 'vue-i18n'\n import { toSnakeCase } from 'utils'\n import PkSvgViewer from '../PkSvgViewer.vue'\n\n const props = defineProps<{\n part: unknown\n isDark?: boolean\n }>()\n\n const { t: $t, te: $te } = useI18n({\n useScope: 'global',\n })\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n code: string\n title?: string\n caption?: string\n }\n }\n return part\n })\n\n const svgError = ref(false)\n\n // Serialized SVG content\n const svgContent = ref('')\n\n enum DiagramType {\n Sequence = 'sequenceDiagram',\n Class = 'classDiagram',\n State = 'stateDiagram',\n ER = 'erDiagram',\n XYChart = 'xychart',\n Flowchart = 'flowchart',\n Graph = 'graph',\n }\n\n const diagramType = computed<DiagramType | undefined>(() => {\n const code = toolPart.value.input?.code?.trimStart()\n if (!code) {\n return undefined\n }\n const firstWord = code.match(/^[A-Za-z-]+/)?.[0]\n switch (firstWord) {\n case 'sequenceDiagram':\n return DiagramType.Sequence\n case 'classDiagram':\n return DiagramType.Class\n case 'stateDiagram':\n return DiagramType.State\n case 'erDiagram':\n return DiagramType.ER\n case 'xychart-beta':\n return DiagramType.XYChart\n case 'flowchart':\n return DiagramType.Flowchart\n case 'graph':\n return DiagramType.Graph\n default:\n return undefined\n }\n })\n\n const diagramTypeLabel = computed(() => {\n if (!diagramType.value) {\n return ''\n }\n return $te(`diagram.${diagramType.value}`)\n ? $t(`diagram.${diagramType.value}`)\n : diagramType.value\n })\n\n const diagramTypeIcon = computed(() => {\n switch (diagramType.value) {\n case DiagramType.Sequence:\n return 'ri:timeline-view'\n case DiagramType.Class:\n return 'ri:organization-chart'\n case DiagramType.State:\n return 'ri:organization-chart'\n case DiagramType.ER:\n return 'ri:organization-chart'\n case DiagramType.XYChart:\n return 'ri:line-chart-line'\n case DiagramType.Flowchart:\n return 'ri:flow-chart'\n case DiagramType.Graph:\n return 'ri:flow-chart'\n default:\n return 'ri:flow-chart'\n }\n })\n\n async function renderDiagram() {\n const code = toolPart.value.input?.code\n if (!code) {\n return\n }\n\n svgError.value = false\n try {\n const { renderMermaidSVG, THEMES } =\n await import('beautiful-mermaid')\n const theme = props.isDark\n ? THEMES['github-dark']\n : THEMES['github-light']\n svgContent.value = renderMermaidSVG(code, theme)\n } catch {\n svgError.value = true\n }\n }\n\n watch([() => toolPart.value.input?.code, () => props.isDark], renderDiagram)\n onMounted(async () => {\n await renderDiagram()\n })\n\n const downloadSvg = () => {\n if (!svgContent.value) {\n return\n }\n const blob = new Blob([svgContent.value], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const url = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = url\n anchor.download = `${toSnakeCase(toolPart.value.input?.title || 'diagram')}.svg`\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n URL.revokeObjectURL(url)\n }\n\n const copyCode = () => {\n const code = toolPart.value.input?.code\n if (code) {\n copy(code)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input?.code\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden\">\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=\"diagramTypeIcon\" class=\"text-16\" />\n <div class=\"flex flex-col items-start gap-2\">\n <strong class=\"font-bold\">{{\n diagramTypeLabel ?? $t('label.diagram')\n }}</strong>\n </div>\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=\"copyCode\" />\n <VvButton\n v-if=\"svgContent\"\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadSvg\" />\n </VvButtonGroup>\n </div>\n <div v-if=\"svgError\" class=\"text-12 text-danger py-8 px-sm\">\n {{ $t('message.diagramRenderError') }}\n </div>\n <PkSvgViewer\n v-else-if=\"svgContent\"\n class=\"pk-tool-show-diagram__stage\"\n :svg=\"svgContent\"\n :title=\"toolPart.input?.title\" />\n <div\n v-else\n class=\"pk-tool-show-diagram__stage flex justify-center items-center\">\n <VvIcon name=\"loading-loop\" class=\"w-24 h-24 text-word-5\" />\n </div>\n <div\n v-if=\"toolPart.input.caption\"\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-t border-surface-3 text-word-3\">\n {{ toolPart.input.caption }}\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-show-diagram {\n // Fixed stage height: the diagram renders lazily (async chunk +\n // dynamic mermaid import), so the loader and the rendered SVG must\n // occupy the same space or the chat scroll position jumps around.\n // The SVG scales to fit; zoom/pan and the lightbox cover the rest.\n &__stage {\n height: 384px;\n\n .pk-svg-viewer__stage,\n .pk-svg-viewer__content {\n height: 100%;\n }\n }\n }\n</style>\n","<script setup lang=\"ts\">\n import { computed, onMounted, ref, watch } from 'vue'\n import { useClipboard } from '@vueuse/core'\n import { useI18n } from 'vue-i18n'\n import { toSnakeCase } from 'utils'\n import PkSvgViewer from '../PkSvgViewer.vue'\n\n const props = defineProps<{\n part: unknown\n isDark?: boolean\n }>()\n\n const { t: $t, te: $te } = useI18n({\n useScope: 'global',\n })\n\n const { copy, copied } = useClipboard()\n\n const toolPart = computed(() => {\n const part = props.part as {\n input?: {\n code: string\n title?: string\n caption?: string\n }\n }\n return part\n })\n\n const svgError = ref(false)\n\n // Serialized SVG content\n const svgContent = ref('')\n\n enum DiagramType {\n Sequence = 'sequenceDiagram',\n Class = 'classDiagram',\n State = 'stateDiagram',\n ER = 'erDiagram',\n XYChart = 'xychart',\n Flowchart = 'flowchart',\n Graph = 'graph',\n }\n\n const diagramType = computed<DiagramType | undefined>(() => {\n const code = toolPart.value.input?.code?.trimStart()\n if (!code) {\n return undefined\n }\n const firstWord = code.match(/^[A-Za-z-]+/)?.[0]\n switch (firstWord) {\n case 'sequenceDiagram':\n return DiagramType.Sequence\n case 'classDiagram':\n return DiagramType.Class\n case 'stateDiagram':\n return DiagramType.State\n case 'erDiagram':\n return DiagramType.ER\n case 'xychart-beta':\n return DiagramType.XYChart\n case 'flowchart':\n return DiagramType.Flowchart\n case 'graph':\n return DiagramType.Graph\n default:\n return undefined\n }\n })\n\n const diagramTypeLabel = computed(() => {\n if (!diagramType.value) {\n return ''\n }\n return $te(`diagram.${diagramType.value}`)\n ? $t(`diagram.${diagramType.value}`)\n : diagramType.value\n })\n\n const diagramTypeIcon = computed(() => {\n switch (diagramType.value) {\n case DiagramType.Sequence:\n return 'ri:timeline-view'\n case DiagramType.Class:\n return 'ri:organization-chart'\n case DiagramType.State:\n return 'ri:organization-chart'\n case DiagramType.ER:\n return 'ri:organization-chart'\n case DiagramType.XYChart:\n return 'ri:line-chart-line'\n case DiagramType.Flowchart:\n return 'ri:flow-chart'\n case DiagramType.Graph:\n return 'ri:flow-chart'\n default:\n return 'ri:flow-chart'\n }\n })\n\n async function renderDiagram() {\n const code = toolPart.value.input?.code\n if (!code) {\n return\n }\n\n svgError.value = false\n try {\n const { renderMermaidSVG, THEMES } =\n await import('beautiful-mermaid')\n const theme = props.isDark\n ? THEMES['github-dark']\n : THEMES['github-light']\n svgContent.value = renderMermaidSVG(code, theme)\n } catch {\n svgError.value = true\n }\n }\n\n watch([() => toolPart.value.input?.code, () => props.isDark], renderDiagram)\n onMounted(async () => {\n await renderDiagram()\n })\n\n const downloadSvg = () => {\n if (!svgContent.value) {\n return\n }\n const blob = new Blob([svgContent.value], {\n type: 'image/svg+xml;charset=utf-8',\n })\n const url = URL.createObjectURL(blob)\n const anchor = document.createElement('a')\n anchor.href = url\n anchor.download = `${toSnakeCase(toolPart.value.input?.title || 'diagram')}.svg`\n document.body.appendChild(anchor)\n anchor.click()\n document.body.removeChild(anchor)\n URL.revokeObjectURL(url)\n }\n\n const copyCode = () => {\n const code = toolPart.value.input?.code\n if (code) {\n copy(code)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"toolPart?.input?.code\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden\">\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=\"diagramTypeIcon\" class=\"text-16\" />\n <div class=\"flex flex-col items-start gap-2\">\n <strong class=\"font-bold\">{{\n diagramTypeLabel ?? $t('label.diagram')\n }}</strong>\n </div>\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=\"copyCode\" />\n <VvButton\n v-if=\"svgContent\"\n modifiers=\"action-quiet-small\"\n icon=\"ri:download-line\"\n :label=\"$t('action.download')\"\n @click=\"downloadSvg\" />\n </VvButtonGroup>\n </div>\n <div v-if=\"svgError\" class=\"text-12 text-danger py-8 px-sm\">\n {{ $t('message.diagramRenderError') }}\n </div>\n <PkSvgViewer\n v-else-if=\"svgContent\"\n class=\"pk-tool-show-diagram__stage\"\n :svg=\"svgContent\"\n :title=\"toolPart.input?.title\" />\n <div\n v-else\n class=\"pk-tool-show-diagram__stage flex justify-center items-center\">\n <VvIcon name=\"loading-loop\" class=\"w-24 h-24 text-word-5\" />\n </div>\n <div\n v-if=\"toolPart.input.caption\"\n class=\"px-sm py-6 bg-surface-1 min-h-40 text-12 border-t border-surface-3 text-word-3\">\n {{ toolPart.input.caption }}\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n .pk-tool-show-diagram {\n // Fixed stage height: the diagram renders lazily (async chunk +\n // dynamic mermaid import), so the loader and the rendered SVG must\n // occupy the same space or the chat scroll position jumps around.\n // The SVG scales to fit; zoom/pan and the lightbox cover the rest.\n &__stage {\n height: 384px;\n\n .pk-svg-viewer__stage,\n .pk-svg-viewer__content {\n height: 100%;\n }\n }\n }\n</style>\n"],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { r as e } from "./PkStreamingMarkdown-By0JBQUl.js";
2
+ import "./src-DCfvejyT.js";
3
+ import { t } from "./PkHeldImage-BqnlurT_.js";
4
+ import { VvIcon as n } from "@volverjs/ui-vue/components";
5
+ import { Fragment as r, computed as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createVNode as c, defineComponent as l, normalizeClass as u, openBlock as d, renderList as f, toDisplayString as p, unref as m } from "vue";
6
+ //#region ../../packages/utils/src/video-source.ts
7
+ var h = (e) => e.replace(/[^a-zA-Z0-9_-]/g, ""), g = (e, t) => e === t || e.endsWith(`.${t}`), _ = (e) => {
8
+ if (e.hostname.endsWith("youtu.be")) return h(e.pathname.split("/")[1] ?? "") || null;
9
+ let t = e.searchParams.get("v");
10
+ if (t) return h(t) || null;
11
+ let n = e.pathname.match(/^\/(?:shorts|live|embed|v)\/([^/?#]+)/);
12
+ return n && h(n[1]) || null;
13
+ }, v = (e) => {
14
+ let t = e.pathname.match(/(?:^|\/)(\d+)(?:$|[/?#])/);
15
+ return t ? t[1] : null;
16
+ };
17
+ function y(e, t) {
18
+ let n;
19
+ try {
20
+ n = new URL(e);
21
+ } catch {
22
+ return {
23
+ provider: "file",
24
+ url: e,
25
+ embedUrl: e
26
+ };
27
+ }
28
+ let r = n.hostname.toLowerCase();
29
+ if (g(r, "youtube.com") || g(r, "youtu.be") || g(r, "youtube-nocookie.com")) {
30
+ let t = _(n);
31
+ if (t) return {
32
+ provider: "youtube",
33
+ url: e,
34
+ videoId: t,
35
+ embedUrl: `https://www.youtube-nocookie.com/embed/${t}`,
36
+ thumbnailUrl: `https://img.youtube.com/vi/${t}/hqdefault.jpg`
37
+ };
38
+ }
39
+ if (g(r, "vimeo.com")) {
40
+ let t = v(n);
41
+ if (t) return {
42
+ provider: "vimeo",
43
+ url: e,
44
+ videoId: t,
45
+ embedUrl: `https://player.vimeo.com/video/${t}?dnt=1`
46
+ };
47
+ }
48
+ return t && t !== "file" ? {
49
+ provider: t,
50
+ url: e,
51
+ embedUrl: e
52
+ } : {
53
+ provider: "file",
54
+ url: e,
55
+ embedUrl: e
56
+ };
57
+ }
58
+ //#endregion
59
+ //#region ../../packages/components/src/chat/PkToolShowVideo.vue?vue&type=script&setup=true&lang.ts
60
+ var b = {
61
+ key: 0,
62
+ class: "border border-surface-3 rounded-xl w-full overflow-hidden bg-surface"
63
+ }, x = { class: "px-sm py-6 bg-surface-1 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40" }, S = { class: "font-bold" }, C = {
64
+ key: 0,
65
+ class: "w-full overflow-hidden",
66
+ style: { "aspect-ratio": "16 / 9" }
67
+ }, w = ["src", "poster"], T = ["href"], E = {
68
+ key: 2,
69
+ class: "relative w-full overflow-hidden bg-black",
70
+ style: { "aspect-ratio": "16 / 9" }
71
+ }, D = ["src", "title"], O = {
72
+ key: 3,
73
+ class: "p-sm flex flex-col gap-4 border-t border-surface-3"
74
+ }, k = {
75
+ key: 0,
76
+ class: "font-bold text-14"
77
+ }, A = {
78
+ key: 1,
79
+ class: "text-12 text-word-3"
80
+ }, j = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", M = /* @__PURE__ */ l({
81
+ __name: "PkToolShowVideo",
82
+ props: { part: {} },
83
+ setup(l) {
84
+ let h = l, g = ["www.youtube-nocookie.com", "player.vimeo.com"], _ = e(), v = i(() => (h.part.input?.videos ?? []).map((e) => {
85
+ let t = y(e.url, e.provider), n = (t.provider === "file" ? [t.embedUrl, e.poster] : [t.embedUrl]).filter((e) => !!e && !g.includes(_.hostOf(e) ?? ""));
86
+ return {
87
+ ...e,
88
+ source: t,
89
+ gated: n,
90
+ held: n.some((e) => !_.canLoad(e))
91
+ };
92
+ }));
93
+ function M(e) {
94
+ for (let t of e) _.release(t);
95
+ }
96
+ return (e, i) => {
97
+ let l = n;
98
+ return v.value.length ? (d(), o("div", b, [s("div", x, [c(l, {
99
+ name: "ri:film-line",
100
+ class: "text-16"
101
+ }), s("strong", S, p(e.$t("label.video")), 1)]), (d(!0), o(r, null, f(v.value, (e, n) => (d(), o("div", {
102
+ key: e.url,
103
+ class: u(["flex flex-col", { "border-t border-surface-3": n > 0 }])
104
+ }, [e.held ? (d(), o("div", C, [c(t, {
105
+ host: m(_).hostOf(e.gated[0]),
106
+ kind: "video",
107
+ fill: "",
108
+ onRelease: (t) => M(e.gated)
109
+ }, null, 8, ["host", "onRelease"])])) : e.source.provider === "file" ? (d(), o("video", {
110
+ key: 1,
111
+ src: e.source.embedUrl,
112
+ poster: e.poster,
113
+ controls: "",
114
+ preload: "metadata",
115
+ playsinline: "",
116
+ class: "w-full bg-black",
117
+ style: {
118
+ "aspect-ratio": "16 / 9",
119
+ "max-height": "480px"
120
+ }
121
+ }, [s("a", {
122
+ href: e.url,
123
+ target: "_blank",
124
+ rel: "noopener noreferrer"
125
+ }, p(e.title ?? e.url), 9, T)], 8, w)) : (d(), o("div", E, [s("iframe", {
126
+ src: e.source.embedUrl,
127
+ title: e.title ?? e.url,
128
+ loading: "lazy",
129
+ referrerpolicy: "strict-origin-when-cross-origin",
130
+ allow: j,
131
+ allowfullscreen: "",
132
+ class: "absolute inset-0 w-full h-full border-0"
133
+ }, null, 8, D)])), e.title || e.description ? (d(), o("div", O, [e.title ? (d(), o("strong", k, p(e.title), 1)) : a("", !0), e.description ? (d(), o("span", A, p(e.description), 1)) : a("", !0)])) : a("", !0)], 2))), 128))])) : a("", !0);
134
+ };
135
+ }
136
+ });
137
+ //#endregion
138
+ export { M as default };
139
+
140
+ //# sourceMappingURL=PkToolShowVideo-Cw2QqlRI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PkToolShowVideo-Cw2QqlRI.js","names":["$t","__unplugin_components_0","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass","PkHeldImage","_unref","_createCommentVNode","_sfc_main","useChatImageGate","sanitizeId","raw","hostMatches","host","domain","youtubeId","u","v","m","vimeoId","parseVideoSource","url","id","hint","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","IFRAME_ALLOW","PkToolShowVideo_default","defineComponent","props","__props","PLAYER_HOSTS","imageGate","videos","computed","source","video","gated","src","release","urls","_component_VvIcon","VvIcon","openBlock","createElementBlock","createElementVNode","createVNode","toDisplayString","_ctx","Fragment","renderList","normalizeClass","index","PkHeldImage_default","unref","createCommentVNode"],"sources":["../../../../packages/utils/src/video-source.ts","../../../../packages/components/src/chat/PkToolShowVideo.vue","../../../../packages/components/src/chat/PkToolShowVideo.vue"],"sourcesContent":["/**\n * Video source parsing shared by the backend platform renderer and the frontend\n * player component, so both classify a video URL the same way.\n *\n * A URL is either a known provider (YouTube/Vimeo), which plays through the\n * provider's iframe embed, or a direct media file (`file`), which plays in a\n * native `<video>` element. Detection is by URL shape; an explicit `hint` is\n * used only as a fallback when the URL alone is inconclusive.\n */\n\nexport type VideoProvider = 'youtube' | 'vimeo' | 'file'\n\nexport interface ParsedVideoSource {\n provider: VideoProvider\n /** The original URL, unchanged. */\n url: string\n /**\n * The URL to actually load: the provider iframe embed URL for\n * YouTube/Vimeo, or the direct file URL for `file`.\n */\n embedUrl: string\n /** The provider video id (providers only). */\n videoId?: string\n /**\n * A preview image URL derived from the provider, when one is available\n * without an extra API call (currently YouTube only). Lets a link-only\n * surface (e.g. a Teams card) show a thumbnail instead of a bare link.\n */\n thumbnailUrl?: string\n}\n\n/** Keep only characters that are legal in a provider video id. */\nconst sanitizeId = (raw: string): string => raw.replace(/[^a-zA-Z0-9_-]/g, '')\n\n/**\n * True when `host` is exactly `domain` or a subdomain of it. Guards against\n * lookalike hosts (e.g. `notyoutube.com`) that a bare substring check would\n * misclassify.\n */\nconst hostMatches = (host: string, domain: string): boolean =>\n host === domain || host.endsWith(`.${domain}`)\n\n/** Extract the YouTube video id from any of its URL shapes, or null. */\nconst youtubeId = (u: URL): string | null => {\n // youtu.be/<id>\n if (u.hostname.endsWith('youtu.be')) {\n return sanitizeId(u.pathname.split('/')[1] ?? '') || null\n }\n // youtube.com/watch?v=<id>\n const v = u.searchParams.get('v')\n if (v) {\n return sanitizeId(v) || null\n }\n // youtube.com/shorts/<id>, /live/<id>, /embed/<id>, /v/<id>\n const m = u.pathname.match(/^\\/(?:shorts|live|embed|v)\\/([^/?#]+)/)\n return m ? sanitizeId(m[1]) || null : null\n}\n\n/** Extract the Vimeo (numeric) video id, or null. */\nconst vimeoId = (u: URL): string | null => {\n // player.vimeo.com/video/<id> or vimeo.com/<id>\n const m = u.pathname.match(/(?:^|\\/)(\\d+)(?:$|[/?#])/)\n return m ? m[1] : null\n}\n\n/**\n * Classify a video URL into a provider + a loadable embed/file URL.\n * Falls back to `file` (native `<video>`) for anything not recognized as a\n * supported provider, or when a provider is matched but no id can be extracted.\n */\nexport function parseVideoSource(\n url: string,\n hint?: VideoProvider,\n): ParsedVideoSource {\n let u: URL | undefined\n try {\n u = new URL(url)\n } catch {\n // Not an absolute URL: treat as a direct file reference.\n return { provider: 'file', url, embedUrl: url }\n }\n\n const host = u.hostname.toLowerCase()\n\n const isYouTube =\n hostMatches(host, 'youtube.com') ||\n hostMatches(host, 'youtu.be') ||\n hostMatches(host, 'youtube-nocookie.com')\n if (isYouTube) {\n const id = youtubeId(u)\n if (id) {\n return {\n provider: 'youtube',\n url,\n videoId: id,\n embedUrl: `https://www.youtube-nocookie.com/embed/${id}`,\n thumbnailUrl: `https://img.youtube.com/vi/${id}/hqdefault.jpg`,\n }\n }\n }\n\n if (hostMatches(host, 'vimeo.com')) {\n const id = vimeoId(u)\n if (id) {\n return {\n provider: 'vimeo',\n url,\n videoId: id,\n // `dnt=1`: the player sets no cookies and records no session\n // data, the Vimeo counterpart of youtube-nocookie above.\n embedUrl: `https://player.vimeo.com/video/${id}?dnt=1`,\n }\n }\n }\n\n // Honor an explicit provider hint only if we could not extract an id from a\n // provider URL (so a caller-tagged provider link still routes to an iframe\n // via its original URL rather than a broken native <video>).\n if (hint && hint !== 'file') {\n return { provider: hint, url, embedUrl: url }\n }\n\n return { provider: 'file', url, embedUrl: url }\n}\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n import { useChatImageGate } from './chatImagePolicy'\n import PkHeldImage from './PkHeldImage.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n /**\n * Where a YouTube or Vimeo player lives: the url is built here from the\n * video id, so nothing the model wrote reaches these hosts but the id.\n */\n const PLAYER_HOSTS = ['www.youtube-nocookie.com', 'player.vimeo.com']\n\n // A file, its poster, or an embed this card does not recognize, fetch the\n // url the model wrote as soon as they render: from a host the agent does\n // not list they wait for a click, like an image (chatImagePolicy.ts).\n const imageGate = useChatImageGate()\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => {\n const source = parseVideoSource(video.url, video.provider)\n const fetched =\n source.provider === 'file'\n ? [source.embedUrl, video.poster]\n : [source.embedUrl]\n const gated = fetched.filter(\n (src): src is string =>\n !!src &&\n !PLAYER_HOSTS.includes(imageGate.hostOf(src) ?? ''),\n )\n return {\n ...video,\n source,\n gated,\n held: gated.some((src) => !imageGate.canLoad(src)),\n }\n })\n })\n\n function release(urls: string[]) {\n for (const url of urls) {\n imageGate.release(url)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\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 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <!-- Each video bleeds to the card's edges, like the map of the\n location card: the card's overflow clips the bottom corners. -->\n <div\n v-for=\"(video, index) in videos\"\n :key=\"video.url\"\n class=\"flex flex-col\"\n :class=\"{ 'border-t border-surface-3': index > 0 }\">\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <div\n v-if=\"video.held\"\n class=\"w-full overflow-hidden\"\n style=\"aspect-ratio: 16 / 9\">\n <PkHeldImage\n :host=\"imageGate.hostOf(video.gated[0])\"\n kind=\"video\"\n fill\n @release=\"release(video.gated)\" />\n </div>\n <video\n v-else-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full bg-black\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a :href=\"video.url\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden bg-black\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <div\n v-if=\"video.title || video.description\"\n class=\"p-sm flex flex-col gap-4 border-t border-surface-3\">\n <strong v-if=\"video.title\" class=\"font-bold text-14\">\n {{ video.title }}\n </strong>\n <span v-if=\"video.description\" class=\"text-12 text-word-3\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed } from 'vue'\n import { parseVideoSource, type VideoProvider } from 'utils'\n import { useChatImageGate } from './chatImagePolicy'\n import PkHeldImage from './PkHeldImage.vue'\n\n const props = defineProps<{\n part: unknown\n }>()\n\n interface VideoInput {\n url: string\n title?: string\n description?: string\n poster?: string\n provider?: VideoProvider\n }\n\n // Permissions granted to provider embeds (YouTube/Vimeo players).\n const IFRAME_ALLOW =\n 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n\n /**\n * Where a YouTube or Vimeo player lives: the url is built here from the\n * video id, so nothing the model wrote reaches these hosts but the id.\n */\n const PLAYER_HOSTS = ['www.youtube-nocookie.com', 'player.vimeo.com']\n\n // A file, its poster, or an embed this card does not recognize, fetch the\n // url the model wrote as soon as they render: from a host the agent does\n // not list they wait for a click, like an image (chatImagePolicy.ts).\n const imageGate = useChatImageGate()\n\n const videos = computed(() => {\n const part = props.part as { input?: { videos?: VideoInput[] } }\n return (part.input?.videos ?? []).map((video) => {\n const source = parseVideoSource(video.url, video.provider)\n const fetched =\n source.provider === 'file'\n ? [source.embedUrl, video.poster]\n : [source.embedUrl]\n const gated = fetched.filter(\n (src): src is string =>\n !!src &&\n !PLAYER_HOSTS.includes(imageGate.hostOf(src) ?? ''),\n )\n return {\n ...video,\n source,\n gated,\n held: gated.some((src) => !imageGate.canLoad(src)),\n }\n })\n })\n\n function release(urls: string[]) {\n for (const url of urls) {\n imageGate.release(url)\n }\n }\n</script>\n\n<template>\n <div\n v-if=\"videos.length\"\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 text-12 border-b border-surface-3 text-word-3 flex items-center gap-8 min-h-40\">\n <VvIcon name=\"ri:film-line\" class=\"text-16\" />\n <strong class=\"font-bold\">\n {{ $t('label.video') }}\n </strong>\n </div>\n <!-- Each video bleeds to the card's edges, like the map of the\n location card: the card's overflow clips the bottom corners. -->\n <div\n v-for=\"(video, index) in videos\"\n :key=\"video.url\"\n class=\"flex flex-col\"\n :class=\"{ 'border-t border-surface-3': index > 0 }\">\n <!-- Direct file: native player. Handles MP4/WebM/OGG and works\n inside the widget's Shadow DOM without any extra CSS. -->\n <div\n v-if=\"video.held\"\n class=\"w-full overflow-hidden\"\n style=\"aspect-ratio: 16 / 9\">\n <PkHeldImage\n :host=\"imageGate.hostOf(video.gated[0])\"\n kind=\"video\"\n fill\n @release=\"release(video.gated)\" />\n </div>\n <video\n v-else-if=\"video.source.provider === 'file'\"\n :src=\"video.source.embedUrl\"\n :poster=\"video.poster\"\n controls\n preload=\"metadata\"\n playsinline\n class=\"w-full bg-black\"\n style=\"aspect-ratio: 16 / 9; max-height: 480px\">\n <a :href=\"video.url\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ video.title ?? video.url }}\n </a>\n </video>\n <!-- Provider (YouTube/Vimeo): iframe embed, 16:9 responsive. -->\n <div\n v-else\n class=\"relative w-full overflow-hidden bg-black\"\n style=\"aspect-ratio: 16 / 9\">\n <iframe\n :src=\"video.source.embedUrl\"\n :title=\"video.title ?? video.url\"\n loading=\"lazy\"\n referrerpolicy=\"strict-origin-when-cross-origin\"\n :allow=\"IFRAME_ALLOW\"\n allowfullscreen\n class=\"absolute inset-0 w-full h-full border-0\"></iframe>\n </div>\n <div\n v-if=\"video.title || video.description\"\n class=\"p-sm flex flex-col gap-4 border-t border-surface-3\">\n <strong v-if=\"video.title\" class=\"font-bold text-14\">\n {{ video.title }}\n </strong>\n <span v-if=\"video.description\" class=\"text-12 text-word-3\">\n {{ video.description }}\n </span>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
package/dist-vue/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as e } from "./_chunks/rolldown-runtime-Dy4uBu1J.js";
2
2
  import { i as t, r as n, t as r } from "./_chunks/PkToolShowForm-C9HbwRWB.js";
3
3
  import { C as i, T as a, _ as o, b as s, f as c, m as l, o as u, r as d, s as f, u as p, v as m, w as h, x as g } from "./_chunks/schemas-Bt5eFdV0.js";
4
- import { i as _, n as v, r as y, t as ee } from "./_chunks/PkChatbotMessages-BDh_t2MT.js";
4
+ import { i as _, n as v, r as y, t as ee } from "./_chunks/PkChatbotMessages-CVefdmkP.js";
5
5
  import { i as b, o as x, r as S } from "./_chunks/Media-Bzv3zEWR.js";
6
6
  import { B as C, D as te, E as w, F as ne, I as re, L as ie, O as ae, P as oe, R as se, T as ce, U as le, _ as ue, b as de, d as fe, g as pe, i as me, k as he, m as ge, n as T, o as _e, p as ve, r as ye, t as be, u as xe, v as Se, w as Ce, y as we, z as Te } from "./_chunks/Agent-Bd_4UVe4.js";
7
7
  import { c as Ee, d as De, l as Oe, r as ke, s as Ae, t as je, u as Me } from "./_chunks/Document-BrMThi12.js";
@@ -14,7 +14,7 @@ import { a as Ue, c as We, l as Ge } from "./_chunks/message-BOiF6Bt5.js";
14
14
  import { t as Ke } from "./_chunks/useSafeLocalStorage-OwzVTZud.js";
15
15
  import { t as qe } from "./_chunks/useDialogConfirm-BxhvsnRr.js";
16
16
  import { n as Je, r as Ye, t as Xe } from "./_chunks/PkChatbotViewConversations-uaKc5XAv.js";
17
- import { i as Ze, n as Qe, r as $e, t as et } from "./_chunks/PkChatbotViewChat-Cd5t_ESd.js";
17
+ import { i as Ze, n as Qe, r as $e, t as et } from "./_chunks/PkChatbotViewChat-BOankj81.js";
18
18
  import { t as tt } from "./_chunks/PkChatbotError-CRGbK09-.js";
19
19
  import { t as nt } from "./_chunks/useImageFallback-5vQIO0pC.js";
20
20
  import { t as rt } from "./_chunks/useLocalizedString-PfaKjIQY.js";
@@ -36,7 +36,7 @@ import { t as jn } from "./_chunks/PkChatbotStepToolDetail-riS6wIt-.js";
36
36
  import { n as Mn, t as Nn } from "./_chunks/PkChatbotInput-DB2wkyr2.js";
37
37
  import { t as Pn } from "./_chunks/PkChatbotEmptyState-vFXaIkiC.js";
38
38
  import { t as Fn } from "./_chunks/PkChatbotViewProfile-tUMdwSR1.js";
39
- import { t as In } from "./_chunks/PkChatbot-BsTXbdI2.js";
39
+ import { t as In } from "./_chunks/PkChatbot-DP2XuKXf.js";
40
40
  import { i as Ln, r as Rn, t as zn } from "./_chunks/PkToolShowSources-C1P3VCOr.js";
41
41
  import { t as Bn } from "./_chunks/mcpOAuthReport-BeZDTl87.js";
42
42
  import { t as Vn } from "./_chunks/PkToolShowEmail-C591LR5N.js";
@@ -577,7 +577,7 @@ var aa = ra, oa = { class: "flex items-center gap-4 mb-4" }, sa = { class: "font
577
577
  }
578
578
  });
579
579
  //#endregion
580
- //#region virtual:intlify-i18n-0
580
+ //#region virtual:intlify-i18n-2
581
581
  function ga(e) {
582
582
  let t = e;
583
583
  t.__i18n = t.__i18n || [], t.__i18n.push({
@@ -684,7 +684,7 @@ var _a = ha, va = { class: "flex items-center gap-4 mb-4" }, ya = { class: "font
684
684
  }
685
685
  });
686
686
  //#endregion
687
- //#region virtual:intlify-i18n-2
687
+ //#region virtual:intlify-i18n-3
688
688
  function Ta(e) {
689
689
  let t = e;
690
690
  t.__i18n = t.__i18n || [], t.__i18n.push({
@@ -16189,7 +16189,7 @@ var SC = /*#__PURE__*/ yC(bC, [["render", xC]]), CC = {
16189
16189
  }
16190
16190
  });
16191
16191
  //#endregion
16192
- //#region virtual:intlify-i18n-3
16192
+ //#region virtual:intlify-i18n-4
16193
16193
  function MC(e) {
16194
16194
  let t = e;
16195
16195
  t.__i18n = t.__i18n || [], t.__i18n.push({
@@ -16400,7 +16400,7 @@ var NC = jC, PC = { class: "block text-smaller mt-4" }, FC = { class: "block tex
16400
16400
  }
16401
16401
  });
16402
16402
  //#endregion
16403
- //#region virtual:intlify-i18n-4
16403
+ //#region virtual:intlify-i18n-0
16404
16404
  function zC(e) {
16405
16405
  let t = e;
16406
16406
  t.__i18n = t.__i18n || [], t.__i18n.push({