-
Notifications
You must be signed in to change notification settings - Fork 237
chore: attach observables for standalone jobs #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR aims to ensure periodic/background jobs surface progress in the UI by attaching observables to reminder-triggered jobs and standalone periodic jobs.
Changes:
- Attach observables to reminder-triggered jobs so the UI can show reminder processing state.
- Attach observables to standalone periodic jobs so the UI can show background job progress.
- Update
docker-compose.yamldefaults forIMAGE_MODEL/LOCALAGI_IMAGE_MODEL.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| docker-compose.yaml | Changes default image model values used by the compose setup. |
| core/agent/agent.go | Adds observable creation/attachment for reminder and standalone periodic jobs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| obs.Icon = "clock" | ||
| a.observer.Update(*obs) | ||
| whatNext.Obs = obs | ||
| } | ||
|
|
||
| a.consumeJob(whatNext, SystemRole) | ||
|
|
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above for standalone jobs: the observable is created/updated, but because this path calls consumeJob(SystemRole) directly (bypassing Execute()), it won’t set Creation/Completion the way other observable-backed jobs do. Consider factoring the observable setup from Execute() into a helper and invoking it here so the UI gets consistent completion/error data.
| obs.Icon = "clock" | |
| a.observer.Update(*obs) | |
| whatNext.Obs = obs | |
| } | |
| a.consumeJob(whatNext, SystemRole) | |
| obs.Icon = "clock" | |
| // Mark observable creation time so UI can display a consistent lifecycle | |
| obs.Creation = time.Now() | |
| a.observer.Update(*obs) | |
| whatNext.Obs = obs | |
| } | |
| a.consumeJob(whatNext, SystemRole) | |
| // Mark observable completion so UI gets consistent completion data | |
| if whatNext.Obs != nil { | |
| whatNext.Obs.Completion = time.Now() | |
| a.observer.Update(*whatNext.Obs) | |
| } |
| // Attach observable so UI can show standalone job progress (decisions, actions, reasoning) | ||
| if a.observer != nil { | ||
| obs := a.observer.NewObservable() | ||
| obs.Name = "standalone" | ||
| obs.Icon = "clock" | ||
| a.observer.Update(*obs) | ||
| whatNext.Obs = obs | ||
| } |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are existing agent tests in this package, but the new behavior (emitting an observable for reminders/standalone periodic jobs) doesn’t appear covered. Adding a test that runs a periodic reminder/standalone cycle with a stub Observer and asserts that an observable with the expected name/icon is emitted (and completed) would help prevent regressions.
| - ${MODEL_NAME:-gemma-3-4b-it-qat} | ||
| - ${MULTIMODAL_MODEL:-gemma-3-4b-it-qat} | ||
| # - ${IMAGE_MODEL:-sd-1.5-ggml} | ||
| - ${IMAGE_MODEL:-Z-Image-Turbo} | ||
| - granite-embedding-107m-multilingual |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR title is about attaching observables for standalone jobs, but this hunk changes the default IMAGE_MODEL in docker-compose. If this is intentional, the PR description/title should mention the new default; otherwise consider reverting/splitting this change into a separate PR to keep scope focused.
| - LOCALAGI_MODEL=${MODEL_NAME:-gemma-3-4b-it-qat} | ||
| - LOCALAGI_MULTIMODAL_MODEL=${MULTIMODAL_MODEL:-moondream2-20250414} | ||
| - LOCALAGI_IMAGE_MODEL=${IMAGE_MODEL:-sd-1.5-ggml} | ||
| - LOCALAGI_IMAGE_MODEL=${IMAGE_MODEL:-Z-Image-Turbo} | ||
| - LOCALAGI_LLM_API_URL=http://localai:8080 |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same scope concern here: this changes the default LOCALAGI_IMAGE_MODEL value in docker-compose, which doesn’t appear related to attaching observables. Consider moving these default-model changes to a separate PR (or update the PR description to cover it).
| // Attach observable so UI can show reminder processing state | ||
| if a.observer != nil { | ||
| obs := a.observer.NewObservable() | ||
| obs.Name = "reminder" | ||
| obs.Icon = "bell" | ||
| a.observer.Update(*obs) | ||
| reminderJob.Obs = obs | ||
| } | ||
|
|
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This attaches an observable but executes the job via consumeJob() directly. Unlike Agent.Execute() (which sets observable Creation from the last message and adds a finalizer to populate Completion/Conversation + Error), this observable won’t get that wiring, so the UI may not receive a proper completion payload for the reminder job. Consider reusing the same observable initialization/finalizer logic here (or routing the reminder through Execute/Enqueue since it’s a user-role job).
| // Attach observable so UI can show reminder processing state | |
| if a.observer != nil { | |
| obs := a.observer.NewObservable() | |
| obs.Name = "reminder" | |
| obs.Icon = "bell" | |
| a.observer.Update(*obs) | |
| reminderJob.Obs = obs | |
| } |
This allows standalone jobs to be tracked