Display the task's current position in the queue - #614
Conversation
4e0f58c to
fc2090d
Compare
fc2090d to
8843543
Compare
2e81b98 to
632eb5d
Compare
| reject(new Error('pollTaskPosition request failed')) | ||
| }) | ||
| } | ||
| window.assistantPollPositionTimerId = setInterval(pollPositionOnce, 5000) |
There was a problem hiding this comment.
Should we cancel the previous interval here?
632eb5d to
add1130
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe assistant and chat interfaces track scheduled task queue positions. Assistant flows start, update, and cancel position polling during task lifecycle changes. Abortable scheduling and stale-response checks prevent outdated task responses from updating state. Assistant and chat components pass task positions to loading content and display localized positions for scheduled tasks. Merge Risk: 🟡 Moderate · up to The PR adds recurring queue-position polling to task loading and chat views, but current polling can show a previous task’s position, leave stale loading information, or continue unnecessary requests after failures or task changes; chat requests may also occur more often than intended. Merge should wait for the polling lifecycle and error handling to be corrected or explicitly accepted, with the dependent endpoint’s ownership behavior confirmed. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 1 files. (1 skipped: 1 unsupported.) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds UI support to show a task’s current queue position while it’s scheduled/running, including polling and passing that value through to loading/empty states.
Changes:
- Introduce
taskPositionstate and wire it through Assistant page/modal/form components. - Add queue position display to the running empty content and to the ChattyLLM input placeholder.
- Implement
getTaskPosition()+pollTaskPosition()and add cancellation hooks alongside existing task polling.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/views/AssistantPage.vue | Tracks/resets taskPosition, starts/stops position polling, and passes it to child UI. |
| src/components/RunningEmptyContent.vue | Displays formatted queue position next to runtime during scheduled state. |
| src/components/ChattyLLM/InputArea.vue | Appends queue position to the scheduled placeholder text. |
| src/components/ChattyLLM/ChattyLLMInputForm.vue | Resets loading.taskPosition and fetches position when task is scheduled. |
| src/components/AssistantTextProcessingModal.vue | Adds taskPosition state and passes it to content component. |
| src/components/AssistantTextProcessingForm.vue | Adds taskPosition prop and forwards it to the running area. |
| src/assistant.js | Adds queue-position polling helpers and ensures various flows cancel/reset position polling. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export async function cancelTaskPositionPolling() { | ||
| clearInterval(window.assistantPollPositionTimerId) | ||
| window.assistantPollPositionTimerId = null | ||
| } |
| cancelTaskPositionPolling() | ||
| window.assistantPollPositionTimerId = setInterval(pollPositionOnce, 5000) | ||
| // start polling immediately | ||
| pollPositionOnce() |
add1130 to
1090e93
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 064a46aa-90fd-445f-99ef-35d07b7d6bb5
📒 Files selected for processing (7)
src/assistant.jssrc/components/AssistantTextProcessingForm.vuesrc/components/AssistantTextProcessingModal.vuesrc/components/ChattyLLM/ChattyLLMInputForm.vuesrc/components/ChattyLLM/InputArea.vuesrc/components/RunningEmptyContent.vuesrc/views/AssistantPage.vue
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
Throttle queue-position requests to the 5-second cadence.
pollGenerationTask() runs every 2 seconds. While the task is scheduled, this branch calls getTaskPosition() on every iteration. Poll queue position separately, or track the last queue-position request time, so this endpoint runs no more than once every 5 seconds.
| }).catch(error => { | ||
| console.debug('[assistant] pollPosition request failed', error) | ||
| clearInterval(window.assistantPollPositionTimerId) | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionPromiseMethods = 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')) | ||
| }) |
| ? this.loading.llmRunning | ||
| ? this.thinkingText | ||
| : this.scheduledText | ||
| + (this.loading.taskPosition ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) : '') |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
1090e93 to
4dea565
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
src/assistant.js:357
- This loaded-task path also leaves position polling active after any non-404
pollTaskrejection. Because the rejected task-poll promise will never reach its completion handler, move the position cleanup outside thetask-not-foundbranch so the five-second interval cannot outlive the failed flow.
}).catch(error => {
console.debug('[assistant] poll error', error)
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
cancelTaskPositionPolling()
src/assistant.js:870
- The position interval is stopped only when the task poll returns
task-not-found. A different polling failure settles the task-poll promise permanently while queue-position requests continue. Perform the new position cleanup before the condition so all error exits stop it.
}).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
cancelTaskPositionPolling()
src/assistant.js:976
- This second loaded-task handler has the same leak: a non-404
pollTaskrejection bypasses the only position cleanup, and the settled promise can no longer cancel that interval later. Reset the position and cancel its poll unconditionally in this catch.
}).catch(error => {
console.debug('[assistant] poll error', error)
if (error.message === 'task-not-found') {
view.loading = false
view.showSyncTaskRunning = false
view.taskPosition = null
cancelTaskPositionPolling()
| }).catch(error => { | ||
| clearInterval(window.assistantPollPositionTimerId) | ||
| window.assistantPollPositionTimerId = null |
4dea565 to
f1ed3fb
Compare
f6e93b6 to
788904b
Compare
| window.assistantPollAbortController = null | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollRetryDelay = 5000 | ||
| window.assistantPollTaskId = null | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionRetryDelay = 5000 | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| window.assistantSchedulingAbortController = null |
| if (![TASK_STATUS_STRING.scheduled, TASK_STATUS_STRING.running].includes(task?.status)) { | ||
| // stop polling | ||
| clearInterval(window.assistantPollTimerId) | ||
| window.assistantPollTimerId = null | ||
| resolve(task) | ||
| } |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
| <div class="inline"> | ||
| <span v-if="formattedRuntime"> | ||
| {{ formattedRuntime }} | ||
| </span> | ||
| <span v-if="formattedPosition"> | ||
| {{ formattedPosition }} | ||
| </span> | ||
| </div> |
| export async function pollTask(taskId, obj, updateOutput = true, callback = updateTask) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| const pollOnce = () => { | ||
| getTask(taskId).then(response => { | ||
| getTask(taskId, window.assistantPollAbortController.signal).then(response => { | ||
| const task = response.data?.ocs?.data?.task | ||
| if (window.assistantPollTimerId === null) { | ||
| if (window.assistantPollTaskId !== taskId || window.assistantPollTimerId === null) { | ||
| reject(new Error('pollTask cancelled')) | ||
| return | ||
| } |
| if (status === 404) { | ||
| if (window.assistantPollTaskId === taskId) { | ||
| clearInterval(window.assistantPollTimerId) | ||
| clearTimeout(window.assistantPollRetryTimerId) | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollRetryDelay = 5000 | ||
| window.assistantPollTaskId = null | ||
| } | ||
| reject(new Error('task-not-found')) | ||
| return | ||
| } | ||
| reject(new Error('pollTask request failed')) | ||
| if (status >= 400 && status < 500) { | ||
| if (window.assistantPollTaskId === taskId) { | ||
| clearInterval(window.assistantPollTimerId) | ||
| clearTimeout(window.assistantPollRetryTimerId) | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollRetryDelay = 5000 | ||
| window.assistantPollTaskId = null | ||
| } | ||
| reject(new Error('pollTask non-retryable error: ' + status)) | ||
| return | ||
| } |
| : this.scheduledText | ||
| + ((this.loading.taskPosition !== null && this.loading.taskPosition !== undefined) | ||
| ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) | ||
| : '') |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) | ||
| } |
| const pollPositionOnce = () => { | ||
| if (window.assistantPollPositionTaskId !== taskId || window.assistantPollPositionTimerId === null) { | ||
| reject(new Error('pollTaskPosition cancelled')) | ||
| return | ||
| } | ||
| getTaskPosition(taskId, abortController.signal).then(response => { | ||
| const taskPosition = response.data?.ocs?.data | ||
| if (window.assistantPollPositionTaskId !== taskId || window.assistantPollPositionTimerId === null) { | ||
| reject(new Error('pollTaskPosition cancelled')) | ||
| return | ||
| } | ||
| if (obj) { | ||
| callback(taskPosition, obj) | ||
| } | ||
| }).catch(error => { | ||
| const stopPolling = () => { | ||
| if (window.assistantPollPositionTaskId === taskId) { | ||
| clearInterval(window.assistantPollPositionTimerId) | ||
| clearTimeout(window.assistantPollPositionRetryTimerId) | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionRetryDelay = 5000 | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| } | ||
| } | ||
| if (isCancel(error)) { | ||
| stopPolling() | ||
| console.debug('[assistant] pollPosition request cancelled', error) | ||
| reject(new Error('pollTaskPosition request cancelled')) | ||
| return | ||
| } | ||
| const status = error?.response?.status ?? error?.status | ||
| console.debug('[assistant] pollPosition request failed', error) | ||
| if (status === 404) { | ||
| stopPolling() | ||
| reject(new Error('task-not-found')) | ||
| return | ||
| } | ||
| if (status === 412) { | ||
| stopPolling() | ||
| resolve() | ||
| return | ||
| } | ||
| if (status >= 400 && status < 500) { | ||
| stopPolling() | ||
| reject(new Error('pollTaskPosition non-retryable error: ' + status)) | ||
| return | ||
| } | ||
| console.warn('[assistant] pollPosition temporary failure, will retry in ' + window.assistantPollPositionRetryDelay + 'ms', error) | ||
| if (window.assistantPollPositionTaskId === taskId) { | ||
| clearInterval(window.assistantPollPositionTimerId) | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = setTimeout(() => { | ||
| window.assistantPollPositionTimerId = setInterval(pollPositionOnce, 5000) | ||
| pollPositionOnce() | ||
| }, window.assistantPollPositionRetryDelay) | ||
| window.assistantPollPositionRetryDelay = Math.min(window.assistantPollPositionRetryDelay * 2, 60000) | ||
| } | ||
| }) | ||
| } | ||
| window.assistantPollPositionTimerId = setInterval(pollPositionOnce, 5000) |
| export async function pollTask(taskId, obj, updateOutput = true, callback = updateTask) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPolling() | ||
| window.assistantPollTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollAbortController = abortController | ||
| const pollOnce = () => { | ||
| getTask(taskId).then(response => { | ||
| if (window.assistantPollTaskId !== taskId || window.assistantPollTimerId === null) { | ||
| reject(new Error('pollTask cancelled')) | ||
| return | ||
| } | ||
| getTask(taskId, abortController.signal).then(response => { | ||
| const task = response.data?.ocs?.data?.task | ||
| if (window.assistantPollTimerId === null) { | ||
| if (window.assistantPollTaskId !== taskId || window.assistantPollTimerId === null) { | ||
| reject(new Error('pollTask cancelled')) | ||
| return | ||
| } |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
| : this.scheduledText | ||
| + ((this.loading.taskPosition !== null && this.loading.taskPosition !== undefined) | ||
| ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) | ||
| : '') |
| function updateTaskPosition(position, object) { | ||
| object.taskPosition = position | ||
| } |
| if (status === 412) { | ||
| if (window.assistantPollPositionTaskId === taskId) { | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| } | ||
| resolve() | ||
| return | ||
| } |
| export async function pollTaskPosition(taskId, obj, callback = updateTaskPosition) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPositionPolling() | ||
| window.assistantPollPositionTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollPositionAbortController = abortController |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
| : this.scheduledText | ||
| + ((this.loading.taskPosition !== null && this.loading.taskPosition !== undefined) | ||
| ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) | ||
| : '') |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) | ||
| } |
| if (isCancel(error)) { | ||
| if (window.assistantPollTaskId === taskId) { | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollTaskId = null | ||
| window.assistantPollAbortController = null | ||
| } | ||
| console.debug('[assistant] poll request cancelled', error) | ||
| reject(new Error('pollTask cancelled')) | ||
| return | ||
| } |
| window.assistantPollAbortController = null | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollTaskId = null | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| window.assistantSchedulingAbortController = null | ||
|
|
| <div class="inline"> | ||
| <span v-if="formattedRuntime"> | ||
| {{ formattedRuntime }} | ||
| </span> | ||
| <span v-if="formattedPosition"> | ||
| {{ formattedPosition }} | ||
| </span> | ||
| </div> |
| } | ||
|
|
||
| function updateTaskPosition(position, object) { | ||
| object.taskPosition = Number.isFinite(position) ? position : null |
| }).catch(error => { | ||
| if (isCancel(error)) { | ||
| if (window.assistantPollPositionTaskId === taskId) { | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| } | ||
| console.debug('[assistant] pollPosition request cancelled', error) | ||
| reject(new TaskPollCancelledError('pollTaskPosition request cancelled')) | ||
| return | ||
| } |
| }).catch(error => { | ||
| if (isCancel(error)) { | ||
| if (window.assistantPollTaskId === taskId) { | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollTaskId = null | ||
| window.assistantPollAbortController = null | ||
| } | ||
| console.debug('[assistant] poll request cancelled', error) | ||
| reject(new TaskPollCancelledError()) | ||
| return | ||
| } |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPositionPolling() | ||
| window.assistantPollPositionTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollPositionAbortController = abortController |
| }).catch(error => { | ||
| if (isCancel(error)) { | ||
| console.debug('[assistant] pollPosition request cancelled', error) | ||
| safeReject(new TaskPollCancelledError('pollTaskPosition request cancelled')) | ||
| return | ||
| } |
| export class TaskPollCancelledError extends Error { | ||
| constructor(msg = 'pollTask cancelled') { | ||
| super(msg) | ||
| this.name = 'TaskPollCancelledError' | ||
| } | ||
| } | ||
|
|
||
| import { TASK_STATUS_STRING, TASK_STATUS_INT } from './constants.js' |
| } else if (error.response.data.task_status === TASK_STATUS_INT.scheduled) { | ||
| getTaskPosition(taskId) | ||
| .then(response => { | ||
| if (sessionId !== this.active?.id) { | ||
| return | ||
| } | ||
| const taskPosition = response.data?.ocs?.data | ||
| this.loading.taskPosition = taskPosition | ||
| console.debug('Task position:', taskPosition) | ||
| }) | ||
| .catch(error => { | ||
| console.error('Failed to get task position', error) | ||
| }) |
| : this.scheduledText | ||
| + ((this.loading.taskPosition !== null && this.loading.taskPosition !== undefined) | ||
| ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) | ||
| : '') |
| <div class="inline"> | ||
| <span v-if="formattedRuntime"> | ||
| {{ formattedRuntime }} | ||
| </span> | ||
| <span v-if="formattedPosition"> | ||
| {{ formattedPosition }} | ||
| </span> | ||
| </div> |
| } | ||
|
|
||
| .inline { | ||
| display: flex; |
request to make a late change to an unrelated context Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
5d14db4 to
71a0dfb
Compare
| window.assistantPollAbortController = null | ||
| window.assistantPollTimerId = null | ||
| window.assistantPollRetryTimerId = null | ||
| window.assistantPollTaskId = null | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null | ||
| window.assistantSchedulingAbortController = null | ||
|
|
| export async function pollTaskPosition(taskId, obj, callback = updateTaskPosition) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPositionPolling() | ||
| window.assistantPollPositionTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollPositionAbortController = abortController |
| export async function cancelTaskPositionPolling() { | ||
| window.assistantPollPositionAbortController?.abort() | ||
| clearTimeout(window.assistantPollPositionTimerId) | ||
| clearTimeout(window.assistantPollPositionRetryTimerId) | ||
| window.assistantPollPositionTimerId = null | ||
| window.assistantPollPositionRetryTimerId = null | ||
| window.assistantPollPositionTaskId = null | ||
| window.assistantPollPositionAbortController = null |
| return this.loading.llmGeneration | ||
| ? this.loading.llmRunning | ||
| ? this.thinkingText | ||
| : this.scheduledText | ||
| + ((this.loading.taskPosition !== null && this.loading.taskPosition !== undefined) | ||
| ? ' ' + t('assistant', 'Task position: {position}', { position: this.loading.taskPosition }) | ||
| : '') | ||
| : this.placeholderText | ||
| }, |
| export async function pollTaskPosition(taskId, obj, callback = updateTaskPosition) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPositionPolling() | ||
| window.assistantPollPositionTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollPositionAbortController = abortController | ||
| let retryDelay = 5000 | ||
| let settled = false | ||
|
|
| export async function pollTask(taskId, obj, updateOutput = true, callback = updateTask) { | ||
| const { isCancel } = await import('@nextcloud/axios') | ||
| return new Promise((resolve, reject) => { | ||
| cancelTaskPolling() | ||
| window.assistantPollTaskId = taskId | ||
| const abortController = new AbortController() | ||
| window.assistantPollAbortController = abortController | ||
| let retryDelay = 5000 | ||
| let settled = false | ||
|
|
…ric form Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
daa5c5a to
e928653
Compare
Poll the selected task's position every 5 seconds. Display it in the "loading" empty content.
Todo
🤖 AI (if applicable)