Commit Graph

77 Commits

Author SHA1 Message Date
Cameron
c71c45150e feat: add ignoreBotReactions config toggle for Discord (#508) 2026-03-06 12:03:42 -08:00
Cameron
761de6d716 feat: add set-conversation command (CLI, API, channel, portal) (#512) 2026-03-06 11:30:06 -08:00
Cameron
025fd38d5f feat: add per-group daily message limits (dailyLimit + dailyUserLimit) (#484) 2026-03-04 12:55:49 -08:00
dustindoan
587621d9e4 fix: close API server on shutdown to prevent EADDRINUSE (#477)
Co-authored-by: Dustin Doan <dustin@myhealthspan.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:40:58 -08:00
Nouamane Benbrahim
94b7eea127 feat: unified lettabot initialization via lettactl (agents.yml) (#393)
Co-authored-by: Cameron <cameron@pfiffer.org>
2026-03-03 14:13:13 -08:00
Jason Carreira
e7f6e85880 feat(polling): add custom prompt support for Gmail email polling (#471)
Co-authored-by: Letta Code <noreply@letta.com>
2026-03-03 11:24:58 -08:00
Cameron
dac3ae4a05 fix: raise default heartbeat interval to 4h, add cost warning in wizard (#467) 2026-03-02 18:36:58 -08:00
github-actions[bot]
157a192fba fix: guard against n-1 desync in stream result handling (#444)
Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: Cameron <cpfiffer@users.noreply.github.com>
2026-03-02 13:44:21 -08:00
Cameron
6a2493da5c feat: make streaming edits toggleable per-channel, disabled by default (#436) 2026-02-27 16:08:51 -08:00
Cameron
481b458af1 feat: cloud deployment support with inline config, Dockerfile, and admin portal (#434) 2026-02-27 15:24:17 -08:00
Cameron
9421027234 fix: scope cron jobs to individual agents in multi-agent mode (#432) 2026-02-27 14:58:48 -08:00
Cameron
3bf245a84e feat: outbound message redaction for secrets and PII (#416) 2026-02-26 15:39:49 -08:00
Cameron
d11777a1a2 feat: per-agent workingDir config (#412) 2026-02-26 14:22:16 -08:00
Cameron
325136ace3 feat: per-agent allowedTools and disallowedTools config (#410) 2026-02-26 13:50:58 -08:00
Cameron
955bdacab7 fix: merge env var credentials into YAML channel blocks and warn on silent skip (#408) 2026-02-26 10:48:14 -08:00
Cameron
d283f837ac refactor: migrate runtime console.log calls to structured logger (#397) 2026-02-26 10:16:38 -08:00
Cameron
e96ddc1db1 feat: add voice memo responses via TTS (#394) 2026-02-25 16:47:33 -08:00
Cameron
3c7352274e refactor: deduplicate sleep helpers into src/utils (#399) 2026-02-25 14:29:31 -08:00
Cameron
07d6939ead refactor: deduplicate parse helpers into src/utils (#398) 2026-02-25 14:27:06 -08:00
Jason Carreira
69b3d165d6 Add per-channel conversation overrides (#340)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cameron <cameron@pfiffer.org>
2026-02-24 11:14:26 -08:00
Cameron
1cad6e6508 feat(core): structured logging with pino (#368) 2026-02-23 16:35:23 -08:00
Jason Carreira
1fbd6d5a2e Add send-file directive and Discord/CLI file support (#319)
Co-authored-by: Jason Carreira <jason@visotrust.com>
Co-authored-by: Cameron <cameron@pfiffer.org>
Co-authored-by: Charles Packer <packercharles@gmail.com>
Co-authored-by: Sarah Wooders <sarahwooders@gmail.com>
Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 15:44:34 -08:00
Cameron
6bda859559 fix: default memfs to false instead of undefined (#362) 2026-02-23 12:59:13 -08:00
Cameron
4fa212a9a1 fix: harden agent store persistence and startup agent discovery (#357) 2026-02-23 12:06:53 -08:00
Cameron
0544102fe3 feat: display tool calls and reasoning in channel output (#302) 2026-02-23 09:15:43 -08:00
github-actions[bot]
a3c944bd13 feat: expose memfs (memory filesystem) option in lettabot config and SDK session (#336)
Adds features.memfs config key that controls whether the Letta Code CLI
receives --memfs or --no-memfs when creating/resuming SDK sessions. This
enables lettabot users to opt into git-backed memory filesystem (context
repositories) for persistent local memory sync.

- Config types: memfs?: boolean on AgentConfig.features, LettaBotConfig.features, BotConfig
- Bot wiring: baseSessionOptions() and createAgent() pass memfs to SDK when defined
- Main wiring: YAML config takes precedence, LETTABOT_MEMFS env var as fallback
- Legacy fix: conversations passthrough in single-agent normalization
- Tests: 3 memfs wiring tests (true/false/undefined), 2 conversations passthrough tests
- Docs: configuration.md section with known limitations, example YAML

Fixes #335

Written by Cameron and Letta Code

"The best way to predict the future is to implement it." -- David Heinemeier Hansson
2026-02-22 05:37:01 +01:00
Cameron
560380d721 feat: per-channel conversation routing (#299) 2026-02-13 17:21:38 -08:00
Cameron
296db3a858 fix: expose WhatsApp/Signal connection fields in per-agent config (#294) 2026-02-12 18:40:46 -08:00
John Wessel
d0a34d209e Auto-bind to 0.0.0.0 on container platforms for health checks (#291)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 18:38:47 -08:00
Cameron
014c2b56aa fix: read heartbeat target from per-agent config (#292) 2026-02-12 18:36:25 -08:00
Cameron
b79d705a99 perf: reuse SDK session subprocess across messages (#289) 2026-02-12 11:24:58 -08:00
Cameron
01ed38a15d feat: per-agent todo system with heartbeat integration (#288) 2026-02-12 10:23:14 -08:00
Cameron
046f15feaa fix: centralize strict config loading and fail fast on invalid config (#280) 2026-02-11 10:47:16 -08:00
Cameron
c0f82ccd63 Merge remote-tracking branch 'origin/fix/server-api-config' into HEAD
# Conflicts:
#	docs/configuration.md
#	src/config/io.ts
#	src/main.ts
2026-02-10 20:39:54 -08:00
Charles Packer
de1adcf4fe fix: fix server terminology with mode aliases (#277) 2026-02-10 20:34:29 -08:00
Cameron
c4c8b17018 fix: support server.api config, preserve api across onboard, fix load error logging
Three bugs fixed:

1. server.api is now the canonical location for API server config (port,
   host, CORS). Users naturally nest api under server -- this now works.
   Top-level api still accepted with a deprecation warning.

2. Onboarding no longer silently drops api and attachments config when
   saving. Both interactive and non-interactive paths now preserve
   unmanaged top-level fields from the existing config.

3. When YAML parsing fails, the log no longer misleadingly says
   "Loaded from lettabot.yaml". A didLoadFail() flag enables accurate
   status reporting without changing 17+ loadConfig() call sites.

Written by Cameron ◯ Letta Code

"The map is not the territory, but a good map sure helps you find port 6702."
2026-02-10 20:16:36 -08:00
Cameron
57f102dfd4 feat: add loom ASCII art startup banner (#270) 2026-02-10 17:57:19 -08:00
ghosttigerllc-bit
28adc22388 feat: add telegram-mtproto channel for user account messaging (#189)
Co-authored-by: Kai <noreply@gtb.ai>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Cameron <cameron@pfiffer.org>
2026-02-10 17:25:44 -08:00
Charles Packer
c7cb3b723b Merge pull request #260 from letta-ai/feat/disallow-interactive-plan-tools
feat: add disallowed interactive tools config for sessions
2026-02-10 16:20:33 -08:00
Cameron
c410decd18 feat: unified group modes (open/listen/mention-only) (#267)
Consolidates listeningGroups and groups.requireMention into a single
groups config with explicit mode per group. Backward compatible --
legacy formats auto-normalize with deprecation warnings.

- Add shared group-mode.ts with isGroupAllowed/resolveGroupMode helpers
- Update all 5 channel adapters to use mode-based gating
- Default to mention-only for configured entries (safe), open when no config
- Listening mode now set at adapter level, bot.ts has legacy fallback
- Fix YAML large-ID parsing for groups map keys (Discord snowflakes)
- Add migration in normalizeAgents for listeningGroups + requireMention
- Add unit tests for group-mode helpers + update all gating tests
- Update docs, README, and example config

Closes #266

Written by Cameron and Letta Code

"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery
2026-02-10 16:01:21 -08:00
Cameron
e8a97a2cbb fix: add stream debug visibility for tool calls and UUID gap detection (#264)
Tool call events between assistant messages were invisible in [Stream]
debug output, making it hard to understand message finalization timing.

- Add sawNonAssistantSinceLastUuid tracking to warn when assistant UUID
  changes with no visible tool_call/reasoning events in between
- Replace [Bot] tool logging with [Stream]-prefixed structured summaries
  (>>> TOOL CALL, <<< TOOL RESULT) for greppable output
- Bridge DEBUG=1 to DEBUG_SDK=1 so SDK-level dropped wire messages are
  visible when debugging

Written by Cameron ◯ Letta Code

"The stream does not resist the rock; it flows around it, revealing its shape." -- Unknown
2026-02-10 14:49:06 -08:00
Cameron
f5371a9ba7 feat: add group gating to Telegram, Discord, and Slack (#258) (#265)
WhatsApp and Signal already had groups config with requireMention and
group allowlists. This brings the same pattern to the remaining three
channels, giving operators consistent control over which groups the bot
participates in and whether mentions are required.

- New `groups` config for Telegram, Discord, Slack (per-group allowlist
  with requireMention, wildcard support)
- Telegram: standalone gating module with entity, text, command, and
  regex mention detection; applied to text, voice, and attachment handlers
- Discord: inline gating using native message.mentions API
- Slack: gating in message handler (drops non-mentions) and app_mention
  handler (allowlist check); helper methods on adapter
- Signal: pass wasMentioned through to InboundMessage (was detected but
  never forwarded)
- Config wiring: groups/mentionPatterns forwarded from main.ts to all
  adapter constructors
- 17 new tests for Telegram gating

Written by Cameron ◯ Letta Code

"Even in the group chat of life, sometimes you gotta be @mentioned
to know the universe is talking to you." — Ancient Internet Proverb
2026-02-10 14:47:19 -08:00
cpacker
c1ca8a8080 feat: add disallowed interactive tools config for sessions 2026-02-10 13:21:58 -08:00
Cameron
df18cba565 feat: configurable displayName prefix for agent messages in group chats (#255)
Add optional displayName field to agent config. When set, outbound
agent responses are prefixed (e.g. "💜 Signo: Hello!").

Useful in multi-agent group chats where multiple bots share a channel
and users need to tell them apart.

Closes #252

Written by Cameron ◯ Letta Code

"The details are not the details. They make the design." -- Charles Eames
2026-02-10 12:08:45 -08:00
Gabriele Sarti
0dbd743f7f feat: add listening mode for groups (#208)
Add `listeningGroups` config option (per-channel, same pattern as
`instantGroups`) where the bot periodically reads group messages and
sends them to the Letta agent for memory updates, but force-suppresses
response delivery unless the bot is explicitly mentioned.

- Add `isListeningMode` field to `InboundMessage`
- Add `listeningGroups` to all 5 channel configs
- Map `listeningGroups` to env vars in `configToEnv()`
- Rename `fixInstantGroupIds` to `fixLargeGroupIds` to also fix
  `listeningGroups` entries (Discord snowflake precision fix)
- Build `listeningGroupIds` set and pass to bot
- Tag messages as listening mode in `processGroupBatch()` when group
  is in listening mode and bot wasn't mentioned
- In `processMessage()`: skip typing indicator, heartbeat target
  update, recovery error messages, and force-suppress response
  delivery for listening mode messages
- Add `[OBSERVATION ONLY]` header to batch envelope for listening mode
- Document in lettabot.example.yaml

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:01:26 -08:00
Cameron
f2ec8f60c2 feat: support multiple Gmail accounts for polling (#244)
Add multi-account Gmail polling with per-account seen tracking, updated
onboarding flow, and config/env resolution.

Based on jasoncarreira's work in #214, rebased onto current main and
cleaned up:
- parseGmailAccounts() extracted to polling/service.ts with 10 unit tests
- Per-account seen email tracking (Map<string, Set<string>>) with legacy
  migration from single-account format
- Onboarding supports multi-select for existing accounts + add new
- Config resolution: polling.gmail.accounts > integrations.google.accounts
  (legacy) > GMAIL_ACCOUNT env (comma-separated)
- GoogleAccountConfig type for per-account service selection
- Updated docs/configuration.md

Closes #214.

Written by Cameron ◯ Letta Code

"Good artists copy, great artists steal." - Pablo Picasso
2026-02-09 16:58:34 -08:00
Cameron
2c2ecbce9b fix: switch group batching from fixed timer to 5-second debounce (#237)
The old 10-minute fixed timer caused groups to feel unresponsive after
inactivity. Now uses debounce: timer resets on every new message, flushes
after 5 seconds of quiet. @mentions still flush immediately.

New config: groupDebounceSec (default 5). Old groupPollIntervalMin still
works (converted to ms) for backward compatibility.

Fixes #229

Written by Cameron ◯ Letta Code

"The user is always right. If there is a problem with the use of the system, it's the system that's wrong, not the user." -- Don Norman
2026-02-09 11:11:24 -08:00
Cameron
4effadccb9 merge: resolve conflict with main (multi-agent architecture)
- Keep multi-agent normalizeAgents() flow from main
- Integrate deprecation warning for agent.model from PR
- Remove model from LettaBot constructor (server-side property)
- Remove Model: display from single-agent startup log

Written by Cameron ◯ Letta Code

"The best interface is no interface." -- Golden Krishna
2026-02-09 10:52:32 -08:00
Cameron
673f247793 feat: custom heartbeat prompt via YAML config or file (#233)
* feat: custom heartbeat prompt via YAML config or file

Wire up the existing but unused HeartbeatConfig.prompt field so users
can customize what the agent sees during heartbeats. Adds three ways
to set it: inline YAML (prompt), file-based (promptFile, re-read each
tick for live editing), and env var (HEARTBEAT_PROMPT). Also documents
the <no-reply/> opt-out behavior.

Fixes #232

Written by Cameron ◯ Letta Code

"The only way to do great work is to love what you do." -- Steve Jobs

* test: add coverage for heartbeat prompt resolution

Tests buildCustomHeartbeatPrompt and HeartbeatService prompt resolution:
- default prompt fallback
- inline prompt usage
- promptFile loading
- inline > promptFile precedence
- live reload (file re-read each tick)
- graceful fallback on missing file
- empty file falls back to default

Written by Cameron ◯ Letta Code

"The only way to do great work is to love what you do." -- Steve Jobs
2026-02-09 10:01:15 -08:00
Cameron
40586cdc9a fix: multi-agent state isolation and config.id wiring (#218)
Two bugs from the Phase 1 merge:

1. Store not scoped to agent name: LettaBot constructor passed no agent
   name to Store, so all agents in multi-agent mode shared the same
   agentId/conversationId state. Now passes config.agentName.

2. agentConfig.id ignored: Users could set `id: agent-abc123` in YAML
   but it was never applied. Now checked before store verification.

Written by Cameron ◯ Letta Code

"The best error message is the one that never shows up." -- Thomas Fuchs
2026-02-08 21:56:47 -08:00