mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-19 22:20:46 +08:00
feat(scheduler): add scheduled jobs with channel-aware delivery
Introduce persisted cron/interval jobs, gateway scheduler loop, worker turns, and admin CRUD/edit UI. Route proactive reminders via the originating chat channel (WhatsApp vs WeChat), harden Weixin outbound with durable queue and PG-compatible polling, and fix chat UI to show each scheduled reminder separately. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
5336f8835f
commit
47813f6a94
45 changed files with 4956 additions and 43 deletions
80
assistant_migrations/versions/002_scheduled_jobs.py
Normal file
80
assistant_migrations/versions/002_scheduled_jobs.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
"""Add scheduled_job tables for PostgreSQL deployments."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy import text
|
||||
|
||||
revision = "002_scheduled_jobs"
|
||||
down_revision = "001_assistant_pg_initial"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
if bind.dialect.name != "postgresql":
|
||||
return
|
||||
op.execute(
|
||||
text(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS scheduled_job (
|
||||
id TEXT PRIMARY KEY,
|
||||
tenant_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
schedule_kind TEXT NOT NULL,
|
||||
schedule_expr TEXT NOT NULL,
|
||||
timezone TEXT NOT NULL DEFAULT 'Asia/Shanghai',
|
||||
prompt_text TEXT NOT NULL,
|
||||
interaction_mode TEXT NOT NULL DEFAULT 'expert',
|
||||
specialist TEXT NOT NULL DEFAULT 'generalist',
|
||||
lang TEXT NOT NULL DEFAULT 'zh',
|
||||
delivery_json TEXT NOT NULL DEFAULT '{}',
|
||||
source_session_id TEXT,
|
||||
created_by_user_id TEXT NOT NULL DEFAULT '',
|
||||
source TEXT NOT NULL DEFAULT 'admin',
|
||||
next_run_at TEXT,
|
||||
last_run_at TEXT,
|
||||
last_run_status TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
op.execute(text("CREATE INDEX IF NOT EXISTS idx_scheduled_job_due ON scheduled_job(status, next_run_at)"))
|
||||
op.execute(
|
||||
text(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS scheduled_job_run (
|
||||
id TEXT PRIMARY KEY,
|
||||
job_id TEXT NOT NULL REFERENCES scheduled_job(id) ON DELETE CASCADE,
|
||||
tenant_id TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
scheduled_at TEXT NOT NULL,
|
||||
started_at TEXT,
|
||||
finished_at TEXT,
|
||||
session_id TEXT,
|
||||
oclaw_task_id TEXT,
|
||||
run_id TEXT,
|
||||
reply_text TEXT NOT NULL DEFAULT '',
|
||||
delivery_status_json TEXT NOT NULL DEFAULT '{}',
|
||||
error TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
op.execute(
|
||||
text("CREATE INDEX IF NOT EXISTS idx_scheduled_job_run_job ON scheduled_job_run(job_id, created_at DESC)")
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
if bind.dialect.name != "postgresql":
|
||||
return
|
||||
op.execute(text("DROP TABLE IF EXISTS scheduled_job_run"))
|
||||
op.execute(text("DROP TABLE IF EXISTS scheduled_job"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue