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
7 changes: 7 additions & 0 deletions src/gateway/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { saveAttachments as _saveAttachments, type AttachmentResult } from "./at
import { handleStreaming as _handleStream } from "./streaming";
import { handleNew, handleRestart, handleUpdate, handleCompact, handleStatus, handleStop, handleVerbose, handleDoctor, handleCrons, type CommandContext } from "./commands";
import { handleModel } from "./model-command";
import { handleLater } from "./later-command";
import { TelegramAdapter } from "../transports";
import type { TransportAdapter } from "../transports";
import { hostname } from "node:os";
Expand Down Expand Up @@ -271,6 +272,12 @@ export class Gateway {
return;
}

// Handle /later command
if (isCommandWithArgs(userText.trim(), "/later") || isCommand(userText.trim(), "/later")) {
await handleLater({ thread, text: userText.trim(), postWithFallback: (t, txt) => this.postWithFallback(t, txt) });
return;
}

// Dispatch to agent turn handler
await this.handleAgentTurn(thread, agentThreadId, userText, rawAttachments, verboseThreads, threadLocks, abortControllers);
};
Expand Down
57 changes: 57 additions & 0 deletions src/gateway/later-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* gateway/later-command.ts — Handle the /later command
*
* Quickly capture ideas/notes to ~/.roundhouse/workspace/later.md
* without interrupting the current conversation flow.
*/

import { homedir } from "node:os";
import { join } from "node:path";
import { appendFileSync, mkdirSync, existsSync, readFileSync } from "node:fs";

const WORKSPACE_DIR = join(homedir(), ".roundhouse", "workspace");
const LATER_PATH = join(WORKSPACE_DIR, "later.md");

export interface LaterCommandContext {
thread: any;
text: string;
postWithFallback: (thread: any, text: string) => Promise<void>;
}

function ensureWorkspace(): void {
if (!existsSync(WORKSPACE_DIR)) {
mkdirSync(WORKSPACE_DIR, { recursive: true });
}
}

function ensureLaterFile(): void {
ensureWorkspace();
if (!existsSync(LATER_PATH)) {
appendFileSync(LATER_PATH, "# Later\n\nIdeas, reminders, and things to get back to.\n\n");
}
}

export async function handleLater(ctx: LaterCommandContext): Promise<void> {
const { thread, text, postWithFallback } = ctx;
const idea = text.replace(/^\/later\s*/i, "").trim();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse /later@bot suffix before extracting idea

The idea extraction regex only strips /later followed by whitespace, so Telegram group-style commands like /later@MyBot or /later@MyBot buy milk are parsed incorrectly: the first case is treated as a new idea @MyBot instead of showing the list, and the second saves @MyBot buy milk instead of just the note text. Since command routing already accepts @botname variants, this handler should strip the optional @... suffix as part of command parsing to avoid corrupting saved entries in group chats.

Useful? React with 👍 / 👎.


// No argument: show contents
if (!idea) {
ensureLaterFile();
const contents = readFileSync(LATER_PATH, "utf8").trim();
const lines = contents.split("\n").filter(l => l.startsWith("- "));
if (lines.length === 0) {
await postWithFallback(thread, "📋 *Later list is empty.*\n\n_Usage:_ `/later buy more coffee`");
} else {
await postWithFallback(thread, `📋 *Later* (${lines.length} items):\n\n${lines.join("\n")}\n\n_File:_ \`~/.roundhouse/workspace/later.md\``);
}
return;
}

// Append the idea
ensureLaterFile();
const timestamp = new Date().toISOString().slice(0, 10);
appendFileSync(LATER_PATH, `- ${idea} _(${timestamp})_\n`);

await postWithFallback(thread, `✅ Saved: "${idea}"`);
}
8 changes: 8 additions & 0 deletions src/gateway/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

Available tools that can be invoked via shell commands during agent turns.

## Workspace Directory

**All new files, scratch work, downloads, and artifacts you create go under `~/.roundhouse/workspace/`.**
Do NOT create files directly in `~/` or pollute the home directory. Use subdirectories as needed:
- `~/.roundhouse/workspace/` — default working directory for any task output
- `~/.roundhouse/workspace/later.md` — ideas saved via `/later`
- `~/.roundhouse/workspace/<project>/` — project-specific files if needed

## roundhouse cron add

Schedule recurring or one-shot jobs. The user may ask you to "remind me", "check every X", "do Y later", or "schedule Z".
Expand Down
1 change: 1 addition & 0 deletions src/transports/telegram/bot-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const BOT_COMMANDS: BotCommand[] = [
{ command: "new", description: "Start a fresh conversation" },
{ command: "compact", description: "Compact context window" },
{ command: "model", description: "Show or switch AI model" },
{ command: "later", description: "Save an idea for later" },
{ command: "verbose", description: "Toggle verbose tool output" },
{ command: "stop", description: "Stop the current agent run" },
{ command: "restart", description: "Restart agent process" },
Expand Down
Loading