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>
This commit is contained in:
@@ -10,6 +10,7 @@ Send a message to the most recent chat, or target a specific channel/chat.
|
||||
```bash
|
||||
lettabot-message send --text "Hello from a background task"
|
||||
lettabot-message send --text "Hello" --channel slack --chat C123456
|
||||
lettabot-message send --file /tmp/report.pdf --text "Report attached" --channel discord --chat 123456789
|
||||
```
|
||||
|
||||
## lettabot-react
|
||||
@@ -34,3 +35,4 @@ Notes:
|
||||
- History fetch is not supported by the Telegram Bot API, Signal, or WhatsApp.
|
||||
- If you omit `--channel` or `--chat`, the CLI falls back to the last message target stored in `lettabot-agent.json`.
|
||||
- You need the channel-specific bot token set (`DISCORD_BOT_TOKEN` or `SLACK_BOT_TOKEN`).
|
||||
- File sending uses the API server and requires `LETTABOT_API_KEY` (supported: telegram, slack, discord, whatsapp).
|
||||
|
||||
@@ -455,6 +455,21 @@ Precedence: `prompt` (inline YAML) > `HEARTBEAT_PROMPT` (env var) > `promptFile`
|
||||
| `features.heartbeat.prompt` | string | _(none)_ | Custom heartbeat prompt text |
|
||||
| `features.heartbeat.promptFile` | string | _(none)_ | Path to prompt file (relative to working dir) |
|
||||
|
||||
### Send-File Directory
|
||||
|
||||
The `<send-file>` [response directive](./directives.md) allows the agent to send files to channels. For security, file paths are restricted to a configurable directory:
|
||||
|
||||
```yaml
|
||||
features:
|
||||
sendFileDir: ./data/outbound # Default: agent working directory
|
||||
```
|
||||
|
||||
Only files inside this directory (and its subdirectories) can be sent. Paths that resolve outside it are blocked. This prevents prompt injection attacks from exfiltrating sensitive files.
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `features.sendFileDir` | string | _(workingDir)_ | Directory that `<send-file>` paths must be inside |
|
||||
|
||||
### Cron Jobs
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -41,6 +41,28 @@ Adds an emoji reaction to a message.
|
||||
- Unicode emoji: direct characters like `👍`
|
||||
- `message` (optional) -- Target message ID. Defaults to the message that triggered the response.
|
||||
|
||||
### `<send-file>`
|
||||
|
||||
Sends a file or image to the same channel/chat as the triggering message.
|
||||
|
||||
```xml
|
||||
<send-file path="/tmp/report.pdf" caption="Report attached" />
|
||||
<send-file path="/tmp/photo.png" kind="image" caption="Look!" />
|
||||
<send-file path="/tmp/temp-export.csv" cleanup="true" />
|
||||
```
|
||||
|
||||
**Attributes:**
|
||||
- `path` / `file` (required) -- Local file path on the LettaBot server
|
||||
- `caption` / `text` (optional) -- Caption text for the file
|
||||
- `kind` (optional) -- `image` or `file` (defaults to auto-detect based on extension)
|
||||
- `cleanup` (optional) -- `true` to delete the file after sending (default: false)
|
||||
|
||||
**Security:**
|
||||
- File paths are restricted to the configured `sendFileDir` directory (defaults to `data/outbound/` under the agent's working directory). Paths outside this directory are blocked and logged.
|
||||
- Symlinks that resolve outside the allowed directory are also blocked.
|
||||
- File size is limited to `sendFileMaxSize` (default: 50MB).
|
||||
- The `cleanup` attribute only works when `sendFileCleanup: true` is set in the agent's features config (disabled by default).
|
||||
|
||||
### `<no-reply/>`
|
||||
|
||||
Suppresses response delivery entirely. The agent's text is discarded.
|
||||
@@ -66,13 +88,13 @@ Backslash-escaped quotes (common when LLMs generate XML inside a JSON context) a
|
||||
|
||||
## Channel Support
|
||||
|
||||
| Channel | `addReaction` | Notes |
|
||||
|-----------|:---:|-------|
|
||||
| Telegram | Yes | Limited to Telegram's [allowed reaction set](https://core.telegram.org/bots/api#reactiontype) (~75 emoji) |
|
||||
| Slack | Yes | Uses Slack emoji names (`:thumbsup:` style). Custom workspace emoji supported. |
|
||||
| Discord | Yes | Unicode emoji and common aliases. Custom server emoji not yet supported. |
|
||||
| WhatsApp | No | Directive is skipped with a warning |
|
||||
| Signal | No | Directive is skipped with a warning |
|
||||
| Channel | `addReaction` | `send-file` | Notes |
|
||||
|-----------|:---:|:---:|-------|
|
||||
| Telegram | Yes | Yes | Reactions limited to Telegram's [allowed reaction set](https://core.telegram.org/bots/api#reactiontype). |
|
||||
| Slack | Yes | Yes | Reactions use Slack emoji names (`:thumbsup:` style). |
|
||||
| Discord | Yes | Yes | Custom server emoji not yet supported. |
|
||||
| WhatsApp | No | Yes | Reactions skipped with a warning. |
|
||||
| Signal | No | No | Directive skipped with a warning. |
|
||||
|
||||
When a channel doesn't implement `addReaction`, the directive is silently skipped and a warning is logged. This never blocks message delivery.
|
||||
|
||||
@@ -112,7 +134,7 @@ The parser (`src/core/directives.ts`) is designed to be extensible. Adding a new
|
||||
3. Add a parsing case in `parseChildDirectives()`
|
||||
4. Add an execution case in `executeDirectives()` in `bot.ts`
|
||||
|
||||
See issue [#240](https://github.com/letta-ai/lettabot/issues/240) for planned directives like `<send-file>`.
|
||||
See issue [#240](https://github.com/letta-ai/lettabot/issues/240) for planned directives.
|
||||
|
||||
## Source
|
||||
|
||||
|
||||
Reference in New Issue
Block a user