Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,15 @@ File: [`src/claude.rs`](src/claude.rs)
| New chat | `claude -p --session-id <uuid>` |
| Resumed chat | `claude -p --resume <uuid>` |
| Instructions | `--append-system-prompt <composed system sections>` |
| Images | base64 content blocks over `--input-format stream-json` stdin |
| Unattended job | `--permission-mode bypassPermissions` |
| Evaluator | safe mode, no tools, no MCP, no Chrome, no session persistence |

Push chooses Claude's initial session ID and marks it started before execution
so a partial create failure is not retried as another create.
so a partial create failure is not retried as another create. Text-only turns
keep the single-result JSON command contract. Image turns use one streaming JSON
user message and parse the final result event without putting image data in
process arguments.

### Codex

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ toml = "1"
toml_edit = "0.23"
uuid = { version = "1", features = ["v4"] }
anyhow = "1"
base64 = "0.22"
humantime = "2"
sha2 = "0.10"
chrono-tz = "0.10"
Expand Down
19 changes: 9 additions & 10 deletions docs/telegram.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ Telegram-only preflight does not open `chat.db` and does not require macOS or

## Image Messages

With Codex or Pi selected for the conversation, send the bot a Telegram photo
or an image document. Push accepts JPEG, PNG, and WebP files. A caption becomes
the message text; an image without a caption is still accepted. Telegram media
groups are processed as separate messages.
Send the bot a Telegram photo or an image document with Claude Code, Codex, or
Pi selected for the conversation. Push accepts JPEG, PNG, and WebP files. A
caption becomes the message text; an image without a caption is still accepted.
Telegram media groups are processed as separate messages.

Push downloads an image only after the private-chat and sender allowlist checks
pass. The declared and downloaded size must fit within the 6 MiB per-message
Expand All @@ -67,13 +67,12 @@ Validated bytes are written to an owner-only temporary directory under
`$PUSH_HOME/cache`, attached to the agent turn, and removed after success,
failure, timeout, interruption, or session recovery. Push stores the caption or
an `[Image attachment]` placeholder in conversation history, not the image
bytes. The image is sent through the configured Codex or Pi model provider, so
review that provider's image and data controls before using this feature. Pi
receives images using its native `@image-path` arguments while message text
continues through standard input.
bytes. The image is sent through the configured model provider, so review that
provider's image and data controls before using this feature. Claude Code
receives base64 content blocks through streaming JSON input. Pi receives native
`@image-path` arguments while message text continues through standard input.

Image input for Claude Code, and sending generated images back through Telegram,
are not supported yet.
Sending generated images back through Telegram is not supported yet.

## Voice Messages

Expand Down
11 changes: 0 additions & 11 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,6 @@ impl Runner {
matches!(self, Runner::Claude(_))
}

pub fn supports_images(&self) -> bool {
if matches!(self, Runner::Codex(_) | Runner::Pi(_)) {
return true;
}
#[cfg(test)]
if let Self::Fake(runner) = self {
return matches!(runner.backend, AgentBackend::Codex | AgentBackend::Pi);
}
false
}

pub async fn run(&self, req: Request<'_>, timeout: Duration) -> Result<RunOutput, RunError> {
match self {
Runner::Claude(r) => r.run(req, timeout).await,
Expand Down
Loading
Loading