Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions src/assistant.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Aura from '@primeuix/themes/aura'
import { listen } from '@nextcloud/notify_push'

window.assistantPollTimerId = null
window.assistantPollPositionTimerId = null

listen('taskprocessing:task_update', (type, body) => {
console.debug('[assistant] received task update push notification', type, body)
Expand Down Expand Up @@ -168,13 +169,15 @@ export async function openAssistantForm({

modalMountPoint.addEventListener('cancel', () => {
cancelTaskPolling()
cancelTaskPositionPolling()
app.unmount()
OCA.Assistant.isAssistantDialogOpen = false
reject(new Error('User cancellation'))
})
const syncSubmit = (inputs, taskTypeId, newTaskCustomId = '') => {
view.loading = true
view.showSyncTaskRunning = true
view.taskPosition = null
view.isNotifyEnabled = false
view.progress = null
view.expectedRuntime = null
Expand All @@ -196,6 +199,11 @@ export async function openAssistantForm({
const hasPush = listenToTaskNotifications(task.id)
console.debug('[assistant] HAS PUSH', hasPush)

pollTaskPosition(task.id, view).then(() => {
console.debug('[assistant] pollTaskPosition finished')
}).catch(error => {
console.debug('[assistant] pollPosition error', error.message)
})
// no need to update the task output with polling if we have push notifications
pollTask(task.id, view, !hasPush).then(finishedTask => {
console.debug('pollTask.then', finishedTask)
Expand Down Expand Up @@ -224,12 +232,14 @@ export async function openAssistantForm({
resolve(finishedTask)
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
emit('assistant:task:updated', finishedTask)
}).catch(error => {
console.debug('[assistant] poll error', error.message)
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.outputs = null
view.selectedTaskId = null
Expand All @@ -241,6 +251,7 @@ export async function openAssistantForm({
.catch(error => {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
console.error('Assistant scheduling error', error?.response?.data?.ocs?.data?.message)
showError(t('assistant', 'Assistant error') + ': ' + t('assistant', 'Something went wrong when scheduling the task'))
})
Expand All @@ -258,7 +269,9 @@ export async function openAssistantForm({
const task = data.detail
console.debug('[assistant] loading task', task)
cancelTaskPolling()
cancelTaskPositionPolling()
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.loading = false
view.taskStatus = task.status
Expand Down Expand Up @@ -291,6 +304,7 @@ export async function openAssistantForm({

view.loading = true
view.showSyncTaskRunning = true
view.taskPosition = null
view.progress = null
view.expectedRuntime = (updatedTask?.completionExpectedAt - updatedTask?.scheduledAt) || null
view.startedAt = lastTask?.startedAt || null
Expand All @@ -299,6 +313,11 @@ export async function openAssistantForm({
const hasPush = listenToTaskNotifications(task.id)
console.debug('[assistant] HAS PUSH', hasPush)

pollTaskPosition(updatedTask.id, view).then(() => {
console.debug('[assistant] pollTaskPosition finished')
}).catch(error => {
console.debug('[assistant] pollPosition error', error.message)
})
pollTask(updatedTask.id, view, !hasPush).then(finishedTask => {
console.debug('pollTask.then', finishedTask)
if (finishedTask.status === TASK_STATUS_STRING.successful) {
Expand All @@ -322,12 +341,14 @@ export async function openAssistantForm({
// resolve(finishedTask)
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
emit('assistant:task:updated', finishedTask)
}).catch(error => {
console.debug('[assistant] poll error', error)
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.outputs = null
view.selectedTaskId = null
Expand All @@ -343,8 +364,10 @@ export async function openAssistantForm({
modalMountPoint.addEventListener('new-task', () => {
console.debug('[assistant] new task')
cancelTaskPolling()
cancelTaskPositionPolling()
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.outputs = null
view.selectedTaskId = null
Expand All @@ -358,10 +381,12 @@ export async function openAssistantForm({
})
modalMountPoint.addEventListener('cancel-task', () => {
cancelTaskPolling()
cancelTaskPositionPolling()
setNotifyReady(lastTask.id, false)
cancelTask(lastTask.id).then(res => {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.selectedTaskId = null
view.outputs = null
view.taskStatus = null
Expand Down Expand Up @@ -393,6 +418,55 @@ function updateTask(task, object, updateOutput = true) {
object.completionExpectedAt = task?.completionExpectedAt
}

function updateTaskPosition(position, object) {
object.taskPosition = position
}

/**
* Poll the task position
*
* @param {number} taskId the task ID
* @param {object} obj the object to update
* @param {Function} callback the function to call to update the object
* @return {Promise<*>}
*/
export async function pollTaskPosition(taskId, obj, callback = updateTaskPosition) {
return new Promise((resolve, reject) => {
const pollPositionOnce = () => {
if (window.assistantPollPositionTimerId === null) {
reject(new Error('pollTaskPosition cancelled'))
return
}
getTaskPosition(taskId).then(response => {
const taskPosition = response.data?.ocs?.data
if (window.assistantPollPositionTimerId === null) {
reject(new Error('pollTaskPosition cancelled'))
return
}
if (obj) {
callback(taskPosition, obj)
}
}).catch(error => {
console.debug('[assistant] pollPosition request failed', error)
clearInterval(window.assistantPollPositionTimerId)
window.assistantPollPositionTimerId = null
if (error.status === 404) {
reject(new Error('task-not-found'))
return
} else if (error.status === 412) {
// the task is not scheduled anymore
resolve()
return
}
reject(new Error('pollTaskPosition request failed'))
})
}
// start polling immediately
pollPositionOnce()
window.assistantPollPositionTimerId = setInterval(pollPositionOnce, 5000)
})
}

/**
* Poll the task to update its status
*
Expand Down Expand Up @@ -443,6 +517,11 @@ export async function cancelTaskPolling() {
window.assistantPollTimerId = null
}

export async function cancelTaskPositionPolling() {
clearInterval(window.assistantPollPositionTimerId)
window.assistantPollPositionTimerId = null
}

export async function getTask(taskId) {
window.assistantAbortController = new AbortController()
const { default: axios } = await import('@nextcloud/axios')
Expand All @@ -451,6 +530,13 @@ export async function getTask(taskId) {
return axios.get(url, { signal: window.assistantAbortController.signal })
}

export async function getTaskPosition(taskId) {
const { default: axios } = await import('@nextcloud/axios')
const { generateOcsUrl } = await import('@nextcloud/router')
const url = generateOcsUrl('taskprocessing/tasks/{taskId}/queue_position', { taskId })
return axios.get(url, {})
}

export async function getNotifyReady(taskId) {
const { default: axios } = await import('@nextcloud/axios')
const { generateOcsUrl } = await import('@nextcloud/router')
Expand Down Expand Up @@ -688,6 +774,7 @@ export async function openAssistantTask(

modalMountPoint.addEventListener('cancel', () => {
cancelTaskPolling()
cancelTaskPositionPolling()
app.unmount()
OCA.Assistant.isAssistantDialogOpen = false
})
Expand All @@ -709,6 +796,7 @@ export async function openAssistantTask(
const syncSubmit = (inputs, taskTypeId, newTaskCustomId = '') => {
view.loading = true
view.showSyncTaskRunning = true
view.taskPosition = null
view.isNotifyEnabled = false
view.expectedRuntime = null
view.startedAt = null
Expand All @@ -728,6 +816,11 @@ export async function openAssistantTask(
const hasPush = listenToTaskNotifications(task.id)
console.debug('[assistant] HAS PUSH', hasPush)

pollTaskPosition(task.id, view).then(() => {
console.debug('[assistant] pollTaskPosition finished')
}).catch(error => {
console.debug('[assistant] pollPosition error', error.message)
})
pollTask(task.id, view, !hasPush).then(finishedTask => {
if (finishedTask.status === TASK_STATUS_STRING.successful) {
view.outputs = finishedTask?.output
Expand All @@ -749,13 +842,15 @@ export async function openAssistantTask(
// resolve(finishedTask)
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
emit('assistant:task:updated', finishedTask)
}).catch(error => {
console.debug('[assistant] poll error', error)
view.outputs = null
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.selectedTaskId = null
lastTask = null
Expand All @@ -766,6 +861,7 @@ export async function openAssistantTask(
.catch(error => {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
console.error('Assistant scheduling error', error?.response?.data?.ocs?.data?.message)
showError(t('assistant', 'Assistant error') + ': ' + t('assistant', 'Something went wrong when scheduling the task'))
})
Expand All @@ -780,7 +876,9 @@ export async function openAssistantTask(
modalMountPoint.addEventListener('load-task', (data) => {
const task = data.detail
cancelTaskPolling()
cancelTaskPositionPolling()
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.loading = false
view.taskStatus = task.status
Expand Down Expand Up @@ -813,13 +911,19 @@ export async function openAssistantTask(

view.loading = true
view.showSyncTaskRunning = true
view.taskPosition = null
view.progress = null
view.expectedRuntime = (updatedTask?.completionExpectedAt - updatedTask?.scheduledAt) || null
view.startedAt = lastTask?.startedAt || null
view.completionExpectedAt = lastTask?.completionExpectedAt || null

const hasPush = listenToTaskNotifications(task.id)

pollTaskPosition(updatedTask.id, view).then(() => {
console.debug('[assistant] pollTaskPosition finished')
}).catch(error => {
console.debug('[assistant] pollPosition error', error.message)
})
pollTask(updatedTask.id, view, !hasPush).then(finishedTask => {
console.debug('pollTask.then', finishedTask)
if (finishedTask.status === TASK_STATUS_STRING.successful) {
Expand All @@ -843,12 +947,14 @@ export async function openAssistantTask(
// resolve(finishedTask)
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
emit('assistant:task:updated', finishedTask)
}).catch(error => {
console.debug('[assistant] poll error', error)
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.outputs = null
view.selectedTaskId = null
Expand All @@ -864,8 +970,10 @@ export async function openAssistantTask(
modalMountPoint.addEventListener('new-task', () => {
console.debug('[assistant] new task')
cancelTaskPolling()
cancelTaskPositionPolling()
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.isNotifyEnabled = false
view.outputs = null
view.selectedTaskId = null
Expand All @@ -879,10 +987,12 @@ export async function openAssistantTask(
})
modalMountPoint.addEventListener('cancel-task', () => {
cancelTaskPolling()
cancelTaskPositionPolling()
setNotifyReady(lastTask.id, false)
cancelTask(lastTask.id).then(res => {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
view.selectedTaskId = null
view.outputs = null
view.taskStatus = null
Expand Down
5 changes: 5 additions & 0 deletions src/components/AssistantTextProcessingForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
class="running-area"
:description="shortInput"
:progress="progress"
:task-position="taskPosition"
:expected-runtime="expectedRuntime"
:started-at="startedAt"
:completion-expected-at="completionExpectedAt"
Expand Down Expand Up @@ -283,6 +284,10 @@ export default {
type: Boolean,
default: false,
},
taskPosition: {
type: [Number, null],
default: null,
},
shortInput: {
type: String,
required: true,
Expand Down
2 changes: 2 additions & 0 deletions src/components/AssistantTextProcessingModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
:loading="loading"
:action-buttons="actionButtons"
:show-sync-task-running="showSyncTaskRunning"
:task-position="taskPosition"
:short-input="shortInput"
:progress="progress"
:expected-runtime="expectedRuntime"
Expand Down Expand Up @@ -130,6 +131,7 @@ export default {
completionExpectedAt: null,
isNotifyEnabled: false,
showSyncTaskRunning: false,
taskPosition: null,
showScheduleConfirmation: false,
// from props
selectedTaskId: this.initSelectedTaskId,
Expand Down
Loading
Loading