Skip to content

Commit 0235374

Browse files
committed
fix(telegram): enable file attachments in final answers + update domain
- Make sendMedia handler fall back to SendDocument for unknown media types (zip, csv, pdf, etc.) - Add explicit file attachment instructions to Telegram system prompt (MEDIA:document:/path) - Update odek website URL from kode.21no.de → odek.21no.de in defaultSystem + Quick Facts - Update test to validate document fallback instead of error
1 parent c2f4088 commit 0235374

4 files changed

Lines changed: 23 additions & 17 deletions

File tree

cmd/odek/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ var version string
4747
//
4848
// Users can override this with --system, ODEK_SYSTEM, or system field
4949
// in config files. The default is used when no override is provided.
50-
const defaultSystem = `⚠️ ANTI-PATTERN — NEVER do this: call search_files, browser, shell, or any tool to look up basic facts about odek (its website, owner, repository, stack, or configuration). These are all defined in THIS prompt. If a user asks "what is odek's website?", just answer: https://kode.21no.de. Tool calls for odek facts waste time and tokens.
50+
const defaultSystem = `⚠️ ANTI-PATTERN — NEVER do this: call search_files, browser, shell, or any tool to look up basic facts about odek (its website, owner, repository, stack, or configuration). These are all defined in THIS prompt. If a user asks "what is odek's website?", just answer: https://odek.21no.de. Tool calls for odek facts waste time and tokens.
5151
5252
You are odek — an expert software engineer who ships. You have deep knowledge of systems, architecture, and the craft of writing software. You work fast, think clearly, and build things that last.
5353
@@ -56,7 +56,7 @@ About odek:
5656
binary (~11 MB, instant startup) that implements the ReAct loop with tools,
5757
skills, memory, sub-agents, and sandboxing.
5858
- Built by 21no.de (https://21no.de), an AI/systems research lab.
59-
- Website: https://kode.21no.de
59+
- Website: https://odek.21no.de
6060
- GitHub: injected from config (see Repository URL below).
6161
- Stack: Go 1.24+, minimal dependencies, Docker sandbox support,
6262
layered config (global → project → env → CLI), Telegram bot integration.

cmd/odek/telegram.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,22 @@ func telegramCmd(args []string) error {
149149

150150
// Telegram-specific Quick Facts and recovery guidance
151151
systemMessage += "\n\nQuick Facts (use these, do NOT search):\n"
152-
systemMessage += "- odek website: https://kode.21no.de\n"
152+
systemMessage += "- odek website: https://odek.21no.de\n"
153153
systemMessage += "- Built by: 21no.de (https://21no.de)\n"
154154
if resolved.GithubRepoUrl != "" {
155155
systemMessage += fmt.Sprintf("- Source code: %s\n", resolved.GithubRepoUrl)
156156
}
157-
systemMessage += "- Binary name: odek (repo is called kode on GitHub)\n"
157+
systemMessage += "- Binary name: odek\n"
158158
systemMessage += "- Language: Go, minimal dependencies, ~11 MB binary\n"
159159
systemMessage += "\n"
160+
systemMessage += "File attachment:\n"
161+
systemMessage += "- You CAN send files (zip, pdf, images, csv, etc.) in BOTH intermediate replies\n"
162+
systemMessage += " (via send_message with the 'file' parameter) AND in your final answer.\n"
163+
systemMessage += "- For final answers: include MEDIA:document:/absolute/path/to/file at the START\n"
164+
systemMessage += " of your response to attach a file. The user will receive it as a native document.\n"
165+
systemMessage += "- For images: use MEDIA:photo:/path, for voice: MEDIA:voice:/path.\n"
166+
systemMessage += "- The file MUST exist on disk at the path you provide.\n"
167+
systemMessage += "\n"
160168
systemMessage += "Tool failure recovery:\n"
161169
systemMessage += "- If a tool fails with 'no such file' or returns empty, check pwd first.\n"
162170
systemMessage += "- NEVER run 'find /' or recursive searches from root — they hang.\n"

internal/telegram/handler.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,11 +446,12 @@ func (h *Handler) sendMedia(chatID int64, text string, replyToMessageID int) {
446446
}
447447
_, err = h.Bot.SendDocument(chatID, filePath, "", opts)
448448
default:
449-
h.log.Error("unknown media type", "chat_id", chatID, "media_type", mediaType)
450-
if h.OnError != nil {
451-
h.OnError(chatID, fmt.Errorf("telegram: unknown media type: %s", mediaType))
449+
// Unknown media type — send as a document (zip, csv, pdf, etc.)
450+
var opts *SendOpts
451+
if replyToMessageID != 0 {
452+
opts = &SendOpts{ReplyToMessageID: replyToMessageID}
452453
}
453-
return
454+
_, err = h.Bot.SendDocument(chatID, filePath, "", opts)
454455
}
455456

456457
if err != nil {

internal/telegram/handler_test.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,21 +1086,18 @@ func TestSendResponse_MediaUnknownType(t *testing.T) {
10861086
bot := testBot(t, ts)
10871087
h := NewHandler(bot)
10881088

1089-
errCalled := false
1090-
h.OnError = func(_ int64, err error) {
1091-
errCalled = true
1092-
}
1093-
10941089
h.SendResponse(123, "MEDIA:video:"+tmpPath, 0)
10951090

10961091
reqs := rec.all()
1092+
found := false
10971093
for _, req := range reqs {
1098-
if strings.HasSuffix(req.Path, "/sendPhoto") || strings.HasSuffix(req.Path, "/sendVoice") || strings.HasSuffix(req.Path, "/sendDocument") {
1099-
t.Errorf("unexpected send request for unknown media type: %s", req.Path)
1094+
if strings.HasSuffix(req.Path, "/sendDocument") {
1095+
found = true
1096+
break
11001097
}
11011098
}
1102-
if !errCalled {
1103-
t.Error("OnError was not called for unknown media type")
1099+
if !found {
1100+
t.Error("expected sendDocument for unknown media type, got none")
11041101
}
11051102
}
11061103

0 commit comments

Comments
 (0)