@pagelines/sdk 1.0.776 → 1.0.778
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.
- package/dist/AgentProvider.js.map +1 -1
- package/dist/AgentWrap.js +6 -4
- package/dist/AgentWrap.js.map +1 -1
- package/dist/contract.js +817 -832
- package/dist/contract.js.map +1 -1
- package/dist/widget.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentProvider.js","names":["$emit","$slots","$slots","$slots"],"sources":["../ui/EffectTransitionList.vue","../ui/EffectTransitionList.vue","../agent/ui/ElAuthGate.vue","../agent/ui/ElAuthGate.vue","../agent/ui/ElAgentAbout.vue","../agent/ui/ElAgentAbout.vue","../agent/ui/ElAgentHeader.vue","../agent/ui/ElAgentHeader.vue","../agent/ui/AgentSidebarClose.vue","../agent/ui/AgentSidebarClose.vue","../agent/ui/ElSidebar.vue","../agent/ui/ElSidebar.vue","../agent/ui/ElAgentModeSidebar.vue","../agent/ui/ElAgentModeSidebar.vue","../agent/ui/ElAgentSidebar.vue","../agent/ui/ElAgentSidebar.vue","../agent/ui/AgentChat.vue","../agent/ui/AgentChat.vue","../agent/ui/AgentProvider.vue","../agent/ui/AgentProvider.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// SDK-local copy of src/ui/effects/EffectTransitionList.vue — the SDK package\n// must not import app source, so the primitives it needs live here.\nconst { disabled = false, mode: _mode = 'block' } = defineProps<{ disabled?: boolean, mode?: 'block' | 'inline' }>()\n</script>\n\n<template>\n <TransitionGroup :name=\"!disabled ? 'nlist' : ''\">\n <slot />\n </TransitionGroup>\n</template>\n\n<style>\n.nlist-enter-active,\n.nlist-leave-active,\n.nlist-move {\n transition: all 600ms cubic-bezier(0.68, -0.55, 0.27, 1.55);\n}\n\n.nlist-enter-from {\n opacity: 0;\n transform: translateX(-30px) scale(0.9);\n}\n\n.nlist-enter-to {\n opacity: 1;\n transform: translateX(0) scale(1);\n}\n\n.nlist-leave-active {\n position: absolute;\n}\n\n.nlist-leave-to {\n opacity: 0;\n transform: scale(0.9);\n}\n</style>\n","<script lang=\"ts\" setup>\n// SDK-local copy of src/ui/effects/EffectTransitionList.vue — the SDK package\n// must not import app source, so the primitives it needs live here.\nconst { disabled = false, mode: _mode = 'block' } = defineProps<{ disabled?: boolean, mode?: 'block' | 'inline' }>()\n</script>\n\n<template>\n <TransitionGroup :name=\"!disabled ? 'nlist' : ''\">\n <slot />\n </TransitionGroup>\n</template>\n\n<style>\n.nlist-enter-active,\n.nlist-leave-active,\n.nlist-move {\n transition: all 600ms cubic-bezier(0.68, -0.55, 0.27, 1.55);\n}\n\n.nlist-enter-from {\n opacity: 0;\n transform: translateX(-30px) scale(0.9);\n}\n\n.nlist-enter-to {\n opacity: 1;\n transform: translateX(0) scale(1);\n}\n\n.nlist-leave-active {\n position: absolute;\n}\n\n.nlist-leave-to {\n opacity: 0;\n transform: scale(0.9);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { computed, ref, watch } from 'vue'\nimport EffectTransitionList from '../../ui/EffectTransitionList.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport AgentInputEmail from './AgentInputEmail.vue'\nimport AgentInputOneTimeCode from './AgentInputOneTimeCode.vue'\n\nconst { sdk } = defineProps<{ sdk: PageLinesSDK }>()\n\nconst form = ref({ email: '', code: '' })\nconst step = ref<'email' | 'code'>('email')\nconst isSubmitting = ref(false)\n\n// Engine array for step configuration\nconst stepConfig = {\n email: {\n title: 'Enter Your Email',\n button: { label: 'Continue', disabled: () => !form.value.email || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n const success = await sdk.auth.requestAuthCode({ email: form.value.email })\n if (success)\n step.value = 'code'\n } finally {\n isSubmitting.value = false\n }\n },\n },\n code: {\n title: 'Enter Verification Code',\n button: { label: 'Verify', disabled: () => form.value.code.length !== 6 || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n await sdk.auth.loginWithCode({ email: form.value.email, code: form.value.code })\n } finally {\n isSubmitting.value = false\n }\n },\n },\n}\n\nconst currentStep = computed(() => stepConfig[step.value])\n\n// Watch for successful authentication - UI will update when activeUser becomes defined\nwatch(() => sdk.activeUser.value, (newUser) => {\n if (newUser && step.value === 'code') {\n // Auth succeeded - parent component will handle UI transition\n // This log helps debug the auth flow\n console.log('[ElAuthGate] Authentication successful', { email: newUser.email })\n }\n})\n</script>\n\n<template>\n <div data-test=\"auth-form\" :data-test-mode=\"step\" class=\"flex flex-col items-center justify-center h-full p-6\">\n <div class=\"w-full max-w-xs space-y-12\">\n <p v-if=\"sdk.error.value\" class=\"text-xs text-theme-400 text-center\">\n {{ sdk.error.value }}\n </p>\n\n <h3 class=\"text-base font-light text-white text-center\">\n {{ currentStep.title }}\n </h3>\n\n <div class=\"space-y-6 relative\">\n <EffectTransitionList>\n <div v-if=\"step === 'email'\" key=\"email-field\" class=\"w-full\">\n <AgentInputEmail\n v-model=\"form.email\"\n data-test=\"auth-email-input\"\n @keyup.enter=\"currentStep.action\"\n />\n </div>\n <div v-else key=\"code-field\" class=\"w-full\">\n <AgentInputOneTimeCode\n v-model=\"form.code\"\n :length=\"6\"\n :focus-first=\"true\"\n data-test=\"auth-code-input\"\n @auto-submit=\"currentStep.action\"\n />\n </div>\n\n <div :key=\"currentStep.button.label\" class=\"space-y-4 w-full\">\n <ElAgentButton\n theme=\"primary\"\n size=\"md\"\n class=\"w-full\"\n data-test=\"auth-submit\"\n :loading=\"sdk.loading.value\"\n :disabled=\"currentStep.button.disabled() || sdk.loading.value\"\n @click=\"currentStep.action\"\n >\n {{ currentStep.button.label }}\n </ElAgentButton>\n\n <button\n v-if=\"step === 'code'\"\n class=\"w-full text-xs text-white/50 hover:text-white/70 transition-colors py-2\"\n @click=\"step = 'email'\"\n >\n Change Email\n </button>\n </div>\n </EffectTransitionList>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { computed, ref, watch } from 'vue'\nimport EffectTransitionList from '../../ui/EffectTransitionList.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport AgentInputEmail from './AgentInputEmail.vue'\nimport AgentInputOneTimeCode from './AgentInputOneTimeCode.vue'\n\nconst { sdk } = defineProps<{ sdk: PageLinesSDK }>()\n\nconst form = ref({ email: '', code: '' })\nconst step = ref<'email' | 'code'>('email')\nconst isSubmitting = ref(false)\n\n// Engine array for step configuration\nconst stepConfig = {\n email: {\n title: 'Enter Your Email',\n button: { label: 'Continue', disabled: () => !form.value.email || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n const success = await sdk.auth.requestAuthCode({ email: form.value.email })\n if (success)\n step.value = 'code'\n } finally {\n isSubmitting.value = false\n }\n },\n },\n code: {\n title: 'Enter Verification Code',\n button: { label: 'Verify', disabled: () => form.value.code.length !== 6 || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n await sdk.auth.loginWithCode({ email: form.value.email, code: form.value.code })\n } finally {\n isSubmitting.value = false\n }\n },\n },\n}\n\nconst currentStep = computed(() => stepConfig[step.value])\n\n// Watch for successful authentication - UI will update when activeUser becomes defined\nwatch(() => sdk.activeUser.value, (newUser) => {\n if (newUser && step.value === 'code') {\n // Auth succeeded - parent component will handle UI transition\n // This log helps debug the auth flow\n console.log('[ElAuthGate] Authentication successful', { email: newUser.email })\n }\n})\n</script>\n\n<template>\n <div data-test=\"auth-form\" :data-test-mode=\"step\" class=\"flex flex-col items-center justify-center h-full p-6\">\n <div class=\"w-full max-w-xs space-y-12\">\n <p v-if=\"sdk.error.value\" class=\"text-xs text-theme-400 text-center\">\n {{ sdk.error.value }}\n </p>\n\n <h3 class=\"text-base font-light text-white text-center\">\n {{ currentStep.title }}\n </h3>\n\n <div class=\"space-y-6 relative\">\n <EffectTransitionList>\n <div v-if=\"step === 'email'\" key=\"email-field\" class=\"w-full\">\n <AgentInputEmail\n v-model=\"form.email\"\n data-test=\"auth-email-input\"\n @keyup.enter=\"currentStep.action\"\n />\n </div>\n <div v-else key=\"code-field\" class=\"w-full\">\n <AgentInputOneTimeCode\n v-model=\"form.code\"\n :length=\"6\"\n :focus-first=\"true\"\n data-test=\"auth-code-input\"\n @auto-submit=\"currentStep.action\"\n />\n </div>\n\n <div :key=\"currentStep.button.label\" class=\"space-y-4 w-full\">\n <ElAgentButton\n theme=\"primary\"\n size=\"md\"\n class=\"w-full\"\n data-test=\"auth-submit\"\n :loading=\"sdk.loading.value\"\n :disabled=\"currentStep.button.disabled() || sdk.loading.value\"\n @click=\"currentStep.action\"\n >\n {{ currentStep.button.label }}\n </ElAgentButton>\n\n <button\n v-if=\"step === 'code'\"\n class=\"w-full text-xs text-white/50 hover:text-white/70 transition-colors py-2\"\n @click=\"step = 'email'\"\n >\n Change Email\n </button>\n </div>\n </EffectTransitionList>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '../schema'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport ElModeHeader from './ElModeHeader.vue'\n\nconst { agent, isOnline = false } = defineProps<{\n agent: Agent\n isOnline?: boolean\n}>()\n</script>\n\n<template>\n <div class=\"flex-1 flex flex-col min-h-0 py-6 space-y-6 h-full overflow-scroll [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden relative\">\n <!-- Name/Avatar Header -->\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <div class=\"flex-1 space-y-6 pb-12\">\n\n\n <!-- About Section -->\n <div v-if=\"agent.summary.value\" class=\"text-sm bg-white/10 backdrop-blur-sm rounded-2xl p-4 border border-white/20 space-y-3\">\n <h3 class=\"font-medium text-white/50\">\n About\n </h3>\n <div class=\" text-white/70 leading-relaxed\" v-html=\"agent.summary.value\" />\n </div>\n\n <!-- Entity Type Info -->\n <div v-if=\"agent.entityType.value === 'company'\" class=\"bg-white/5 backdrop-blur-sm rounded-2xl p-4 border border-white/10\">\n <h3 class=\"text-sm font-medium text-white/90 mb-2\">\n Company Info\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n This is a company agent representing {{ agent.name.value }}.\n </p>\n </div>\n\n <!-- Email Contact -->\n <div v-if=\"agent.email.value\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Contact\n </h3>\n <a\n :href=\"`mailto:${agent.email.value}`\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/5 hover:bg-white/10 border border-white/10 text-white/80 text-sm justify-start h-10 w-full\"\n >\n <span class=\"i-heroicons-envelope flex items-center size-[1.1em] mt-[-.07em]\" />\n Email\n </a>\n </div>\n\n <!-- Social Accounts -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Links\n </h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <a\n v-for=\"account in agent.accounts.value\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/10 hover:bg-white/20 border border-white/20 text-white/80 text-sm\"\n >\n <span class=\"flex items-center size-[1.1em] mt-[-.07em]\" :class=\"SOCIAL_PLATFORMS[account.platform].icon\" />\n {{ SOCIAL_PLATFORMS[account.platform].label }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '../schema'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport ElModeHeader from './ElModeHeader.vue'\n\nconst { agent, isOnline = false } = defineProps<{\n agent: Agent\n isOnline?: boolean\n}>()\n</script>\n\n<template>\n <div class=\"flex-1 flex flex-col min-h-0 py-6 space-y-6 h-full overflow-scroll [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden relative\">\n <!-- Name/Avatar Header -->\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <div class=\"flex-1 space-y-6 pb-12\">\n\n\n <!-- About Section -->\n <div v-if=\"agent.summary.value\" class=\"text-sm bg-white/10 backdrop-blur-sm rounded-2xl p-4 border border-white/20 space-y-3\">\n <h3 class=\"font-medium text-white/50\">\n About\n </h3>\n <div class=\" text-white/70 leading-relaxed\" v-html=\"agent.summary.value\" />\n </div>\n\n <!-- Entity Type Info -->\n <div v-if=\"agent.entityType.value === 'company'\" class=\"bg-white/5 backdrop-blur-sm rounded-2xl p-4 border border-white/10\">\n <h3 class=\"text-sm font-medium text-white/90 mb-2\">\n Company Info\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n This is a company agent representing {{ agent.name.value }}.\n </p>\n </div>\n\n <!-- Email Contact -->\n <div v-if=\"agent.email.value\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Contact\n </h3>\n <a\n :href=\"`mailto:${agent.email.value}`\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/5 hover:bg-white/10 border border-white/10 text-white/80 text-sm justify-start h-10 w-full\"\n >\n <span class=\"i-heroicons-envelope flex items-center size-[1.1em] mt-[-.07em]\" />\n Email\n </a>\n </div>\n\n <!-- Social Accounts -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Links\n </h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <a\n v-for=\"account in agent.accounts.value\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/10 hover:bg-white/20 border border-white/20 text-white/80 text-sm\"\n >\n <span class=\"flex items-center size-[1.1em] mt-[-.07em]\" :class=\"SOCIAL_PLATFORMS[account.platform].icon\" />\n {{ SOCIAL_PLATFORMS[account.platform].label }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '@pagelines/core'\nimport { handleImageError } from '../utils'\n\ninterface Props {\n agent: Agent\n isOnline?: boolean\n}\n\nconst { agent, isOnline = false } = defineProps<Props>()\n\n</script>\n\n<template>\n <!-- Centered layout for default \"self\" mode with large avatar and online indicator -->\n <div class=\"flex flex-col items-center text-center gap-4\">\n <!-- Avatar with online indicator -->\n <div class=\"relative flex-shrink-0\">\n <div class=\"w-20 h-20 sm:w-24 sm:h-24 rounded-full overflow-hidden border-4 border-white\">\n <img\n :src=\"agent.avatarUrl.value\"\n :alt=\"agent.displayName.value\"\n class=\"w-full h-full object-cover\"\n @error=\"handleImageError\"\n />\n </div>\n\n <div class=\"absolute top-1.5 right-1.5\">\n <template v-if=\"isOnline\">\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white\" />\n </template>\n <div v-else class=\"size-4 bg-theme-400 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Name and title -->\n <div class=\"min-w-0\">\n <h1 class=\"text-3xl font-light text-white mb-2 truncate\">\n {{ agent.displayName.value }}\n </h1>\n <p class=\"text-base font-light text-white/60 line-clamp-1\">\n {{ agent.title.value }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '@pagelines/core'\nimport { handleImageError } from '../utils'\n\ninterface Props {\n agent: Agent\n isOnline?: boolean\n}\n\nconst { agent, isOnline = false } = defineProps<Props>()\n\n</script>\n\n<template>\n <!-- Centered layout for default \"self\" mode with large avatar and online indicator -->\n <div class=\"flex flex-col items-center text-center gap-4\">\n <!-- Avatar with online indicator -->\n <div class=\"relative flex-shrink-0\">\n <div class=\"w-20 h-20 sm:w-24 sm:h-24 rounded-full overflow-hidden border-4 border-white\">\n <img\n :src=\"agent.avatarUrl.value\"\n :alt=\"agent.displayName.value\"\n class=\"w-full h-full object-cover\"\n @error=\"handleImageError\"\n />\n </div>\n\n <div class=\"absolute top-1.5 right-1.5\">\n <template v-if=\"isOnline\">\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white\" />\n </template>\n <div v-else class=\"size-4 bg-theme-400 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Name and title -->\n <div class=\"min-w-0\">\n <h1 class=\"text-3xl font-light text-white mb-2 truncate\">\n {{ agent.displayName.value }}\n </h1>\n <p class=\"text-base font-light text-white/60 line-clamp-1\">\n {{ agent.title.value }}\n </p>\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport { onMounted, ref } from 'vue'\n\ndefineOptions({ name: 'SelfSidebarClose' })\n\ndefineEmits<{\n click: [event: MouseEvent]\n}>()\n\nconst inView = ref(false)\n\nonMounted(() => {\n setTimeout(() => {\n inView.value = true\n }, 100)\n})\n</script>\n\n<template>\n <a\n class=\"close block cursor-pointer w-[60px] h-[60px] rounded-full transition-all duration-1000 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-110 active:scale-90 hover:rotate-90\"\n @click=\"$emit('click', $event)\"\n >\n <!-- Background circle (invisible, for hover area) -->\n <span class=\"absolute inset-0 rounded-full transition-all\" />\n\n <!-- Close lines container -->\n <span class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[28px] h-[28px] overflow-hidden\">\n <!-- Line 1 - animates from bottom-left to center, rotates 45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 rotate-45' : 'translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.15s\"\n />\n\n <!-- Line 2 - animates from top-left to center, rotates -45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 -rotate-45' : '-translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.45s\"\n />\n </span>\n </a>\n</template>\n","<script lang=\"ts\" setup>\nimport { onMounted, ref } from 'vue'\n\ndefineOptions({ name: 'SelfSidebarClose' })\n\ndefineEmits<{\n click: [event: MouseEvent]\n}>()\n\nconst inView = ref(false)\n\nonMounted(() => {\n setTimeout(() => {\n inView.value = true\n }, 100)\n})\n</script>\n\n<template>\n <a\n class=\"close block cursor-pointer w-[60px] h-[60px] rounded-full transition-all duration-1000 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-110 active:scale-90 hover:rotate-90\"\n @click=\"$emit('click', $event)\"\n >\n <!-- Background circle (invisible, for hover area) -->\n <span class=\"absolute inset-0 rounded-full transition-all\" />\n\n <!-- Close lines container -->\n <span class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[28px] h-[28px] overflow-hidden\">\n <!-- Line 1 - animates from bottom-left to center, rotates 45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 rotate-45' : 'translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.15s\"\n />\n\n <!-- Line 2 - animates from top-left to center, rotates -45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 -rotate-45' : '-translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.45s\"\n />\n </span>\n </a>\n</template>\n","<script lang=\"ts\" setup>\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport AgentSidebarClose from './AgentSidebarClose.vue'\n\ndefineOptions({ name: 'ElSidebar', inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: boolean\n items: NavItem[]\n position?: 'left' | 'right'\n title?: string\n widthClasses?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst position = props.position || 'left'\nconst widthClasses = props.widthClasses || 'w-[80%] max-w-[300px]'\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst visibleItems = computed(() => props.items.filter((item) => !item.isHidden))\n\nfunction handleItemClick(item: NavItem) {\n if (item.isDisabled)\n return\n\n if (item.onClick) {\n item.onClick({ item, event: new MouseEvent('click') })\n } else if (item.href) {\n if (item.href.includes('http')) {\n window.open(item.href, item.target || '_self')?.focus()\n } else {\n window.location.href = item.href\n }\n }\n\n isOpen.value = false\n}\n\n// Position-specific classes\nconst transitionClasses = computed(() => {\n if (position === 'left') {\n return {\n enter: '-translate-x-full',\n leave: '-translate-x-full',\n position: 'justify-start',\n closeButton: '-right-16',\n }\n } else {\n return {\n enter: 'translate-x-full',\n leave: 'translate-x-full',\n position: 'justify-end',\n closeButton: '-left-16',\n }\n }\n})\n</script>\n\n<template>\n <!-- Backdrop -->\n <Transition\n enter-active-class=\"transition-opacity duration-300 ease-out\"\n leave-active-class=\"transition-opacity duration-200 ease-in\"\n enter-from-class=\"opacity-0\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-40 bg-black/50 backdrop-blur-sm\"\n @click=\"isOpen = false\"\n />\n </Transition>\n\n <!-- Sidebar -->\n <Transition\n enter-active-class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"transitionClasses.enter\"\n enter-to-class=\"translate-x-0\"\n leave-from-class=\"translate-x-0\"\n :leave-to-class=\"transitionClasses.leave\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-50 flex\"\n :class=\"transitionClasses.position\"\n @click=\"isOpen = false\"\n >\n <!-- Menu Panel -->\n <div\n class=\"relative h-full shadow-2xl bg-black/30 backdrop-blur-xl flex flex-col justify-center\"\n :class=\"widthClasses\"\n @click.stop\n >\n <AgentSidebarClose\n class=\"absolute top-4 z-10 text-white\"\n :class=\"transitionClasses.closeButton\"\n @click=\"isOpen = false\"\n />\n\n <!-- Title -->\n <div v-if=\"title\" class=\"px-9 pt-12 pb-4\">\n <h3 class=\"text-base font-medium text-theme-400\">\n {{ title }}\n </h3>\n </div>\n\n <!-- Header Slot -->\n <div v-if=\"$slots.header\" class=\"px-4 pb-8 border-b border-white/10\">\n <slot name=\"header\" />\n </div>\n\n <!-- Menu Items -->\n <div class=\"flex-1 p-6 space-y-2 overflow-y-auto\" :class=\"{ 'pt-6': !title && !$slots.header, 'pt-4': title || $slots.header }\">\n <TransitionGroup\n enter-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n enter-to-class=\"translate-x-0 opacity-100\"\n leave-from-class=\"translate-x-0 opacity-100\"\n :leave-to-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n >\n <button\n v-for=\"(item, index) in visibleItems\"\n :key=\"item.key || item.label || index\"\n :style=\"{ transitionDelay: `${index * 40}ms` }\"\n class=\"cursor-pointer w-full text-left p-3 rounded-xl transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group\"\n :class=\"[\n item.isActive\n ? 'bg-primary-500/20 border border-primary-500/40'\n : 'hover:bg-white/10',\n item.isDisabled && 'opacity-50 cursor-not-allowed',\n ]\"\n :disabled=\"item.isDisabled\"\n @click=\"handleItemClick(item)\"\n >\n <div class=\"flex items-center gap-3\">\n <i\n v-if=\"item.icon?.src\"\n class=\"size-5 flex-shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group-hover:scale-110\"\n :class=\"[\n item.icon.src,\n item.isActive ? 'text-primary-400' : 'text-white/70 group-hover:text-white',\n ]\"\n />\n <div class=\"flex-1\">\n <div\n class=\"font-medium text-sm\"\n :class=\"item.isActive ? 'text-primary-300' : 'text-white'\"\n >\n {{ item.label }}\n </div>\n <div v-if=\"item.subLabel\" class=\"text-xs text-white/50 mt-0.5\">\n {{ item.subLabel }}\n </div>\n </div>\n </div>\n </button>\n </TransitionGroup>\n </div>\n\n <!-- Footer -->\n <div class=\"p-6\">\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </Transition>\n</template>\n","<script lang=\"ts\" setup>\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport AgentSidebarClose from './AgentSidebarClose.vue'\n\ndefineOptions({ name: 'ElSidebar', inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: boolean\n items: NavItem[]\n position?: 'left' | 'right'\n title?: string\n widthClasses?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst position = props.position || 'left'\nconst widthClasses = props.widthClasses || 'w-[80%] max-w-[300px]'\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst visibleItems = computed(() => props.items.filter((item) => !item.isHidden))\n\nfunction handleItemClick(item: NavItem) {\n if (item.isDisabled)\n return\n\n if (item.onClick) {\n item.onClick({ item, event: new MouseEvent('click') })\n } else if (item.href) {\n if (item.href.includes('http')) {\n window.open(item.href, item.target || '_self')?.focus()\n } else {\n window.location.href = item.href\n }\n }\n\n isOpen.value = false\n}\n\n// Position-specific classes\nconst transitionClasses = computed(() => {\n if (position === 'left') {\n return {\n enter: '-translate-x-full',\n leave: '-translate-x-full',\n position: 'justify-start',\n closeButton: '-right-16',\n }\n } else {\n return {\n enter: 'translate-x-full',\n leave: 'translate-x-full',\n position: 'justify-end',\n closeButton: '-left-16',\n }\n }\n})\n</script>\n\n<template>\n <!-- Backdrop -->\n <Transition\n enter-active-class=\"transition-opacity duration-300 ease-out\"\n leave-active-class=\"transition-opacity duration-200 ease-in\"\n enter-from-class=\"opacity-0\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-40 bg-black/50 backdrop-blur-sm\"\n @click=\"isOpen = false\"\n />\n </Transition>\n\n <!-- Sidebar -->\n <Transition\n enter-active-class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"transitionClasses.enter\"\n enter-to-class=\"translate-x-0\"\n leave-from-class=\"translate-x-0\"\n :leave-to-class=\"transitionClasses.leave\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-50 flex\"\n :class=\"transitionClasses.position\"\n @click=\"isOpen = false\"\n >\n <!-- Menu Panel -->\n <div\n class=\"relative h-full shadow-2xl bg-black/30 backdrop-blur-xl flex flex-col justify-center\"\n :class=\"widthClasses\"\n @click.stop\n >\n <AgentSidebarClose\n class=\"absolute top-4 z-10 text-white\"\n :class=\"transitionClasses.closeButton\"\n @click=\"isOpen = false\"\n />\n\n <!-- Title -->\n <div v-if=\"title\" class=\"px-9 pt-12 pb-4\">\n <h3 class=\"text-base font-medium text-theme-400\">\n {{ title }}\n </h3>\n </div>\n\n <!-- Header Slot -->\n <div v-if=\"$slots.header\" class=\"px-4 pb-8 border-b border-white/10\">\n <slot name=\"header\" />\n </div>\n\n <!-- Menu Items -->\n <div class=\"flex-1 p-6 space-y-2 overflow-y-auto\" :class=\"{ 'pt-6': !title && !$slots.header, 'pt-4': title || $slots.header }\">\n <TransitionGroup\n enter-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n enter-to-class=\"translate-x-0 opacity-100\"\n leave-from-class=\"translate-x-0 opacity-100\"\n :leave-to-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n >\n <button\n v-for=\"(item, index) in visibleItems\"\n :key=\"item.key || item.label || index\"\n :style=\"{ transitionDelay: `${index * 40}ms` }\"\n class=\"cursor-pointer w-full text-left p-3 rounded-xl transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group\"\n :class=\"[\n item.isActive\n ? 'bg-primary-500/20 border border-primary-500/40'\n : 'hover:bg-white/10',\n item.isDisabled && 'opacity-50 cursor-not-allowed',\n ]\"\n :disabled=\"item.isDisabled\"\n @click=\"handleItemClick(item)\"\n >\n <div class=\"flex items-center gap-3\">\n <i\n v-if=\"item.icon?.src\"\n class=\"size-5 flex-shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group-hover:scale-110\"\n :class=\"[\n item.icon.src,\n item.isActive ? 'text-primary-400' : 'text-white/70 group-hover:text-white',\n ]\"\n />\n <div class=\"flex-1\">\n <div\n class=\"font-medium text-sm\"\n :class=\"item.isActive ? 'text-primary-300' : 'text-white'\"\n >\n {{ item.label }}\n </div>\n <div v-if=\"item.subLabel\" class=\"text-xs text-white/50 mt-0.5\">\n {{ item.subLabel }}\n </div>\n </div>\n </div>\n </button>\n </TransitionGroup>\n </div>\n\n <!-- Footer -->\n <div class=\"p-6\">\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </Transition>\n</template>\n","<script lang=\"ts\" setup>\nimport type { AgentMode } from '../schema'\nimport type { AgentChatController } from '../AgentController'\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport { AGENT_MODES } from '../schema'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentModeSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n chatController?: AgentChatController\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst currentMode = computed(() => props.chatController?.agentMode?.value ?? 'self')\n\nconst modeItems = computed<NavItem[]>(() => AGENT_MODES.map((mode) => ({\n key: mode.mode,\n icon: { src: mode.icon },\n label: mode.label,\n isActive: currentMode.value === mode.mode,\n onClick: () => {\n props.chatController?.setMode(mode.mode as AgentMode)\n },\n})))\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"modeItems\"\n position=\"right\"\n title=\"Mode\"\n width-classes=\"w-[80%] max-w-[255px]\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { AgentMode } from '../schema'\nimport type { AgentChatController } from '../AgentController'\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport { AGENT_MODES } from '../schema'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentModeSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n chatController?: AgentChatController\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst currentMode = computed(() => props.chatController?.agentMode?.value ?? 'self')\n\nconst modeItems = computed<NavItem[]>(() => AGENT_MODES.map((mode) => ({\n key: mode.mode,\n icon: { src: mode.icon },\n label: mode.label,\n isActive: currentMode.value === mode.mode,\n onClick: () => {\n props.chatController?.setMode(mode.mode as AgentMode)\n },\n})))\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"modeItems\"\n position=\"right\"\n title=\"Mode\"\n width-classes=\"w-[80%] max-w-[255px]\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { NavItem } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed } from 'vue'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n agent: Agent\n sdk: PageLinesSDK\n title?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst menuItems = computed<NavItem[]>(() => {\n const items: NavItem[] = [\n {\n key: 'share',\n icon: { src: 'i-tabler-share' },\n label: 'Share this assistant',\n onClick: () => {\n const url = `${window.location.origin}/@${props.agent.handle.value || props.agent.agentId.value}`\n // TODO: Show notification that URL was copied (SDK has no notify host).\n navigator.clipboard.writeText(url).catch((err) => {\n console.error('ElAgentSidebar: clipboard.writeText rejected', err)\n })\n },\n },\n {\n key: 'profile',\n icon: { src: 'i-tabler-user' },\n label: 'View full profile',\n onClick: () => {\n window.open(`/@${props.agent.handle.value || props.agent.agentId.value}`, '_blank')\n },\n },\n {\n key: 'create',\n icon: { src: 'i-tabler-sparkles' },\n label: 'Create your own',\n onClick: () => {\n window.open('/auth', '_blank')\n },\n },\n ]\n\n // Add logout option if user is authenticated\n if (props.sdk.activeUser.value) {\n items.push({\n key: 'logout',\n icon: { src: 'i-tabler-logout' },\n label: 'Logout',\n onClick: async () => {\n await props.sdk.auth.logout()\n },\n })\n }\n\n return items\n})\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"menuItems\"\n position=\"left\"\n :title=\"title || 'Menu'\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { NavItem } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed } from 'vue'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n agent: Agent\n sdk: PageLinesSDK\n title?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst menuItems = computed<NavItem[]>(() => {\n const items: NavItem[] = [\n {\n key: 'share',\n icon: { src: 'i-tabler-share' },\n label: 'Share this assistant',\n onClick: () => {\n const url = `${window.location.origin}/@${props.agent.handle.value || props.agent.agentId.value}`\n // TODO: Show notification that URL was copied (SDK has no notify host).\n navigator.clipboard.writeText(url).catch((err) => {\n console.error('ElAgentSidebar: clipboard.writeText rejected', err)\n })\n },\n },\n {\n key: 'profile',\n icon: { src: 'i-tabler-user' },\n label: 'View full profile',\n onClick: () => {\n window.open(`/@${props.agent.handle.value || props.agent.agentId.value}`, '_blank')\n },\n },\n {\n key: 'create',\n icon: { src: 'i-tabler-sparkles' },\n label: 'Create your own',\n onClick: () => {\n window.open('/auth', '_blank')\n },\n },\n ]\n\n // Add logout option if user is authenticated\n if (props.sdk.activeUser.value) {\n items.push({\n key: 'logout',\n icon: { src: 'i-tabler-logout' },\n label: 'Logout',\n onClick: async () => {\n await props.sdk.auth.logout()\n },\n })\n }\n\n return items\n})\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"menuItems\"\n position=\"left\"\n :title=\"title || 'Menu'\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { AgentChatControllerSettings } from '../AgentController'\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { ColorName, SuggestedPrompt } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport FSpinner from '../../ui/FSpinner.vue'\nimport { getColorSchemeOklch } from '@pagelines/core'\nimport { AGENT_MODES } from '../schema'\nimport { AgentChatController } from '../AgentController'\nimport { getAgentAvatarUrl, parseButtonTemplate } from '../utils'\nimport ElAuthGate from './ElAuthGate.vue'\nimport ElModeHeader from './ElModeHeader.vue'\nimport ElAgentAbout from './ElAgentAbout.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport ElAgentChat from './ElAgentChat.vue'\nimport ElAgentHeader from './ElAgentHeader.vue'\nimport ElAgentModeSidebar from './ElAgentModeSidebar.vue'\nimport ElAgentSidebar from './ElAgentSidebar.vue'\n\nconst {\n sdk,\n agent,\n context,\n firstMessage,\n buttonText,\n buttonIcon,\n hasClose = false,\n isActive = true,\n loading = false,\n theme = 'green',\n requireAuth = false,\n chatOnly = false,\n bare = false,\n emptyStateMessage,\n suggestedPrompts = [],\n createVoiceClientFn,\n} = defineProps<{\n sdk: PageLinesSDK\n agent: Agent\n context?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n isActive?: boolean\n loading?: boolean\n theme?: ColorName\n requireAuth?: boolean\n chatOnly?: boolean\n /** Render chat without profile chrome so a host page can provide it. */\n bare?: boolean\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n /** Voice transport, supplied by hosts that ship it. See the note in createChatController. */\n createVoiceClientFn?: AgentChatControllerSettings['createVoiceClientFn']\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\nconst chatController = shallowRef<AgentChatController>()\nconst isSidebarOpen = ref(false)\nconst isModeSidebarOpen = ref(false)\nconst initError = ref<string>()\nconst rootElement = ref<HTMLElement>()\n\nconst agentMode = computed(() => chatController.value?.agentMode?.value ?? 'self')\nconst isOnline = computed(() => chatController.value?.textState.value.isConnected ?? false)\n\n// Check if user is authenticated\nconst isAuthenticated = computed(() => sdk.activeUser.value !== undefined)\n\n// Current mode for button display\nconst currentMode = computed(() => AGENT_MODES.find((btn) => btn.mode === agentMode.value))\n\nfunction createChatController() {\n if (chatController.value) {\n chatController.value.destroy()\n }\n\n try {\n chatController.value = new AgentChatController({\n sdk,\n agent,\n context,\n firstMessage,\n // No voice wiring here on purpose: this component is reachable from the\n // embeddable widget (PLWidget lazy-loads its modal/inline modes, and the\n // IIFE build inlines those), so any static edge to the LiveKit transport\n // lands a WebRTC stack on every host page. Hosts that do voice pass\n // `createVoiceClientFn` down themselves.\n ...(createVoiceClientFn ? { createVoiceClientFn } : {}),\n onTurnStarted: () => emit('turnStarted'),\n onTurnCompleted: conversationId => emit('turnCompleted', conversationId),\n })\n } catch (error) {\n console.error('AgentChatController creation failed:', error)\n throw error\n }\n}\n\ntry {\n createChatController()\n} catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n}\n\n// Set theme CSS variables\nfunction applyTheme(themeName: ColorName) {\n if (!rootElement.value)\n return\n\n const colorScheme = getColorSchemeOklch(themeName)\n\n // Set --primary-* CSS variables on component root for Shadow DOM compatibility\n Object.entries(colorScheme).forEach(([scale, value]) => {\n rootElement.value!.style.setProperty(`--primary-${scale}`, value)\n })\n}\n\nonMounted(() => {\n try {\n applyTheme(theme)\n\n // In chatOnly mode, jump straight to chat\n if (chatOnly && chatController.value) {\n chatController.value.setMode('chat')\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n }\n})\n\nonUnmounted(() => {\n if (chatController.value) {\n chatController.value.destroy()\n }\n})\n\n// Watch theme changes and reapply\nwatch(() => theme, (newTheme) => {\n applyTheme(newTheme)\n})\n\n// Reset to self mode when user logs out\nwatch(() => sdk.activeUser.value, (newUser, oldUser) => {\n // User logged out (had user, now undefined)\n if (oldUser && !newUser && chatController.value) {\n chatController.value.setMode('self')\n }\n})\n\nconst isLowQuality = computed(() => {\n return !!(agent.cover.value?.src && agent.cover.value?.quality === 'low') || !!(agent.avatar.value?.src && agent.avatar.value?.quality === 'low')\n})\n\nconst backdropClass = computed(() => {\n const out = [isLowQuality.value ? 'backdrop-blur-sm' : '']\n\n if(isLowQuality.value && agentMode.value === 'self') {\n out.push('from-black/80 via-black/60 to-black/80')\n }\n else if (agentMode.value === 'self') {\n out.push('from-black/70 via-black/50 to-black/80')\n }\n else {\n out.push('from-black/90 via-black/90 to-black/100')\n }\n\n return out.join(' ')\n})\n\n// Icon preset mapping\nconst ICON_MAP: Record<ButtonIconPreset, string> = {\n phone: 'i-heroicons-phone',\n calendar: 'i-heroicons-calendar',\n question: 'i-heroicons-question-mark-circle',\n message: 'i-heroicons-chat-bubble-left-right',\n sparkles: 'i-heroicons-sparkles',\n}\n\n// Resolve button text with template variables\nconst resolvedButtonText = computed(() => {\n return parseButtonTemplate({\n template: buttonText || 'Talk to {name}',\n agent: agent.toConfig(),\n })\n})\n\n// Resolve button icon from preset or default to phone\nconst resolvedButtonIcon = computed(() => {\n return ICON_MAP[buttonIcon || 'phone'] || ICON_MAP.phone\n})\n</script>\n\n<template>\n <div\n ref=\"rootElement\"\n :key=\"getAgentAvatarUrl(agent.toConfig())\"\n class=\"pagelines-sdk @container/agent pagelines-agent w-full h-full overflow-hidden relative\"\n data-test=\"agent-chat\"\n >\n <div v-if=\"loading\" class=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-theme-800 to-theme-950 rounded-3xl z-10\">\n <FSpinner class=\"text-white size-8\" />\n </div>\n\n <!-- bare: no background at any layer — the host page owns the canvas\n (the app tints its chat surface bg-theme-25/50); any paint here\n shows as a stripe against the host tint. -->\n <div\n v-else-if=\"agent && !initError\"\n class=\"absolute inset-0\"\n :class=\"bare ? '' : 'bg-cover bg-center bg-no-repeat'\"\n :style=\"bare ? undefined : { backgroundImage: `url(${getAgentAvatarUrl(agent.toConfig())})` }\"\n :data-quality=\"agent.avatar.value?.quality || 'none'\"\n >\n <div\n v-if=\"!bare\"\n class=\"absolute inset-0 bg-gradient-to-br z-0\"\n :class=\"backdropClass\"\n />\n <div\n class=\"relative z-10 flex flex-col h-full transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] will-change-transform\"\n :class=\"isActive ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'\"\n >\n <div v-if=\"!bare || hasClose\" class=\"relative z-30 p-2\" :class=\"!bare && agentMode !== 'self' ? 'backdrop-blur-lg' : ''\">\n <!-- A bare chat embed supplies its own surrounding header. -->\n <div v-if=\"chatOnly\" class=\"flex items-center\" :class=\"bare ? 'justify-end' : ''\">\n <div v-if=\"!bare\" class=\"flex flex-1 items-center gap-3 pl-2\">\n <img\n :src=\"getAgentAvatarUrl(agent.toConfig())\"\n :alt=\"agent.displayName.value\"\n class=\"size-8 rounded-full object-cover\"\n />\n <span class=\"text-sm font-medium text-white/90\">{{ agent.displayName.value }}</span>\n </div>\n <div v-if=\"hasClose\" class=\"flex justify-end\">\n <button\n class=\"flex cursor-pointer items-center rounded-2xl p-3 transition-colors\"\n :class=\"bare ? 'text-theme-500 hover:bg-theme-50' : 'text-white/70 hover:bg-white/10'\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n\n <!-- Full header with mode selector and sidebars -->\n <div v-else class=\"flex items-center\" :class=\"hasClose ? '' : 'justify-between'\">\n <!-- Left side: Sidebar toggle with user avatar -->\n <div :class=\"hasClose ? 'flex-1 basis-0' : ''\">\n <button\n class=\"cursor-pointer p-2 flex items-center gap-2 rounded-2xl text-white/70 hover:bg-white/10 transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-105 active:scale-95\"\n @click=\"isSidebarOpen = true\"\n >\n <i class=\"i-tabler-menu size-7\" />\n </button>\n </div>\n\n <!-- Center: Mode selector button (centered when hasClose=true) -->\n <button\n class=\"flex items-center gap-2 px-3.5 py-3 rounded-2xl text-white/90 hover:bg-white/10 transition-all cursor-pointer flex-grow-0\"\n :class=\"{ 'bg-white/10': isModeSidebarOpen }\"\n @click=\"isModeSidebarOpen = true\"\n >\n <i :class=\"currentMode?.icon\" class=\"size-4 opacity-60\" />\n <span class=\"text-sm\">{{ currentMode?.label }}</span>\n <i class=\"i-tabler-chevron-down size-4\" />\n </button>\n\n <!-- Right side: Close button (only in widget mode) -->\n <div v-if=\"hasClose\" class=\"flex-1 basis-0 flex justify-end\">\n <button\n class=\"cursor-pointer flex items-center p-3 rounded-2xl text-white/70 hover:bg-white/10 transition-colors\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n </div>\n\n <!-- chatOnly: skip all modes, show chat directly -->\n <!-- bare: the host page owns the canvas (the app tints its chat\n surface bg-theme-25/50); painting white here left the composer\n footer's matching tint as a visible stripe. -->\n <div\n v-if=\"chatOnly\"\n class=\"relative z-20 flex min-h-0 w-full flex-1 flex-col\"\n :class=\"bare ? '' : 'px-4'\"\n >\n <div class=\"min-h-0 w-full flex-1\" :class=\"bare ? '' : 'mx-auto max-w-md'\">\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n :scope=\"isAuthenticated ? 'private' : 'public'\"\n :empty-state-message=\"emptyStateMessage\"\n :suggested-prompts=\"suggestedPrompts\"\n :variant=\"bare ? 'light' : 'dark'\"\n :show-header=\"!bare\"\n :centered=\"bare\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </ElAgentChat>\n </div>\n </div>\n\n <!-- Full agent interface modes -->\n <template v-else>\n <div\n v-if=\"agentMode === 'self'\"\n class=\"h-full pb-12 flex-1 flex flex-col relative z-20 min-h-0 px-4 @[480px]/agent:px-6 max-w-md mx-auto w-full\"\n >\n <!-- Top spacer -->\n <div class=\"flex-1 basis-0 mb-12\" />\n\n <!-- Avatar header -->\n <ElAgentHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <!-- Bottom section with button and social links -->\n <div class=\"flex-1 basis-0 flex flex-col justify-start pt-8 gap-7\">\n <ElAgentButton\n theme=\"primary\"\n size=\"lg\"\n class=\"w-full\"\n :icon=\"resolvedButtonIcon\"\n data-test=\"voice-button\"\n @click=\"chatController?.setMode('talk')\"\n >\n {{ resolvedButtonText }}\n </ElAgentButton>\n\n <!-- Social icon links -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"flex items-center justify-center gap-3\">\n <a\n v-for=\"account in (agent.accounts.value || []).filter(a => SOCIAL_PLATFORMS[a.platform])\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n class=\"size-12 rounded-full text-white/60 hover:text-white hover:bg-white/5 border border-white/0 hover:border-white/10 flex items-center justify-center transition-all duration-200 hover:scale-105\"\n >\n <i :class=\"SOCIAL_PLATFORMS[account.platform].icon\" class=\"size-5 \" />\n </a>\n </div>\n </div>\n </div>\n <div\n v-else-if=\"agentMode === 'talk'\"\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full gap-4 px-4\"\n >\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <template v-else>\n <!-- Sticky header with backdrop blur - full width -->\n <div>\n <div class=\"max-w-md mx-auto\">\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n </div>\n </div>\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n />\n </template>\n </div>\n <div\n v-else\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full px-4 @[480px]/agent:px-6\"\n >\n <div class=\"flex-1 min-h-0 max-w-md mx-auto w-full\">\n <template v-if=\"agentMode === 'chat'\">\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <ElAgentChat\n v-else\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n show-header\n />\n </template>\n <ElAgentAbout\n v-else-if=\"agentMode === 'info'\"\n :agent=\"agent\"\n :is-online=\"isOnline\"\n />\n </div>\n </div>\n </template>\n\n </div>\n </div>\n <div v-else-if=\"initError\" class=\"bg-gradient-to-br from-theme-800 to-theme-950 text-white flex items-center justify-center h-full p-8\">\n <div class=\"text-center max-w-md space-y-4\">\n <div class=\"flex justify-center\">\n <div class=\"rounded-full bg-red-500/20 flex items-center justify-center size-10\">\n <i class=\"i-tabler-alert-circle size-6 text-red-400\" />\n </div>\n </div>\n <h3 class=\"text-lg font-medium\">\n Agent Error\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n {{ initError }}\n </p>\n </div>\n </div>\n <div v-else class=\"bg-white/10 backdrop-blur-sm text-white/70 flex items-center justify-center h-full\">\n Couldn't load your assistant. Please try again later.\n </div>\n\n <!-- Agent Sidebar (left) — hidden in chatOnly mode -->\n <ElAgentSidebar\n v-if=\"!chatOnly\"\n v-model=\"isSidebarOpen\"\n :agent=\"agent\"\n :sdk=\"sdk\"\n :title=\"agent.displayName.value\"\n data-test=\"agent-sidebar\"\n />\n\n <!-- Mode Sidebar (right) — hidden in chatOnly mode -->\n <ElAgentModeSidebar\n v-if=\"!chatOnly\"\n v-model=\"isModeSidebarOpen\"\n :chat-controller=\"chatController\"\n data-test=\"agent-mode-sidebar\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { AgentChatControllerSettings } from '../AgentController'\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { ColorName, SuggestedPrompt } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport FSpinner from '../../ui/FSpinner.vue'\nimport { getColorSchemeOklch } from '@pagelines/core'\nimport { AGENT_MODES } from '../schema'\nimport { AgentChatController } from '../AgentController'\nimport { getAgentAvatarUrl, parseButtonTemplate } from '../utils'\nimport ElAuthGate from './ElAuthGate.vue'\nimport ElModeHeader from './ElModeHeader.vue'\nimport ElAgentAbout from './ElAgentAbout.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport ElAgentChat from './ElAgentChat.vue'\nimport ElAgentHeader from './ElAgentHeader.vue'\nimport ElAgentModeSidebar from './ElAgentModeSidebar.vue'\nimport ElAgentSidebar from './ElAgentSidebar.vue'\n\nconst {\n sdk,\n agent,\n context,\n firstMessage,\n buttonText,\n buttonIcon,\n hasClose = false,\n isActive = true,\n loading = false,\n theme = 'green',\n requireAuth = false,\n chatOnly = false,\n bare = false,\n emptyStateMessage,\n suggestedPrompts = [],\n createVoiceClientFn,\n} = defineProps<{\n sdk: PageLinesSDK\n agent: Agent\n context?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n isActive?: boolean\n loading?: boolean\n theme?: ColorName\n requireAuth?: boolean\n chatOnly?: boolean\n /** Render chat without profile chrome so a host page can provide it. */\n bare?: boolean\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n /** Voice transport, supplied by hosts that ship it. See the note in createChatController. */\n createVoiceClientFn?: AgentChatControllerSettings['createVoiceClientFn']\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\nconst chatController = shallowRef<AgentChatController>()\nconst isSidebarOpen = ref(false)\nconst isModeSidebarOpen = ref(false)\nconst initError = ref<string>()\nconst rootElement = ref<HTMLElement>()\n\nconst agentMode = computed(() => chatController.value?.agentMode?.value ?? 'self')\nconst isOnline = computed(() => chatController.value?.textState.value.isConnected ?? false)\n\n// Check if user is authenticated\nconst isAuthenticated = computed(() => sdk.activeUser.value !== undefined)\n\n// Current mode for button display\nconst currentMode = computed(() => AGENT_MODES.find((btn) => btn.mode === agentMode.value))\n\nfunction createChatController() {\n if (chatController.value) {\n chatController.value.destroy()\n }\n\n try {\n chatController.value = new AgentChatController({\n sdk,\n agent,\n context,\n firstMessage,\n // No voice wiring here on purpose: this component is reachable from the\n // embeddable widget (PLWidget lazy-loads its modal/inline modes, and the\n // IIFE build inlines those), so any static edge to the LiveKit transport\n // lands a WebRTC stack on every host page. Hosts that do voice pass\n // `createVoiceClientFn` down themselves.\n ...(createVoiceClientFn ? { createVoiceClientFn } : {}),\n onTurnStarted: () => emit('turnStarted'),\n onTurnCompleted: conversationId => emit('turnCompleted', conversationId),\n })\n } catch (error) {\n console.error('AgentChatController creation failed:', error)\n throw error\n }\n}\n\ntry {\n createChatController()\n} catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n}\n\n// Set theme CSS variables\nfunction applyTheme(themeName: ColorName) {\n if (!rootElement.value)\n return\n\n const colorScheme = getColorSchemeOklch(themeName)\n\n // Set --primary-* CSS variables on component root for Shadow DOM compatibility\n Object.entries(colorScheme).forEach(([scale, value]) => {\n rootElement.value!.style.setProperty(`--primary-${scale}`, value)\n })\n}\n\nonMounted(() => {\n try {\n applyTheme(theme)\n\n // In chatOnly mode, jump straight to chat\n if (chatOnly && chatController.value) {\n chatController.value.setMode('chat')\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n }\n})\n\nonUnmounted(() => {\n if (chatController.value) {\n chatController.value.destroy()\n }\n})\n\n// Watch theme changes and reapply\nwatch(() => theme, (newTheme) => {\n applyTheme(newTheme)\n})\n\n// Reset to self mode when user logs out\nwatch(() => sdk.activeUser.value, (newUser, oldUser) => {\n // User logged out (had user, now undefined)\n if (oldUser && !newUser && chatController.value) {\n chatController.value.setMode('self')\n }\n})\n\nconst isLowQuality = computed(() => {\n return !!(agent.cover.value?.src && agent.cover.value?.quality === 'low') || !!(agent.avatar.value?.src && agent.avatar.value?.quality === 'low')\n})\n\nconst backdropClass = computed(() => {\n const out = [isLowQuality.value ? 'backdrop-blur-sm' : '']\n\n if(isLowQuality.value && agentMode.value === 'self') {\n out.push('from-black/80 via-black/60 to-black/80')\n }\n else if (agentMode.value === 'self') {\n out.push('from-black/70 via-black/50 to-black/80')\n }\n else {\n out.push('from-black/90 via-black/90 to-black/100')\n }\n\n return out.join(' ')\n})\n\n// Icon preset mapping\nconst ICON_MAP: Record<ButtonIconPreset, string> = {\n phone: 'i-heroicons-phone',\n calendar: 'i-heroicons-calendar',\n question: 'i-heroicons-question-mark-circle',\n message: 'i-heroicons-chat-bubble-left-right',\n sparkles: 'i-heroicons-sparkles',\n}\n\n// Resolve button text with template variables\nconst resolvedButtonText = computed(() => {\n return parseButtonTemplate({\n template: buttonText || 'Talk to {name}',\n agent: agent.toConfig(),\n })\n})\n\n// Resolve button icon from preset or default to phone\nconst resolvedButtonIcon = computed(() => {\n return ICON_MAP[buttonIcon || 'phone'] || ICON_MAP.phone\n})\n</script>\n\n<template>\n <div\n ref=\"rootElement\"\n :key=\"getAgentAvatarUrl(agent.toConfig())\"\n class=\"pagelines-sdk @container/agent pagelines-agent w-full h-full overflow-hidden relative\"\n data-test=\"agent-chat\"\n >\n <div v-if=\"loading\" class=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-theme-800 to-theme-950 rounded-3xl z-10\">\n <FSpinner class=\"text-white size-8\" />\n </div>\n\n <!-- bare: no background at any layer — the host page owns the canvas\n (the app tints its chat surface bg-theme-25/50); any paint here\n shows as a stripe against the host tint. -->\n <div\n v-else-if=\"agent && !initError\"\n class=\"absolute inset-0\"\n :class=\"bare ? '' : 'bg-cover bg-center bg-no-repeat'\"\n :style=\"bare ? undefined : { backgroundImage: `url(${getAgentAvatarUrl(agent.toConfig())})` }\"\n :data-quality=\"agent.avatar.value?.quality || 'none'\"\n >\n <div\n v-if=\"!bare\"\n class=\"absolute inset-0 bg-gradient-to-br z-0\"\n :class=\"backdropClass\"\n />\n <div\n class=\"relative z-10 flex flex-col h-full transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] will-change-transform\"\n :class=\"isActive ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'\"\n >\n <div v-if=\"!bare || hasClose\" class=\"relative z-30 p-2\" :class=\"!bare && agentMode !== 'self' ? 'backdrop-blur-lg' : ''\">\n <!-- A bare chat embed supplies its own surrounding header. -->\n <div v-if=\"chatOnly\" class=\"flex items-center\" :class=\"bare ? 'justify-end' : ''\">\n <div v-if=\"!bare\" class=\"flex flex-1 items-center gap-3 pl-2\">\n <img\n :src=\"getAgentAvatarUrl(agent.toConfig())\"\n :alt=\"agent.displayName.value\"\n class=\"size-8 rounded-full object-cover\"\n />\n <span class=\"text-sm font-medium text-white/90\">{{ agent.displayName.value }}</span>\n </div>\n <div v-if=\"hasClose\" class=\"flex justify-end\">\n <button\n class=\"flex cursor-pointer items-center rounded-2xl p-3 transition-colors\"\n :class=\"bare ? 'text-theme-500 hover:bg-theme-50' : 'text-white/70 hover:bg-white/10'\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n\n <!-- Full header with mode selector and sidebars -->\n <div v-else class=\"flex items-center\" :class=\"hasClose ? '' : 'justify-between'\">\n <!-- Left side: Sidebar toggle with user avatar -->\n <div :class=\"hasClose ? 'flex-1 basis-0' : ''\">\n <button\n class=\"cursor-pointer p-2 flex items-center gap-2 rounded-2xl text-white/70 hover:bg-white/10 transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-105 active:scale-95\"\n @click=\"isSidebarOpen = true\"\n >\n <i class=\"i-tabler-menu size-7\" />\n </button>\n </div>\n\n <!-- Center: Mode selector button (centered when hasClose=true) -->\n <button\n class=\"flex items-center gap-2 px-3.5 py-3 rounded-2xl text-white/90 hover:bg-white/10 transition-all cursor-pointer flex-grow-0\"\n :class=\"{ 'bg-white/10': isModeSidebarOpen }\"\n @click=\"isModeSidebarOpen = true\"\n >\n <i :class=\"currentMode?.icon\" class=\"size-4 opacity-60\" />\n <span class=\"text-sm\">{{ currentMode?.label }}</span>\n <i class=\"i-tabler-chevron-down size-4\" />\n </button>\n\n <!-- Right side: Close button (only in widget mode) -->\n <div v-if=\"hasClose\" class=\"flex-1 basis-0 flex justify-end\">\n <button\n class=\"cursor-pointer flex items-center p-3 rounded-2xl text-white/70 hover:bg-white/10 transition-colors\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n </div>\n\n <!-- chatOnly: skip all modes, show chat directly -->\n <!-- bare: the host page owns the canvas (the app tints its chat\n surface bg-theme-25/50); painting white here left the composer\n footer's matching tint as a visible stripe. -->\n <div\n v-if=\"chatOnly\"\n class=\"relative z-20 flex min-h-0 w-full flex-1 flex-col\"\n :class=\"bare ? '' : 'px-4'\"\n >\n <div class=\"min-h-0 w-full flex-1\" :class=\"bare ? '' : 'mx-auto max-w-md'\">\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n :scope=\"isAuthenticated ? 'private' : 'public'\"\n :empty-state-message=\"emptyStateMessage\"\n :suggested-prompts=\"suggestedPrompts\"\n :variant=\"bare ? 'light' : 'dark'\"\n :show-header=\"!bare\"\n :centered=\"bare\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </ElAgentChat>\n </div>\n </div>\n\n <!-- Full agent interface modes -->\n <template v-else>\n <div\n v-if=\"agentMode === 'self'\"\n class=\"h-full pb-12 flex-1 flex flex-col relative z-20 min-h-0 px-4 @[480px]/agent:px-6 max-w-md mx-auto w-full\"\n >\n <!-- Top spacer -->\n <div class=\"flex-1 basis-0 mb-12\" />\n\n <!-- Avatar header -->\n <ElAgentHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <!-- Bottom section with button and social links -->\n <div class=\"flex-1 basis-0 flex flex-col justify-start pt-8 gap-7\">\n <ElAgentButton\n theme=\"primary\"\n size=\"lg\"\n class=\"w-full\"\n :icon=\"resolvedButtonIcon\"\n data-test=\"voice-button\"\n @click=\"chatController?.setMode('talk')\"\n >\n {{ resolvedButtonText }}\n </ElAgentButton>\n\n <!-- Social icon links -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"flex items-center justify-center gap-3\">\n <a\n v-for=\"account in (agent.accounts.value || []).filter(a => SOCIAL_PLATFORMS[a.platform])\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n class=\"size-12 rounded-full text-white/60 hover:text-white hover:bg-white/5 border border-white/0 hover:border-white/10 flex items-center justify-center transition-all duration-200 hover:scale-105\"\n >\n <i :class=\"SOCIAL_PLATFORMS[account.platform].icon\" class=\"size-5 \" />\n </a>\n </div>\n </div>\n </div>\n <div\n v-else-if=\"agentMode === 'talk'\"\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full gap-4 px-4\"\n >\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <template v-else>\n <!-- Sticky header with backdrop blur - full width -->\n <div>\n <div class=\"max-w-md mx-auto\">\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n </div>\n </div>\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n />\n </template>\n </div>\n <div\n v-else\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full px-4 @[480px]/agent:px-6\"\n >\n <div class=\"flex-1 min-h-0 max-w-md mx-auto w-full\">\n <template v-if=\"agentMode === 'chat'\">\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <ElAgentChat\n v-else\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n show-header\n />\n </template>\n <ElAgentAbout\n v-else-if=\"agentMode === 'info'\"\n :agent=\"agent\"\n :is-online=\"isOnline\"\n />\n </div>\n </div>\n </template>\n\n </div>\n </div>\n <div v-else-if=\"initError\" class=\"bg-gradient-to-br from-theme-800 to-theme-950 text-white flex items-center justify-center h-full p-8\">\n <div class=\"text-center max-w-md space-y-4\">\n <div class=\"flex justify-center\">\n <div class=\"rounded-full bg-red-500/20 flex items-center justify-center size-10\">\n <i class=\"i-tabler-alert-circle size-6 text-red-400\" />\n </div>\n </div>\n <h3 class=\"text-lg font-medium\">\n Agent Error\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n {{ initError }}\n </p>\n </div>\n </div>\n <div v-else class=\"bg-white/10 backdrop-blur-sm text-white/70 flex items-center justify-center h-full\">\n Couldn't load your assistant. Please try again later.\n </div>\n\n <!-- Agent Sidebar (left) — hidden in chatOnly mode -->\n <ElAgentSidebar\n v-if=\"!chatOnly\"\n v-model=\"isSidebarOpen\"\n :agent=\"agent\"\n :sdk=\"sdk\"\n :title=\"agent.displayName.value\"\n data-test=\"agent-sidebar\"\n />\n\n <!-- Mode Sidebar (right) — hidden in chatOnly mode -->\n <ElAgentModeSidebar\n v-if=\"!chatOnly\"\n v-model=\"isModeSidebarOpen\"\n :chat-controller=\"chatController\"\n data-test=\"agent-mode-sidebar\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { SuggestedPrompt } from '@pagelines/core'\nimport type { Agent, AgentConfig } from '../schema'\nimport AgentChat from './AgentChat.vue'\nimport AgentWrap from './AgentWrap.vue'\n\nconst props = defineProps<{\n sdk?: PageLinesSDK\n agent?: AgentConfig\n handle?: string\n context?: string\n clientContext?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n chatOnly?: boolean\n bare?: boolean\n apiBase?: string\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\n</script>\n\n<template>\n <!-- slotProps.xxx = data resolved by AgentWrap (sdk, agent, context, firstMessage)\n props.xxx = rendering config passed through unchanged (buttonText, buttonIcon, hasClose, chatOnly) -->\n <AgentWrap\n v-slot=\"slotProps\"\n v-bind=\"props\"\n class=\"agent-provider size-full relative\"\n >\n <AgentChat\n :sdk=\"slotProps.sdk\"\n :agent=\"slotProps.agent\"\n :context=\"slotProps.context\"\n :first-message=\"slotProps.firstMessage\"\n :button-text=\"props.buttonText\"\n :button-icon=\"props.buttonIcon\"\n :has-close=\"props.hasClose\"\n :chat-only=\"props.chatOnly\"\n :bare=\"props.bare\"\n :empty-state-message=\"props.emptyStateMessage\"\n :suggested-prompts=\"props.suggestedPrompts\"\n :is-active=\"true\"\n class=\"size-full\"\n @close=\"emit('close', $event)\"\n @error=\"emit('error', $event)\"\n @turn-started=\"emit('turnStarted')\"\n @turn-completed=\"emit('turnCompleted', $event)\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </AgentChat>\n </AgentWrap>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { SuggestedPrompt } from '@pagelines/core'\nimport type { Agent, AgentConfig } from '../schema'\nimport AgentChat from './AgentChat.vue'\nimport AgentWrap from './AgentWrap.vue'\n\nconst props = defineProps<{\n sdk?: PageLinesSDK\n agent?: AgentConfig\n handle?: string\n context?: string\n clientContext?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n chatOnly?: boolean\n bare?: boolean\n apiBase?: string\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\n</script>\n\n<template>\n <!-- slotProps.xxx = data resolved by AgentWrap (sdk, agent, context, firstMessage)\n props.xxx = rendering config passed through unchanged (buttonText, buttonIcon, hasClose, chatOnly) -->\n <AgentWrap\n v-slot=\"slotProps\"\n v-bind=\"props\"\n class=\"agent-provider size-full relative\"\n >\n <AgentChat\n :sdk=\"slotProps.sdk\"\n :agent=\"slotProps.agent\"\n :context=\"slotProps.context\"\n :first-message=\"slotProps.firstMessage\"\n :button-text=\"props.buttonText\"\n :button-icon=\"props.buttonIcon\"\n :has-close=\"props.hasClose\"\n :chat-only=\"props.chatOnly\"\n :bare=\"props.bare\"\n :empty-state-message=\"props.emptyStateMessage\"\n :suggested-prompts=\"props.suggestedPrompts\"\n :is-active=\"true\"\n class=\"size-full\"\n @close=\"emit('close', $event)\"\n @error=\"emit('error', $event)\"\n @turn-started=\"emit('turnStarted')\"\n @turn-completed=\"emit('turnCompleted', $event)\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </AgentChat>\n </AgentWrap>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentProvider.js","names":["$emit","$slots","$slots","$slots"],"sources":["../ui/EffectTransitionList.vue","../ui/EffectTransitionList.vue","../agent/ui/ElAuthGate.vue","../agent/ui/ElAuthGate.vue","../agent/ui/ElAgentAbout.vue","../agent/ui/ElAgentAbout.vue","../agent/ui/ElAgentHeader.vue","../agent/ui/ElAgentHeader.vue","../agent/ui/AgentSidebarClose.vue","../agent/ui/AgentSidebarClose.vue","../agent/ui/ElSidebar.vue","../agent/ui/ElSidebar.vue","../agent/ui/ElAgentModeSidebar.vue","../agent/ui/ElAgentModeSidebar.vue","../agent/ui/ElAgentSidebar.vue","../agent/ui/ElAgentSidebar.vue","../agent/ui/AgentChat.vue","../agent/ui/AgentChat.vue","../agent/ui/AgentProvider.vue","../agent/ui/AgentProvider.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n// SDK-local copy of src/ui/effects/EffectTransitionList.vue — the SDK package\n// must not import app source, so the primitives it needs live here.\nconst { disabled = false, mode: _mode = 'block' } = defineProps<{ disabled?: boolean, mode?: 'block' | 'inline' }>()\n</script>\n\n<template>\n <TransitionGroup :name=\"!disabled ? 'nlist' : ''\">\n <slot />\n </TransitionGroup>\n</template>\n\n<style>\n.nlist-enter-active,\n.nlist-leave-active,\n.nlist-move {\n transition: all 600ms cubic-bezier(0.68, -0.55, 0.27, 1.55);\n}\n\n.nlist-enter-from {\n opacity: 0;\n transform: translateX(-30px) scale(0.9);\n}\n\n.nlist-enter-to {\n opacity: 1;\n transform: translateX(0) scale(1);\n}\n\n.nlist-leave-active {\n position: absolute;\n}\n\n.nlist-leave-to {\n opacity: 0;\n transform: scale(0.9);\n}\n</style>\n","<script lang=\"ts\" setup>\n// SDK-local copy of src/ui/effects/EffectTransitionList.vue — the SDK package\n// must not import app source, so the primitives it needs live here.\nconst { disabled = false, mode: _mode = 'block' } = defineProps<{ disabled?: boolean, mode?: 'block' | 'inline' }>()\n</script>\n\n<template>\n <TransitionGroup :name=\"!disabled ? 'nlist' : ''\">\n <slot />\n </TransitionGroup>\n</template>\n\n<style>\n.nlist-enter-active,\n.nlist-leave-active,\n.nlist-move {\n transition: all 600ms cubic-bezier(0.68, -0.55, 0.27, 1.55);\n}\n\n.nlist-enter-from {\n opacity: 0;\n transform: translateX(-30px) scale(0.9);\n}\n\n.nlist-enter-to {\n opacity: 1;\n transform: translateX(0) scale(1);\n}\n\n.nlist-leave-active {\n position: absolute;\n}\n\n.nlist-leave-to {\n opacity: 0;\n transform: scale(0.9);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { computed, ref, watch } from 'vue'\nimport EffectTransitionList from '../../ui/EffectTransitionList.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport AgentInputEmail from './AgentInputEmail.vue'\nimport AgentInputOneTimeCode from './AgentInputOneTimeCode.vue'\n\nconst { sdk } = defineProps<{ sdk: PageLinesSDK }>()\n\nconst form = ref({ email: '', code: '' })\nconst step = ref<'email' | 'code'>('email')\nconst isSubmitting = ref(false)\n\n// Engine array for step configuration\nconst stepConfig = {\n email: {\n title: 'Enter Your Email',\n button: { label: 'Continue', disabled: () => !form.value.email || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n const success = await sdk.auth.requestAuthCode({ email: form.value.email })\n if (success)\n step.value = 'code'\n } finally {\n isSubmitting.value = false\n }\n },\n },\n code: {\n title: 'Enter Verification Code',\n button: { label: 'Verify', disabled: () => form.value.code.length !== 6 || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n await sdk.auth.loginWithCode({ email: form.value.email, code: form.value.code })\n } finally {\n isSubmitting.value = false\n }\n },\n },\n}\n\nconst currentStep = computed(() => stepConfig[step.value])\n\n// Watch for successful authentication - UI will update when activeUser becomes defined\nwatch(() => sdk.activeUser.value, (newUser) => {\n if (newUser && step.value === 'code') {\n // Auth succeeded - parent component will handle UI transition\n // This log helps debug the auth flow\n console.log('[ElAuthGate] Authentication successful', { email: newUser.email })\n }\n})\n</script>\n\n<template>\n <div data-test=\"auth-form\" :data-test-mode=\"step\" class=\"flex flex-col items-center justify-center h-full p-6\">\n <div class=\"w-full max-w-xs space-y-12\">\n <p v-if=\"sdk.error.value\" class=\"text-xs text-theme-400 text-center\">\n {{ sdk.error.value }}\n </p>\n\n <h3 class=\"text-base font-light text-white text-center\">\n {{ currentStep.title }}\n </h3>\n\n <div class=\"space-y-6 relative\">\n <EffectTransitionList>\n <div v-if=\"step === 'email'\" key=\"email-field\" class=\"w-full\">\n <AgentInputEmail\n v-model=\"form.email\"\n data-test=\"auth-email-input\"\n @keyup.enter=\"currentStep.action\"\n />\n </div>\n <div v-else key=\"code-field\" class=\"w-full\">\n <AgentInputOneTimeCode\n v-model=\"form.code\"\n :length=\"6\"\n :focus-first=\"true\"\n data-test=\"auth-code-input\"\n @auto-submit=\"currentStep.action\"\n />\n </div>\n\n <div :key=\"currentStep.button.label\" class=\"space-y-4 w-full\">\n <ElAgentButton\n theme=\"primary\"\n size=\"md\"\n class=\"w-full\"\n data-test=\"auth-submit\"\n :loading=\"sdk.loading.value\"\n :disabled=\"currentStep.button.disabled() || sdk.loading.value\"\n @click=\"currentStep.action\"\n >\n {{ currentStep.button.label }}\n </ElAgentButton>\n\n <button\n v-if=\"step === 'code'\"\n class=\"w-full text-xs text-white/50 hover:text-white/70 transition-colors py-2\"\n @click=\"step = 'email'\"\n >\n Change Email\n </button>\n </div>\n </EffectTransitionList>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { computed, ref, watch } from 'vue'\nimport EffectTransitionList from '../../ui/EffectTransitionList.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport AgentInputEmail from './AgentInputEmail.vue'\nimport AgentInputOneTimeCode from './AgentInputOneTimeCode.vue'\n\nconst { sdk } = defineProps<{ sdk: PageLinesSDK }>()\n\nconst form = ref({ email: '', code: '' })\nconst step = ref<'email' | 'code'>('email')\nconst isSubmitting = ref(false)\n\n// Engine array for step configuration\nconst stepConfig = {\n email: {\n title: 'Enter Your Email',\n button: { label: 'Continue', disabled: () => !form.value.email || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n const success = await sdk.auth.requestAuthCode({ email: form.value.email })\n if (success)\n step.value = 'code'\n } finally {\n isSubmitting.value = false\n }\n },\n },\n code: {\n title: 'Enter Verification Code',\n button: { label: 'Verify', disabled: () => form.value.code.length !== 6 || isSubmitting.value },\n action: async () => {\n if (isSubmitting.value) return\n isSubmitting.value = true\n try {\n await sdk.auth.loginWithCode({ email: form.value.email, code: form.value.code })\n } finally {\n isSubmitting.value = false\n }\n },\n },\n}\n\nconst currentStep = computed(() => stepConfig[step.value])\n\n// Watch for successful authentication - UI will update when activeUser becomes defined\nwatch(() => sdk.activeUser.value, (newUser) => {\n if (newUser && step.value === 'code') {\n // Auth succeeded - parent component will handle UI transition\n // This log helps debug the auth flow\n console.log('[ElAuthGate] Authentication successful', { email: newUser.email })\n }\n})\n</script>\n\n<template>\n <div data-test=\"auth-form\" :data-test-mode=\"step\" class=\"flex flex-col items-center justify-center h-full p-6\">\n <div class=\"w-full max-w-xs space-y-12\">\n <p v-if=\"sdk.error.value\" class=\"text-xs text-theme-400 text-center\">\n {{ sdk.error.value }}\n </p>\n\n <h3 class=\"text-base font-light text-white text-center\">\n {{ currentStep.title }}\n </h3>\n\n <div class=\"space-y-6 relative\">\n <EffectTransitionList>\n <div v-if=\"step === 'email'\" key=\"email-field\" class=\"w-full\">\n <AgentInputEmail\n v-model=\"form.email\"\n data-test=\"auth-email-input\"\n @keyup.enter=\"currentStep.action\"\n />\n </div>\n <div v-else key=\"code-field\" class=\"w-full\">\n <AgentInputOneTimeCode\n v-model=\"form.code\"\n :length=\"6\"\n :focus-first=\"true\"\n data-test=\"auth-code-input\"\n @auto-submit=\"currentStep.action\"\n />\n </div>\n\n <div :key=\"currentStep.button.label\" class=\"space-y-4 w-full\">\n <ElAgentButton\n theme=\"primary\"\n size=\"md\"\n class=\"w-full\"\n data-test=\"auth-submit\"\n :loading=\"sdk.loading.value\"\n :disabled=\"currentStep.button.disabled() || sdk.loading.value\"\n @click=\"currentStep.action\"\n >\n {{ currentStep.button.label }}\n </ElAgentButton>\n\n <button\n v-if=\"step === 'code'\"\n class=\"w-full text-xs text-white/50 hover:text-white/70 transition-colors py-2\"\n @click=\"step = 'email'\"\n >\n Change Email\n </button>\n </div>\n </EffectTransitionList>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '../schema'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport ElModeHeader from './ElModeHeader.vue'\n\nconst { agent, isOnline = false } = defineProps<{\n agent: Agent\n isOnline?: boolean\n}>()\n</script>\n\n<template>\n <div class=\"flex-1 flex flex-col min-h-0 py-6 space-y-6 h-full overflow-scroll [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden relative\">\n <!-- Name/Avatar Header -->\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <div class=\"flex-1 space-y-6 pb-12\">\n\n\n <!-- About Section -->\n <div v-if=\"agent.summary.value\" class=\"text-sm bg-white/10 backdrop-blur-sm rounded-2xl p-4 border border-white/20 space-y-3\">\n <h3 class=\"font-medium text-white/50\">\n About\n </h3>\n <div class=\" text-white/70 leading-relaxed\" v-html=\"agent.summary.value\" />\n </div>\n\n <!-- Entity Type Info -->\n <div v-if=\"agent.entityType.value === 'company'\" class=\"bg-white/5 backdrop-blur-sm rounded-2xl p-4 border border-white/10\">\n <h3 class=\"text-sm font-medium text-white/90 mb-2\">\n Company Info\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n This is a company agent representing {{ agent.name.value }}.\n </p>\n </div>\n\n <!-- Email Contact -->\n <div v-if=\"agent.email.value\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Contact\n </h3>\n <a\n :href=\"`mailto:${agent.email.value}`\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/5 hover:bg-white/10 border border-white/10 text-white/80 text-sm justify-start h-10 w-full\"\n >\n <span class=\"i-heroicons-envelope flex items-center size-[1.1em] mt-[-.07em]\" />\n Email\n </a>\n </div>\n\n <!-- Social Accounts -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Links\n </h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <a\n v-for=\"account in agent.accounts.value\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/10 hover:bg-white/20 border border-white/20 text-white/80 text-sm\"\n >\n <span class=\"flex items-center size-[1.1em] mt-[-.07em]\" :class=\"SOCIAL_PLATFORMS[account.platform].icon\" />\n {{ SOCIAL_PLATFORMS[account.platform].label }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '../schema'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport ElModeHeader from './ElModeHeader.vue'\n\nconst { agent, isOnline = false } = defineProps<{\n agent: Agent\n isOnline?: boolean\n}>()\n</script>\n\n<template>\n <div class=\"flex-1 flex flex-col min-h-0 py-6 space-y-6 h-full overflow-scroll [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden relative\">\n <!-- Name/Avatar Header -->\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <div class=\"flex-1 space-y-6 pb-12\">\n\n\n <!-- About Section -->\n <div v-if=\"agent.summary.value\" class=\"text-sm bg-white/10 backdrop-blur-sm rounded-2xl p-4 border border-white/20 space-y-3\">\n <h3 class=\"font-medium text-white/50\">\n About\n </h3>\n <div class=\" text-white/70 leading-relaxed\" v-html=\"agent.summary.value\" />\n </div>\n\n <!-- Entity Type Info -->\n <div v-if=\"agent.entityType.value === 'company'\" class=\"bg-white/5 backdrop-blur-sm rounded-2xl p-4 border border-white/10\">\n <h3 class=\"text-sm font-medium text-white/90 mb-2\">\n Company Info\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n This is a company agent representing {{ agent.name.value }}.\n </p>\n </div>\n\n <!-- Email Contact -->\n <div v-if=\"agent.email.value\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Contact\n </h3>\n <a\n :href=\"`mailto:${agent.email.value}`\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/5 hover:bg-white/10 border border-white/10 text-white/80 text-sm justify-start h-10 w-full\"\n >\n <span class=\"i-heroicons-envelope flex items-center size-[1.1em] mt-[-.07em]\" />\n Email\n </a>\n </div>\n\n <!-- Social Accounts -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"space-y-3\">\n <h3 class=\"text-sm font-medium text-white/90\">\n Links\n </h3>\n <div class=\"grid grid-cols-2 gap-3\">\n <a\n v-for=\"account in agent.accounts.value\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"relative inline-flex items-center justify-center gap-2 rounded-full px-4 py-2 font-medium transition-colors duration-200 focus:outline-none active:opacity-80 cursor-pointer bg-white/10 hover:bg-white/20 border border-white/20 text-white/80 text-sm\"\n >\n <span class=\"flex items-center size-[1.1em] mt-[-.07em]\" :class=\"SOCIAL_PLATFORMS[account.platform].icon\" />\n {{ SOCIAL_PLATFORMS[account.platform].label }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '@pagelines/core'\nimport { handleImageError } from '../utils'\n\ninterface Props {\n agent: Agent\n isOnline?: boolean\n}\n\nconst { agent, isOnline = false } = defineProps<Props>()\n\n</script>\n\n<template>\n <!-- Centered layout for default \"self\" mode with large avatar and online indicator -->\n <div class=\"flex flex-col items-center text-center gap-4\">\n <!-- Avatar with online indicator -->\n <div class=\"relative flex-shrink-0\">\n <div class=\"w-20 h-20 sm:w-24 sm:h-24 rounded-full overflow-hidden border-4 border-white\">\n <img\n :src=\"agent.avatarUrl.value\"\n :alt=\"agent.displayName.value\"\n class=\"w-full h-full object-cover\"\n @error=\"handleImageError\"\n />\n </div>\n\n <div class=\"absolute top-1.5 right-1.5\">\n <template v-if=\"isOnline\">\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white\" />\n </template>\n <div v-else class=\"size-4 bg-theme-400 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Name and title -->\n <div class=\"min-w-0\">\n <h1 class=\"text-3xl font-light text-white mb-2 truncate\">\n {{ agent.displayName.value }}\n </h1>\n <p class=\"text-base font-light text-white/60 line-clamp-1\">\n {{ agent.title.value }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Agent } from '@pagelines/core'\nimport { handleImageError } from '../utils'\n\ninterface Props {\n agent: Agent\n isOnline?: boolean\n}\n\nconst { agent, isOnline = false } = defineProps<Props>()\n\n</script>\n\n<template>\n <!-- Centered layout for default \"self\" mode with large avatar and online indicator -->\n <div class=\"flex flex-col items-center text-center gap-4\">\n <!-- Avatar with online indicator -->\n <div class=\"relative flex-shrink-0\">\n <div class=\"w-20 h-20 sm:w-24 sm:h-24 rounded-full overflow-hidden border-4 border-white\">\n <img\n :src=\"agent.avatarUrl.value\"\n :alt=\"agent.displayName.value\"\n class=\"w-full h-full object-cover\"\n @error=\"handleImageError\"\n />\n </div>\n\n <div class=\"absolute top-1.5 right-1.5\">\n <template v-if=\"isOnline\">\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-4 bg-green-500 rounded-full ring-2 ring-white\" />\n </template>\n <div v-else class=\"size-4 bg-theme-400 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Name and title -->\n <div class=\"min-w-0\">\n <h1 class=\"text-3xl font-light text-white mb-2 truncate\">\n {{ agent.displayName.value }}\n </h1>\n <p class=\"text-base font-light text-white/60 line-clamp-1\">\n {{ agent.title.value }}\n </p>\n </div>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport { onMounted, ref } from 'vue'\n\ndefineOptions({ name: 'SelfSidebarClose' })\n\ndefineEmits<{\n click: [event: MouseEvent]\n}>()\n\nconst inView = ref(false)\n\nonMounted(() => {\n setTimeout(() => {\n inView.value = true\n }, 100)\n})\n</script>\n\n<template>\n <a\n class=\"close block cursor-pointer w-[60px] h-[60px] rounded-full transition-all duration-1000 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-110 active:scale-90 hover:rotate-90\"\n @click=\"$emit('click', $event)\"\n >\n <!-- Background circle (invisible, for hover area) -->\n <span class=\"absolute inset-0 rounded-full transition-all\" />\n\n <!-- Close lines container -->\n <span class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[28px] h-[28px] overflow-hidden\">\n <!-- Line 1 - animates from bottom-left to center, rotates 45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 rotate-45' : 'translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.15s\"\n />\n\n <!-- Line 2 - animates from top-left to center, rotates -45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 -rotate-45' : '-translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.45s\"\n />\n </span>\n </a>\n</template>\n","<script lang=\"ts\" setup>\nimport { onMounted, ref } from 'vue'\n\ndefineOptions({ name: 'SelfSidebarClose' })\n\ndefineEmits<{\n click: [event: MouseEvent]\n}>()\n\nconst inView = ref(false)\n\nonMounted(() => {\n setTimeout(() => {\n inView.value = true\n }, 100)\n})\n</script>\n\n<template>\n <a\n class=\"close block cursor-pointer w-[60px] h-[60px] rounded-full transition-all duration-1000 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-110 active:scale-90 hover:rotate-90\"\n @click=\"$emit('click', $event)\"\n >\n <!-- Background circle (invisible, for hover area) -->\n <span class=\"absolute inset-0 rounded-full transition-all\" />\n\n <!-- Close lines container -->\n <span class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[28px] h-[28px] overflow-hidden\">\n <!-- Line 1 - animates from bottom-left to center, rotates 45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 rotate-45' : 'translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.15s\"\n />\n\n <!-- Line 2 - animates from top-left to center, rotates -45deg -->\n <span\n class=\"absolute h-full w-[3px] rounded-[5px] left-[13px] transition-all duration-[400ms] ease-[cubic-bezier(0.52,0.01,0.16,1)]\"\n :class=\"inView ? 'translate-y-0 translate-x-0 -rotate-45' : '-translate-y-[30px] -translate-x-[30px] rotate-0'\"\n style=\"background-color: currentColor; transition-delay: 0.45s\"\n />\n </span>\n </a>\n</template>\n","<script lang=\"ts\" setup>\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport AgentSidebarClose from './AgentSidebarClose.vue'\n\ndefineOptions({ name: 'ElSidebar', inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: boolean\n items: NavItem[]\n position?: 'left' | 'right'\n title?: string\n widthClasses?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst position = props.position || 'left'\nconst widthClasses = props.widthClasses || 'w-[80%] max-w-[300px]'\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst visibleItems = computed(() => props.items.filter((item) => !item.isHidden))\n\nfunction handleItemClick(item: NavItem) {\n if (item.isDisabled)\n return\n\n if (item.onClick) {\n item.onClick({ item, event: new MouseEvent('click') })\n } else if (item.href) {\n if (item.href.includes('http')) {\n window.open(item.href, item.target || '_self')?.focus()\n } else {\n window.location.href = item.href\n }\n }\n\n isOpen.value = false\n}\n\n// Position-specific classes\nconst transitionClasses = computed(() => {\n if (position === 'left') {\n return {\n enter: '-translate-x-full',\n leave: '-translate-x-full',\n position: 'justify-start',\n closeButton: '-right-16',\n }\n } else {\n return {\n enter: 'translate-x-full',\n leave: 'translate-x-full',\n position: 'justify-end',\n closeButton: '-left-16',\n }\n }\n})\n</script>\n\n<template>\n <!-- Backdrop -->\n <Transition\n enter-active-class=\"transition-opacity duration-300 ease-out\"\n leave-active-class=\"transition-opacity duration-200 ease-in\"\n enter-from-class=\"opacity-0\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-40 bg-black/50 backdrop-blur-sm\"\n @click=\"isOpen = false\"\n />\n </Transition>\n\n <!-- Sidebar -->\n <Transition\n enter-active-class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"transitionClasses.enter\"\n enter-to-class=\"translate-x-0\"\n leave-from-class=\"translate-x-0\"\n :leave-to-class=\"transitionClasses.leave\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-50 flex\"\n :class=\"transitionClasses.position\"\n @click=\"isOpen = false\"\n >\n <!-- Menu Panel -->\n <div\n class=\"relative h-full shadow-2xl bg-black/30 backdrop-blur-xl flex flex-col justify-center\"\n :class=\"widthClasses\"\n @click.stop\n >\n <AgentSidebarClose\n class=\"absolute top-4 z-10 text-white\"\n :class=\"transitionClasses.closeButton\"\n @click=\"isOpen = false\"\n />\n\n <!-- Title -->\n <div v-if=\"title\" class=\"px-9 pt-12 pb-4\">\n <h3 class=\"text-base font-medium text-theme-400\">\n {{ title }}\n </h3>\n </div>\n\n <!-- Header Slot -->\n <div v-if=\"$slots.header\" class=\"px-4 pb-8 border-b border-white/10\">\n <slot name=\"header\" />\n </div>\n\n <!-- Menu Items -->\n <div class=\"flex-1 p-6 space-y-2 overflow-y-auto\" :class=\"{ 'pt-6': !title && !$slots.header, 'pt-4': title || $slots.header }\">\n <TransitionGroup\n enter-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n enter-to-class=\"translate-x-0 opacity-100\"\n leave-from-class=\"translate-x-0 opacity-100\"\n :leave-to-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n >\n <button\n v-for=\"(item, index) in visibleItems\"\n :key=\"item.key || item.label || index\"\n :style=\"{ transitionDelay: `${index * 40}ms` }\"\n class=\"cursor-pointer w-full text-left p-3 rounded-xl transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group\"\n :class=\"[\n item.isActive\n ? 'bg-primary-500/20 border border-primary-500/40'\n : 'hover:bg-white/10',\n item.isDisabled && 'opacity-50 cursor-not-allowed',\n ]\"\n :disabled=\"item.isDisabled\"\n @click=\"handleItemClick(item)\"\n >\n <div class=\"flex items-center gap-3\">\n <i\n v-if=\"item.icon?.src\"\n class=\"size-5 flex-shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group-hover:scale-110\"\n :class=\"[\n item.icon.src,\n item.isActive ? 'text-primary-400' : 'text-white/70 group-hover:text-white',\n ]\"\n />\n <div class=\"flex-1\">\n <div\n class=\"font-medium text-sm\"\n :class=\"item.isActive ? 'text-primary-300' : 'text-white'\"\n >\n {{ item.label }}\n </div>\n <div v-if=\"item.subLabel\" class=\"text-xs text-white/50 mt-0.5\">\n {{ item.subLabel }}\n </div>\n </div>\n </div>\n </button>\n </TransitionGroup>\n </div>\n\n <!-- Footer -->\n <div class=\"p-6\">\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </Transition>\n</template>\n","<script lang=\"ts\" setup>\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport AgentSidebarClose from './AgentSidebarClose.vue'\n\ndefineOptions({ name: 'ElSidebar', inheritAttrs: false })\n\nconst props = defineProps<{\n modelValue: boolean\n items: NavItem[]\n position?: 'left' | 'right'\n title?: string\n widthClasses?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst position = props.position || 'left'\nconst widthClasses = props.widthClasses || 'w-[80%] max-w-[300px]'\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst visibleItems = computed(() => props.items.filter((item) => !item.isHidden))\n\nfunction handleItemClick(item: NavItem) {\n if (item.isDisabled)\n return\n\n if (item.onClick) {\n item.onClick({ item, event: new MouseEvent('click') })\n } else if (item.href) {\n if (item.href.includes('http')) {\n window.open(item.href, item.target || '_self')?.focus()\n } else {\n window.location.href = item.href\n }\n }\n\n isOpen.value = false\n}\n\n// Position-specific classes\nconst transitionClasses = computed(() => {\n if (position === 'left') {\n return {\n enter: '-translate-x-full',\n leave: '-translate-x-full',\n position: 'justify-start',\n closeButton: '-right-16',\n }\n } else {\n return {\n enter: 'translate-x-full',\n leave: 'translate-x-full',\n position: 'justify-end',\n closeButton: '-left-16',\n }\n }\n})\n</script>\n\n<template>\n <!-- Backdrop -->\n <Transition\n enter-active-class=\"transition-opacity duration-300 ease-out\"\n leave-active-class=\"transition-opacity duration-200 ease-in\"\n enter-from-class=\"opacity-0\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-40 bg-black/50 backdrop-blur-sm\"\n @click=\"isOpen = false\"\n />\n </Transition>\n\n <!-- Sidebar -->\n <Transition\n enter-active-class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"transitionClasses.enter\"\n enter-to-class=\"translate-x-0\"\n leave-from-class=\"translate-x-0\"\n :leave-to-class=\"transitionClasses.leave\"\n >\n <div\n v-if=\"isOpen\"\n class=\"absolute inset-0 z-50 flex\"\n :class=\"transitionClasses.position\"\n @click=\"isOpen = false\"\n >\n <!-- Menu Panel -->\n <div\n class=\"relative h-full shadow-2xl bg-black/30 backdrop-blur-xl flex flex-col justify-center\"\n :class=\"widthClasses\"\n @click.stop\n >\n <AgentSidebarClose\n class=\"absolute top-4 z-10 text-white\"\n :class=\"transitionClasses.closeButton\"\n @click=\"isOpen = false\"\n />\n\n <!-- Title -->\n <div v-if=\"title\" class=\"px-9 pt-12 pb-4\">\n <h3 class=\"text-base font-medium text-theme-400\">\n {{ title }}\n </h3>\n </div>\n\n <!-- Header Slot -->\n <div v-if=\"$slots.header\" class=\"px-4 pb-8 border-b border-white/10\">\n <slot name=\"header\" />\n </div>\n\n <!-- Menu Items -->\n <div class=\"flex-1 p-6 space-y-2 overflow-y-auto\" :class=\"{ 'pt-6': !title && !$slots.header, 'pt-4': title || $slots.header }\">\n <TransitionGroup\n enter-active-class=\"transition-all duration-400 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n leave-active-class=\"transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)]\"\n :enter-from-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n enter-to-class=\"translate-x-0 opacity-100\"\n leave-from-class=\"translate-x-0 opacity-100\"\n :leave-to-class=\"position === 'left' ? '-translate-x-4 opacity-0' : 'translate-x-4 opacity-0'\"\n >\n <button\n v-for=\"(item, index) in visibleItems\"\n :key=\"item.key || item.label || index\"\n :style=\"{ transitionDelay: `${index * 40}ms` }\"\n class=\"cursor-pointer w-full text-left p-3 rounded-xl transition-all duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group\"\n :class=\"[\n item.isActive\n ? 'bg-primary-500/20 border border-primary-500/40'\n : 'hover:bg-white/10',\n item.isDisabled && 'opacity-50 cursor-not-allowed',\n ]\"\n :disabled=\"item.isDisabled\"\n @click=\"handleItemClick(item)\"\n >\n <div class=\"flex items-center gap-3\">\n <i\n v-if=\"item.icon?.src\"\n class=\"size-5 flex-shrink-0 transition-transform duration-200 ease-[cubic-bezier(0.25,1,0.33,1)] group-hover:scale-110\"\n :class=\"[\n item.icon.src,\n item.isActive ? 'text-primary-400' : 'text-white/70 group-hover:text-white',\n ]\"\n />\n <div class=\"flex-1\">\n <div\n class=\"font-medium text-sm\"\n :class=\"item.isActive ? 'text-primary-300' : 'text-white'\"\n >\n {{ item.label }}\n </div>\n <div v-if=\"item.subLabel\" class=\"text-xs text-white/50 mt-0.5\">\n {{ item.subLabel }}\n </div>\n </div>\n </div>\n </button>\n </TransitionGroup>\n </div>\n\n <!-- Footer -->\n <div class=\"p-6\">\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </Transition>\n</template>\n","<script lang=\"ts\" setup>\nimport type { AgentMode } from '../schema'\nimport type { AgentChatController } from '../AgentController'\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport { AGENT_MODES } from '../schema'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentModeSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n chatController?: AgentChatController\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst currentMode = computed(() => props.chatController?.agentMode?.value ?? 'self')\n\nconst modeItems = computed<NavItem[]>(() => AGENT_MODES.map((mode) => ({\n key: mode.mode,\n icon: { src: mode.icon },\n label: mode.label,\n isActive: currentMode.value === mode.mode,\n onClick: () => {\n props.chatController?.setMode(mode.mode as AgentMode)\n },\n})))\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"modeItems\"\n position=\"right\"\n title=\"Mode\"\n width-classes=\"w-[80%] max-w-[255px]\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { AgentMode } from '../schema'\nimport type { AgentChatController } from '../AgentController'\nimport type { NavItem } from '@pagelines/core'\nimport { computed } from 'vue'\nimport { AGENT_MODES } from '../schema'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentModeSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n chatController?: AgentChatController\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst currentMode = computed(() => props.chatController?.agentMode?.value ?? 'self')\n\nconst modeItems = computed<NavItem[]>(() => AGENT_MODES.map((mode) => ({\n key: mode.mode,\n icon: { src: mode.icon },\n label: mode.label,\n isActive: currentMode.value === mode.mode,\n onClick: () => {\n props.chatController?.setMode(mode.mode as AgentMode)\n },\n})))\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"modeItems\"\n position=\"right\"\n title=\"Mode\"\n width-classes=\"w-[80%] max-w-[255px]\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { NavItem } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed } from 'vue'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n agent: Agent\n sdk: PageLinesSDK\n title?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst menuItems = computed<NavItem[]>(() => {\n const items: NavItem[] = [\n {\n key: 'share',\n icon: { src: 'i-tabler-share' },\n label: 'Share this assistant',\n onClick: () => {\n const url = `${window.location.origin}/@${props.agent.handle.value || props.agent.agentId.value}`\n // TODO: Show notification that URL was copied (SDK has no notify host).\n navigator.clipboard.writeText(url).catch((err) => {\n console.error('ElAgentSidebar: clipboard.writeText rejected', err)\n })\n },\n },\n {\n key: 'profile',\n icon: { src: 'i-tabler-user' },\n label: 'View full profile',\n onClick: () => {\n window.open(`/@${props.agent.handle.value || props.agent.agentId.value}`, '_blank')\n },\n },\n {\n key: 'create',\n icon: { src: 'i-tabler-sparkles' },\n label: 'Create your own',\n onClick: () => {\n window.open('/auth', '_blank')\n },\n },\n ]\n\n // Add logout option if user is authenticated\n if (props.sdk.activeUser.value) {\n items.push({\n key: 'logout',\n icon: { src: 'i-tabler-logout' },\n label: 'Logout',\n onClick: async () => {\n await props.sdk.auth.logout()\n },\n })\n }\n\n return items\n})\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"menuItems\"\n position=\"left\"\n :title=\"title || 'Menu'\"\n />\n</template>\n","<script lang=\"ts\" setup>\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { NavItem } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed } from 'vue'\nimport ElSidebar from './ElSidebar.vue'\n\ndefineOptions({ name: 'AgentSidebar' })\n\nconst props = defineProps<{\n modelValue: boolean\n agent: Agent\n sdk: PageLinesSDK\n title?: string\n}>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n}>()\n\nconst isOpen = computed({\n get: () => props.modelValue,\n set: (value) => emit('update:modelValue', value),\n})\n\nconst menuItems = computed<NavItem[]>(() => {\n const items: NavItem[] = [\n {\n key: 'share',\n icon: { src: 'i-tabler-share' },\n label: 'Share this assistant',\n onClick: () => {\n const url = `${window.location.origin}/@${props.agent.handle.value || props.agent.agentId.value}`\n // TODO: Show notification that URL was copied (SDK has no notify host).\n navigator.clipboard.writeText(url).catch((err) => {\n console.error('ElAgentSidebar: clipboard.writeText rejected', err)\n })\n },\n },\n {\n key: 'profile',\n icon: { src: 'i-tabler-user' },\n label: 'View full profile',\n onClick: () => {\n window.open(`/@${props.agent.handle.value || props.agent.agentId.value}`, '_blank')\n },\n },\n {\n key: 'create',\n icon: { src: 'i-tabler-sparkles' },\n label: 'Create your own',\n onClick: () => {\n window.open('/auth', '_blank')\n },\n },\n ]\n\n // Add logout option if user is authenticated\n if (props.sdk.activeUser.value) {\n items.push({\n key: 'logout',\n icon: { src: 'i-tabler-logout' },\n label: 'Logout',\n onClick: async () => {\n await props.sdk.auth.logout()\n },\n })\n }\n\n return items\n})\n</script>\n\n<template>\n <ElSidebar\n v-model=\"isOpen\"\n :items=\"menuItems\"\n position=\"left\"\n :title=\"title || 'Menu'\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { AgentChatControllerSettings } from '../AgentController'\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { ColorName, SuggestedPrompt } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport FSpinner from '../../ui/FSpinner.vue'\nimport { getColorSchemeOklch } from '@pagelines/core'\nimport { AGENT_MODES } from '../schema'\nimport { AgentChatController } from '../AgentController'\nimport { getAgentAvatarUrl, parseButtonTemplate } from '../utils'\nimport ElAuthGate from './ElAuthGate.vue'\nimport ElModeHeader from './ElModeHeader.vue'\nimport ElAgentAbout from './ElAgentAbout.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport ElAgentChat from './ElAgentChat.vue'\nimport ElAgentHeader from './ElAgentHeader.vue'\nimport ElAgentModeSidebar from './ElAgentModeSidebar.vue'\nimport ElAgentSidebar from './ElAgentSidebar.vue'\n\nconst {\n sdk,\n agent,\n context,\n firstMessage,\n buttonText,\n buttonIcon,\n hasClose = false,\n isActive = true,\n loading = false,\n theme = 'green',\n requireAuth = false,\n chatOnly = false,\n bare = false,\n emptyStateMessage,\n suggestedPrompts = [],\n createVoiceClientFn,\n} = defineProps<{\n sdk: PageLinesSDK\n agent: Agent\n context?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n isActive?: boolean\n loading?: boolean\n theme?: ColorName\n requireAuth?: boolean\n chatOnly?: boolean\n /** Render chat without profile chrome so a host page can provide it. */\n bare?: boolean\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n /** Voice transport, supplied by hosts that ship it. See the note in createChatController. */\n createVoiceClientFn?: AgentChatControllerSettings['createVoiceClientFn']\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\nconst chatController = shallowRef<AgentChatController>()\nconst isSidebarOpen = ref(false)\nconst isModeSidebarOpen = ref(false)\nconst initError = ref<string>()\nconst rootElement = ref<HTMLElement>()\n\nconst agentMode = computed(() => chatController.value?.agentMode?.value ?? 'self')\nconst isOnline = computed(() => chatController.value?.textState.value.isConnected ?? false)\n\n// Check if user is authenticated\nconst isAuthenticated = computed(() => sdk.activeUser.value !== undefined)\n\n// Current mode for button display\nconst currentMode = computed(() => AGENT_MODES.find((btn) => btn.mode === agentMode.value))\n\nfunction createChatController() {\n if (chatController.value) {\n chatController.value.destroy()\n }\n\n try {\n chatController.value = new AgentChatController({\n sdk,\n agent,\n context,\n firstMessage,\n // No voice wiring here on purpose: this component is reachable from the\n // embeddable widget (PLWidget lazy-loads its modal/inline modes, and the\n // IIFE build inlines those), so any static edge to the LiveKit transport\n // lands a WebRTC stack on every host page. Hosts that do voice pass\n // `createVoiceClientFn` down themselves.\n ...(createVoiceClientFn ? { createVoiceClientFn } : {}),\n onTurnStarted: () => emit('turnStarted'),\n onTurnCompleted: conversationId => emit('turnCompleted', conversationId),\n })\n } catch (error) {\n console.error('AgentChatController creation failed:', error)\n throw error\n }\n}\n\ntry {\n createChatController()\n} catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n}\n\n// Set theme CSS variables\nfunction applyTheme(themeName: ColorName) {\n if (!rootElement.value)\n return\n\n const colorScheme = getColorSchemeOklch(themeName)\n\n // Set --primary-* CSS variables on component root for Shadow DOM compatibility\n Object.entries(colorScheme).forEach(([scale, value]) => {\n rootElement.value!.style.setProperty(`--primary-${scale}`, value)\n })\n}\n\nonMounted(() => {\n try {\n applyTheme(theme)\n\n // In chatOnly mode, jump straight to chat\n if (chatOnly && chatController.value) {\n chatController.value.setMode('chat')\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n }\n})\n\nonUnmounted(() => {\n if (chatController.value) {\n chatController.value.destroy()\n }\n})\n\n// Watch theme changes and reapply\nwatch(() => theme, (newTheme) => {\n applyTheme(newTheme)\n})\n\n// Reset to self mode when user logs out\nwatch(() => sdk.activeUser.value, (newUser, oldUser) => {\n // User logged out (had user, now undefined)\n if (oldUser && !newUser && chatController.value) {\n chatController.value.setMode('self')\n }\n})\n\nconst isLowQuality = computed(() => {\n return !!(agent.cover.value?.src && agent.cover.value?.quality === 'low') || !!(agent.avatar.value?.src && agent.avatar.value?.quality === 'low')\n})\n\nconst backdropClass = computed(() => {\n const out = [isLowQuality.value ? 'backdrop-blur-sm' : '']\n\n if(isLowQuality.value && agentMode.value === 'self') {\n out.push('from-black/80 via-black/60 to-black/80')\n }\n else if (agentMode.value === 'self') {\n out.push('from-black/70 via-black/50 to-black/80')\n }\n else {\n out.push('from-black/90 via-black/90 to-black/100')\n }\n\n return out.join(' ')\n})\n\n// Icon preset mapping\nconst ICON_MAP: Record<ButtonIconPreset, string> = {\n phone: 'i-heroicons-phone',\n calendar: 'i-heroicons-calendar',\n question: 'i-heroicons-question-mark-circle',\n message: 'i-heroicons-chat-bubble-left-right',\n sparkles: 'i-heroicons-sparkles',\n}\n\n// Resolve button text with template variables\nconst resolvedButtonText = computed(() => {\n return parseButtonTemplate({\n template: buttonText || 'Talk to {name}',\n agent: agent.toConfig(),\n })\n})\n\n// Resolve button icon from preset or default to phone\nconst resolvedButtonIcon = computed(() => {\n return ICON_MAP[buttonIcon || 'phone'] || ICON_MAP.phone\n})\n</script>\n\n<template>\n <div\n ref=\"rootElement\"\n :key=\"getAgentAvatarUrl(agent.toConfig())\"\n class=\"pagelines-sdk @container/agent pagelines-agent w-full h-full overflow-hidden relative\"\n data-test=\"agent-chat\"\n >\n <div v-if=\"loading\" class=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-theme-800 to-theme-950 rounded-3xl z-10\">\n <FSpinner class=\"text-white size-8\" />\n </div>\n\n <!-- bare: no background at any layer — the host page owns the canvas\n (the app's chat surface is white); any paint here shows as a\n stripe against the host canvas. -->\n <div\n v-else-if=\"agent && !initError\"\n class=\"absolute inset-0\"\n :class=\"bare ? '' : 'bg-cover bg-center bg-no-repeat'\"\n :style=\"bare ? undefined : { backgroundImage: `url(${getAgentAvatarUrl(agent.toConfig())})` }\"\n :data-quality=\"agent.avatar.value?.quality || 'none'\"\n >\n <div\n v-if=\"!bare\"\n class=\"absolute inset-0 bg-gradient-to-br z-0\"\n :class=\"backdropClass\"\n />\n <div\n class=\"relative z-10 flex flex-col h-full transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] will-change-transform\"\n :class=\"isActive ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'\"\n >\n <div v-if=\"!bare || hasClose\" class=\"relative z-30 p-2\" :class=\"!bare && agentMode !== 'self' ? 'backdrop-blur-lg' : ''\">\n <!-- A bare chat embed supplies its own surrounding header. -->\n <div v-if=\"chatOnly\" class=\"flex items-center\" :class=\"bare ? 'justify-end' : ''\">\n <div v-if=\"!bare\" class=\"flex flex-1 items-center gap-3 pl-2\">\n <img\n :src=\"getAgentAvatarUrl(agent.toConfig())\"\n :alt=\"agent.displayName.value\"\n class=\"size-8 rounded-full object-cover\"\n />\n <span class=\"text-sm font-medium text-white/90\">{{ agent.displayName.value }}</span>\n </div>\n <div v-if=\"hasClose\" class=\"flex justify-end\">\n <button\n class=\"flex cursor-pointer items-center rounded-2xl p-3 transition-colors\"\n :class=\"bare ? 'text-theme-500 hover:bg-theme-50' : 'text-white/70 hover:bg-white/10'\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n\n <!-- Full header with mode selector and sidebars -->\n <div v-else class=\"flex items-center\" :class=\"hasClose ? '' : 'justify-between'\">\n <!-- Left side: Sidebar toggle with user avatar -->\n <div :class=\"hasClose ? 'flex-1 basis-0' : ''\">\n <button\n class=\"cursor-pointer p-2 flex items-center gap-2 rounded-2xl text-white/70 hover:bg-white/10 transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-105 active:scale-95\"\n @click=\"isSidebarOpen = true\"\n >\n <i class=\"i-tabler-menu size-7\" />\n </button>\n </div>\n\n <!-- Center: Mode selector button (centered when hasClose=true) -->\n <button\n class=\"flex items-center gap-2 px-3.5 py-3 rounded-2xl text-white/90 hover:bg-white/10 transition-all cursor-pointer flex-grow-0\"\n :class=\"{ 'bg-white/10': isModeSidebarOpen }\"\n @click=\"isModeSidebarOpen = true\"\n >\n <i :class=\"currentMode?.icon\" class=\"size-4 opacity-60\" />\n <span class=\"text-sm\">{{ currentMode?.label }}</span>\n <i class=\"i-tabler-chevron-down size-4\" />\n </button>\n\n <!-- Right side: Close button (only in widget mode) -->\n <div v-if=\"hasClose\" class=\"flex-1 basis-0 flex justify-end\">\n <button\n class=\"cursor-pointer flex items-center p-3 rounded-2xl text-white/70 hover:bg-white/10 transition-colors\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n </div>\n\n <!-- chatOnly: skip all modes, show chat directly -->\n <!-- bare: the host page owns the canvas (the app's chat surface is\n white); a mismatched paint here reads as a stripe against it. -->\n <div\n v-if=\"chatOnly\"\n class=\"relative z-20 flex min-h-0 w-full flex-1 flex-col\"\n :class=\"bare ? '' : 'px-4'\"\n >\n <div class=\"min-h-0 w-full flex-1\" :class=\"bare ? '' : 'mx-auto max-w-md'\">\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n :scope=\"isAuthenticated ? 'private' : 'public'\"\n :empty-state-message=\"emptyStateMessage\"\n :suggested-prompts=\"suggestedPrompts\"\n :variant=\"bare ? 'light' : 'dark'\"\n :show-header=\"!bare\"\n :centered=\"bare\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </ElAgentChat>\n </div>\n </div>\n\n <!-- Full agent interface modes -->\n <template v-else>\n <div\n v-if=\"agentMode === 'self'\"\n class=\"h-full pb-12 flex-1 flex flex-col relative z-20 min-h-0 px-4 @[480px]/agent:px-6 max-w-md mx-auto w-full\"\n >\n <!-- Top spacer -->\n <div class=\"flex-1 basis-0 mb-12\" />\n\n <!-- Avatar header -->\n <ElAgentHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <!-- Bottom section with button and social links -->\n <div class=\"flex-1 basis-0 flex flex-col justify-start pt-8 gap-7\">\n <ElAgentButton\n theme=\"primary\"\n size=\"lg\"\n class=\"w-full\"\n :icon=\"resolvedButtonIcon\"\n data-test=\"voice-button\"\n @click=\"chatController?.setMode('talk')\"\n >\n {{ resolvedButtonText }}\n </ElAgentButton>\n\n <!-- Social icon links -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"flex items-center justify-center gap-3\">\n <a\n v-for=\"account in (agent.accounts.value || []).filter(a => SOCIAL_PLATFORMS[a.platform])\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n class=\"size-12 rounded-full text-white/60 hover:text-white hover:bg-white/5 border border-white/0 hover:border-white/10 flex items-center justify-center transition-all duration-200 hover:scale-105\"\n >\n <i :class=\"SOCIAL_PLATFORMS[account.platform].icon\" class=\"size-5 \" />\n </a>\n </div>\n </div>\n </div>\n <div\n v-else-if=\"agentMode === 'talk'\"\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full gap-4 px-4\"\n >\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <template v-else>\n <!-- Sticky header with backdrop blur - full width -->\n <div>\n <div class=\"max-w-md mx-auto\">\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n </div>\n </div>\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n />\n </template>\n </div>\n <div\n v-else\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full px-4 @[480px]/agent:px-6\"\n >\n <div class=\"flex-1 min-h-0 max-w-md mx-auto w-full\">\n <template v-if=\"agentMode === 'chat'\">\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <ElAgentChat\n v-else\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n show-header\n />\n </template>\n <ElAgentAbout\n v-else-if=\"agentMode === 'info'\"\n :agent=\"agent\"\n :is-online=\"isOnline\"\n />\n </div>\n </div>\n </template>\n\n </div>\n </div>\n <div v-else-if=\"initError\" class=\"bg-gradient-to-br from-theme-800 to-theme-950 text-white flex items-center justify-center h-full p-8\">\n <div class=\"text-center max-w-md space-y-4\">\n <div class=\"flex justify-center\">\n <div class=\"rounded-full bg-red-500/20 flex items-center justify-center size-10\">\n <i class=\"i-tabler-alert-circle size-6 text-red-400\" />\n </div>\n </div>\n <h3 class=\"text-lg font-medium\">\n Agent Error\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n {{ initError }}\n </p>\n </div>\n </div>\n <div v-else class=\"bg-white/10 backdrop-blur-sm text-white/70 flex items-center justify-center h-full\">\n Couldn't load your assistant. Please try again later.\n </div>\n\n <!-- Agent Sidebar (left) — hidden in chatOnly mode -->\n <ElAgentSidebar\n v-if=\"!chatOnly\"\n v-model=\"isSidebarOpen\"\n :agent=\"agent\"\n :sdk=\"sdk\"\n :title=\"agent.displayName.value\"\n data-test=\"agent-sidebar\"\n />\n\n <!-- Mode Sidebar (right) — hidden in chatOnly mode -->\n <ElAgentModeSidebar\n v-if=\"!chatOnly\"\n v-model=\"isModeSidebarOpen\"\n :chat-controller=\"chatController\"\n data-test=\"agent-mode-sidebar\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { AgentChatControllerSettings } from '../AgentController'\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { ColorName, SuggestedPrompt } from '@pagelines/core'\nimport { Agent } from '../schema'\nimport { computed, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'\nimport { SOCIAL_PLATFORMS } from '../../constants/socialPlatforms'\nimport FSpinner from '../../ui/FSpinner.vue'\nimport { getColorSchemeOklch } from '@pagelines/core'\nimport { AGENT_MODES } from '../schema'\nimport { AgentChatController } from '../AgentController'\nimport { getAgentAvatarUrl, parseButtonTemplate } from '../utils'\nimport ElAuthGate from './ElAuthGate.vue'\nimport ElModeHeader from './ElModeHeader.vue'\nimport ElAgentAbout from './ElAgentAbout.vue'\nimport ElAgentButton from './ElAgentButton.vue'\nimport ElAgentChat from './ElAgentChat.vue'\nimport ElAgentHeader from './ElAgentHeader.vue'\nimport ElAgentModeSidebar from './ElAgentModeSidebar.vue'\nimport ElAgentSidebar from './ElAgentSidebar.vue'\n\nconst {\n sdk,\n agent,\n context,\n firstMessage,\n buttonText,\n buttonIcon,\n hasClose = false,\n isActive = true,\n loading = false,\n theme = 'green',\n requireAuth = false,\n chatOnly = false,\n bare = false,\n emptyStateMessage,\n suggestedPrompts = [],\n createVoiceClientFn,\n} = defineProps<{\n sdk: PageLinesSDK\n agent: Agent\n context?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n isActive?: boolean\n loading?: boolean\n theme?: ColorName\n requireAuth?: boolean\n chatOnly?: boolean\n /** Render chat without profile chrome so a host page can provide it. */\n bare?: boolean\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n /** Voice transport, supplied by hosts that ship it. See the note in createChatController. */\n createVoiceClientFn?: AgentChatControllerSettings['createVoiceClientFn']\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\nconst chatController = shallowRef<AgentChatController>()\nconst isSidebarOpen = ref(false)\nconst isModeSidebarOpen = ref(false)\nconst initError = ref<string>()\nconst rootElement = ref<HTMLElement>()\n\nconst agentMode = computed(() => chatController.value?.agentMode?.value ?? 'self')\nconst isOnline = computed(() => chatController.value?.textState.value.isConnected ?? false)\n\n// Check if user is authenticated\nconst isAuthenticated = computed(() => sdk.activeUser.value !== undefined)\n\n// Current mode for button display\nconst currentMode = computed(() => AGENT_MODES.find((btn) => btn.mode === agentMode.value))\n\nfunction createChatController() {\n if (chatController.value) {\n chatController.value.destroy()\n }\n\n try {\n chatController.value = new AgentChatController({\n sdk,\n agent,\n context,\n firstMessage,\n // No voice wiring here on purpose: this component is reachable from the\n // embeddable widget (PLWidget lazy-loads its modal/inline modes, and the\n // IIFE build inlines those), so any static edge to the LiveKit transport\n // lands a WebRTC stack on every host page. Hosts that do voice pass\n // `createVoiceClientFn` down themselves.\n ...(createVoiceClientFn ? { createVoiceClientFn } : {}),\n onTurnStarted: () => emit('turnStarted'),\n onTurnCompleted: conversationId => emit('turnCompleted', conversationId),\n })\n } catch (error) {\n console.error('AgentChatController creation failed:', error)\n throw error\n }\n}\n\ntry {\n createChatController()\n} catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n}\n\n// Set theme CSS variables\nfunction applyTheme(themeName: ColorName) {\n if (!rootElement.value)\n return\n\n const colorScheme = getColorSchemeOklch(themeName)\n\n // Set --primary-* CSS variables on component root for Shadow DOM compatibility\n Object.entries(colorScheme).forEach(([scale, value]) => {\n rootElement.value!.style.setProperty(`--primary-${scale}`, value)\n })\n}\n\nonMounted(() => {\n try {\n applyTheme(theme)\n\n // In chatOnly mode, jump straight to chat\n if (chatOnly && chatController.value) {\n chatController.value.setMode('chat')\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Couldn\\'t initialize your assistant'\n initError.value = message\n emit('error', message)\n }\n})\n\nonUnmounted(() => {\n if (chatController.value) {\n chatController.value.destroy()\n }\n})\n\n// Watch theme changes and reapply\nwatch(() => theme, (newTheme) => {\n applyTheme(newTheme)\n})\n\n// Reset to self mode when user logs out\nwatch(() => sdk.activeUser.value, (newUser, oldUser) => {\n // User logged out (had user, now undefined)\n if (oldUser && !newUser && chatController.value) {\n chatController.value.setMode('self')\n }\n})\n\nconst isLowQuality = computed(() => {\n return !!(agent.cover.value?.src && agent.cover.value?.quality === 'low') || !!(agent.avatar.value?.src && agent.avatar.value?.quality === 'low')\n})\n\nconst backdropClass = computed(() => {\n const out = [isLowQuality.value ? 'backdrop-blur-sm' : '']\n\n if(isLowQuality.value && agentMode.value === 'self') {\n out.push('from-black/80 via-black/60 to-black/80')\n }\n else if (agentMode.value === 'self') {\n out.push('from-black/70 via-black/50 to-black/80')\n }\n else {\n out.push('from-black/90 via-black/90 to-black/100')\n }\n\n return out.join(' ')\n})\n\n// Icon preset mapping\nconst ICON_MAP: Record<ButtonIconPreset, string> = {\n phone: 'i-heroicons-phone',\n calendar: 'i-heroicons-calendar',\n question: 'i-heroicons-question-mark-circle',\n message: 'i-heroicons-chat-bubble-left-right',\n sparkles: 'i-heroicons-sparkles',\n}\n\n// Resolve button text with template variables\nconst resolvedButtonText = computed(() => {\n return parseButtonTemplate({\n template: buttonText || 'Talk to {name}',\n agent: agent.toConfig(),\n })\n})\n\n// Resolve button icon from preset or default to phone\nconst resolvedButtonIcon = computed(() => {\n return ICON_MAP[buttonIcon || 'phone'] || ICON_MAP.phone\n})\n</script>\n\n<template>\n <div\n ref=\"rootElement\"\n :key=\"getAgentAvatarUrl(agent.toConfig())\"\n class=\"pagelines-sdk @container/agent pagelines-agent w-full h-full overflow-hidden relative\"\n data-test=\"agent-chat\"\n >\n <div v-if=\"loading\" class=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-theme-800 to-theme-950 rounded-3xl z-10\">\n <FSpinner class=\"text-white size-8\" />\n </div>\n\n <!-- bare: no background at any layer — the host page owns the canvas\n (the app's chat surface is white); any paint here shows as a\n stripe against the host canvas. -->\n <div\n v-else-if=\"agent && !initError\"\n class=\"absolute inset-0\"\n :class=\"bare ? '' : 'bg-cover bg-center bg-no-repeat'\"\n :style=\"bare ? undefined : { backgroundImage: `url(${getAgentAvatarUrl(agent.toConfig())})` }\"\n :data-quality=\"agent.avatar.value?.quality || 'none'\"\n >\n <div\n v-if=\"!bare\"\n class=\"absolute inset-0 bg-gradient-to-br z-0\"\n :class=\"backdropClass\"\n />\n <div\n class=\"relative z-10 flex flex-col h-full transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] will-change-transform\"\n :class=\"isActive ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'\"\n >\n <div v-if=\"!bare || hasClose\" class=\"relative z-30 p-2\" :class=\"!bare && agentMode !== 'self' ? 'backdrop-blur-lg' : ''\">\n <!-- A bare chat embed supplies its own surrounding header. -->\n <div v-if=\"chatOnly\" class=\"flex items-center\" :class=\"bare ? 'justify-end' : ''\">\n <div v-if=\"!bare\" class=\"flex flex-1 items-center gap-3 pl-2\">\n <img\n :src=\"getAgentAvatarUrl(agent.toConfig())\"\n :alt=\"agent.displayName.value\"\n class=\"size-8 rounded-full object-cover\"\n />\n <span class=\"text-sm font-medium text-white/90\">{{ agent.displayName.value }}</span>\n </div>\n <div v-if=\"hasClose\" class=\"flex justify-end\">\n <button\n class=\"flex cursor-pointer items-center rounded-2xl p-3 transition-colors\"\n :class=\"bare ? 'text-theme-500 hover:bg-theme-50' : 'text-white/70 hover:bg-white/10'\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n\n <!-- Full header with mode selector and sidebars -->\n <div v-else class=\"flex items-center\" :class=\"hasClose ? '' : 'justify-between'\">\n <!-- Left side: Sidebar toggle with user avatar -->\n <div :class=\"hasClose ? 'flex-1 basis-0' : ''\">\n <button\n class=\"cursor-pointer p-2 flex items-center gap-2 rounded-2xl text-white/70 hover:bg-white/10 transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:scale-105 active:scale-95\"\n @click=\"isSidebarOpen = true\"\n >\n <i class=\"i-tabler-menu size-7\" />\n </button>\n </div>\n\n <!-- Center: Mode selector button (centered when hasClose=true) -->\n <button\n class=\"flex items-center gap-2 px-3.5 py-3 rounded-2xl text-white/90 hover:bg-white/10 transition-all cursor-pointer flex-grow-0\"\n :class=\"{ 'bg-white/10': isModeSidebarOpen }\"\n @click=\"isModeSidebarOpen = true\"\n >\n <i :class=\"currentMode?.icon\" class=\"size-4 opacity-60\" />\n <span class=\"text-sm\">{{ currentMode?.label }}</span>\n <i class=\"i-tabler-chevron-down size-4\" />\n </button>\n\n <!-- Right side: Close button (only in widget mode) -->\n <div v-if=\"hasClose\" class=\"flex-1 basis-0 flex justify-end\">\n <button\n class=\"cursor-pointer flex items-center p-3 rounded-2xl text-white/70 hover:bg-white/10 transition-colors\"\n @click.stop=\"emit('close', 'button')\"\n >\n <i class=\"size-6 i-tabler-x\" />\n </button>\n </div>\n </div>\n </div>\n\n <!-- chatOnly: skip all modes, show chat directly -->\n <!-- bare: the host page owns the canvas (the app's chat surface is\n white); a mismatched paint here reads as a stripe against it. -->\n <div\n v-if=\"chatOnly\"\n class=\"relative z-20 flex min-h-0 w-full flex-1 flex-col\"\n :class=\"bare ? '' : 'px-4'\"\n >\n <div class=\"min-h-0 w-full flex-1\" :class=\"bare ? '' : 'mx-auto max-w-md'\">\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n :scope=\"isAuthenticated ? 'private' : 'public'\"\n :empty-state-message=\"emptyStateMessage\"\n :suggested-prompts=\"suggestedPrompts\"\n :variant=\"bare ? 'light' : 'dark'\"\n :show-header=\"!bare\"\n :centered=\"bare\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </ElAgentChat>\n </div>\n </div>\n\n <!-- Full agent interface modes -->\n <template v-else>\n <div\n v-if=\"agentMode === 'self'\"\n class=\"h-full pb-12 flex-1 flex flex-col relative z-20 min-h-0 px-4 @[480px]/agent:px-6 max-w-md mx-auto w-full\"\n >\n <!-- Top spacer -->\n <div class=\"flex-1 basis-0 mb-12\" />\n\n <!-- Avatar header -->\n <ElAgentHeader :agent=\"agent\" :is-online=\"isOnline\" />\n\n <!-- Bottom section with button and social links -->\n <div class=\"flex-1 basis-0 flex flex-col justify-start pt-8 gap-7\">\n <ElAgentButton\n theme=\"primary\"\n size=\"lg\"\n class=\"w-full\"\n :icon=\"resolvedButtonIcon\"\n data-test=\"voice-button\"\n @click=\"chatController?.setMode('talk')\"\n >\n {{ resolvedButtonText }}\n </ElAgentButton>\n\n <!-- Social icon links -->\n <div v-if=\"agent.accounts.value && agent.accounts.value.length > 0\" class=\"flex items-center justify-center gap-3\">\n <a\n v-for=\"account in (agent.accounts.value || []).filter(a => SOCIAL_PLATFORMS[a.platform])\"\n :key=\"`${account.platform}-${account.handle}`\"\n :href=\"SOCIAL_PLATFORMS[account.platform].getUrl(account.handle)\"\n target=\"_blank\"\n class=\"size-12 rounded-full text-white/60 hover:text-white hover:bg-white/5 border border-white/0 hover:border-white/10 flex items-center justify-center transition-all duration-200 hover:scale-105\"\n >\n <i :class=\"SOCIAL_PLATFORMS[account.platform].icon\" class=\"size-5 \" />\n </a>\n </div>\n </div>\n </div>\n <div\n v-else-if=\"agentMode === 'talk'\"\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full gap-4 px-4\"\n >\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <template v-else>\n <!-- Sticky header with backdrop blur - full width -->\n <div>\n <div class=\"max-w-md mx-auto\">\n <ElModeHeader :agent=\"agent\" :is-online=\"isOnline\" />\n </div>\n </div>\n <ElAgentChat\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n />\n </template>\n </div>\n <div\n v-else\n class=\"flex-1 flex flex-col relative z-20 min-h-0 w-full px-4 @[480px]/agent:px-6\"\n >\n <div class=\"flex-1 min-h-0 max-w-md mx-auto w-full\">\n <template v-if=\"agentMode === 'chat'\">\n <ElAuthGate v-if=\"requireAuth && !isAuthenticated\" :sdk=\"sdk\" />\n <ElAgentChat\n v-else\n :chat-controller=\"chatController\"\n :agent=\"agent\"\n show-header\n />\n </template>\n <ElAgentAbout\n v-else-if=\"agentMode === 'info'\"\n :agent=\"agent\"\n :is-online=\"isOnline\"\n />\n </div>\n </div>\n </template>\n\n </div>\n </div>\n <div v-else-if=\"initError\" class=\"bg-gradient-to-br from-theme-800 to-theme-950 text-white flex items-center justify-center h-full p-8\">\n <div class=\"text-center max-w-md space-y-4\">\n <div class=\"flex justify-center\">\n <div class=\"rounded-full bg-red-500/20 flex items-center justify-center size-10\">\n <i class=\"i-tabler-alert-circle size-6 text-red-400\" />\n </div>\n </div>\n <h3 class=\"text-lg font-medium\">\n Agent Error\n </h3>\n <p class=\"text-sm text-white/70 leading-relaxed\">\n {{ initError }}\n </p>\n </div>\n </div>\n <div v-else class=\"bg-white/10 backdrop-blur-sm text-white/70 flex items-center justify-center h-full\">\n Couldn't load your assistant. Please try again later.\n </div>\n\n <!-- Agent Sidebar (left) — hidden in chatOnly mode -->\n <ElAgentSidebar\n v-if=\"!chatOnly\"\n v-model=\"isSidebarOpen\"\n :agent=\"agent\"\n :sdk=\"sdk\"\n :title=\"agent.displayName.value\"\n data-test=\"agent-sidebar\"\n />\n\n <!-- Mode Sidebar (right) — hidden in chatOnly mode -->\n <ElAgentModeSidebar\n v-if=\"!chatOnly\"\n v-model=\"isModeSidebarOpen\"\n :chat-controller=\"chatController\"\n data-test=\"agent-mode-sidebar\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { SuggestedPrompt } from '@pagelines/core'\nimport type { Agent, AgentConfig } from '../schema'\nimport AgentChat from './AgentChat.vue'\nimport AgentWrap from './AgentWrap.vue'\n\nconst props = defineProps<{\n sdk?: PageLinesSDK\n agent?: AgentConfig\n handle?: string\n context?: string\n clientContext?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n chatOnly?: boolean\n bare?: boolean\n apiBase?: string\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\n</script>\n\n<template>\n <!-- slotProps.xxx = data resolved by AgentWrap (sdk, agent, context, firstMessage)\n props.xxx = rendering config passed through unchanged (buttonText, buttonIcon, hasClose, chatOnly) -->\n <AgentWrap\n v-slot=\"slotProps\"\n v-bind=\"props\"\n class=\"agent-provider size-full relative\"\n >\n <AgentChat\n :sdk=\"slotProps.sdk\"\n :agent=\"slotProps.agent\"\n :context=\"slotProps.context\"\n :first-message=\"slotProps.firstMessage\"\n :button-text=\"props.buttonText\"\n :button-icon=\"props.buttonIcon\"\n :has-close=\"props.hasClose\"\n :chat-only=\"props.chatOnly\"\n :bare=\"props.bare\"\n :empty-state-message=\"props.emptyStateMessage\"\n :suggested-prompts=\"props.suggestedPrompts\"\n :is-active=\"true\"\n class=\"size-full\"\n @close=\"emit('close', $event)\"\n @error=\"emit('error', $event)\"\n @turn-started=\"emit('turnStarted')\"\n @turn-completed=\"emit('turnCompleted', $event)\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </AgentChat>\n </AgentWrap>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport type { ButtonIconPreset } from '../../widget/PLWidget'\nimport type { SuggestedPrompt } from '@pagelines/core'\nimport type { Agent, AgentConfig } from '../schema'\nimport AgentChat from './AgentChat.vue'\nimport AgentWrap from './AgentWrap.vue'\n\nconst props = defineProps<{\n sdk?: PageLinesSDK\n agent?: AgentConfig\n handle?: string\n context?: string\n clientContext?: string\n firstMessage?: string\n buttonText?: string\n buttonIcon?: ButtonIconPreset\n hasClose?: boolean\n chatOnly?: boolean\n bare?: boolean\n apiBase?: string\n emptyStateMessage?: string\n suggestedPrompts?: SuggestedPrompt[]\n}>()\n\ndefineSlots<{\n 'empty-heading': (props: { agent: Agent, isLight: boolean }) => any\n}>()\n\nconst emit = defineEmits<{\n close: [value: string]\n error: [message: string]\n turnStarted: []\n turnCompleted: [conversationId: string]\n}>()\n\n</script>\n\n<template>\n <!-- slotProps.xxx = data resolved by AgentWrap (sdk, agent, context, firstMessage)\n props.xxx = rendering config passed through unchanged (buttonText, buttonIcon, hasClose, chatOnly) -->\n <AgentWrap\n v-slot=\"slotProps\"\n v-bind=\"props\"\n class=\"agent-provider size-full relative\"\n >\n <AgentChat\n :sdk=\"slotProps.sdk\"\n :agent=\"slotProps.agent\"\n :context=\"slotProps.context\"\n :first-message=\"slotProps.firstMessage\"\n :button-text=\"props.buttonText\"\n :button-icon=\"props.buttonIcon\"\n :has-close=\"props.hasClose\"\n :chat-only=\"props.chatOnly\"\n :bare=\"props.bare\"\n :empty-state-message=\"props.emptyStateMessage\"\n :suggested-prompts=\"props.suggestedPrompts\"\n :is-active=\"true\"\n class=\"size-full\"\n @close=\"emit('close', $event)\"\n @error=\"emit('error', $event)\"\n @turn-started=\"emit('turnStarted')\"\n @turn-completed=\"emit('turnCompleted', $event)\"\n >\n <template v-if=\"$slots['empty-heading']\" #empty-heading=\"headingProps\">\n <slot name=\"empty-heading\" v-bind=\"headingProps\" />\n </template>\n </AgentChat>\n </AgentWrap>\n</template>\n"],"mappings":"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"}
|
package/dist/AgentWrap.js
CHANGED
|
@@ -4558,7 +4558,9 @@ var kr = [
|
|
|
4558
4558
|
o = Date.now() + si;
|
|
4559
4559
|
}
|
|
4560
4560
|
function pin() {
|
|
4561
|
-
i.value = !0, scrollToBottom()
|
|
4561
|
+
i.value = !0, o = 0, scrollToBottom(), requestAnimationFrame(() => {
|
|
4562
|
+
scrollToBottom(), requestAnimationFrame(scrollToBottom);
|
|
4563
|
+
});
|
|
4562
4564
|
}
|
|
4563
4565
|
return t({ pin }), te(() => {
|
|
4564
4566
|
requestAnimationFrame(() => {
|
|
@@ -5222,7 +5224,7 @@ var di = ["data-voice-state", "data-voice-activity"], fi = { class: "flex flex-1
|
|
|
5222
5224
|
}, [o[25] || (o[25] = v("i", { class: "i-tabler-file size-3.5" }, null, -1)), b(" " + I(e.filename), 1)], 10, Li))], 64))), 128))], 2)) : h("", !0), messageRenderParts(e).length ? (j(), _("div", {
|
|
5223
5225
|
key: 1,
|
|
5224
5226
|
"data-test": "messaging-message-content",
|
|
5225
|
-
class: T(e.sender === "user" ? K.value ? "rounded-[14px] px-4 py-2.5 bg-theme-
|
|
5227
|
+
class: T(e.sender === "user" ? K.value ? "rounded-[14px] px-4 py-2.5 bg-theme-50 text-theme-900" : "rounded-[14px] px-4 py-2.5 bg-white/10 text-white" : K.value ? "text-theme-800" : "text-white/95")
|
|
5226
5228
|
}, [(j(!0), _(f, null, P(messageRenderParts(e), (t) => (j(), _(f, { key: t.key }, [t.kind === "text" && t.text ? (j(), _("div", Ri, [x(ai, {
|
|
5227
5229
|
text: t.text,
|
|
5228
5230
|
inverted: e.sender === "user" || !K.value,
|
|
@@ -5327,7 +5329,7 @@ var di = ["data-voice-state", "data-voice-activity"], fi = { class: "flex flex-1
|
|
|
5327
5329
|
class: T(["left-0 right-0 z-30 px-5 pb-[max(env(safe-area-inset-bottom),1rem)]", [
|
|
5328
5330
|
B.value.length === 0 || e.centered ? "relative shrink-0" : "absolute bottom-0",
|
|
5329
5331
|
e.centered && B.value.length > 0 ? "pt-0" : "pt-3",
|
|
5330
|
-
K.value ? e.centered ? "bg-theme-
|
|
5332
|
+
K.value ? e.centered ? "bg-theme-0" : "bg-gradient-to-t from-theme-0/90 via-theme-0/55 to-transparent" : "bg-gradient-to-t from-black/90 via-black/60 to-transparent"
|
|
5331
5333
|
]])
|
|
5332
5334
|
}, [
|
|
5333
5335
|
Ee.value.length > 0 ? (j(), _("div", {
|
|
@@ -5360,7 +5362,7 @@ var di = ["data-voice-state", "data-voice-activity"], fi = { class: "flex flex-1
|
|
|
5360
5362
|
v("div", {
|
|
5361
5363
|
"data-test": "messaging-composer",
|
|
5362
5364
|
"data-composer-action": Me.value,
|
|
5363
|
-
class: T(["w-full cursor-text rounded-2xl px-4 pb-2.5 pt-3 transition-colors duration-200", [e.centered ? "max-w-[720px] mx-auto
|
|
5365
|
+
class: T(["w-full cursor-text rounded-2xl px-4 pb-2.5 pt-3 transition-colors duration-200", [e.centered ? "max-w-[720px] mx-auto" : "", K.value ? "bg-white shadow-[0_1px_2px_rgba(15,23,42,0.05),0_8px_24px_rgba(15,23,42,0.05)] ring-1 ring-theme-200 hover:ring-theme-300 focus-within:ring-theme-300" : "bg-white/10 backdrop-blur-xl ring-1 ring-white/15 hover:ring-white/25 focus-within:bg-white/15 focus-within:ring-white/25"]]),
|
|
5364
5366
|
onClick: focusComposer
|
|
5365
5367
|
}, [Be.value ? (j(), _("div", {
|
|
5366
5368
|
key: 1,
|