Skip to content
Open
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
9 changes: 5 additions & 4 deletions src/bot/events/telegram-event-delivery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { promises as fs } from "fs";
import * as os from "os";
import * as path from "path";
import { fileURLToPath } from "url";
import { InputFile, type Bot, type Context } from "grammy";
import type { CodeFileData } from "../../app/formatters/summary-formatter.js";
import { logger } from "../../utils/logger.js";
Expand All @@ -14,9 +14,10 @@ import {
} from "../messages/telegram-text.js";
import type { TelegramRenderedPart } from "../render/types.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const TEMP_DIR = path.join(__dirname, "..", "..", ".tmp");
// The package directory can be read-only (a global npm install is owned by
// root), so outgoing files belong under the OS temp directory, not next to the
// compiled code. A failed mkdir there broke every tool-output upload.
const TEMP_DIR = path.join(os.tmpdir(), "opencode-telegram-bot");

type TelegramApi = Bot<Context>["api"];
type SendMessageOptions = Parameters<TelegramApi["sendMessage"]>[2];
Expand Down
28 changes: 28 additions & 0 deletions tests/bot/events/telegram-event-delivery.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { promises as fs } from "fs";
import * as os from "os";
import * as path from "path";
import { describe, expect, it, vi } from "vitest";
import {
TelegramEventDelivery,
Expand All @@ -10,6 +13,7 @@ function createDestination() {
sendMessageDraft: vi.fn().mockResolvedValue(true),
editMessageText: vi.fn().mockResolvedValue(undefined),
deleteMessage: vi.fn().mockResolvedValue(true),
sendDocument: vi.fn().mockResolvedValue({ message_id: 11 }),
};

return { api, destination: { api, chatId: 42 } as unknown as TelegramDestination };
Expand Down Expand Up @@ -91,4 +95,28 @@ describe("bot/events/telegram-event-delivery", () => {
expect(api.sendMessage).toHaveBeenNthCalledWith(2, 42, "draft reply", agentPreview);
expect(api.sendMessage).toHaveBeenNthCalledWith(3, 42, "🌐 webfetch https://example.com/");
});

it("stages outgoing documents in the OS temp directory, not beside the installed package", async () => {
const { destination } = createDestination();
const writeFile = vi.spyOn(fs, "writeFile").mockResolvedValue(undefined);

let stagedPath = "";
writeFile.mockImplementation((filePath) => {
stagedPath = String(filePath);
return Promise.resolve();
});

try {
await new TelegramEventDelivery().sendDocument(destination, {
buffer: Buffer.from("diff"),
filename: "write_app.ts.txt",
caption: "",
});
} finally {
writeFile.mockRestore();
}

expect(stagedPath).not.toBe("");
expect(path.dirname(stagedPath)).toBe(path.join(os.tmpdir(), "opencode-telegram-bot"));
});
});
Loading