feat: timing task#1677
Conversation
📝 WalkthroughWalkthroughAdds a full scheduled-tasks feature: shared types and Zod IPC routes, config persistence with normalization, a timer-backed ScheduledTasksService with start/stop and mutation routes, presenter/runtime/lifecycle wiring, renderer client and settings UI, i18n across locales, and unit tests for core scheduling logic. ChangesScheduled Tasks Feature
Sequence DiagramsequenceDiagram
Renderer->>Presenter: scheduledTasksList / scheduledTasksUpsert / scheduledTasksFireNow
Presenter->>ScheduledTasksService: list / upsert / fireNow
ScheduledTasksService->>ScheduledTasksService: computeNextFireAt & arm timers
ScheduledTasksService->>SessionCreator: createSessionForTask (autoSend)
SessionCreator->>ChatService: sendMessage
ScheduledTasksService->>NotificationPresenter: showNotification
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (2)
src/main/presenter/scheduledTasks/index.ts (1)
271-278: 💤 Low valueConsider adding exhaustive handling for action kinds.
If a new action kind is added to the schema in the future, this function will silently do nothing. Adding an exhaustive check would catch such additions at compile time:
Suggested pattern
if (action.kind === 'prompt') { if (action.autoSend) { await this.runPromptAutoSend(taskId, action) return } await this.runPromptDraft(taskId, action) + return } + + const _exhaustive: never = action + log.warn('[ScheduledTasks] Unknown action kind:', (_exhaustive as ScheduledTaskAction).kind) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/presenter/scheduledTasks/index.ts` around lines 271 - 278, The current handler for action kinds only handles 'prompt' and silently ignores any future kinds; update the function containing this snippet (the method that calls runPromptAutoSend and runPromptDraft) to use an exhaustive check (e.g., convert the if into a switch on action.kind or add a final default that calls an assertNever/throws) so unknown action.kind values fail at compile/runtime. Reference the symbols action.kind, runPromptAutoSend, runPromptDraft and add a guard (throw or assertNever) for unhandled kinds to ensure the TypeScript compiler enforces exhaustive handling when new kinds are added.src/renderer/settings/components/ScheduledTasksSettings.vue (1)
550-558: ⚡ Quick winUse SCREAMING_SNAKE_CASE for constants.
Rename
dayOfWeekOptionstoDAY_OF_WEEK_OPTIONSfor guideline compliance.As per coding guidelines, "Constants must use SCREAMING_SNAKE_CASE naming".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/settings/components/ScheduledTasksSettings.vue` around lines 550 - 558, Rename the constant dayOfWeekOptions to DAY_OF_WEEK_OPTIONS and update all usages to the new name; this includes the declaration (const DAY_OF_WEEK_OPTIONS: Record<number, string> = { ... }) and any references in the component script/template where dayOfWeekOptions is accessed (e.g., in computed properties, methods, or template bindings) so the identifier is consistent with SCREAMING_SNAKE_CASE guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/features/scheduled-tasks/plan.md`:
- Around line 60-63: Update the documentation line that mentions the stale test
location: replace the string referencing `test/main/scheduledTasks/` with the
correct test file/path `test/main/presenter/scheduledTasks.test.ts` in the
docs/features/scheduled-tasks/plan.md entry that describes unit tests for
computeNextFireAt and normalizeScheduledTasksConfig so the validation checklist
points to the actual tests.
In `@src/main/presenter/scheduledTasks/normalize.ts`:
- Around line 120-134: Normalization currently allows duplicate task ids from
rawTasks which will break id-keyed operations; in the reduce that builds tasks
(using sanitizeTask and variable tasks) add deduplication by tracking seen ids
(e.g., a Set seenIds) and when a sanitized task's id collides either regenerate
a new unique id (via an existing id generator or by appending a deterministic
suffix/sequence until unique) or skip duplicates, then insert the final unique
id into seenIds before pushing; ensure this logic runs inside the reduce before
acc.push and that the returned object (version: SCHEDULED_TASKS_VERSION, tasks)
contains only tasks with unique ids.
In `@src/main/routes/index.ts`:
- Around line 322-348: The captured mainWindowWebContentsId variable can become
stale; move the webContents id lookup into the scheduled task callback so it is
evaluated at execution time. In the deps.scheduledTasks.setSessionCreator
createSessionForTask implementation, replace uses of the outer
mainWindowWebContentsId with a fresh read like
deps.windowPresenter.mainWindow?.webContents?.id ?? -1 (same fallback) when
constructing the session options, keeping the windowId lookup as-is so both ids
are resolved at runtime.
In `@src/renderer/settings/components/ScheduledTasksSettings.vue`:
- Around line 669-691: persistTask and other commit handlers can be applied
out-of-order and overwrite newer edits; add a "latest-write-wins" guard by
introducing a numeric saveCounter (ref) at component scope, increment it before
each network request, capture its value in the local request (e.g., const reqId
= ++saveCounter.value), then when the response arrives only assign
settings.value (or merge into it) if reqId === saveCounter.value; update the
same pattern in commitTask and the other save handlers referenced (the calls
around lines 693-699, 731-732, 781-782, 807-808, 839-840, 861-862) and prefer
merging response.settings into the current settings.value rather than blindly
replacing it to avoid stomping concurrent local changes.
In `@src/renderer/src/i18n/da-DK/settings.json`:
- Around line 1281-1340: The scheduledTasks block in the da-DK locale is still
in English; translate every string inside the scheduledTasks object (e.g.,
scheduledTasks.title, scheduledTasks.description, scheduledTasks.hint,
scheduledTasks.newTask, defaults.name/title/body, trigger.* like
kindOnce/kindDaily/firesAt/time/description, action.* like
kindNotify/kindPrompt/titlePlaceholder/agentIdPlaceholder/modelIdPlaceholder/systemPrompt/autoSend/description,
weekday.* keys, listTitle/listDescription, and summary.*) into Danish, keeping
all interpolation tokens (e.g., {time}, {day}, {trigger}, {action}) and
placeholder semantics intact. Ensure translations preserve capitalization and UI
context (placeholders remain short), and do not change key names or token
syntax.
In `@src/renderer/src/i18n/fa-IR/settings.json`:
- Around line 1348-1407: The scheduledTasks block in the fa-IR locale is still
English; translate every string under "scheduledTasks" (including nested keys:
defaults, trigger, action, weekday, listTitle, listDescription, summary and
their children like namePlaceholder, fireNow, kindOnce/kindDaily/kindWeekly,
firesAt, dayOfWeek, time, titleField, titlePlaceholder, body, message,
agentIdPlaceholder, modelIdPlaceholder, systemPrompt, autoSend, weekday names,
and summary templates) into Persian; keep the same key names and interpolation
tokens ({time},{day},{trigger},{action}) intact and ensure plural/format
patterns match the originals so the UI reads fully in Persian.
In `@src/renderer/src/i18n/fr-FR/settings.json`:
- Around line 1348-1407: The scheduledTasks section contains English strings
that must be translated to French; update the "scheduledTasks" object and all
nested keys (e.g., defaults, trigger, action, weekday, listTitle,
listDescription, summary) with French translations while preserving keys,
placeholders and interpolation tokens like {time}, {day}, {trigger}, and
{action} exactly as-is and not altering identifiers such as "kindOnce",
"kindDaily", "agentIdPlaceholder" or "modelIdPlaceholder".
In `@src/renderer/src/i18n/he-IL/settings.json`:
- Around line 1348-1406: The scheduledTasks block contains untranslated English
strings; update the he-IL translations for the scheduledTasks object (keys such
as title, description, hint, newTask, empty, namePlaceholder, fireNow,
fireNowSuccess, defaults, trigger.*, action.*, weekday.*, listTitle,
listDescription, summary.*) to Hebrew equivalents so the UI is consistent in the
he-IL locale—edit the scheduledTasks JSON entries to provide proper Hebrew text
for each of those keys (including nested keys like trigger.kindOnce,
action.kindNotify, weekday.sun, summary.daily, etc.).
In `@src/renderer/src/i18n/ja-JP/settings.json`:
- Line 1371: In the ja-JP settings.json under the scheduledTasks block there are
leftover English values (e.g., the "description" value currently "Choose when
this task runs." and several other strings in the same scheduledTasks object).
Replace those English strings with their correct Japanese translations while
preserving the exact JSON keys and structure (escape characters and punctuation
unchanged). Locate the scheduledTasks object and update every untranslated value
in that block so all strings are consistent in Japanese.
In `@src/renderer/src/i18n/ko-KR/settings.json`:
- Line 1371: The scheduledTasks localization block contains English strings
(e.g., the "description" value "Choose when this task runs." plus other entries
around the scheduledTasks block at the same section) that must be translated
into Korean; open the scheduledTasks entries in the ko-KR settings.json (look
for the "scheduledTasks" object and keys like "description" and the strings
around lines ~1371, ~1388, ~1399-1405) and replace each English value with the
appropriate Korean translation, keeping the JSON keys unchanged and preserving
punctuation/formatting and surrounding quotes.
In `@src/renderer/src/i18n/pt-BR/settings.json`:
- Around line 1348-1407: The scheduledTasks block was added with English strings
in the pt-BR locale; translate every value under the "scheduledTasks" object
(keys: title, description, hint, newTask, empty, namePlaceholder, fireNow,
fireNowSuccess, defaults.*, trigger.*, action.*, weekday.*, listTitle,
listDescription, summary.*) into Brazilian Portuguese so the pt-BR file contains
localized text (keep placeholders like {trigger}, {action}, {time}, {day}
intact).
In `@src/renderer/src/i18n/ru-RU/settings.json`:
- Around line 1348-1407: Translate all English values inside the scheduledTasks
JSON object to Russian while preserving the JSON keys and placeholder tokens;
update fields including title, description, hint, newTask, empty,
namePlaceholder, fireNow, fireNowSuccess, defaults (name, title, body), trigger
(title, kind, kindOnce, kindDaily, kindWeekly, firesAt, dayOfWeek, time,
description), action (title, kind, kindNotify, kindPrompt, titleField,
titlePlaceholder, body, message, agentId, agentIdPlaceholder, modelId,
modelIdPlaceholder, systemPrompt, autoSend, description), weekday entries
(sun–sat), listTitle, listDescription, and summary templates; keep placeholder
variables like {trigger}, {action}, {time}, {day} and any colon/format hints
intact and do not change key names or JSON structure.
In `@src/renderer/src/i18n/zh-CN/settings.json`:
- Line 1449: The "systemPrompt" JSON key currently has an English value; update
its value to the Chinese localized string (e.g., replace "System Prompt" with
"系统提示" or the agreed translation) so it matches the surrounding localization;
edit the entry for "systemPrompt" in the settings JSON to the Chinese text.
---
Nitpick comments:
In `@src/main/presenter/scheduledTasks/index.ts`:
- Around line 271-278: The current handler for action kinds only handles
'prompt' and silently ignores any future kinds; update the function containing
this snippet (the method that calls runPromptAutoSend and runPromptDraft) to use
an exhaustive check (e.g., convert the if into a switch on action.kind or add a
final default that calls an assertNever/throws) so unknown action.kind values
fail at compile/runtime. Reference the symbols action.kind, runPromptAutoSend,
runPromptDraft and add a guard (throw or assertNever) for unhandled kinds to
ensure the TypeScript compiler enforces exhaustive handling when new kinds are
added.
In `@src/renderer/settings/components/ScheduledTasksSettings.vue`:
- Around line 550-558: Rename the constant dayOfWeekOptions to
DAY_OF_WEEK_OPTIONS and update all usages to the new name; this includes the
declaration (const DAY_OF_WEEK_OPTIONS: Record<number, string> = { ... }) and
any references in the component script/template where dayOfWeekOptions is
accessed (e.g., in computed properties, methods, or template bindings) so the
identifier is consistent with SCREAMING_SNAKE_CASE guidelines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3fd72c24-9962-44f2-98a5-8cd382229306
📒 Files selected for processing (54)
docs/features/scheduled-tasks/plan.mddocs/features/scheduled-tasks/spec.mddocs/features/scheduled-tasks/tasks.mddocs/issues/scheduled-task-prompt-picker-ux/plan.mddocs/issues/scheduled-task-prompt-picker-ux/spec.mddocs/issues/scheduled-task-prompt-picker-ux/tasks.mddocs/issues/scheduled-tasks-clone-error/plan.mddocs/issues/scheduled-tasks-clone-error/spec.mddocs/issues/scheduled-tasks-clone-error/tasks.mddocs/issues/scheduled-tasks-real-dispatch/plan.mddocs/issues/scheduled-tasks-real-dispatch/spec.mddocs/issues/scheduled-tasks-real-dispatch/tasks.mdsrc/main/presenter/configPresenter/index.tssrc/main/presenter/index.tssrc/main/presenter/lifecyclePresenter/hooks/after-start/scheduledTasksStartHook.tssrc/main/presenter/lifecyclePresenter/hooks/beforeQuit/scheduledTasksStopHook.tssrc/main/presenter/lifecyclePresenter/hooks/index.tssrc/main/presenter/scheduledTasks/index.tssrc/main/presenter/scheduledTasks/normalize.tssrc/main/routes/index.tssrc/renderer/api/ScheduledTasksClient.tssrc/renderer/settings/components/ScheduledTasksSettings.vuesrc/renderer/settings/main.tssrc/renderer/src/i18n/da-DK/routes.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/en-US/routes.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/fa-IR/routes.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/routes.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/routes.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/ja-JP/routes.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/routes.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/pt-BR/routes.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/routes.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/zh-CN/routes.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-HK/routes.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/zh-TW/routes.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/shared/contracts/routes.tssrc/shared/contracts/routes/scheduledTasks.routes.tssrc/shared/contracts/routes/system.routes.tssrc/shared/scheduledTasks.tssrc/shared/settingsNavigation.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/scheduledTasks.test.ts
Adds a new settings page (Tools → 定时任务) for creating one-shot, daily, and weekly scheduled tasks. Each task can either raise a system notification or send a preset prompt to a chosen agent — with an opt-in autoSend toggle that bypasses the deeplink draft path via sessionService.createSession. A small in-process scheduler arms one setTimeout per task with a 12h chained-timeout cap; missed one-shot tasks are backfilled on next launch, recurring tasks are not. Persisted via ConfigPresenter, normalized on read to drop any malformed records.
f6e3d5c to
ed04a62
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/main/presenter/scheduledTasks/normalize.ts (1)
13-61: ⚡ Quick winRename these schema constants to SCREAMING_SNAKE_CASE.
TriggerSchema,ActionSchema,ScheduledTaskSchema, andLooseSchedulerSettingsSchemadon't match the repository constant-naming rule. As per coding guidelines,src/**/*.{ts,tsx,js,jsx,vue}: Constants must use SCREAMING_SNAKE_CASE naming.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/presenter/scheduledTasks/normalize.ts` around lines 13 - 61, Rename the constant schema identifiers to SCREAMING_SNAKE_CASE and update all their usages: change TriggerSchema -> TRIGGER_SCHEMA, ActionSchema -> ACTION_SCHEMA, ScheduledTaskSchema -> SCHEDULED_TASK_SCHEMA, and LooseSchedulerSettingsSchema -> LOOSE_SCHEDULER_SETTINGS_SCHEMA; ensure the z.discriminatedUnion/z.object definitions remain identical and update any references within this file (or imports/exports) that use TriggerSchema, ActionSchema, ScheduledTaskSchema, or LooseSchedulerSettingsSchema so they now reference the new names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/presenter/configPresenter/index.ts`:
- Around line 3201-3213: getScheduledTasksConfig and setScheduledTasksConfig are
directly using this.store which bypasses the key-aware settings store; change
both to use the key-aware store returned by
getSettingsStoreForKey('scheduledTasks') so reads/writes follow DB-backed
settings after sqlite attach. Specifically, inside getScheduledTasksConfig call
const store = this.getSettingsStoreForKey('scheduledTasks') then read with
store.get, normalize via normalizeScheduledTasksConfig and write back with
store.set if needed; do the same in setScheduledTasksConfig: normalize with
normalizeScheduledTasksConfig, then persist using the key-specific store.set and
return the normalized value.
In `@src/main/presenter/scheduledTasks/index.ts`:
- Around line 240-253: The current fireAndPersist method always calls markFired
in the finally block even if dispatch(task) throws, causing failed dispatches
(especially one-shot tasks) to be marked consumed; change the control flow so
markFired(task) is only called on successful dispatch (i.e., inside the try
after await this.dispatch(task) or in an explicit success branch) and ensure the
existing re-arm logic that uses list().tasks and armTask(refreshed, Date.now())
still runs for recurring tasks only when dispatch succeeded; keep dispatch error
logging (log.error) in the catch block and do not call markFired there.
---
Nitpick comments:
In `@src/main/presenter/scheduledTasks/normalize.ts`:
- Around line 13-61: Rename the constant schema identifiers to
SCREAMING_SNAKE_CASE and update all their usages: change TriggerSchema ->
TRIGGER_SCHEMA, ActionSchema -> ACTION_SCHEMA, ScheduledTaskSchema ->
SCHEDULED_TASK_SCHEMA, and LooseSchedulerSettingsSchema ->
LOOSE_SCHEDULER_SETTINGS_SCHEMA; ensure the z.discriminatedUnion/z.object
definitions remain identical and update any references within this file (or
imports/exports) that use TriggerSchema, ActionSchema, ScheduledTaskSchema, or
LooseSchedulerSettingsSchema so they now reference the new names.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0e1c6a41-9f15-4b0d-8ef5-29d1f9af7bfb
📒 Files selected for processing (41)
docs/features/scheduled-tasks/plan.mddocs/features/scheduled-tasks/spec.mddocs/features/scheduled-tasks/tasks.mddocs/issues/scheduled-task-prompt-picker-ux/plan.mddocs/issues/scheduled-task-prompt-picker-ux/spec.mddocs/issues/scheduled-task-prompt-picker-ux/tasks.mddocs/issues/scheduled-tasks-clone-error/plan.mddocs/issues/scheduled-tasks-clone-error/spec.mddocs/issues/scheduled-tasks-clone-error/tasks.mddocs/issues/scheduled-tasks-real-dispatch/plan.mddocs/issues/scheduled-tasks-real-dispatch/spec.mddocs/issues/scheduled-tasks-real-dispatch/tasks.mdsrc/main/presenter/configPresenter/index.tssrc/main/presenter/index.tssrc/main/presenter/lifecyclePresenter/hooks/after-start/scheduledTasksStartHook.tssrc/main/presenter/lifecyclePresenter/hooks/beforeQuit/scheduledTasksStopHook.tssrc/main/presenter/lifecyclePresenter/hooks/index.tssrc/main/presenter/scheduledTasks/index.tssrc/main/presenter/scheduledTasks/normalize.tssrc/main/routes/index.tssrc/renderer/api/ScheduledTasksClient.tssrc/renderer/settings/components/ScheduledTasksSettings.vuesrc/renderer/settings/main.tssrc/renderer/src/i18n/da-DK/routes.jsonsrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/en-US/routes.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/fa-IR/routes.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/routes.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/routes.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/ja-JP/routes.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/routes.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/pt-BR/routes.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/routes.jsonsrc/renderer/src/i18n/ru-RU/settings.json
💤 Files with no reviewable changes (16)
- src/renderer/src/i18n/he-IL/routes.json
- src/renderer/src/i18n/ru-RU/routes.json
- src/renderer/src/i18n/fr-FR/routes.json
- src/renderer/src/i18n/ja-JP/routes.json
- src/renderer/src/i18n/pt-BR/routes.json
- src/renderer/src/i18n/fa-IR/routes.json
- src/renderer/src/i18n/pt-BR/settings.json
- src/renderer/src/i18n/ko-KR/routes.json
- src/renderer/src/i18n/ko-KR/settings.json
- src/renderer/src/i18n/ru-RU/settings.json
- src/renderer/src/i18n/en-US/settings.json
- src/renderer/src/i18n/fa-IR/settings.json
- src/renderer/src/i18n/en-US/routes.json
- src/renderer/src/i18n/he-IL/settings.json
- src/renderer/src/i18n/ja-JP/settings.json
- src/renderer/src/i18n/fr-FR/settings.json
✅ Files skipped from review due to trivial changes (13)
- docs/issues/scheduled-tasks-real-dispatch/plan.md
- docs/features/scheduled-tasks/spec.md
- src/renderer/settings/main.ts
- docs/issues/scheduled-tasks-clone-error/spec.md
- src/renderer/src/i18n/da-DK/routes.json
- docs/features/scheduled-tasks/tasks.md
- docs/issues/scheduled-tasks-clone-error/tasks.md
- docs/issues/scheduled-tasks-clone-error/plan.md
- docs/issues/scheduled-task-prompt-picker-ux/plan.md
- docs/issues/scheduled-task-prompt-picker-ux/tasks.md
- docs/issues/scheduled-tasks-real-dispatch/tasks.md
- docs/issues/scheduled-tasks-real-dispatch/spec.md
- docs/features/scheduled-tasks/plan.md
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/presenter/scheduledTasks/index.ts (1)
319-337:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTreat
sessionId: nullas an auto-send failure.
createSessionForTask()can return{ sessionId: null }from the route wiring, but this branch is handled as success here. That means the task can be marked fired even though no session was created and no prompt was sent. Fall back to draft mode when nosessionIdcomes back.Suggested fix
try { - await this.sessionCreator.createSessionForTask({ + const { sessionId } = await this.sessionCreator.createSessionForTask({ agentId: action.agentId ?? SCHEDULED_TASK_DEFAULT_AGENT_ID, message: action.message, providerId: action.providerId, modelId: action.modelId, systemPrompt: action.systemPrompt }) + + if (!sessionId) { + log.warn('[ScheduledTasks] Session creation returned no session id; falling back to draft mode') + await this.runPromptDraft(taskId, action) + return + } await this.notificationPresenter.showNotification({ id: `scheduled:${taskId}`, title: action.title, body: action.message.slice(0, 200)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/presenter/scheduledTasks/index.ts` around lines 319 - 337, The current try block treats any completion of this.sessionCreator.createSessionForTask(...) as success even when it returns { sessionId: null }; change the flow to capture the return (e.g. const result = await this.sessionCreator.createSessionForTask(...)) and if result.sessionId is null, throw or directly call this.runPromptDraft(taskId, action) and skip the notificationPresenter.showNotification call so the task isn't considered sent; keep the existing catch that logs via log.error('[ScheduledTasks] Failed to create session for task:', error) and falls back to this.runPromptDraft as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/main/presenter/scheduledTasks/index.ts`:
- Around line 319-337: The current try block treats any completion of
this.sessionCreator.createSessionForTask(...) as success even when it returns {
sessionId: null }; change the flow to capture the return (e.g. const result =
await this.sessionCreator.createSessionForTask(...)) and if result.sessionId is
null, throw or directly call this.runPromptDraft(taskId, action) and skip the
notificationPresenter.showNotification call so the task isn't considered sent;
keep the existing catch that logs via log.error('[ScheduledTasks] Failed to
create session for task:', error) and falls back to this.runPromptDraft as
before.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ab7b433e-a807-4ec5-85d6-11aa2501f95a
📒 Files selected for processing (32)
docs/features/scheduled-tasks/plan.mddocs/features/scheduled-tasks/tasks.mdsrc/main/presenter/scheduledTasks/index.tssrc/main/presenter/scheduledTasks/normalize.tssrc/main/routes/index.tssrc/renderer/settings/components/ScheduledTasksSettings.vuesrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/de-DE/routes.jsonsrc/renderer/src/i18n/de-DE/settings.jsonsrc/renderer/src/i18n/es-ES/routes.jsonsrc/renderer/src/i18n/es-ES/settings.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/id-ID/routes.jsonsrc/renderer/src/i18n/id-ID/settings.jsonsrc/renderer/src/i18n/it-IT/routes.jsonsrc/renderer/src/i18n/it-IT/settings.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ms-MY/routes.jsonsrc/renderer/src/i18n/ms-MY/settings.jsonsrc/renderer/src/i18n/pl-PL/routes.jsonsrc/renderer/src/i18n/pl-PL/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/tr-TR/routes.jsonsrc/renderer/src/i18n/tr-TR/settings.jsonsrc/renderer/src/i18n/vi-VN/routes.jsonsrc/renderer/src/i18n/vi-VN/settings.jsonsrc/renderer/src/i18n/zh-CN/settings.jsontest/main/presenter/scheduledTasks.test.ts
✅ Files skipped from review due to trivial changes (15)
- src/renderer/src/i18n/de-DE/routes.json
- src/renderer/src/i18n/vi-VN/routes.json
- src/renderer/src/i18n/es-ES/routes.json
- src/renderer/src/i18n/ms-MY/routes.json
- src/renderer/src/i18n/pl-PL/routes.json
- src/renderer/src/i18n/it-IT/settings.json
- src/renderer/src/i18n/da-DK/settings.json
- docs/features/scheduled-tasks/tasks.md
- src/renderer/src/i18n/de-DE/settings.json
- docs/features/scheduled-tasks/plan.md
- src/renderer/src/i18n/ja-JP/settings.json
- src/renderer/src/i18n/ko-KR/settings.json
- src/renderer/src/i18n/zh-CN/settings.json
- src/renderer/src/i18n/id-ID/settings.json
- src/renderer/src/i18n/ru-RU/settings.json
closes #1567
Summary by CodeRabbit
New Features
Bug Fixes
Documentation & Tests