Skip to content

feat(kiloclaw): deliver morning briefing to configured channels#2813

Open
joshavant wants to merge 17 commits intomainfrom
feat/morning-briefing-channel-delivery
Open

feat(kiloclaw): deliver morning briefing to configured channels#2813
joshavant wants to merge 17 commits intomainfrom
feat/morning-briefing-channel-delivery

Conversation

@joshavant
Copy link
Copy Markdown
Contributor

@joshavant joshavant commented Apr 25, 2026

Summary

  • Deliver Morning Briefing runs to configured Telegram/Discord/Slack channels after report generation, while keeping generation success independent from delivery outcomes and persisting per-channel delivery metadata.
  • Add deterministic target resolution with safe fallbacks (single-candidate channel config auto-targeting), timeout/retry hardening, and warmup-aware API/UI behavior to prevent transient disabled-state flaps during boot.
  • Refactor delivery internals into dedicated modules, improve report/message formatting (trim verbose web snippets, simplify Failures section), and polish dashboard presentation (icon, aligned metadata, provider-friendly delivery labels).

Verification

  • Verified in development by triggering Run Now from the dashboard across boot/warmup transitions and confirming no transient incorrect "Disabled" state is shown before settling.
  • Verified report generation succeeds and persists markdown even when delivery fails, and delivery outcomes are shown in the UI via "Last delivery" once settled.
  • Verified Telegram delivery on a real dev instance after redeploy with timeout/retry hardening, including fallback routing from configured channel targets.

Visual Changes

Screenshot 2026-04-24 at 11 39 44 PM

Reviewer Notes

  • A final formatting-only commit (style(web): apply formatting for morning briefing UI) was added to satisfy pre-push hooks.
  • Untracked local planning document .plans/morning-briefing-channel-delivery.md is intentionally not included in this PR.

Send generated briefings to configured Telegram, Discord, and Slack routes with channel-friendly formatting and delivery status reporting so users can receive briefings where they work. Add robust routing, timeout/retry hardening, and run-path warmup handling so generation success is decoupled from delivery flakiness.
Split command and channel-delivery concerns into dedicated modules, tighten timeout retry semantics, and reuse shared UI typing to reduce schema drift. Add cron JSON compatibility fallback to avoid controller/runtime option skew.
Render morning briefing delivery failures with reason-only text in Settings so stored command errors remain available for diagnostics without leaking message content in the dashboard.
Treat gateway and briefing readiness as boot-session fresh data to avoid stale Disabled flaps, and clear cached gateway/morning-briefing queries on start, provision, and restarts so controls remain in warmup state until current boot data arrives.
Stop emitting synthetic enabled=false during morning-briefing warmup and treat gateway_warming_up as authoritative in the dashboard card. Keep warmup badge styling and delivery visibility gated until status fields are resolved to prevent transient Disabled and Last delivery flaps.
Move Last delivery beneath Last generated, render channel/status labels with user-friendly capitalization, and top-align action buttons so the card layout stays consistent as metadata lines appear.
Add a topical Morning Briefing icon, keep delivery labels user-friendly and capitalized, and place the source summary in the same content column so metadata lines share a consistent leading edge.
Render Morning Briefing Last delivery entries as provider-first labels with status in parentheses while keeping the bullet delimiter for readability.
Rename the report heading to Failures and keep the section omitted when no failures exist so the daily briefing body stays concise and focused.
}

function convertInlineMarkdownToText(line: string): string {
const withLinksExpanded = line.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1 - $2');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WARNING: Markdown link conversion breaks valid URLs containing )

formatBriefingMarkdownForMessage() expands links with \[([^\]]+)\]\(([^)]+)\), which stops at the first closing parenthesis. Any briefing item whose URL includes ) (common in docs and wiki links) will be truncated before delivery, so the channel message contains a broken target even though the saved markdown is correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 4e845d2e7. Replaced regex-only link expansion with a balanced-parentheses parser in briefing-utils.ts and added regression coverage in briefing-utils.test.ts for URLs containing nested ) so channel messages preserve full links.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Apr 25, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

No new issues in the incremental diff.

Fix these issues in Kilo Cloud

Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
services/kiloclaw/plugins/kiloclaw-morning-briefing/src/index.ts 708 collectLinear() sets cwd to <stateDir>/workspace without creating that directory, so fresh instances can fail Linear collection with ENOENT.
Files Reviewed (3 files)
  • services/kiloclaw/plugins/kiloclaw-morning-briefing/src/delivery-utils.ts - 0 issues
  • services/kiloclaw/src/durable-objects/gateway-controller-types.ts - 0 issues
  • services/kiloclaw/src/durable-objects/morning-briefing-delivery-constants.ts - 0 issues

Reviewed by gpt-5.4-20260305 · 814,836 tokens

Replace regex-only markdown link expansion with a balanced-parentheses parser so channel messages keep full URLs when links contain nested parentheses.
Use endpoint-specific warmup retry policy so morning-briefing run no longer retries timeout errors that can overlap in-flight runs and duplicate sends. Return a dedicated run-timeout response code for clients.
Extract morning briefing card state derivation and add regression coverage for stale enabled values plus gateway_warming_up payloads so the card stays in warmup state instead of flashing Disabled.
Store concise delivery failure details instead of full command text to reduce sensitive payload exposure while preserving operator diagnostics. Update lifecycle assertions to match sanitized error persistence.
Rename timeout test semantics, add focused delivery-utils unit coverage, and emit structured delivery outcome events for sent/skipped/failed paths. Include latest Morning Briefing warmup/source-summary alignment tweak in the same push-ready set.
@joshavant joshavant enabled auto-merge (squash) April 25, 2026 05:50
Comment on lines +107 to +114
const DELIVERY_CHANNELS = ['telegram', 'discord', 'slack'] as const;
const DELIVERY_STATUSES = ['sent', 'skipped', 'failed'] as const;
const DELIVERY_REASONS = [
'missing_target',
'ambiguous_target',
'send_failed',
'config_unavailable',
] as const;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be good if we didn't have to duplicate these here and in services/kiloclaw/plugins/kiloclaw-morning-briefing/src/delivery-utils.ts

@jeanduplessis jeanduplessis disabled auto-merge April 25, 2026 05:57
Extract delivery channel/status/reason enums into a shared module and reuse them in gateway response schemas and plugin delivery utilities to prevent drift.
@joshavant joshavant force-pushed the feat/morning-briefing-channel-delivery branch from 4c0a8ce to 384cc0d Compare April 25, 2026 06:51
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