Repository navigation
Conversation
Adds a minimal built-in plugin (opencode.schedule) that registers `/schedule <30s|15m|2h> <prompt>` and `/schedule off`. Each schedule is saved in plugin storage keyed by session ID and re-queues the prompt with delivery "queue" on a fixed interval, modeled on the warming plugin loop. When a location loads, the plugin restarts only schedules whose session belongs to that location, so a session is never double-scheduled. Known gaps (prototype): schedules resume after a server restart only once something loads the session's location, and intervals longer than the 60-minute location inactivity TTL stop when the location is evicted. Verified: core typecheck passes; against an isolated `serve` instance, a 5s schedule admitted prompts every 5s, stopped across a restart, and resumed after the session's location was reloaded by a manual prompt.
Moves schedule timers out of the per-Location plugin into a new global SessionSchedule service. Previously timers lived in the Location's plugin scope, so they stopped on server restart until something reloaded the Location, and stopped whenever the Location was evicted after 60 minutes of inactivity. Timers now live in the global service and call Session.prompt, which loads the Location on demand, so schedules fire even when the session is not open. - SessionSchedule persists entries in KV (session.schedule/<id>) and exposes set/remove/resume. A deleted session ends its schedule. - The managed server calls resume at boot next to restart continuity; unmanaged servers sharing the database do not restore schedules. - The opencode.schedule plugin now only registers /schedule and delegates to the service; the per-Location restore logic is removed. Verified: core and server typecheck; against an isolated managed-mode server, a 5s schedule fired every 5s, resumed after a restart with no client touching the session, and `/schedule off` stopped the boot-restored timer. Server tests: 3 OpenAI OAuth port tests fail identically without this change.
Prettier wrapped the long catchCause line; no behavior change.
Adds schedule_create, schedule_list and schedule_cancel tools in the opencode namespace so the agent can schedule prompts back into its own session. schedule_create accepts `every` (30s/15m/2h/1d), `at` (ISO 8601 with offset) for a single run, or both (`at` sets the first run). SessionSchedule now stores multiple schedules per session, keyed by a new `sch_` ID, and persists the absolute next fire time instead of only the interval. This replaces the one-schedule-per-session model and fixes restarts resetting the countdown: one-shots fire at their original time after a restart, and overdue recurring schedules fire once then resume their cadence rather than bursting. `/schedule off` now cancels every schedule in the session. Past `at` times, missing timing and invalid intervals return tool errors. Verified with an isolated managed-mode server and a scripted OpenAI-compatible mock model driving `execute`: create every 5s fired every 5s; `at` fired at 15:55:42.013 for a 15:55:42 target; a one-shot created before a restart fired on time after it (15:56:23.013); list returned both schedules with server time; cancel stopped firing; invalid inputs returned the three expected errors. core and server typecheck.
|
This covers my use case. When a Claude subscription window runs out, I want to queue a prompt in the same session for the reset time instead of coming back to type it. Is anything blocking this from leaving draft? I'm happy to test it. It could also be the resume step for #43126. |
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
None yet. Draft prototype for discussion.
Type of change
What does this PR do?
Lets the agent (and the user) schedule prompts back into a session, so a session can act as a background job: recurring checks ("every 15m") or a single run at an absolute time.
Agent tools (
opencodenamespace, next tosession_rename):schedule_create({ prompt, every?, at? }):everyis30s/15m/2h/1d, andatis an ISO 8601 timestamp with offset. Passatalone for a one-shot,everyalone to start one interval from now, or both to set the first run and then repeat.schedule_list()returns the session's schedules plus the current server time, so the model can sanity-check absolute times.schedule_cancel({ id })only cancels schedules in the calling session.User command:
/schedule 15m <prompt>and/schedule off(cancels all in the session).How it runs
SessionSchedule(packages/core/src/session/schedule.ts) is a global service. Each schedule (sch_…ID) is stored in KV with its absolute next fire time, and the service runs a timer that callsSession.promptwithdelivery: "queue".resumeat boot next to restart continuity. One-shots fire at their original time after a restart. An overdue recurring schedule fires once, then continues its cadence instead of bursting. Unmanaged servers sharing the database don't restore schedules.Not included, to keep this minimal: no approval gate or minimum interval, and no cron expressions.
How did you verify your code works?
core/servertypecheck and pre-pushbun run checkpass. End-to-end against an isolated managed-mode server (separate XDG dirs and DB), with a scripted OpenAI-compatible mock model calling the tools throughexecute:schedule_create({ every: "5s" })produced prompts every 5s.schedule_create({ at })fired once, at 15:55:42.013 for a 15:55:42 target.schedule_listreturned both schedules and server time;schedule_cancelstopped firing.at, missing timing, and an invalid interval each returned a clear tool error.packages/servertests: 3 OpenAI OAuth callback-port tests fail, identically on the base commit without this change.Screenshots / recordings
N/A (no UI change).
Checklist