docs: align engine terminology in telegram and docs (#162)

This commit is contained in:
banteg
2026-01-17 13:55:49 +04:00
committed by GitHub
parent 0818e848b3
commit 9d7c6fcd8c
26 changed files with 64 additions and 63 deletions
+1 -1
View File
@@ -165,7 +165,7 @@ sequenceDiagram
Command->>RunnerBridge: run_one/run_many (optional)
RunnerBridge->>Telegram: Send progress/final
else Default routing
Bridge->>Bridge: Parse directives<br/>(/engine, /project, @branch)
Bridge->>Bridge: Parse directives<br/>(/&lt;engine-id&gt;, /&lt;project-alias&gt;, @branch)
Bridge->>Bridge: Extract resume token<br/>from reply
Bridge->>Bridge: Resolve worktree<br/>(if @branch)
+1 -1
View File
@@ -72,7 +72,7 @@ This lets you:
## IDs and collisions
Entrypoint names become plugin IDs and appear in user-facing surfaces (CLI subcommands, Telegram commands, `/engine` directives).
Entrypoint names become plugin IDs and appear in user-facing surfaces (CLI subcommands, Telegram commands, `/<engine-id>` directives).
Takopi validates IDs and rejects collisions with reserved names.
Plugin IDs must match:
+1 -1
View File
@@ -27,7 +27,7 @@ Reply-to-continue works even if topics or chat sessions are enabled.
For each message, Takopi:
- parses directive prefixes (`/engine`, `/project`, `@branch`) from the first non-empty line
- parses directive prefixes (`/<engine-id>`, `/<project-alias>`, `@branch`) from the first non-empty line
- attempts to extract a resume token by polling available runners
- if a resume token is found, routes to the matching runner; otherwise uses the configured default engine
+1 -2
View File
@@ -29,7 +29,7 @@ Use `/agent`:
- In normal chats, it affects the whole chat.
- In group chats, only admins can change defaults.
Selection precedence (highest to lowest): resume token → `/engine` directive → topic default → chat default → project default → global default.
Selection precedence (highest to lowest): resume token → `/<engine-id>` directive → topic default → chat default → project default → global default.
## Engine installation
@@ -40,4 +40,3 @@ Takopi shells out to engine CLIs. Install them and make sure theyre on your `
- [Commands & directives](../reference/commands-and-directives.md)
- [Config reference](../reference/config.md)
+3 -3
View File
@@ -1,6 +1,6 @@
# Topics
Topics bind Telegram **forum threads** to a project/branch context. Each topic keeps its own session and default agent, which is ideal for teams or multi-project work.
Topics bind Telegram **forum threads** to a project/branch context. Each topic keeps its own session and default engine, which is ideal for teams or multi-project work.
!!! tip "Workspace workflow"
If you chose the **workspace** workflow during [onboarding](../tutorials/install.md), topics are already enabled. This guide covers advanced topic configuration and usage.
@@ -9,7 +9,7 @@ Topics bind Telegram **forum threads** to a project/branch context. Each topic k
- Keep each thread tied to a repo + branch
- Avoid context collisions in busy team chats
- Set a default agent per topic with `/agent set`
- Set a default engine per topic with `/agent set`
## Requirements checklist
@@ -76,7 +76,7 @@ Note: Outside topics (private chats or main group chats), `/ctx` binds the chat
Use `/new` inside the topic to clear stored sessions for that thread.
## Set a default agent per topic
## Set a default engine per topic
Use `/agent set` inside the topic:
+1 -1
View File
@@ -44,7 +44,7 @@ echo ".worktrees/" >> ~/.config/git/ignore
## Context persistence
When project/worktree context is active, Takopi includes a `ctx:` footer in messages.
When you reply, this context carries forward (you usually dont need to repeat `/project @branch`).
When you reply, this context carries forward (you usually dont need to repeat `/<project-alias> @branch`).
## Related
+3 -1
View File
@@ -24,7 +24,9 @@ mytransport = "mytransport.backend:BACKEND"
mycommand = "mycommand.backend:BACKEND"
```
## Engine backend plugin (runner)
## Engine backend plugin
An engine backend builds a `Runner` via `build_runner(...)`.
Minimal example:
+1 -1
View File
@@ -68,7 +68,7 @@ Step-by-step guides for new users:
1. [Install & onboard](tutorials/install.md) — set up Takopi and your bot
2. [First run](tutorials/first-run.md) — send a task, watch it stream, continue the conversation
3. [Projects & branches](tutorials/projects-and-branches.md) — target repos from anywhere, run on feature branches
4. [Multi-engine](tutorials/multi-engine.md) — use different agents for different tasks
4. [Multi-engine](tutorials/multi-engine.md) — use different engines for different tasks
## How-to guides
+3 -3
View File
@@ -8,8 +8,8 @@ Takopi parses the first non-empty line of a message for a directive prefix.
| Directive | Example | Effect |
|----------|---------|--------|
| `/engine` | `/codex fix flaky test` | Select an engine for this message. |
| `/project` | `/happy-gadgets add escape-pod` | Select a project alias. |
| `/<engine-id>` | `/codex fix flaky test` | Select an engine for this message. |
| `/<project-alias>` | `/happy-gadgets add escape-pod` | Select a project alias. |
| `@branch` | `@feat/happy-camera rewind to checkpoint` | Run in a worktree for the branch. |
| Combined | `/happy-gadgets @feat/flower-pin observe unseen` | Project + branch. |
@@ -35,7 +35,7 @@ This line is parsed from replies and takes precedence over new directives.
| Command | Description |
|---------|-------------|
| `/cancel` | Reply to the progress message to stop the current run. |
| `/agent` | Show/set the default agent for the current scope. |
| `/agent` | Show/set the default engine for the current scope. |
| `/model` | Show/set the model override for the current scope. |
| `/reasoning` | Show/set the reasoning override for the current scope. |
| `/trigger` | Show/set trigger mode (mentions-only vs all). |
+3 -3
View File
@@ -92,8 +92,8 @@ Takopi parses the first non-empty line of a message for a directive prefix.
Supported directives:
- `/engine` or `/engine@bot`: chooses the engine
- `/project`: chooses a project alias
- `/<engine-id>` or `/<engine-id>@bot`: chooses the engine
- `/<project-alias>`: chooses a project alias
- `@branch`: chooses a git branch/worktree
Rules:
@@ -117,7 +117,7 @@ The `ctx:` line is parsed from replies and takes precedence over new directives.
When a message arrives in a chat whose `chat_id` matches `projects.<alias>.chat_id`,
Takopi defaults the project context to that alias unless a reply `ctx:` or explicit
`/project` directive is present.
`/<project-alias>` directive is present.
In non-topic chats, `/ctx` can bind a chat context. That bound context is treated as
ambient and takes precedence over the default project mapping until cleared.
+1 -1
View File
@@ -8,7 +8,7 @@ If youre trying to understand the *why*, use **[Explanation](../explanation/i
## Most-used reference pages
- [Commands & directives](commands-and-directives.md)
- Message prefixes like `/engine`, `/project`, and `@branch`
- Message prefixes like `/<engine-id>`, `/<project-alias>`, and `@branch`
- In-chat commands like `/cancel`, `/new`, `/ctx`, `/file …`, `/topic …`
- [Configuration](config.md)
- `takopi.toml` options and defaults
+1 -1
View File
@@ -65,7 +65,7 @@ To restore “only respond when invoked” behavior, use trigger mode:
Explicit invocation includes any of:
- `@botname` mention in the message.
- `/engine` or `/project_alias` as the first token.
- `/<engine-id>` or `/<project-alias>` as the first token.
- Replying to a bot message.
- Built-in or plugin slash commands (for example `/agent`, `/model`, `/reasoning`, `/file`, `/trigger`).
+1 -1
View File
@@ -38,7 +38,7 @@ To pin a project or branch for the chat, use:
`/new` clears the session but keeps the bound context.
Tip: set a default agent for this chat with `/agent set claude`.
Tip: set a default engine for this chat with `/agent set claude`.
## Stateless (reply-to-continue)
+3 -3
View File
@@ -19,7 +19,7 @@ Takopi keeps running in your terminal. In Telegram, your bot will post a startup
🐙 takopi is ready
default: codex<br>
agents: codex, claude<br>
engines: codex, claude<br>
projects: none<br>
mode: chat<br>
topics: disabled<br>
@@ -29,7 +29,7 @@ Takopi keeps running in your terminal. In Telegram, your bot will post a startup
The engines/projects list reflects your setup. This tells you:
- Which engine is the default
- Which agents are available (and any missing ones)
- Which engines are available (and any missing ones)
- Which projects are registered
- Which directory Takopi will run in
@@ -131,7 +131,7 @@ If a resume token was already issued (and resume lines are enabled), it will sti
## 7. Try a different engine
Want to use a different agent for one message? Prefix your message with `/<engine>`:
Want to use a different engine for one message? Prefix your message with `/<engine>`:
!!! user "You"
/claude explain the error handling in this codebase
+3 -3
View File
@@ -228,9 +228,9 @@ Once Takopi receives your message:
Takopi scans your PATH for installed agent CLIs:
```
step 4: default agent
step 4: default engine
takopi runs these agents on your computer. switch anytime with /agent.
takopi runs these engines on your computer. switch anytime with /agent.
engine status install command
───────────────────────────────────────────
@@ -239,7 +239,7 @@ takopi runs these agents on your computer. switch anytime with /agent.
opencode ✗ not found npm install -g opencode-ai@latest
pi ✗ not found npm install -g @mariozechner/pi-coding-agent
? choose default agent:
? choose default engine:
codex
claude
```
+7 -7
View File
@@ -1,14 +1,14 @@
# Multi-engine workflows
This tutorial shows you how to use different agents for different tasks and set up defaults so you don't have to think about it.
This tutorial shows you how to use different engines for different tasks and set up defaults so you don't have to think about it.
**What you'll learn:** Engine directives, persistent defaults, and when to use which agent.
**What you'll learn:** Engine directives, persistent defaults, and when to use which engine.
## Why multiple engines?
Different agents have different strengths:
Different engines have different strengths:
| Agent | Good at |
| Engine | Good at |
|-------|---------|
| **Codex** | Fast edits, shell commands, quick fixes |
| **Claude Code** | Complex refactors, architecture, long context |
@@ -65,7 +65,7 @@ Use `/agent set` to change the default for the current scope:
Response:
!!! takopi "Takopi"
chat default agent set to claude
chat default engine set to claude
Now all new conversations in this chat use Claude (unless you explicitly override with `/codex`).
@@ -77,7 +77,7 @@ Check the current default:
Example response:
!!! takopi "Takopi"
agent: claude (chat default)<br>
engine: claude (chat default)<br>
defaults: topic: none, chat: claude, project: none, global: codex<br>
available: codex, claude, opencode, pi
@@ -89,7 +89,7 @@ Clear it:
Response:
!!! takopi "Takopi"
chat default agent cleared.
chat default engine cleared.
## 4. Defaults in topics
+3 -3
View File
@@ -2,7 +2,7 @@
This tutorial shows you how to register repos as projects and run tasks on feature branches without switching directories.
**What you'll learn:** How to target repos from anywhere with `/project`, and run on branches with `@branch`.
**What you'll learn:** How to target repos from anywhere with `/<project-alias>`, and run on branches with `@branch`.
## The problem
@@ -123,7 +123,7 @@ Replies stay on the same branch. Your main checkout is untouched.
## 5. Context persistence
Once you've set a context (via `/project @branch` or by replying), it sticks:
Once you've set a context (via `/<project-alias> @branch` or by replying), it sticks:
!!! user "You"
/happy-gadgets @feat/new-login add tests
@@ -155,7 +155,7 @@ If you mostly work in one repo, set it as the default:
default_project = "happy-gadgets"
```
Now messages without a `/project` prefix go to that repo:
Now messages without a `/<project-alias>` prefix go to that repo:
!!! user "You"
add a health check endpoint
+1 -1
View File
@@ -71,7 +71,7 @@ def _build_startup_message(
return (
f"\N{OCTOPUS} **takopi is ready**\n\n"
f"default: `{runtime.default_engine}` \n"
f"agents: `{engine_list}` \n"
f"engines: `{engine_list}` \n"
f"projects: `{project_list}` \n"
f"mode: `{session_mode}` \n"
f"topics: `{topics_label}` \n"
+9 -9
View File
@@ -25,17 +25,17 @@ async def _check_agent_permissions(
reply = make_reply(cfg, msg)
sender_id = msg.sender_id
if sender_id is None:
await reply(text="cannot verify sender for agent defaults.")
await reply(text="cannot verify sender for engine defaults.")
return False
if msg.is_private:
return True
member = await cfg.bot.get_chat_member(msg.chat_id, sender_id)
if member is None:
await reply(text="failed to verify agent permissions.")
await reply(text="failed to verify engine permissions.")
return False
if member.status in {"creator", "administrator"}:
return True
await reply(text="changing default agents is restricted to group admins.")
await reply(text="changing default engines is restricted to group admins.")
return False
@@ -86,7 +86,7 @@ async def _handle_agent_command(
"project_default": "project default",
"global_default": "global default",
}
agent_line = f"agent: {selection.engine} ({source_labels[selection.source]})"
agent_line = f"engine: {selection.engine} ({source_labels[selection.source]})"
topic_override = None
if tkey is not None and topic_store is not None:
topic_override = await topic_store.get_engine_override(
@@ -159,7 +159,7 @@ async def _handle_agent_command(
if engine not in cfg.runtime.engine_ids:
available = ", ".join(cfg.runtime.engine_ids)
await reply(
text=f"unknown engine `{engine}`.\navailable agents: `{available}`",
text=f"unknown engine `{engine}`.\navailable engines: `{available}`",
)
return
if tkey is not None:
@@ -167,13 +167,13 @@ async def _handle_agent_command(
await reply(text="topic defaults are unavailable.")
return
await topic_store.set_default_engine(tkey[0], tkey[1], engine)
await reply(text=f"topic default agent set to `{engine}`")
await reply(text=f"topic default engine set to `{engine}`")
return
if chat_prefs is None:
await reply(text="chat defaults are unavailable (no config path).")
return
await chat_prefs.set_default_engine(msg.chat_id, engine)
await reply(text=f"chat default agent set to `{engine}`")
await reply(text=f"chat default engine set to `{engine}`")
return
if action == "clear":
@@ -184,13 +184,13 @@ async def _handle_agent_command(
await reply(text="topic defaults are unavailable.")
return
await topic_store.clear_default_engine(tkey[0], tkey[1])
await reply(text="topic default agent cleared.")
await reply(text="topic default engine cleared.")
return
if chat_prefs is None:
await reply(text="chat defaults are unavailable (no config path).")
return
await chat_prefs.clear_default_engine(msg.chat_id)
await reply(text="chat default agent cleared.")
await reply(text="chat default engine cleared.")
return
await reply(text=AGENT_USAGE)
+2 -2
View File
@@ -29,7 +29,7 @@ def build_bot_commands(
cmd = engine_id.lower()
if cmd in seen:
continue
commands.append({"command": cmd, "description": f"use agent: {cmd}"})
commands.append({"command": cmd, "description": f"use engine: {cmd}"})
seen.add(cmd)
for alias in runtime.project_aliases():
cmd = alias.lower()
@@ -73,7 +73,7 @@ def build_bot_commands(
for cmd, description in [
("new", "start a new thread"),
("ctx", "show or update context"),
("agent", "set default agent"),
("agent", "set default engine"),
("model", "set model override"),
("reasoning", "set reasoning override"),
("trigger", "set trigger mode"),
+2 -2
View File
@@ -122,7 +122,7 @@ async def _handle_model_command(
if engine not in engine_ids:
available = ", ".join(cfg.runtime.engine_ids)
await reply(
text=f"unknown engine `{engine}`.\navailable agents: `{available}`"
text=f"unknown engine `{engine}`.\navailable engines: `{available}`"
)
return
scope = await apply_engine_override(
@@ -187,7 +187,7 @@ async def _handle_model_command(
if engine not in engine_ids:
available = ", ".join(cfg.runtime.engine_ids)
await reply(
text=f"unknown engine `{engine}`.\navailable agents: `{available}`"
text=f"unknown engine `{engine}`.\navailable engines: `{available}`"
)
return
scope = await apply_engine_override(
+2 -2
View File
@@ -130,7 +130,7 @@ async def _handle_reasoning_command(
if engine not in engine_ids:
available = ", ".join(cfg.runtime.engine_ids)
await reply(
text=f"unknown engine `{engine}`.\navailable agents: `{available}`"
text=f"unknown engine `{engine}`.\navailable engines: `{available}`"
)
return
normalized_level = level.strip().lower()
@@ -206,7 +206,7 @@ async def _handle_reasoning_command(
if engine not in engine_ids:
available = ", ".join(cfg.runtime.engine_ids)
await reply(
text=f"unknown engine `{engine}`.\navailable agents: `{available}`"
text=f"unknown engine `{engine}`.\navailable engines: `{available}`"
)
return
scope = await apply_engine_override(
+4 -4
View File
@@ -877,7 +877,7 @@ async def step_capture_chat(ui: UI, svc: Services, state: OnboardingState) -> No
async def step_default_engine(ui: UI, svc: Services, state: OnboardingState) -> None:
ui.print("takopi runs these agents on your computer. switch anytime with /agent.")
ui.print("takopi runs these engines on your computer. switch anytime with /agent.")
rows = svc.list_engines()
render_engine_table(ui, rows)
installed_ids = [engine_id for engine_id, installed, _ in rows if installed]
@@ -885,13 +885,13 @@ async def step_default_engine(ui: UI, svc: Services, state: OnboardingState) ->
if installed_ids:
ui.print("")
default_engine = await ui.select(
"choose default agent:",
"choose default engine:",
choices=[(engine_id, engine_id) for engine_id in installed_ids],
)
state.default_engine = require_value(default_engine)
return
ui.print("no agents found. install one and rerun --onboard.")
ui.print("no engines found. install one and rerun --onboard.")
ui.print("")
save_anyway = await ui.confirm("save config anyway?", default=False)
if not save_anyway:
@@ -945,7 +945,7 @@ STEPS: list[OnboardingStep] = [
OnboardingStep("bot token", 1, step_token_and_bot),
OnboardingStep("pick your workflow", 2, step_persona),
OnboardingStep("connect chat", 3, step_capture_chat),
OnboardingStep("default agent", 4, step_default_engine),
OnboardingStep("default engine", 4, step_default_engine),
OnboardingStep("save config", 5, step_save_config),
]
@@ -62,7 +62,7 @@ async def test_agent_show_private_defaults() -> None:
)
text = _last_text(transport)
assert "agent: codex" in text
assert "engine: codex" in text
assert "available: codex" in text
@@ -83,7 +83,7 @@ async def test_agent_set_clear_group_admin(tmp_path: Path) -> None:
)
assert await prefs.get_default_engine(msg.chat_id) == "codex"
assert "chat default agent set" in _last_text(transport)
assert "chat default engine set" in _last_text(transport)
await _handle_agent_command(
cfg,
@@ -95,7 +95,7 @@ async def test_agent_set_clear_group_admin(tmp_path: Path) -> None:
)
assert await prefs.get_default_engine(msg.chat_id) is None
assert "chat default agent cleared" in _last_text(transport)
assert "chat default engine cleared" in _last_text(transport)
@pytest.mark.anyio
@@ -135,7 +135,7 @@ async def test_agent_set_invalid_engine(tmp_path: Path) -> None:
text = _last_text(transport)
assert "unknown engine" in text
assert "available agents" in text
assert "available engines" in text
@pytest.mark.anyio
+2 -2
View File
@@ -50,7 +50,7 @@ def test_build_startup_message_includes_missing_engines(tmp_path: Path) -> None:
)
assert "takopi is ready" in message
assert "agents: `codex (not installed: pi)`" in message
assert "engines: `codex (not installed: pi)`" in message
assert "projects: `none`" in message
@@ -92,7 +92,7 @@ def test_build_startup_message_surfaces_unavailable_engine_reasons(
topics=TelegramTopicsSettings(),
)
assert "agents: `codex" in message
assert "engines: `codex" in message
assert "misconfigured: pi" in message
assert "failed to load: claude" in message
+1 -1
View File
@@ -136,7 +136,7 @@ def test_build_bot_commands_includes_cancel_and_engine() -> None:
assert {"command": "file", "description": "upload or fetch files"} in commands
assert {"command": "new", "description": "start a new thread"} in commands
assert {"command": "ctx", "description": "show or update context"} in commands
assert {"command": "agent", "description": "set default agent"} in commands
assert {"command": "agent", "description": "set default engine"} in commands
assert any(cmd["command"] == "codex" for cmd in commands)