diff --git a/docs/clawd.md b/docs/clawd.md index 426129fd0..5380d1134 100644 --- a/docs/clawd.md +++ b/docs/clawd.md @@ -117,7 +117,7 @@ This is the actual config running on @steipete's Mac (`~/.warelay/warelay.json`) Peter trusts you with a lot of power. Don't betray that trust.`, command: [ "claude", - "--model", "claude-opus-4-5-20251101", // or claude-sonnet-4-5 for faster/cheaper + "--model", "claude-opus-4-5-20251101", // or claude-sonnet-4-5-20250929 for faster/cheaper "-p", "--output-format", "json", "--dangerously-skip-permissions", // lets Claude run commands freely diff --git a/src/auto-reply/types.ts b/src/auto-reply/types.ts index 145beb98e..65d54518a 100644 --- a/src/auto-reply/types.ts +++ b/src/auto-reply/types.ts @@ -1,5 +1,5 @@ export type GetReplyOptions = { - onReplyStart?: () => Promise | void; + onReplyStart?: () => Promise | void; }; export type ReplyPayload = { diff --git a/src/twilio/typing.ts b/src/twilio/typing.ts index adf234fa7..60f74c2ba 100644 --- a/src/twilio/typing.ts +++ b/src/twilio/typing.ts @@ -14,18 +14,26 @@ type TwilioRequester = { request: (options: TwilioRequestOptions) => Promise; }; +export type TypingIndicatorResult = { + sent: boolean; + response?: unknown; + error?: unknown; +}; + export async function sendTypingIndicator( client: TwilioRequester, runtime: RuntimeEnv, messageSid?: string, -) { +): Promise { // Best-effort WhatsApp typing indicator (public beta as of Nov 2025). + // Note: This API also marks the referenced message as read automatically. + // The typing indicator disappears after 25 seconds or when a response is sent. if (!messageSid) { logVerbose("Skipping typing indicator: missing MessageSid"); - return; + return { sent: false }; } try { - await client.request({ + const response = await client.request({ method: "post", uri: "https://messaging.twilio.com/v2/Indicators/Typing.json", form: { @@ -33,11 +41,21 @@ export async function sendTypingIndicator( channel: "whatsapp", }, }); - logVerbose(`Sent typing indicator for inbound ${messageSid}`); + logVerbose( + `Sent typing indicator for inbound ${messageSid} (response: ${JSON.stringify(response)})`, + ); + return { sent: true, response }; } catch (err) { - if (isVerbose()) { - runtime.error(warn("Typing indicator failed (continuing without it)")); - runtime.error(err as Error); + // Always log typing indicator failures (not just in verbose mode) since + // this helps diagnose why read receipts/typing aren't working. + const errorMsg = + err instanceof Error ? err.message : JSON.stringify(err, null, 2); + runtime.error( + warn(`Typing indicator failed for ${messageSid}: ${errorMsg}`), + ); + if (isVerbose() && err instanceof Error && err.stack) { + runtime.error(err.stack); } + return { sent: false, error: err }; } }