Docs: refresh 1.2.0 changelog; fix webhook host import

This commit is contained in:
Peter Steinberger
2025-11-27 18:46:46 +01:00
parent 8acd82aa0d
commit 0cc732dce3
2 changed files with 7 additions and 11 deletions

View File

@@ -3,15 +3,11 @@
## 1.2.0 — Unreleased
### Changes
- **Fixed crash on WebSocket errors:** Wrapped Baileys `connection.update` event listeners in try-catch to prevent unhandled exceptions from killing the relay process. Added WebSocket-level error handlers and global `unhandledRejection`/`uncaughtException` handlers so the relay logs errors and exits gracefully instead of silently crashing.
- Web relay now supports configurable command heartbeats (`inbound.reply.heartbeatMinutes`, default 10m) that ping Claude with a `HEARTBEAT_OK` sentinel; outbound messages are skipped when the token is returned, and normal/verbose logs record each heartbeat tick.
- New `warelay heartbeat` CLI triggers a one-off heartbeat (web provider, auto-detects logged-in session; optional `--to` override). Relay gains `--heartbeat-now` to fire an immediate heartbeat on startup.
- Added `warelay relay:heartbeat` (no tmux) and `warelay relay:heartbeat:tmux` helpers to start relay with an immediate startup heartbeat.
- Relay now prints the active file log path and level on startup so you can tail logs without attaching.
- Heartbeat CLI accepts `--session-id` to force resuming a specific Claude session; fallback heartbeats skip instead of creating a new session when no stored session exists.
- Heartbeat session handling now supports `inbound.reply.session.heartbeatIdleMinutes` and does not refresh `updatedAt` on skipped heartbeats, so sessions still expire on idle.
- Web inbound now resolves WhatsApp Linked IDs (`@lid`) using Baileys reverse mapping files, so new-format senders are no longer dropped.
- `allowFrom: ["*"]` is honored for auto-replies; manual heartbeats require `--to` or `--all` when multiple sessions exist or the allowlist is wildcard-only.
- **Heartbeat UX:** Default heartbeat interval is now 10 minutes for command mode. Heartbeat prompt is `HEARTBEAT ultrathink`; replies of exactly `HEARTBEAT_OK` suppress outbound messages but still log. Fallback heartbeats no longer start fresh sessions when none exist, and skipped heartbeats do not refresh session `updatedAt` (so idle expiry still works). Session-level `heartbeatIdleMinutes` is supported.
- **Heartbeat tooling:** `warelay heartbeat` accepts `--session-id` to force resume a specific Claude session. Added `--heartbeat-now` to relay startup, plus helper scripts `warelay relay:heartbeat` and `warelay relay:heartbeat:tmux` to fire a heartbeat immediately when the relay launches.
- **Prompt structure for Claude:** Introduced one-time `sessionIntro` (system prompt) with per-message `bodyPrefix` of `ultrathink`, so the full prompt is sent only on the first turn; later turns only prepend `ultrathink`. Session idle extended to 7 days (configurable).
- **Robustness:** Added WebSocket error guards for Baileys sessions; global `unhandledRejection`/`uncaughtException` handlers log and exit cleanly. Web inbound now resolves WhatsApp Linked IDs (`@lid`) using Baileys reverse mapping. Media hosting during Twilio webhooks uses the shared host module and is covered by tests.
- **Docs:** README now highlights the Clawd setup with links, and `docs/claude-config.md` contains the live personal config (home folder, prompts, heartbeat behavior, and session settings).
## 1.1.0 — 2025-11-26

View File

@@ -5,7 +5,7 @@ import express, { type Request, type Response } from "express";
import { getReplyFromConfig, type ReplyPayload } from "../auto-reply/reply.js";
import { type EnvConfig, readEnv } from "../env.js";
import { danger, success } from "../globals.js";
import { ensureMediaHosted } from "../media/host.js";
import * as mediaHost from "../media/host.js";
import { attachMediaRoutes } from "../media/server.js";
import { saveMediaSource } from "../media/store.js";
import { defaultRuntime, type RuntimeEnv } from "../runtime.js";
@@ -92,7 +92,7 @@ export async function startWebhook(
try {
let mediaUrl = replyResult.mediaUrl;
if (mediaUrl && !/^https?:\/\//i.test(mediaUrl)) {
const hosted = await ensureMediaHosted(mediaUrl);
const hosted = await mediaHost.ensureMediaHosted(mediaUrl);
mediaUrl = hosted.url;
}
await client.messages.create({