Commit Graph

22 Commits

Author SHA1 Message Date
Cameron
b1d69965b5 feat: add <no-reply/> silent marker for agent opt-out (#196)
* feat: add {{NO_REPLY}} silent marker for agent opt-out

Allow the agent to respond with {{NO_REPLY}} to suppress message
delivery for messages that don't warrant a reply. The marker is
checked in three places: the streaming edit guard (prefix match to
prevent partial sends), finalizeMessage(), and the post-stream
response handler.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: use <no-reply/> XML marker instead of {{NO_REPLY}}

Switch to XML-style self-closing tag for consistency with the XML
envelope format used elsewhere, and because LLMs produce well-formed
XML tags more reliably than template syntax.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add no-reply hint to group chat envelopes

Agents created outside lettabot (via ADE, Letta Cloud) won't have the
system prompt telling them about <no-reply/>. Adding the hint to group
chat envelopes makes the opt-out mechanism self-documenting.

Written by Cameron ◯ Letta Code

"Silence is one of the great arts of conversation." -- Marcus Tullius Cicero

---------

Co-authored-by: Gabriele Sarti <gabriele.sarti996@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 11:08:56 -08:00
Cameron
5dea82acc5 fix: pin baileys to 6.7.21 and fix stale command count test (#193)
The ^6.7.21 caret range resolves to 6.17.16 on fresh npm install, which
ships incompatible TypeScript types (no call signatures on default export).
Pins exact version and adds explicit type annotation on getMessage key param.

Also updates commands.test.ts to expect 5 commands (reset was added but
test still expected 4).

Fixes #192

Written by Cameron ◯ Letta Code

"The caret giveth, and the caret taketh away."
2026-02-06 10:30:04 -08:00
dependabot[bot]
49db36f52f chore(deps): bump @letta-ai/letta-client from 1.7.7 to 1.7.8 (#186)
Bumps [@letta-ai/letta-client](https://github.com/letta-ai/letta-node) from 1.7.7 to 1.7.8.
- [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.7...v1.7.8)

---
updated-dependencies:
- dependency-name: "@letta-ai/letta-client"
  dependency-version: 1.7.8
  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-06 10:25:27 -08:00
Cameron
c85c4a3272 fix: telegram ESM compatibility and improved diagnostics (#161)
- Replace telegram-markdown-v2 with telegramify-markdown (ESM compatible)
- Add raw text fallback when Telegram formatting fails, with error notice
- Improve empty response diagnostics: log agent ID, show conversation ID
- Add reset-conversation command hint to user messages
- Add telegram-format.test.ts with 7 tests

Fixes Railway deployment ERR_REQUIRE_ESM error with remark package.

Written by Cameron and Letta Code

"The best error message is the one that never shows up." - Thomas Fuchs
2026-02-05 10:31:53 -08:00
Cameron
b4058f17ce fix: add keyv as direct dependency (#154)
keyv is a transitive dependency of Baileys via @cacheable/utils,
but since Baileys is in optionalDependencies, some npm versions
don't properly install its transitive dependencies on fresh installs.

Adding keyv as a direct dependency ensures it's always installed.

Fixes ERR_MODULE_NOT_FOUND: Cannot find package 'keyv' on fresh installs.

Written by Cameron ◯ Letta Code

"The best time to fix a dependency bug is before someone reports it.
The second best time is immediately after." - Ancient npm proverb
2026-02-04 18:43:10 -08:00
Cameron
21957f5c6e feat: add slash command support to all channels (#145)
Adds /status, /heartbeat, /help, and /start commands to:
- Signal (was missing all commands)
- Slack (was missing all commands)
- WhatsApp (was missing all commands)
- Discord (was missing /help and /start)

Telegram already had full support.

Changes:
- Create src/core/commands.ts with shared HELP_TEXT and parseCommand()
- Add onCommand property to Signal, Slack, WhatsApp adapters
- Add command detection before onMessage in each adapter
- /help and /start are handled locally, /status and /heartbeat
  delegate to onCommand callback

Fixes #91

Written by Cameron ◯ Letta Code

"Consistency is the last refuge of the unimaginative." - Oscar Wilde
(But sometimes it's just good UX)
2026-02-04 16:56:44 -08:00
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
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
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
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
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
Sarah Wooders
e3f4d43dc8 Merge pull request #35 from letta-ai/fix/message-bubbles-and-tool-approval
Fix message bubbles and tool approval
2026-01-29 22:58:08 -08:00
Sarah Wooders
a41966657a Add Google Workspace setup wizard to onboarding
- Add stepGoogle() wizard that guides users through gog CLI setup
- Check/install gog via Homebrew, guide OAuth credential setup
- Let users select existing accounts or add new ones
- Configure which Google services to enable (gmail, calendar, drive, etc.)
- Add GoogleConfig type and integrations.google to config schema
- Wire GMAIL_ACCOUNT env var from YAML config for polling service
- Add discord.js dependency (fixes build)

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

Co-Authored-By: Letta <noreply@letta.com>
2026-01-29 22:51:53 -08:00
Cameron
fe61c8869f Fix message bubbles and tool approval
- Separate message bubbles when stream message type changes
  (e.g., assistant → tool_call → assistant now sends as separate messages)
- Track sentAnyMessage to avoid spurious "(No response from agent)"
- Add canUseTool workaround for SDK v0.0.3 bypassPermissions bug
  (see letta-ai/letta-code-sdk#10)
- Clean up verbose debug logging

Written by Cameron ◯ Letta Code

"The stream of consciousness is not a river but a series of pools." - William James
2026-01-29 21:58:02 -08:00
Jason Carreira
0f68b9b52f Add Discord channel support (#16)
* Add Discord channel support and pairing (#15)

* Address Discord adapter review feedback

* Fix stream counter after merge

* Remove stream count logging

---------

Co-authored-by: Jason Carreira <jason@visotrust.com>
2026-01-29 14:11:50 -08:00
Sarah Wooders
b72150c193 Add YAML config system (types and io) 2026-01-28 22:50:49 -08:00
Sarah Wooders
22770e6e88 Initial commit - LettaBot multi-channel AI assistant
Co-authored-by: Cameron Pfiffer <cameron@pfiffer.org>
Co-authored-by: Caren Thomas <carenthomas@gmail.com>
Co-authored-by: Charles Packer <packercharles@gmail.com>
Co-authored-by: Sarah Wooders <sarahwooders@gmail.com>
2026-01-28 18:02:51 -08:00