Skip to content

feat: improve dashboard aggregation and telegram support#38

Open
EZotoff wants to merge 8 commits into
masterfrom
feature/telegram-and-sqlite-cache
Open

feat: improve dashboard aggregation and telegram support#38
EZotoff wants to merge 8 commits into
masterfrom
feature/telegram-and-sqlite-cache

Conversation

@EZotoff
Copy link
Copy Markdown
Owner

@EZotoff EZotoff commented Apr 13, 2026

Summary

  • reuse SQLite-backed ingestion and multi-project aggregation work to reduce redundant dashboard reads and cache session summaries
  • add source management and telegram notification service support, including startup wiring and status exposure
  • refine question-status UI styling and document environment/readme sponsorship links

Copilot AI review requested due to automatic review settings April 13, 2026 22:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves multi-project dashboard aggregation efficiency (SQLite reuse + caching) and adds optional Telegram notification support (startup wiring + status endpoint), alongside minor UI/docs tweaks.

Changes:

  • Rework multi-project aggregation to reuse a shared readonly SQLite connection and cache per-project session summaries/time series.
  • Add a Telegram notification service (pinned status message + alerts) and expose its status via a new API endpoint.
  • Minor UI styling adjustment for “question” status and documentation/environment updates.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/ui/components/ProjectStrip.css Refines “question” status dot styling.
src/types.ts Adds Telegram config/status types.
src/server/telegram.ts Introduces Telegram polling/alerting service implementation.
src/server/start.ts Wires multi-project service + optional Telegram service into prod server startup and API.
src/server/dev.ts Same wiring as prod for dev server; adds idleTimeout.
src/server/multi-project.ts Uses shared SQLite DB + caching to reduce redundant reads; parallelizes git ops.
src/server/dashboard.ts Reuses a single SQLite DB handle across multiple derive calls; closes reliably.
src/server/api.ts Accepts injected multi-project service; adds GET /telegram/status.
src/ingest/storage-backend.ts Adds withDbOrOpen and threads optional pre-opened DB through SQLite readers.
src/ingest/sqlite-derive.ts Threads optional DB through derive helpers; adds multi-session helper functions.
src/ingest/session-inclusion.ts Caches derived status during inclusion/sorting to avoid repeated derivations.
src/tests/api.test.ts Updates API tests to inject a mock multi-project service.
README.md Adds Ko-fi badge link.
.env.example Documents Telegram env vars.

[RISK:medium]

[SCORES]
{"security":4,"safety":3,"performance":4,"featureQuality":3,"confidence":4}
[/SCORES]

[SUMMARY]
Main concerns are the Telegram polling loop potentially running overlapping async polls (state races / extra API calls) and missing test coverage for the new /telegram/status endpoint, plus an inconsistent response shape when Telegram is disabled.
[/SUMMARY]

Comment thread src/server/telegram.ts
Comment on lines +308 to +312
function start(): void {
if (timer !== null) return
poll()
timer = setInterval(poll, pollIntervalMs)
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SEVERITY:warning] [DIM:safety]

start() schedules poll() via setInterval(poll, pollIntervalMs) even though poll() is async. If a poll takes longer than the interval, multiple polls can overlap and race on shared state (and potentially trigger extra Telegram API calls / rate limiting). Add an in-flight guard (e.g., a boolean mutex) or switch to a self-scheduling setTimeout loop that awaits poll() completion before scheduling the next run.

Copilot uses AI. Check for mistakes.
Comment thread src/server/telegram.ts

type TelegramState = {
pinnedMessageId: number | null
prevSessionStatuses: Map<string, SessionStatus>
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SEVERITY:nit] [DIM:featureQuality]

prevSessionStatuses is part of TelegramState but isn’t read anywhere in this module, so it’s dead state. Consider removing it (and the related updater) or using it to drive alerting based on actual status transitions.

Suggested change
prevSessionStatuses: Map<string, SessionStatus>

Copilot uses AI. Check for mistakes.
Comment thread src/server/api.ts
Comment on lines +274 to +277
api.get("/telegram/status", (c) => {
if (!opts.telegramStatus) {
return c.json({ ok: true, telegram: { enabled: false } })
}
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SEVERITY:warning] [DIM:featureQuality]

When Telegram is disabled, this endpoint returns telegram: { enabled: false }, but when enabled it returns a full TelegramServiceStatus. Returning different shapes makes clients harder to type and handle. Consider always returning a full status object (with pinnedMessageId/lastUpdateMs/lastError as null and alertsSent as 0) even when disabled.

Copilot uses AI. Check for mistakes.
Comment thread src/server/api.ts
Comment on lines +274 to +279
api.get("/telegram/status", (c) => {
if (!opts.telegramStatus) {
return c.json({ ok: true, telegram: { enabled: false } })
}
return c.json({ ok: true, telegram: opts.telegramStatus() })
})
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SEVERITY:warning] [DIM:featureQuality]

A new API route (GET /telegram/status) was added, but the API route test suite in src/__tests__/api.test.ts doesn’t cover it. Add tests for both cases (telegramStatus unset → disabled response, and telegramStatus provided → returns status) to keep route coverage consistent.

Copilot generated this review using guidance from repository custom instructions.
…f any-error-in-history

Error status was triggered by any tool part with status 'error' in
recent history, causing recoverable refusals (e.g. 'read file before
editing') to persist as Error state. Now only the most recent terminal
tool event (error or completed) determines error status.

Also fixes session-inclusion.ts SQL queries that referenced non-existent
columns (state_status, tool) instead of using json_extract on the data
JSON column.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants