Skip to content

Feature/heartbeat#460

Closed
zbinxp wants to merge 16 commits into
HKUDS:devfrom
zbinxp:feature/heartbeat
Closed

Feature/heartbeat#460
zbinxp wants to merge 16 commits into
HKUDS:devfrom
zbinxp:feature/heartbeat

Conversation

@zbinxp

@zbinxp zbinxp commented May 8, 2026

Copy link
Copy Markdown
Contributor

Description

Problems Solved

  1. Wasted LLM calls: LLM was invoked even when HEARTBEAT.md had no active tasks
  2. Interval not configurable: hardcoded 30 minutes, no way to adjust dynamically
  3. Config lost on restart: editing config.yaml had no effect after service restart
  4. Logs lack bot identity: impossible to distinguish which bot a log line belongs to

Changes

HeartbeatService (deeptutor/tutorbot/heartbeat/service.py)

  • New _has_active_tasks(): parses ## Active Tasks section of HEARTBEAT.md, skips LLM when no real task content (excluding comments/headers/blank lines)
  • New bot_id field, all logs prefixed with (bot=xxx)
  • Constructor accepts bot_id parameter

TutorBotManager (deeptutor/services/tutorbot/manager.py)

  • BotConfig add heartbeat_interval_s: int = 1800 (default 30 min)
  • load_bot_config / save_bot_config / auto_start_bots read/write this field
  • New reload_heartbeat(bot_id) hot-update method — changes to config.yaml take effect immediately

Related Issues

Module(s) Affected

  • agents
  • api
  • config
  • core
  • knowledge
  • logging
  • services
  • tools
  • utils
  • web (Frontend)
  • docs (Documentation)
  • scripts
  • tests
  • Other: ...

Checklist

  • I have read and followed the contribution guidelines.
  • My code follows the project's coding standards.
  • I have run pre-commit run --all-files and fixed any issues.
  • I have added relevant tests for my changes.
  • I have updated the documentation (if necessary).
  • My changes do not introduce any new security vulnerabilities.

Additional Notes

Add any other context or screenshots about the pull request here.

zbinxp and others added 8 commits May 8, 2026 12:13
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reduce LLM calls by:
- Skipping LLM when HEARTBEAT.md mtime+content unchanged
- Doubling interval after consecutive skips (up to 4x base)
- Making interval configurable via BotConfig.heartbeat_interval_s

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add heartbeat_interval_s to BotConfig load/save so it's configurable
  via bot config.yaml instead of hardcoded
- Downgrade adaptive interval logs from info to debug
- Add old->new interval values to reset/extend log messages
- Add UTC timestamp to ConsoleFormatter output

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…heartbeat

- Add _has_active_tasks() to locally parse HEARTBEAT.md and skip LLM
  when no real task content exists under ## Active Tasks
- Remove content-change / mtime / staleness detection (not needed)
- Persist heartbeat_interval_s to config.yaml and reload via
  reload_heartbeat() without restart
- Downgrade adaptive interval logs to debug level

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Keep only: configurable interval via heartbeat_interval_s config,
active-tasks pre-check to skip LLM when no real tasks exist.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…terval_s

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cover _has_active_tasks parsing, heartbeat_interval_s config roundtrip,
and reload_heartbeat hot-update.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@zbinxp

zbinxp commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

smoke tests failed for some tests not touched in this feature

ERROR tests/api/test_notebook_router.py::test_list_entries_empty - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_quiz_results_populates_notebook - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_quiz_results_upserts_on_retry - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_bookmark_toggle - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_delete_entry - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_category_crud_and_association - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'
ERROR tests/api/test_notebook_router.py::test_lookup_entry_by_question - AttributeError: 'module' object at deeptutor.api.routers.sessions has no attribute 'get_sqlite_session_store'

zbinxp and others added 3 commits May 8, 2026 22:04
… tests

The tests were patching only PathService._instance but SQLiteSessionStore
calls get_path_service() which delegates to get_current_path_service().
That function uses a separate _path_services cache keyed by
user.scope.cache_key, creating a second distinct PathService instance
that wasn't being patched.

Fix by:
- Patching PathService._instance to the service being modified
- Clearing _path_services cache
- Pre-registering the patched service at the real admin scope cache key

This ensures both the singleton and the multi-user cache resolve to the
same patched PathService, so get_path_service() returns the patched path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ensures PRs and pushes on feature/heartbeat trigger the full CI pipeline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
question_notebook uses get_sqlite_session_store (imported from
services.session module), while sessions uses get_session_store.
The fixture was patching the wrong symbols causing AttributeError
at test setup.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@zbinxp zbinxp marked this pull request as draft May 8, 2026 14:15
@zbinxp zbinxp marked this pull request as ready for review May 9, 2026 02:17
@zbinxp zbinxp closed this May 11, 2026
@zbinxp zbinxp deleted the feature/heartbeat branch May 11, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants