odysseus/src
pewdiepie-archdaemon 35ed7cbdf1 Cookbook scheduler: calendar events drive model serve windows (experimental, feature-flagged)
Add a calendar-driven scheduler so a user can pick a model in Cookbook, click "Schedule…" instead of "Launch", choose time windows + days of the week + (optional) end date, and have Odysseus auto-launch the serve when the window starts and hard-kill it when the window ends. The calendar IS the source of truth — events on a designated calendar are interpreted as serve schedules, so editing the event in the calendar UI immediately changes the schedule.

Whole feature is gated by setting `cookbook_scheduler_enabled` (default False). Disabling the setting silences the reconciler and the API refuses requests; setting + three new files = entire surface, easy to revert.

New files:
  - src/cookbook_scheduler.py — background reconciler: ticks every 60s, reads next ±90s of calendar events on the designated calendar, launches/kills serves to match. Honors "refuse if GPUs busy" (skips with reason, no retry). Adopts pre-existing manual serves matching the event's model so window-end cleanup still applies. Tags scheduler-owned tasks with `_scheduledBy: <event_uid>` so it never kills serves it doesn't own.
  - routes/cookbook_schedule_routes.py — POST /api/cookbook/schedule/from-cookbook builds RRULE+ICS events from the modal's input (model, slots[], days[], until). GET /upcoming returns the next 24h with per-event status (scheduled / running / adopted / skipped / failed / ended) for the UI. POST /reconcile-now manually kicks the reconciler.
  - static/js/cookbookSchedule.js — Schedule button click handler + modal. Daily/hourly time slot picker, multi-slot ("+ add another time slot"), weekday chips with Weekdays/Weekend/Every-day quicksets, optional Until date. Calls /from-cookbook on save. Whole module is a single IIFE; deleting the file plus its <script> tag removes the UI surface.

Existing files touched (minimal):
  - app.py: register the new router + add the reconcile loop as a startup task (~10 lines, all in one block). Reconcile loop checks the feature flag on every tick, so leaving it running with the flag off costs ~one settings lookup per minute.
  - static/index.html: one new <script> tag for cookbookSchedule.js.
  - static/js/cookbookServe.js: add a "Schedule…" button next to the existing Launch button. Hidden by default; cookbookSchedule.js reveals it after confirming the feature flag is on.
  - static/style.css: ~80 lines for the modal styles (mobile-aware via @media).

User choices baked in:
  - Calendar events are the source of truth.
  - Refuse to launch if GPUs busy (skip + log reason in scheduler.events[uid].reason).
  - Hard kill at event end.
  - No retry on a skipped event within the window.
  - Multi-slot per day supported (one calendar event per slot, shared RRULE).
  - Pre-existing manual serves get adopted at window start so they're killed at end.

Known follow-ups (not in this commit):
  - Settings UI to pick the schedule calendar + toggle the feature flag.
  - Calendar event color/badge for status (running/skipped/failed).
  - "Lazy launch on first request" — currently launches at event start. Replacing _launch_serve with a proxy that defers vllm until the first chat request is a contained future change.
2026-06-05 02:35:23 +09:00
..
search fix(search): align content URL guards 2026-06-04 00:34:06 +01:00
action_intents.py Anchor shell-verb intent patterns to imperative or can-you position (#1664) 2026-06-03 14:23:10 +09:00
agent_loop.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
agent_runs.py Handle incomplete detached agent streams 2026-06-01 16:54:11 +09:00
agent_tools.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
ai_interaction.py fix(ai): scope tool model resolution by owner 2026-06-04 00:37:28 +01:00
api_key_manager.py Stop API key save() from writing other providers' keys as plaintext (#1944) 2026-06-04 04:47:13 +01:00
app_helpers.py fix: inside_base_dir raises TypeError on a non-string path instead of failing closed (#1619) 2026-06-03 09:00:04 +09:00
app_initializer.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
assistant_log.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
auth_helpers.py fix: require_privilege 500s on a non-dict privileges blob from auth.json (#1693) 2026-06-03 13:37:54 +09:00
bg_jobs.py Ignore invalid background job store rows (#1261) 2026-06-03 14:07:14 +09:00
bg_monitor.py Ignore non-string background stream deltas (#1549) 2026-06-03 14:11:45 +09:00
builtin_actions.py feat: Claude Agent integration + cookbook reconnect + UI polish 2026-06-04 08:27:26 +09:00
builtin_mcp.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
caldav_sync.py fix(calendar): scope CalDAV event lookup by calendar 2026-06-04 04:01:21 +01:00
caldav_writeback.py Decrypt CalDAV password before write-back (#1731) 2026-06-03 11:36:12 +09:00
chat_handler.py Use LM Studio-reported vision capability for image passthrough (#1130) 2026-06-02 23:01:04 +09:00
chat_helpers.py fix(vision): recognize Gemma 4 and Phi-4 as vision-capable models (#1704) 2026-06-03 13:36:50 +09:00
chat_processor.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
chroma_client.py fix: ChromaDB unreachable blocks app startup for 30-60s (#326) (#476) 2026-06-01 22:22:41 +09:00
cleanup_service.py Replace cleanup service datetime.utcnow calls (#1494) 2026-06-03 14:14:27 +09:00
config.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
constants.py Align SearXNG fallback URL 2026-06-01 10:50:07 +09:00
context_budget.py feat: adapt agent_input_token_budget to the model context window (#1170) (#1230) 2026-06-03 00:13:53 +09:00
context_compactor.py fix: context_compactor token helpers crash on non-string message text (#1634) 2026-06-03 14:12:14 +09:00
cookbook_scheduler.py Cookbook scheduler: calendar events drive model serve windows (experimental, feature-flagged) 2026-06-05 02:35:23 +09:00
database.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
deep_research.py fix: deep research runs the prompt's example queries when the model echoes them (#1666) 2026-06-03 14:23:07 +09:00
document_actions.py fix: document tidy crashes on a duplicate with NULL timestamps (#1772) 2026-06-03 13:23:01 +09:00
document_processor.py fix: treat Nix files as readable uploads (#2249) 2026-06-04 12:06:24 +02:00
email_thread_parser.py Ignore non-string email thread bodies (#1654) 2026-06-03 14:06:31 +09:00
embeddings.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
endpoint_resolver.py fix(endpoint): import ModelEndpoint from core database 2026-06-04 11:51:47 +01:00
event_bus.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
exceptions.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
goal_based_extractor.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
integrations.py Ignore invalid integration rows (#1404) 2026-06-03 14:07:11 +09:00
llm_core.py fix(models): stabilize proxy endpoint refresh behavior 2026-06-04 04:56:11 +01:00
markitdown_runtime.py fix: is_markitdown_format crashes on a non-string path (#1618) 2026-06-03 09:00:10 +09:00
mcp_manager.py fix: close AsyncExitStack on MCP init/tool-discovery failure (#1493) 2026-06-03 14:23:46 +09:00
memory.py refactor(memory): canonicalize memory imports (#50) 2026-06-04 05:31:15 +01:00
memory_vector.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
model_context.py fix(models): stabilize proxy endpoint refresh behavior 2026-06-04 04:56:11 +01:00
model_discovery.py Reject invalid Tailscale discovery JSON (#1556) 2026-06-03 14:11:31 +09:00
pdf_form_doc.py fix(forms): keep PDF-form export from dropping values when the label has '*' (#1407) 2026-06-03 14:24:07 +09:00
pdf_forms.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
pdf_runtime.py Show a clear message when PyMuPDF is missing 2026-06-01 18:27:17 +09:00
personal_docs.py Skip malformed personal keyword index rows 2026-06-03 13:42:05 +09:00
preset_manager.py Fall back from invalid preset stores (#1402) 2026-06-03 14:12:31 +09:00
prompt_security.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
rag_manager.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
rag_singleton.py Re-enable VectorRAG init with lazy retry 2026-06-01 14:32:13 +09:00
rag_vector.py fix: RAG keyword fallback leaked owner-less documents across users (#1722) 2026-06-03 13:31:33 +09:00
rate_limiter.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
readiness.py feat: add /api/ready readiness probe (DB, data dir, local-first) (#1200) 2026-06-02 23:33:22 +09:00
request_models.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
research_handler.py fix: research source extraction crashes on a non-dict finding (#1714) 2026-06-03 13:34:40 +09:00
research_utils.py Treat non-string research summaries as low quality 2026-06-03 13:42:24 +09:00
secret_storage.py Add native Windows compatibility layer 2026-06-01 15:09:47 +09:00
session_actions.py Odysseus v1.0 2026-05-31 23:58:26 +09:00
settings.py fix(settings): catch PermissionError in load_settings + error-path tests (#1570) 2026-06-03 14:23:27 +09:00
settings_scrub.py Ignore non-object settings scrub inputs (#1645) 2026-06-03 14:11:05 +09:00
task_endpoint.py Harden session endpoint owner scope (#1308) 2026-06-03 02:40:22 +09:00
task_scheduler.py feat: Claude Agent integration + cookbook reconnect + UI polish 2026-06-04 08:27:26 +09:00
teacher_escalation.py fix: evaluate_turn_regex crashes on a non-string agent_reply (#1723) 2026-06-03 13:31:26 +09:00
text_helpers.py fix: _strip_reasoning_prose discards the answer when reasoning trails it (#1643) 2026-06-03 14:23:15 +09:00
tool_execution.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
tool_implementations.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
tool_index.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
tool_parsing.py fix: tool-block parsing crashes on a non-string input (#1628) 2026-06-03 08:59:42 +09:00
tool_schemas.py cookbook agent debug loop: persistent log files, auto-adopt orphan tmux, Codex/Claude skill parity 2026-06-04 23:27:18 +09:00
tool_security.py fix: is_public_blocked_tool crashes on a truthy non-string tool name (#1620) 2026-06-03 14:11:14 +09:00
topic_analyzer.py Topics: hydrate session history before analysis 2026-06-02 20:44:27 +09:00
upload_handler.py fix: treat Nix files as readable uploads (#2249) 2026-06-04 12:06:24 +02:00
upload_limits.py fix(uploads): bound direct upload reads 2026-06-04 00:32:50 +01:00
url_safety.py fix: check_outbound_url crashes on a truthy non-string URL (#1623) 2026-06-03 08:59:49 +09:00
url_security.py Reapply "Merge branch 'main' of github.com:pewdiepie-archdaemon/odysseus" 2026-06-03 22:47:00 +09:00
visual_report.py fix: visual report drops photos whose URL slug contains icon or logo (#1685) 2026-06-03 14:22:45 +09:00
webhook_manager.py Replace webhook manager datetime.utcnow calls (#1499) 2026-06-03 14:14:23 +09:00
youtube_handler.py fix: youtube transcript formatter crashes on a non-dict segment (#1745) 2026-06-03 13:29:08 +09:00