Commit Graph

239 Commits

Author SHA1 Message Date
Peter Steinberger
ae0d35c727 Auto-reply: add verbose session hint 2025-12-03 09:07:17 +00:00
Peter Steinberger
086dd284d6 Auto-reply: add /verbose directives and tool result replies 2025-12-03 09:04:37 +00:00
Peter Steinberger
8ba35a2dc3 Auto-reply: treat prefixed think directives as directive-only 2025-12-03 08:57:30 +00:00
Peter Steinberger
48dfb1c8ca Auto-reply: ack think directives 2025-12-03 08:54:38 +00:00
Peter Steinberger
58520859e5 Auto-reply: add thinking directives 2025-12-03 08:45:23 +00:00
Peter Steinberger
c4b0155cc2 Format: align thinking helpers 2025-12-03 01:02:10 +00:00
Peter Steinberger
38b18202fc Heartbeat: guard optional heartbeatCommand 2025-12-03 00:45:27 +00:00
Peter Steinberger
0f17a7d828 Heartbeat: normalize reply arrays for twilio/web 2025-12-03 00:43:28 +00:00
Peter Steinberger
9da5b9f4bb Heartbeat: normalize array replies 2025-12-03 00:40:19 +00:00
Peter Steinberger
a7fdc7b992 Auto-reply: allow array payloads in signature 2025-12-03 00:35:57 +00:00
Peter Steinberger
f519e22e6d CI: fix command-reply payload typing 2025-12-03 00:33:58 +00:00
Peter Steinberger
ecac4dd72a Auto-reply: format and lint fixes 2025-12-03 00:30:05 +00:00
Peter Steinberger
b6c45485bc Auto-reply: smarter chunking breaks 2025-12-03 00:25:01 +00:00
Peter Steinberger
ec46932259 web: handle multi-payload replies 2025-12-02 23:46:11 +00:00
Peter Steinberger
10182f1182 limits: chunk replies for twilio/web 2025-12-02 23:10:16 +00:00
Peter Steinberger
cfaec9d608 auto-reply: support multi-text RPC outputs 2025-12-02 23:03:55 +00:00
Peter Steinberger
0f6157a49d logging: emit agent/session meta at command start 2025-12-02 21:30:28 +00:00
Peter Steinberger
1df6373cb1 revert: mark system prompt sent on first turn 2025-12-02 21:23:56 +00:00
Peter Steinberger
96722bba08 ci: fix lint and tau rpc typing 2025-12-02 21:12:51 +00:00
Peter Steinberger
4e20a20927 fix(media): clean up files after response finishes 2025-12-02 21:10:18 +00:00
Peter Steinberger
a0d1004909 test(media): add redirect coverage and update changelog 2025-12-02 21:09:26 +00:00
Peter Steinberger
2018c90ae2 chore: tidy claude prompt and drop npm lock 2025-12-02 21:07:37 +00:00
Joao Lisboa
793360c5bb style: fix biome formatting 2025-12-02 21:07:13 +00:00
Joao Lisboa
d8b1a38350 style: fix biome lint errors 2025-12-02 21:07:13 +00:00
Joao Lisboa
499a3e3227 style: fix biome formatting 2025-12-02 21:07:13 +00:00
Joao Lisboa
73a9fdca2a fix: send Claude identity prefix on first session message
The systemSent variable was being set to true before being passed to
runCommandReply, causing the identity prefix to never be injected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:07:13 +00:00
Joao Lisboa
06dd9b8ed8 fix: follow redirects when downloading Twilio media
node:https request() doesn't follow redirects by default, causing
Twilio media URLs (which 302 to CDN) to save placeholder/metadata
instead of actual images.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:07:13 +00:00
Joao Lisboa
a86cb932cf chore: user-agnostic Claude identity and tests
- Use ~/Clawd instead of hardcoded /Users/steipete/clawd
- Add MEDIA: syntax instructions to identity prefix
- Update tests to check for 'scratchpad' instead of specific path

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:07:13 +00:00
Joao Lisboa
2fae0a9f47 fix: media serving and id consistency
- server.ts: Replace sendFile with manual readFile+send to fix
  NotFoundError when serving media (sendFile failed even after stat)
- store.ts: Return id with file extension so it matches actual filename

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:07:13 +00:00
Joao Lisboa
2ec9192010 fix: use export type for type-only re-exports
Fixes build error with isolatedModules.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:06:27 +00:00
Peter Steinberger
b172b538fc perf(pi): reuse tau rpc for command auto-replies 2025-12-02 20:09:51 +00:00
Peter Steinberger
2cf134668c fix(media): block symlink traversal 2025-12-02 18:37:15 +00:00
Joao Lisboa
b94b220156 Fix path traversal vulnerability in media server
The /media/:id endpoint was vulnerable to path traversal attacks.
Since this endpoint is exposed via Tailscale Funnel (unlike the
WhatsApp webhook which requires Twilio signature validation),
attackers could directly request paths like /media/%2e%2e%2fwarelay.json
to access sensitive files in ~/.warelay/ (e.g. warelay.json), or even
escape further to the user's home directory via multiple ../ sequences.

Fix: validate resolved paths stay within the media directory.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 19:33:21 +01:00
Peter Steinberger
26921cbe68 chore(logs): rotate daily and prune after 24h 2025-12-02 17:11:43 +00:00
Peter Steinberger
8844674825 chore(security): purge session store on logout 2025-12-02 16:33:44 +00:00
Peter Steinberger
c9fbe2cb92 chore(security): harden ipc socket 2025-12-02 16:09:40 +00:00
Peter Steinberger
ed080ae988 Tests: cover agents and fix web defaults
Co-authored-by: RealSid08 <RealSid08@users.noreply.github.com>
2025-12-02 11:08:00 +00:00
Peter Steinberger
f31e89d5af Agents: add pluggable CLIs
Co-authored-by: RealSid08 <RealSid08@users.noreply.github.com>
2025-12-02 11:07:46 +00:00
Peter Steinberger
5b54d4de7a feat(web): batch inbound messages 2025-12-02 07:54:13 +00:00
Peter Steinberger
96152f6577 Add typing indicator after IPC send
After sending via IPC, automatically show "composing" indicator so
user knows more messages may be coming from the running session.
2025-12-02 06:58:17 +00:00
Peter Steinberger
e86b507da7 Add IPC to prevent Signal session corruption from concurrent connections
When the relay is running, `warelay send` and `warelay heartbeat` now
communicate via Unix socket IPC (~/.warelay/relay.sock) to send messages
through the relay's existing WhatsApp connection.

Previously, these commands created new Baileys sockets that wrote to the
same auth state files, corrupting the Signal session ratchet and causing
the relay's subsequent sends to fail silently.

Changes:
- Add src/web/ipc.ts with Unix socket server/client
- Relay starts IPC server after connecting
- send command tries IPC first, falls back to direct
- heartbeat uses sendWithIpcFallback helper
- inbound.ts exposes sendMessage on listener object
- Messages sent via IPC are added to echo detection set
2025-12-02 06:31:07 +00:00
Peter Steinberger
2fc3a822c8 web: isolate session fixtures and skip heartbeat when busy 2025-12-02 06:17:16 +00:00
Peter Steinberger
d107b79c63 Fix test corrupting production sessions.json
The test 'falls back to most recent session when no to is provided' was
using resolveStorePath() which returns the real ~/.warelay/sessions.json.
This overwrote production session data with test values, causing session
fragmentation issues.

Changed to use a temp directory like other tests.
2025-12-02 05:54:31 +00:00
Peter Steinberger
c5ab442f46 Fix empty result JSON dump and missing heartbeat prefix
Bug fixes:
- Empty result field handling: Changed truthy check to explicit type
  check (`typeof parsed?.text === "string"`) in command-reply.ts.
  Previously, Claude CLI returning `result: ""` would cause raw JSON
  to be sent to WhatsApp.
- Response prefix on heartbeat: Apply `responsePrefix` to heartbeat
  alert messages in runReplyHeartbeat, matching behavior of regular
  message handler.
2025-12-02 04:29:17 +00:00
Peter Steinberger
c5677df56e Increase watchdog timeout to 30 minutes
Changed from 10 to 30 minutes to avoid false positives when
heartbeatMinutes is set to 10. The watchdog should be significantly
longer than the heartbeat interval to account for:
- Network latency
- Slow command responses
- Brief connection hiccups

With heartbeatMinutes=10, a 30-minute watchdog gives 3x buffer before
triggering auto-restart.
2025-11-30 18:03:19 +00:00
Peter Steinberger
21ba0fb8a4 Fix test isolation to prevent loading real user config
Tests were picking up real ~/.warelay/warelay.json with emojis and
prefixes (like "🦞"), causing test assertions to fail. Added proper
config mocks to all test files.

Changes:
- Mock loadConfig() in index.core.test.ts, inbound.media.test.ts,
  monitor-inbox.test.ts
- Update test-helpers.ts default mock to disable all prefixes
- Tests now use clean config: no messagePrefix, no responsePrefix,
  no timestamp, allowFrom=["*"]

This ensures tests validate core behavior without user-specific config.
The responsePrefix feature itself is already fully config-driven - this
only fixes test isolation.
2025-11-30 18:00:57 +00:00
Peter Steinberger
69319a0569 Add auto-recovery from stuck WhatsApp sessions
Fixes issue where unauthorized messages from +212652169245 (5elements spa)
triggered Bad MAC errors and silently killed the event emitter, preventing
all future message processing.

Changes:
1. Early allowFrom filtering in inbound.ts - blocks unauthorized senders
   before they trigger encryption errors
2. Message timeout watchdog - auto-restarts connection if no messages
   received for 10 minutes
3. Health monitoring in heartbeat - warns if >30 min without messages
4. Mock loadConfig in tests to handle new dependency

Root cause: Event emitter stopped firing after Bad MAC errors from
decryption attempts on messages from unauthorized senders. Connection
stayed alive but all subsequent messages.upsert events silently failed.
2025-11-30 17:53:32 +00:00
Peter Steinberger
37d8e55991 Skip responsePrefix for HEARTBEAT_OK responses
Preserve exact match so warelay recognizes heartbeat responses
and doesn't send them as messages.
2025-11-29 06:02:21 +00:00
Peter Steinberger
8d20edb028 Simplify timestampPrefix: bool or timezone string, default true
- timestampPrefix: true (UTC), false (off), or 'America/New_York'
- Removed separate timestampTimezone option
- Default is now enabled (true/UTC) unless explicitly false
2025-11-29 05:29:29 +00:00
Peter Steinberger
7564c4e7f4 Generalize prefix config: messagePrefix + responsePrefix
Replaces samePhoneMarker/samePhoneResponsePrefix with:
- messagePrefix: prefix for all inbound messages
  - Default: '[warelay]' if no allowFrom, else ''
- responsePrefix: prefix for all outbound replies

Also adds timestamp options:
- timestampPrefix: boolean to enable [Nov 29 06:30] format
- timestampTimezone: IANA timezone (default UTC)

Updated README with new config table entries.
2025-11-29 05:27:58 +00:00