diff --git a/frontend/src/components/expert/components/ExpertChatInput.vue b/frontend/src/components/expert/components/ExpertChatInput.vue
index 5d165ee52c..f349c20f8d 100644
--- a/frontend/src/components/expert/components/ExpertChatInput.vue
+++ b/frontend/src/components/expert/components/ExpertChatInput.vue
@@ -17,6 +17,39 @@
@@ -65,6 +98,7 @@
import { mapActions, mapState } from 'pinia'
import ResizeBar from '../../ResizeBar.vue'
+import ToggleButtonGroup from '../../elements/ToggleButtonGroup.vue'
import CapabilitiesSelector from './CapabilitiesSelector.vue'
import ContextSelector from './context-selection/index.vue'
@@ -80,7 +114,8 @@ export default {
components: {
CapabilitiesSelector,
ContextSelector,
- ResizeBar
+ ResizeBar,
+ ToggleButtonGroup
},
inject: {
togglePinWithWidth: {
@@ -123,8 +158,39 @@ export default {
'isInsightsAgent',
'hasSelectedCapabilities',
'hasMessages',
- 'isWaitingForResponse'
+ 'isWaitingForResponse',
+ 'pendingInput',
+ 'questionCadence',
+ 'planMode'
]),
+ questionCadenceButtons () {
+ return [
+ { title: 'All at once', value: 'all' },
+ { title: 'One at a time', value: 'one' }
+ ]
+ },
+ questionCadenceWrapper: {
+ get () {
+ return this.questionCadence
+ },
+ set (value) {
+ this.setQuestionCadence(value)
+ }
+ },
+ planModeButtons () {
+ return [
+ { title: 'Off', value: 'off' },
+ { title: 'On', value: 'on' }
+ ]
+ },
+ planModeWrapper: {
+ get () {
+ return this.planMode ? 'on' : 'off'
+ },
+ set (value) {
+ this.setPlanMode(value === 'on')
+ }
+ },
isInputDisabled () {
if (this.isSessionExpired) return true
if (this.isWaitingForResponse) return true
@@ -148,6 +214,17 @@ export default {
return this.isImmersiveDevice || this.isImmersiveInstance
}
},
+ watch: {
+ pendingInput (text) {
+ if (text) {
+ this.inputText = text
+ this.setPendingInput('')
+ this.$nextTick(() => {
+ this.$refs.textarea.focus()
+ })
+ }
+ }
+ },
mounted () {
this.bindResizer({
component: this.$refs.resizeTarget,
@@ -158,7 +235,7 @@ export default {
},
methods: {
...mapActions(useProductAssistantStore, ['resetContextSelection']),
- ...mapActions(useProductExpertStore, ['startOver', 'handleQuery', 'handleMessageResponse']),
+ ...mapActions(useProductExpertStore, ['startOver', 'handleQuery', 'handleMessageResponse', 'setPendingInput', 'setQuestionCadence', 'setPlanMode']),
async handleSend () {
if (!this.canSend) return
@@ -232,6 +309,7 @@ export default {
.right-buttons {
display: flex;
gap: 0.5rem;
+ align-items: center;
}
button {
@@ -350,3 +428,42 @@ button {
}
}
+
+
+
diff --git a/frontend/src/components/expert/components/messages/AiMessage.vue b/frontend/src/components/expert/components/messages/AiMessage.vue
index 0fc8817324..2169233b5c 100644
--- a/frontend/src/components/expert/components/messages/AiMessage.vue
+++ b/frontend/src/components/expert/components/messages/AiMessage.vue
@@ -1,18 +1,23 @@
-
+ @failed="setSubItemStreamedState(key)"
+ >
+
+
+
+
diff --git a/frontend/src/components/expert/components/messages/components/resource-cards/StandardResourceCard.vue b/frontend/src/components/expert/components/messages/components/resource-cards/StandardResourceCard.vue
index 11a0f45c01..52fbf44d95 100644
--- a/frontend/src/components/expert/components/messages/components/resource-cards/StandardResourceCard.vue
+++ b/frontend/src/components/expert/components/messages/components/resource-cards/StandardResourceCard.vue
@@ -43,7 +43,7 @@ export default {
emits: ['streaming-complete'],
data () {
return {
- resourceUrl: this.resource.metadata?.streamable.source || this.resource.streamable.url,
+ resourceUrl: this.resource.metadata?.streamable?.source || this.resource.url?.streamable,
resourceTitle: { ...this.resource.title },
resourceMetadataSource: this.resource.metadata?.source
}
diff --git a/frontend/src/components/expert/components/messages/components/resources/QuestionsList.vue b/frontend/src/components/expert/components/messages/components/resources/QuestionsList.vue
new file mode 100644
index 0000000000..00a0daf5a1
--- /dev/null
+++ b/frontend/src/components/expert/components/messages/components/resources/QuestionsList.vue
@@ -0,0 +1,304 @@
+
+
+
+
+
+
{{ q.question }}
+ {{ q.multiSelect ? 'Select all that apply' : 'Select one' }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/stores/context.js b/frontend/src/stores/context.js
index cc89ea8c69..d22eee5f9f 100644
--- a/frontend/src/stores/context.js
+++ b/frontend/src/stores/context.js
@@ -57,7 +57,9 @@ export const useContextStore = defineStore('context', {
pageName: null,
rawRoute: {},
selectedNodes: null,
- scope: 'ff-app'
+ scope: 'ff-app',
+ questionCadence: useProductExpertStore().questionCadence,
+ planMode: useProductExpertStore().planMode
}
}
@@ -106,7 +108,9 @@ export const useContextStore = defineStore('context', {
nodeRedVersion: assistantStore.nodeRedVersion,
rawRoute,
selectedNodes,
- scope
+ scope,
+ questionCadence: useProductExpertStore().questionCadence,
+ planMode: useProductExpertStore().planMode
}
}
},
diff --git a/frontend/src/stores/product-expert.js b/frontend/src/stores/product-expert.js
index a1925a0ed6..1a3a5a2cf2 100644
--- a/frontend/src/stores/product-expert.js
+++ b/frontend/src/stores/product-expert.js
@@ -29,7 +29,10 @@ export const useProductExpertStore = defineStore('product-expert', {
agentMode: SUPPORT_AGENT, // support-agent or insights-agent
loadingVariant: SUPPORT_AGENT,
shouldWakeUpAssistant: false,
+ questionCadence: 'all', // 'all' = ask every clarifying question at once, 'one' = one at a time
+ planMode: false,
inFlightUpdates: [],
+ pendingInput: '',
_seenTransactionIds: new Map()
}),
getters: {
@@ -176,6 +179,9 @@ export const useProductExpertStore = defineStore('product-expert', {
.then(() => { this.loadingVariant = this.agentMode })
}
},
+ setPendingInput (text) {
+ this.pendingInput = text
+ },
async handleQuery ({ query }) {
const agentStore = this._agentStore
@@ -499,6 +505,17 @@ export const useProductExpertStore = defineStore('product-expert', {
this.agentMode = mode
this.loadingVariant = mode
},
+ /**
+ * Sets how clarifying questions are asked: all at once or one at a time.
+ * @param {'all' | 'one'} cadence
+ */
+ setQuestionCadence (cadence) {
+ if (!['all', 'one'].includes(cadence)) return
+ this.questionCadence = cadence
+ },
+ setPlanMode (enabled) {
+ this.planMode = !!enabled
+ },
/**
* Adds a system message to the application's message store.
*
@@ -1063,7 +1080,7 @@ export const useProductExpertStore = defineStore('product-expert', {
}
},
persist: {
- pick: ['shouldWakeUpAssistant'],
+ pick: ['shouldWakeUpAssistant', 'questionCadence', 'planMode'],
storage: localStorage
}
})