Commit Graph

142 Commits

Author SHA1 Message Date
Cameron
541bcf496e Revert "fix: auto-reset conversation when stream receives no data (#142)" (#143)
This reverts commit 4258e92c50.
2026-02-04 15:42:54 -08:00
Cameron
4258e92c50 fix: auto-reset conversation when stream receives no data (#142)
When a conversation has a stuck tool approval from a previous session,
the stream receives NO data at all (not even init). This leaves users
stuck with "(No response from agent)" and no clear path to recovery.

Changes:
- Track if stream received ANY data (not just assistant messages)
- If stream times out with zero data, assume stuck approval state
- Auto-reset conversation and notify user to try again
- Add message type counts to "no response" logs for debugging
- Fix 'system' -> 'init' type comparison (was causing TS error)

This addresses the issue reported by Signo on Discord where responses
were going to ADE instead of the channel due to stuck approvals.

Related issues: #125, #127, #132

Written by Cameron ◯ Letta Code

"When the stream runs dry, dig a new well." - Infrastructure proverb
2026-02-04 15:27:25 -08:00
github-actions[bot]
e4219d0615 fix: use getDataDir() for CronService storage path (#139)
Fix path mismatch between CLI and CronService that caused cron jobs
created via CLI to never be picked up by the running service.

- CLI uses getDataDir() for cron-jobs.json
- CronService was overriding with workingDir path
- Now both use getDataDir() (defaults to cwd or Railway volume)

Fixes #135

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Cameron <cpfiffer@users.noreply.github.com>
2026-02-04 15:10:13 -08:00
Cameron
3e48036db4 feat: add detailed stream message logging (#138)
- Log every stream message type received (tool_call, tool_result, etc.)
- Add message type counts summary at end of stream
- Add DEBUG_STREAM=1 for verbose per-message logging with JSON preview
- Add reasoning and system message type logging
- Include more detail in tool_result logs (error status, content length)

Helps diagnose why watchdog times out when tools appear to be running
in ADE but no tool_call/tool_result messages are received by lettabot.

Written by Cameron ◯ Letta Code

"You can't fix what you can't see." - Debugging wisdom
2026-02-04 13:10:35 -08:00
Cameron
b31a67d024 fix: increase stream idle timeout default from 30s to 120s (#136)
Tools execute client-side without emitting stream messages. Multiple
tool executions (10-20s each) plus API processing gaps can exceed
30s of "idle" time even though the agent is actively working.

Increase default to 120s to prevent false timeouts. Users can still
override via LETTA_STREAM_IDLE_TIMEOUT_MS env var.

Written by Cameron ◯ Letta Code

"Patience is a virtue, especially when waiting for tools." - Ancient proverb
2026-02-04 12:53:09 -08:00
Cameron
550ea6cf2e feat: add inbound reaction handling (#134)
* Add inbound reaction handling

* Add inbound reaction types

* Add reaction envelope test

---------

Co-authored-by: Jason Carreira <jason@visotrust.com>
2026-02-04 12:08:49 -08:00
Cameron
0c79b147f4 fix: add diagnostic logging for tool approval flow (#132) (#133)
Adds logging to help diagnose the issue where tool approvals are
being requested despite bypassPermissions mode:

1. Log session options when created (permissionMode, allowedTools count)
2. Add fallback canUseTool callback that logs warnings if called
   - This should NOT be called when permissionMode=bypassPermissions
   - If logs appear, it indicates the mode isn't being respected
3. Log stream result details (success, hasResponse, resultLen, error)
4. Add context when "(No response from agent)" is sent
   - Suggests checking if ADE is open (session conflict)

If users see "Tool approval requested" warnings in their logs,
it means the bypassPermissions mode isn't working correctly at
the SDK/CLI level.

Closes #132

Written by Cameron ◯ Letta Code

"You can't fix what you can't see." - Debugging proverb
2026-02-04 11:22:48 -08:00
Gabriele Sarti
0aef80157a feat: add lettabot-channels CLI for channel discovery (#121)
Allow the agent to discover channel IDs across Discord and Slack so it
can send messages to channels it hasn't received messages from (e.g.
"write something in #announcements"). Updates the system prompt so the
agent knows the command exists.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:02:35 -08:00
Gabriele Sarti
92c81eb294 fix(telegram): reorder voice handler before generic message handler (#120)
The `message:voice` handler was registered after the generic `message`
handler, which meant grammY matched voice messages to the broader
handler first. The guard clause returned early but didn't forward to
the voice handler, silently dropping voice messages.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:01:22 -08:00
Cameron
c80c7ae7d5 feat: chunked transcription for large audio files (#129)
Whisper API has a 25MB limit. For larger audio files:
1. Split into 10-minute chunks using ffmpeg
2. Transcribe each chunk separately
3. Combine transcriptions into single text

Example output:
```
[Transcription] File too large (32.5MB), splitting into chunks
[Transcription] Split into 4 chunks
[Transcription] Transcribing chunk 1/4 (5120KB)
[Transcription] Transcribing chunk 2/4 (5120KB)
...
[Transcription] Combined 4 chunks into 4521 chars
```

Written by Cameron ◯ Letta Code

"Divide and conquer, then concatenate." - Parallel processing proverb
2026-02-03 23:32:16 -08:00
Cameron
4843ac3d3a fix: convert AAC audio with ffmpeg for transcription (#128)
OpenAI Whisper rejects raw AAC files even when renamed to .m4a - it
checks actual file format, not just extension. Signal voice messages
are often AAC.

Now uses ffmpeg to convert unsupported formats (aac, amr, caf, 3gp)
to MP3 before sending to Whisper API.

Requires ffmpeg installed on system.

Written by Cameron ◯ Letta Code

"When in doubt, transcode it out." - Audio engineering wisdom
2026-02-03 23:27:50 -08:00
Cameron
ac6ec9505d fix: prevent 409 conflicts between heartbeats and user messages (#123)
Heartbeats and user messages were racing to use the agent, causing
409 CONFLICT errors ("Another request is currently being processed").

This adds a processing mutex to `sendToAgent()` (used by heartbeats):
- Waits for any in-progress message processing to complete
- Marks itself as processing to prevent queue from starting
- Releases lock and triggers queue processing when done

This ensures heartbeats and user messages are serialized.

Written by Cameron ◯ Letta Code

"Concurrency is hard. Mutexes are your friend." - Every debugger ever
2026-02-03 22:27:30 -08:00
Cameron
df0343d0be feat: add reset-conversation command and better error detection (#122)
When conversations become corrupted on Letta Cloud, users see empty
responses with no useful error message. This adds:

1. Warning message when empty result detected:
   - Logs: "Agent returned empty result with no response"
   - Suggests running `lettabot reset-conversation`

2. New CLI command `lettabot reset-conversation`:
   - Clears the conversationId from lettabot-agent.json
   - Preserves agent and memory
   - Next message creates fresh conversation

Symptoms of corrupted conversation:
- stop_reason: "error" with empty result
- Messages not appearing in agent history
- duration_api_ms: 0 (no API call made)

Written by Cameron ◯ Letta Code

"When in doubt, start fresh." - Ancient debugging wisdom
2026-02-03 21:59:08 -08:00
github-actions[bot]
41c6e88977 Upgrade Letta Code SDK to 0.0.5 (#117)
Breaking API changes in SDK 0.0.5 require:
- Use createAgent() for new agents with custom systemPrompt and memory
- Remove systemPrompt from createSession()/resumeSession() options

Fixes #116

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Cameron <cpfiffer@users.noreply.github.com>
2026-02-03 18:54:56 -08:00
Parth Modi
d1d758739d feat(whatsapp): add lettabot-message CLI support for text and files (#89)
Merged WhatsApp CLI support with HTTP API server.

Features:
- HTTP API server for CLI-to-bot communication across Docker boundaries
- WhatsApp text + file sending via `lettabot-message send --file photo.jpg`
- Unified multipart endpoint at /api/v1/messages
- Security: timing-safe auth, localhost binding, same-origin CORS
- Bad MAC error handling for WhatsApp encryption renegotiation

Written by Cameron ◯ Letta Code
2026-02-03 17:21:27 -08:00
Cameron
27402d86d8 feat: add stream idle watchdog and session init improvements (#105)
Merged stream idle watchdog and session init improvements.

Features:
- Stream idle watchdog - aborts stuck sessions after timeout
- Periodic waiting logs every 10s when stream is idle
- Persist conversationId immediately after session.initialize()
- Configurable via LETTA_STREAM_IDLE_TIMEOUT_MS

Closes #87, closes #88

Written by Cameron ◯ Letta Code
2026-02-03 17:01:19 -08:00
Parth Modi
c220074e63 feat(whatsapp): add group mention detection and enhanced agent context (#81)
Merged WhatsApp group mention detection and enhanced agent context.

Features:
- Group mention detection (native @mentions, reply-to-bot, regex patterns)
- Enhanced agent context (GROUP tag, @mentioned tag, via +phone)
- Group policies (requireMention, per-group config)
- 27 new tests

Written by Cameron ◯ Letta Code
2026-02-03 17:00:42 -08:00
Cameron
3e3d81b9f2 feat: add Railway volume support for persistent storage (#113)
Auto-detect RAILWAY_VOLUME_MOUNT_PATH and use it for all persistent data
(agent ID, cron jobs, logs). On local machines, data stays in project
directory. Template now includes volume by default.

- Add src/utils/paths.ts with getDataDir() and getWorkingDir() helpers
- Update Store, cron service, CLI tools to use data directory
- Log storage locations on startup for debugging
- Update deploy button URLs with UTM tracking

Written by Cameron ◯ Letta Code

"The best way to predict the future is to invent it." - Alan Kay
2026-02-03 16:49:08 -08:00
Cameron
75f65049bc feat: Railway deployment support with one-click deploy (#106)
* feat: add Railway deployment support with agent auto-discovery

- Add railway.toml for build/deploy config with health checks
- Skip config file requirement when RAILWAY_ENVIRONMENT detected
- Auto-discover existing agent by name on container deploys
- Add findAgentByName() API function for agent lookup
- Add setAgentId() method to LettaBot class
- Add comprehensive Railway deployment docs

One-click deploy flow:
1. Set LETTA_API_KEY + channel tokens
2. LettaBot finds existing agent by AGENT_NAME (default: "LettaBot")
3. If not found, creates on first message
4. Subsequent deploys auto-reconnect to same agent

Written by Cameron ◯ Letta Code

"The best way to predict the future is to deploy it." - Railway, probably

* fix: specify Node 22 for Railway deployment

* fix: fail fast if LETTA_API_KEY is missing

* fix: don't await Telegram bot.start() - it never resolves

* fix: extract message from send_message tool call

* Revert "fix: extract message from send_message tool call"

This reverts commit 370306e49de3728434352d2df1b78c744e888833.

* fix: clear LETTA_AGENT_ID env var when agent doesn't exist

* docs: add Railway deploy button to README and docs

* fix: .nvmrc newline and correct MODEL default in docs
2026-02-03 14:46:37 -08:00
github-actions[bot]
ed0d406a9d fix(signal): wait for attachment file before transcription (#93)
Signal-cli fires SSE events as soon as message metadata arrives, but attachment
files may still be downloading. This race condition caused intermittent voice
transcription failures where only '[Voice message received]' appeared.

Added waitForFile() helper with exponential backoff (up to 5s) that retries
until the attachment file is readable before attempting transcription. Also
applied the same fix to general attachment handling in collectSignalAttachments.

Fixes #92

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Cameron <cpfiffer@users.noreply.github.com>
2026-02-03 13:40:27 -08:00
Cameron
4dea01406e docs: add Telegram setup guide link to README (#103)
Written by Cameron ◯ Letta Code

"The beginning of wisdom is the definition of terms." - Socrates
2026-02-03 13:39:09 -08:00
Cameron
6d4bfdd63d fix(whatsapp): suppress Signal Protocol crypto noise in logs (#102)
Baileys/libsignal logs "Closing open session in favor of incoming
prekey bundle" and similar messages that are normal Signal Protocol
key renegotiation - not errors.

Changes:
- Remove our own crypto error logging (line 810)
- Add console filter to suppress Baileys crypto patterns:
  - prekey bundle messages
  - session renegotiation
  - bad mac errors
  - ratchet/key details

These are harmless noise that confused users into thinking
something was wrong.

Addresses LET-7275

Written by Cameron ◯ Letta Code

"Silence is golden." - Thomas Carlyle
2026-02-03 13:24:35 -08:00
Cameron
12871128e1 feat: default to allowlist for dedicated numbers in onboarding (#100)
When user selects "dedicated bot number" mode (selfChatMode=false),
skip the dmPolicy question and default to allowlist. Prompt for
allowed phone numbers immediately.

This is simpler and safer than pairing mode, which sends codes to
whoever messages the bot.

Users who want pairing or open mode can edit lettabot.yaml manually.

Also updates docs to reflect the new defaults.

Written by Cameron ◯ Letta Code

"Simplicity is the ultimate sophistication." - Leonardo da Vinci
2026-02-03 12:30:27 -08:00
Cameron
b8968a8732 feat: improve selfChatMode messaging in onboarding and startup (#99)
- Reorder options to show "personal number" first (recommended/safe)
- Add warnings when user selects dedicated number mode
- Skip dmPolicy question when selfChatMode is on (irrelevant)
- Add startup warnings when selfChatMode is off
- Add Linear skill for issue management

Addresses LET-7273 - users were confused about WhatsApp configuration.
The safe default (selfChatMode=true) prevents the bot from messaging
your contacts. Only disable this for dedicated bot numbers.

Written by Cameron ◯ Letta Code

"Make the right thing easy and the wrong thing hard." - Kathy Sierra
2026-02-03 12:16:10 -08:00
Cameron
6d246d6e58 fix(transcription): map unsupported audio formats for Whisper/GPT-4o (#96)
Audio transcription may receive formats that aren't in Whisper's
supported list. Add mappings in the transcription module:
- aac → m4a (AAC is M4A compatible)
- amr → mp3 (mobile voice format)
- opus → ogg (Opus in OGG container)
- caf/x-caf → m4a (Apple CAF)
- 3gp/3gpp → mp4 (mobile video format)

This works for both whisper-1 and gpt-4o-transcribe models.

Fixes #92

Written by Cameron ◯ Letta Code

"The devil is in the details." - Ludwig Mies van der Rohe
2026-02-03 11:05:37 -08:00
Cameron
7b6a730df2 docs: comprehensive documentation audit and improvements (#90)
Fixes and updates:
- README.md: Remove duplicate heartbeat troubleshooting section
- docs/getting-started.md: Fix Node version (18→20), commands, repo URL
- docs/commands.md: Rewrite with accurate command list (/start, /status, /heartbeat)
- docs/README.md: New multi-channel architecture diagram
- docs/whatsapp-setup.md: Add selfChatMode safety docs, media support section
- docs/slack-setup.md: Fix broken links

New documentation:
- docs/configuration.md: Complete YAML config reference
- docs/cron-setup.md: Scheduling guide (cron jobs + heartbeats)

Written by Cameron ◯ Letta Code

"Documentation is a love letter that you write to your future self." - Damian Conway
2026-02-02 22:36:06 -08:00
Cameron
3becad2d74 test: add formatter and backoff unit tests (#85)
Add comprehensive tests for core utilities:

formatter.test.ts (23 tests):
- Envelope structure (channel, chatId, messageId)
- Sender formatting (usernames, phone numbers, @ prefixes)
- Group formatting (# prefix for Slack/Discord)
- Format hints per channel
- Attachment formatting with sizes
- Options (includeSender, includeGroup, includeDay)

backoff.test.ts (18 tests):
- computeBackoff() exponential calculation
- Jitter behavior
- Max cap enforcement
- createReconnectManager() state tracking
- sleepWithAbort() with fake timers

Total: 52 -> 93 tests

Written by Cameron ◯ Letta Code

"Testing shows the presence, not the absence of bugs." - Dijkstra
2026-02-02 18:44:35 -08:00
Jason Carreira
895ac15eff Fallback when default conversation is missing (#79)
* Fallback to new conversation when default is missing

* Fallback when stored conversation is missing

* Allow LETTA_SESSION_TIMEOUT_MS override

---------

Co-authored-by: Jason Carreira <jason@visotrust.com>
2026-02-02 18:40:11 -08:00
Cameron
11da398f55 fix(voice): telegram transcription + signal diagnostics (#82)
Telegram:
- Skip voice messages in generic message handler
- Let message:voice handler transcribe properly

Signal:
- Add attachment logging for debugging
- Check file existence before reading
- Warn when audio attachment has no ID

Written by Cameron ◯ Letta Code

"The most effective debugging tool is still careful thought." - Brian Kernighan
2026-02-02 18:17:52 -08:00
Cameron
9de228ca00 docs: explain silent mode for heartbeats and cron jobs (#84)
Adds documentation to help users understand why their agent's responses
during heartbeats/cron jobs aren't being delivered to their chat channels.

- Add "Background Tasks" section explaining silent mode behavior
- Add FAQ entry in Troubleshooting for common issues
- Explain that agents must use `lettabot-message` CLI to send messages

Closes #80

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-02-02 17:50:01 -08:00
Cameron
13d84245c5 feat: add X-Letta-Source header for telemetry (#73)
Add "X-Letta-Source: lettabot" header to Letta API client
for usage tracking/telemetry.

Closes #72

Written by Cameron ◯ Letta Code

"If you can't measure it, you can't improve it." - Peter Drucker
2026-02-02 16:19:17 -08:00
Cameron
7b27ac1b6c fix(transcription): handle AAC audio format from Signal (#76)
Signal voice messages use .aac format which OpenAI Whisper doesn't
accept directly. Fix by normalizing .aac to .m4a (same codec, different
container name) before sending to the API.

Written by Cameron ◯ Letta Code

"The best error message is the one that never shows up." - Thomas Fuchs
2026-02-02 14:58:47 -08:00
Parth Modi
dd105fd556 Production-grade WhatsApp refactoring with Baileys delivery fixes (#66)
* refactor(whatsapp): production-grade modular architecture + delivery fixes

Major refactoring of WhatsApp integration following OpenClaw's battle-tested
patterns. Implements proper separation of concerns, full type safety, and fixes
critical Baileys delivery issues.

Refactored monolithic 882-line file into modular structure:

New structure (14 files, 2,722 lines):
- src/channels/whatsapp/
  - index.ts (750 lines) - Main orchestration
  - session.ts (289 lines) - Socket creation
  - types.ts (110 lines) - Type definitions
  - utils.ts (171 lines) - Helper functions
  - outbound.ts (181 lines) - Message sending
  - inbound/
    - types.ts (106 lines) - Message types
    - extract.ts (173 lines) - Message parsing
    - access-control.ts (189 lines) - Pairing logic

Shared utilities (reusable across channels):
- src/utils/backoff.ts (155 lines) - Reconnection primitives
- src/utils/dedupe-cache.ts (184 lines) - TTL deduplication
- src/utils/creds-queue.ts (233 lines) - Credential management
- src/utils/debouncer.ts (183 lines) - Message batching

1. Message type filtering - Only process "notify" and "append" types
2. Status/broadcast filtering - Skip @status and @broadcast messages
3. Improved deduplication - Use whatsapp:remoteJid:messageId key
4. History handling - Skip auto-reply for "append" type messages
5. Credentials backup - Backup and validate before saving
6. Read receipts - Send for all messages (except self-chat)
7. WebSocket error handling - Prevent crashes from socket errors
8. Group metadata caching - 5min TTL, reduces API calls
9. Connection timestamp filtering - Skip old messages on reconnect
10. Message debouncing - Batch rapid consecutive messages
11. Full type safety - Replaced 26+ 'any' with proper Baileys types

Implements getMessage callback pattern to solve delivery failures:
- Store sent messages for 24h retry capability
- Storage happens at SEND-TIME (not upsert-time) to avoid race conditions
- Prevents "waiting for this message" errors and single tick issues
- Based on Baileys issue #1767 solution

Key insight: Storing messages in messages.upsert listener interferes with
consecutive message processing. Storing at send-time eliminates race conditions.

Full TypeScript type safety with proper Baileys types:
- Imported WASocket, WAMessage, proto.IMessage from Baileys
- Replaced 26+ instances of 'any' with proper types
- Added null checks for type safety
- All functions properly typed

Impact: Both message delivery AND consecutive message handling now work.
Based on OpenClaw analysis and Baileys community solutions.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>

* feat(whatsapp): integrate PR #64 attachment support into modular structure

Port attachment download/upload features from PR #64 to our refactored
modular WhatsApp architecture.

## Features Added

- Media download (images, videos, audio, documents, stickers)
- Media upload (images and documents with captions)
- Size limit enforcement (attachmentsMaxBytes config)
- Metadata-only mode (0 bytes = no download)
- Organized storage (attachmentsDir/whatsapp/chatId/)

## Architecture

Created new module: inbound/media.ts (173 lines)
- unwrapMessageContent() - Unwraps ephemeral/viewOnce messages
- extractMediaPreview() - Quick media detection
- collectAttachments() - Download and save media
- extensionFromMime() - MIME type to extension conversion

Updated modules:
- inbound/types.ts - Added attachments field, AttachmentExtractionConfig
- inbound/extract.ts - Integrated media extraction
- types.ts - Added attachmentsDir, attachmentsMaxBytes to config
- outbound.ts - Added sendFile() for image/document sending
- index.ts - Wired attachment config throughout

## Integration Pattern

Attachments are opt-in via configuration:
- If attachmentsDir configured → Downloads enabled
- If not configured → Text-only mode (backward compatible)
- downloadContentFromMessage imported from Baileys dynamically
- Attachment config passed through extraction pipeline

## Maintains

-  Consecutive message handling
-  getMessage delivery pattern
-  Full type safety
-  Modular architecture
-  All existing functionality

Based on PR #64 by Cameron and Jason, integrated into modular structure.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>

* feat(whatsapp): add addReaction stub for API completeness

Add addReaction method stub to match upstream API.
Currently a no-op as Baileys reactions not yet supported.

Ensures complete ChannelAdapter interface compatibility.

---------

Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-02-02 12:47:23 -08:00
Cameron
f3e619cd7b Add testing infrastructure with vitest (#67)
- Add vitest as dev dependency
- Add test scripts: `npm test` (watch) and `npm run test:run` (CI)
- Add initial unit tests for pure utility functions:
  - src/utils/phone.test.ts (10 tests)
  - src/utils/server.test.ts (10 tests)
  - src/channels/attachments.test.ts (6 tests)

All 26 tests passing.

Written by Cameron ◯ Letta Code
2026-02-01 22:38:25 -08:00
Cameron
67f0550bd3 Add inbound attachment support with download, metadata, and pruning (#64)
* Add inbound attachment handling and pruning

* Add Signal attachment support and logging

- Implement full Signal attachment collection (copies from signal-cli dir)
- Add logging when attachments are saved to disk for all channels
- Skip audio attachments in Signal (handled by voice transcription)

Written by Cameron ◯ Letta Code

* Gitignore bun.lock

Keep lockfile local, don't track in repo.

Written by Cameron ◯ Letta Code

---------

Co-authored-by: Jason Carreira <jason@visotrust.com>
2026-02-01 22:14:30 -08:00
puffo
7f12cbdc60 Unify self-hosted URL detection with shared isLettaCloudUrl() (#60)
Docker service hostnames (e.g. http://letta:8283) were misidentified as
Letta Cloud. Instead of enumerating self-hosted patterns, check against
the known Cloud hostname. Everything else is self-hosted.
2026-02-01 20:36:39 -08:00
Parth Modi
d8d140fa71 fix: normalize WhatsApp phone numbers for consistent pairing (#61)
- Add normalizePhoneForStorage() utility to handle @lid, @s.whatsapp.net suffixes
- Strip @lid/@s.whatsapp.net/@g.us and normalize to E.164 format (+prefix)
- Fix pairing approval format mismatch causing re-prompts for approved contacts
- Normalize userId on extraction, storage, and access checks

Fixes issue where approved contacts get pairing codes on every message
due to format inconsistencies:
- Extracted: 54941422981120@lid
- Checked: +54941422981120@lid
- Stored: 54941422981120@lid
- No match!

Now all formats normalize to: +54941422981120
2026-02-01 20:29:27 -08:00
dependabot[bot]
f27227cfc3 chore(deps): bump @letta-ai/letta-client from 1.7.6 to 1.7.7 (#63)
Bumps [@letta-ai/letta-client](https://github.com/letta-ai/letta-node) from 1.7.6 to 1.7.7.
- [Release notes](https://github.com/letta-ai/letta-node/releases)
- [Changelog](https://github.com/letta-ai/letta-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/letta-ai/letta-node/compare/v1.7.6...v1.7.7)

---
updated-dependencies:
- dependency-name: "@letta-ai/letta-client"
  dependency-version: 1.7.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-01 20:19:16 -08:00
dependabot[bot]
4b681b0fa4 chore(deps): bump @letta-ai/letta-code-sdk from 0.0.3 to 0.0.4 (#62)
* chore(deps): bump @letta-ai/letta-code-sdk from 0.0.3 to 0.0.4

Bumps [@letta-ai/letta-code-sdk](https://github.com/letta-ai/letta-code-sdk) from 0.0.3 to 0.0.4.
- [Release notes](https://github.com/letta-ai/letta-code-sdk/releases)
- [Commits](https://github.com/letta-ai/letta-code-sdk/compare/v0.0.3...v0.0.4)

---
updated-dependencies:
- dependency-name: "@letta-ai/letta-code-sdk"
  dependency-version: 0.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix SDK 0.0.4 API changes

- createSession() signature changed: (agentId?, options?) instead of (options)
- Remove canUseTool callback - bypassPermissions mode auto-allows all tools

Written by Cameron ◯ Letta Code

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cameron Pfiffer <cameron@pfiffer.org>
2026-02-01 20:16:27 -08:00
Cameron
053763bf89 Add voice message transcription support (#54)
* Add voice message transcription support (all channels)

Adds OpenAI Whisper transcription for voice messages across all channels:
- Telegram: ctx.message.voice
- WhatsApp: audioMessage via downloadMediaMessage
- Signal: audio attachments from local files
- Slack: audio files via url_private_download
- Discord: audio attachments

Voice messages sent to agent as "[Voice message]: <transcript>"

Configuration (config takes priority over env):
- lettabot.yaml: transcription.apiKey, transcription.model
- Env: OPENAI_API_KEY, TRANSCRIPTION_MODEL

Closes #47

Written by Cameron ◯ Letta Code

"The best interface is no interface - just talk."

* Add voice message documentation to README

- Add Voice Messages to features list
- Add configuration section for transcription
- Document supported channels

Written by Cameron ◯ Letta Code

* Notify users when voice transcription is not configured

Instead of silently ignoring voice messages, send a helpful message
linking to the documentation.

Written by Cameron ◯ Letta Code

* feat: upgrade to letta-code-sdk main + fix Signal voice transcription

- Switch from published SDK (v0.0.3) to local main branch (file:../letta-code-sdk)
- Update bot.ts for new SDK API: createSession(agentId?, options) signature
- Add conversationId tracking to store for proper conversation persistence
- Fix Signal voice transcription: read attachments from ~/.local/share/signal-cli/attachments/
- Fix Telegram markdown ESM issue: make markdownToTelegramV2 async with dynamic import
- Add transcription config to lettabot.yaml
- Add extensive debug logging for queue and session processing

Signal voice messages now properly transcribe and send to agent.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: update Signal CLI message sender to use daemon JSON-RPC API

- Switch from signal-cli-rest-api to signal-cli daemon (port 8090)
- Use JSON-RPC send method instead of REST /v2/send
- Support group IDs with group: prefix
- Handle 201 responses and empty bodies correctly

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* Add placeholder for untranscribed voice messages on Signal

If a voice-only message arrives and transcription fails or is disabled,
forward a placeholder so the user knows the message was received.

Written by Cameron ◯ Letta Code

---------

Co-authored-by: Letta <noreply@letta.com>
2026-02-01 20:07:57 -08:00
Charles Packer
cf1f03e0c7 Merge pull request #59 from MrDys/main
Update README.md
2026-01-31 14:51:38 -08:00
Sean Hannan
588894d904 Update README.md
Lettabot actually requires Node 20+
2026-01-31 16:31:33 -05:00
Cameron
8017c4617e Add update-notifier to CLI (#53)
Shows a notification when a new version is available, helping users
stay up to date with security fixes.

Written by Cameron ◯ Letta Code
2026-01-30 17:16:49 -08:00
Cameron
6258da1a6e Add update instructions to README (#52)
Written by Cameron ◯ Letta Code
2026-01-30 17:14:14 -08:00
cthomas
c98c5041db Merge pull request #51 from letta-ai/caren/fix-whatsapp-self-chat
fix: whatsapp self-chat setting
2026-01-30 16:46:20 -08:00
Caren Thomas
5c7c2f1fef fix: whatsapp self-chat setting 2026-01-30 16:31:35 -08:00
cthomas
ab8e5651ac Merge pull request #50 from letta-ai/caren/agent-onboarding-improvements
feat: improvements for agent onboarding
2026-01-30 16:30:29 -08:00
Cameron
20ab73cc25 Fix WhatsApp selfChatMode sending to wrong person (#49)
* Fix WhatsApp selfChatMode sending to wrong person

Two safety fixes:

1. Fail-safe on unknown LID - refuse to send instead of letting baileys
   resolve it to potentially the wrong person

2. Improve self-chat detection - remove !senderPn requirement which can
   fail in some cases, causing messages to leak to other contacts

Written by Cameron ◯ Letta Code

"Better to fail loudly than succeed silently at the wrong thing."

* Default selfChatMode to true for WhatsApp and Signal

- main.ts: WhatsApp now uses !== 'false' pattern (like Signal)
- config/io.ts: Only set env var if explicitly false
- onboard.ts: Default to 'personal' in config initialization

Written by Cameron ◯ Letta Code
2026-01-30 16:24:38 -08:00
Caren Thomas
d9de732729 improvements for agent onboarding 2026-01-30 16:21:20 -08:00
cthomas
1d66f42dad feat: add non-interactive onboarding and SKILL.md (#45)
* feat: add non-interactive onboarding and SKILL.md

Add agent-friendly setup flow:
- lettabot onboard --non-interactive flag
- Reads all config from environment variables
- SKILL.md documents env-based setup for agents
- Supports all channels (Telegram, Slack, Discord, WhatsApp, Signal)
- No prompts - ideal for coding agents automating setup

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: address non-interactive setup issues

- Add SLACK_APP_NAME for customizable app name (defaults to LETTA_AGENT_NAME or LettaBot)
- Clarify WhatsApp requires WHATSAPP_ENABLED and WHATSAPP_SELF_CHAT to be explicit
- Document all 5 channels supported (Telegram, Slack, Discord, WhatsApp, Signal)
- Fix WhatsApp selfChat default to be explicit false

* docs: recommend non-interactive setup as primary method

Update README per review feedback to show env-based setup first.
This is simpler for most users and ideal for automation.

* docs: rewrite setup to be AI-first per feedback

Make recommended setup AI-focused:
- Show prompt to paste into AI coding assistants
- AI handles clone/install/config autonomously
- Manual wizard becomes Option 2 for human users

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-30 16:14:29 -08:00