telecodex 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -139
- package/dist/bot/createBot.js +43 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,186 +1,151 @@
|
|
|
1
1
|
# telecodex
|
|
2
2
|
|
|
3
|
-
Telegram
|
|
3
|
+
Use Telegram forum topics as a remote interface for local Codex.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Telegram private chat
|
|
9
|
-
-> one-time admin bootstrap
|
|
10
|
-
|
|
11
|
-
Telegram forum supergroup
|
|
12
|
-
-> one project per supergroup
|
|
13
|
-
-> one topic per Codex thread
|
|
14
|
-
|
|
15
|
-
Telegram
|
|
16
|
-
-> grammY bot + runner
|
|
17
|
-
-> CodexSdkRuntime
|
|
18
|
-
-> @openai/codex-sdk
|
|
19
|
-
-> local Codex login
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
The bot talks to local Codex through `@openai/codex-sdk`, which wraps the local
|
|
23
|
-
`codex` CLI. It does not depend on `codex app-server`.
|
|
24
|
-
|
|
25
|
-
## Runtime contract
|
|
26
|
-
|
|
27
|
-
- Telegram is treated as a remote task interface, not a clone of Codex Desktop.
|
|
28
|
-
- One topic maps to one Codex SDK thread.
|
|
29
|
-
- Each topic has at most one active SDK run.
|
|
30
|
-
- Follow-up messages during an active run are queued and processed in order.
|
|
31
|
-
- The pending queue is in-memory only and is cleared on restart.
|
|
32
|
-
- Text and image messages are mapped to Codex SDK input.
|
|
33
|
-
- A run immediately creates a normal Telegram status message; progress edits that message.
|
|
34
|
-
- telecodex does not use pinned messages for live state.
|
|
35
|
-
- While a run is pending, the bot sends Telegram `typing` activity so the chat does not look dead during long SDK gaps.
|
|
36
|
-
- `/status` is the source of truth for runtime state, active thread id, last SDK event, and queue depth.
|
|
5
|
+
`telecodex` connects a Telegram bot to your local `codex` CLI through the
|
|
6
|
+
official TypeScript SDK. It is meant for remote task execution, not as a full
|
|
7
|
+
clone of Codex Desktop.
|
|
37
8
|
|
|
38
9
|
## Requirements
|
|
39
10
|
|
|
40
|
-
- Node.js 24 or newer
|
|
41
|
-
- A local `codex` CLI installation available on `PATH
|
|
42
|
-
- A valid local Codex login
|
|
11
|
+
- Node.js 24 or newer
|
|
12
|
+
- A local `codex` CLI installation available on `PATH`
|
|
13
|
+
- A valid local Codex login
|
|
14
|
+
- A Telegram bot token
|
|
15
|
+
|
|
16
|
+
Check Codex login first:
|
|
43
17
|
|
|
44
18
|
```bash
|
|
45
19
|
codex login status
|
|
46
20
|
```
|
|
47
21
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
## Install from npm
|
|
22
|
+
## Install
|
|
51
23
|
|
|
52
24
|
```bash
|
|
53
25
|
npm install -g telecodex
|
|
54
26
|
telecodex
|
|
55
27
|
```
|
|
56
28
|
|
|
57
|
-
`telecodex`
|
|
58
|
-
|
|
29
|
+
Installing `telecodex` does not replace the separate `codex` CLI. The bot uses
|
|
30
|
+
your local Codex installation at runtime.
|
|
59
31
|
|
|
60
|
-
##
|
|
32
|
+
## First Launch
|
|
61
33
|
|
|
62
|
-
|
|
34
|
+
On first launch, `telecodex`:
|
|
63
35
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
36
|
+
1. Finds or asks for the local `codex` binary path.
|
|
37
|
+
2. Verifies local Codex login.
|
|
38
|
+
3. Prompts for a Telegram bot token if none is stored yet.
|
|
39
|
+
4. Generates a one-time bootstrap code if no Telegram admin is bound yet.
|
|
40
|
+
5. Waits for that code in a private Telegram chat with the bot.
|
|
67
41
|
|
|
68
|
-
|
|
42
|
+
The first successful sender becomes the admin for that bot instance.
|
|
69
43
|
|
|
70
|
-
|
|
71
|
-
npm run dev
|
|
72
|
-
```
|
|
44
|
+
Optional security override:
|
|
73
45
|
|
|
74
|
-
|
|
75
|
-
|
|
46
|
+
- `TELECODEX_ALLOW_PLAINTEXT_TOKEN_FALLBACK=1` allows storing the Telegram bot
|
|
47
|
+
token unencrypted in local state when the system keychain is unavailable.
|
|
48
|
+
This is disabled by default.
|
|
76
49
|
|
|
77
|
-
##
|
|
50
|
+
## How It Works
|
|
78
51
|
|
|
79
|
-
|
|
52
|
+
- One Telegram forum supergroup represents one project.
|
|
53
|
+
- One topic inside that supergroup represents one Codex thread.
|
|
54
|
+
- Work happens by sending normal messages inside the topic.
|
|
55
|
+
- While a run is active, follow-up messages are queued automatically.
|
|
56
|
+
- `/status` shows the current runtime state.
|
|
80
57
|
|
|
81
|
-
|
|
82
|
-
- Organization or user: `jiangege`
|
|
83
|
-
- Repository: `telecodex`
|
|
84
|
-
- Workflow filename: `publish.yml`
|
|
85
|
-
2. Bump the version locally:
|
|
58
|
+
Private chat is only for bootstrap and lightweight admin actions.
|
|
86
59
|
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
## Quick Start
|
|
61
|
+
|
|
62
|
+
Inside a Telegram forum supergroup:
|
|
63
|
+
|
|
64
|
+
1. Bind the group to a project root:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
/project bind /absolute/path/to/project
|
|
89
68
|
```
|
|
90
69
|
|
|
91
|
-
|
|
70
|
+
2. Create a fresh topic for a new Codex thread:
|
|
92
71
|
|
|
93
|
-
```
|
|
94
|
-
|
|
72
|
+
```text
|
|
73
|
+
/thread new My Task
|
|
95
74
|
```
|
|
96
75
|
|
|
97
|
-
|
|
98
|
-
runs `npm run check`, runs `npm test`, and publishes the package to npm when the tag
|
|
99
|
-
matches the version in `package.json`.
|
|
76
|
+
3. Or resume an existing thread:
|
|
100
77
|
|
|
101
|
-
|
|
78
|
+
```text
|
|
79
|
+
/thread list
|
|
80
|
+
/thread resume <threadId>
|
|
81
|
+
```
|
|
102
82
|
|
|
103
|
-
|
|
83
|
+
4. Send normal messages in the topic to work with Codex.
|
|
104
84
|
|
|
105
|
-
|
|
106
|
-
2. Verifies Codex login.
|
|
107
|
-
3. Asks for a Telegram bot token if none is stored yet.
|
|
108
|
-
4. Generates a one-time bootstrap code if no Telegram admin is bound yet.
|
|
109
|
-
5. Waits for that code in a private chat. The first successful sender becomes the permanent admin for this bot instance.
|
|
85
|
+
## Commands
|
|
110
86
|
|
|
111
|
-
|
|
87
|
+
### General
|
|
112
88
|
|
|
113
|
-
|
|
89
|
+
- `/start` or `/help` - show usage help
|
|
90
|
+
- `/status` - show current state
|
|
91
|
+
- `/stop` - interrupt the active run in the current topic
|
|
114
92
|
|
|
115
|
-
|
|
93
|
+
### Admin
|
|
116
94
|
|
|
117
|
-
- `
|
|
95
|
+
- `/admin` - show admin binding and handoff state
|
|
96
|
+
- `/admin rebind` - issue a temporary handoff code
|
|
97
|
+
- `/admin cancel` - cancel a pending handoff
|
|
118
98
|
|
|
119
|
-
|
|
99
|
+
### Project
|
|
120
100
|
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
- Each topic in that supergroup is one Codex thread.
|
|
125
|
-
- Work happens by sending normal messages inside the topic.
|
|
126
|
-
- `/thread list` shows the saved Codex threads already recorded for the bound project root or its subdirectories.
|
|
127
|
-
- `/thread new <topic-name>` automatically creates a new topic; the first normal message inside it starts a fresh Codex thread.
|
|
128
|
-
- `/thread resume <threadId>` automatically creates a new topic and binds it to an existing thread id.
|
|
129
|
-
- On startup, telecodex probes stored topic bindings once and removes bindings whose Telegram topics no longer exist.
|
|
130
|
-
- On first launch after upgrading from the old SQLite state format, telecodex imports the legacy state once and then deletes the old SQLite files (`state.sqlite` plus sidecars such as `-wal`/`-shm`).
|
|
101
|
+
- `/project` - show the current project binding
|
|
102
|
+
- `/project bind <absolute-path>` - bind the current supergroup to a project root
|
|
103
|
+
- `/project unbind` - remove the project binding
|
|
131
104
|
|
|
132
|
-
|
|
105
|
+
### Threads
|
|
133
106
|
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
- Runtime logs: written by `pino` to `~/.telecodex/logs/telecodex.log`.
|
|
139
|
-
- Working directory: defaults to the directory where you ran `telecodex`.
|
|
107
|
+
- `/thread` - show the current attached thread id in a topic
|
|
108
|
+
- `/thread list` - list saved Codex threads for the current project
|
|
109
|
+
- `/thread new <topic-name>` - create a fresh topic for a new thread
|
|
110
|
+
- `/thread resume <threadId>` - create a topic and bind it to an existing thread
|
|
140
111
|
|
|
141
|
-
|
|
112
|
+
### Session Configuration
|
|
142
113
|
|
|
143
|
-
-
|
|
144
|
-
-
|
|
145
|
-
-
|
|
114
|
+
- `/cwd <absolute-path>`
|
|
115
|
+
- `/mode read|write|danger|yolo`
|
|
116
|
+
- `/sandbox <read-only|workspace-write|danger-full-access>`
|
|
117
|
+
- `/approval <on-request|on-failure|never>`
|
|
118
|
+
- `/yolo on|off`
|
|
119
|
+
- `/model <model-id>`
|
|
120
|
+
- `/effort default|minimal|low|medium|high|xhigh`
|
|
121
|
+
- `/web default|disabled|cached|live`
|
|
122
|
+
- `/network on|off`
|
|
123
|
+
- `/gitcheck skip|enforce`
|
|
124
|
+
- `/adddir list|add <path-inside-project>|add-external <absolute-path>|drop <index>|clear`
|
|
125
|
+
- `/schema show|set <JSON object>|clear`
|
|
126
|
+
- `/codexconfig show|set <JSON object>|clear`
|
|
146
127
|
|
|
147
|
-
##
|
|
128
|
+
## Images
|
|
129
|
+
|
|
130
|
+
- Sending an image in a topic is supported.
|
|
131
|
+
- Telegram photos and image documents are downloaded locally and sent to Codex as
|
|
132
|
+
`local_image` input.
|
|
133
|
+
- Image output is not rendered inline in Telegram text messages.
|
|
134
|
+
|
|
135
|
+
## Storage
|
|
136
|
+
|
|
137
|
+
- Telegram bot token: stored in the system keychain when available
|
|
138
|
+
- Durable local state: `~/.telecodex/state/`
|
|
139
|
+
- Runtime logs: `~/.telecodex/logs/telecodex.log`
|
|
140
|
+
- Codex thread history: read from Codex session files under `$CODEX_HOME/sessions`
|
|
141
|
+
(or `~/.codex/sessions` by default)
|
|
142
|
+
|
|
143
|
+
If an older `~/.telecodex/state.sqlite` exists, telecodex imports it once into
|
|
144
|
+
the JSON state files and then removes the old SQLite files.
|
|
145
|
+
|
|
146
|
+
## Troubleshooting
|
|
147
|
+
|
|
148
|
+
- If startup reports a login problem, run `codex login`.
|
|
149
|
+
- If the bot appears idle for a long time, check `/status`.
|
|
150
|
+
- If you need logs, inspect `~/.telecodex/logs/telecodex.log`.
|
|
148
151
|
|
|
149
|
-
- `/start` or `/help` - show the current usage model.
|
|
150
|
-
- `/status` - in private chat shows global state; in a project topic shows project/thread runtime state.
|
|
151
|
-
- `/admin` - in private chat, show admin binding and handoff status.
|
|
152
|
-
- `/admin rebind` - in private chat, issue a time-limited handoff code for transferring control to another Telegram account.
|
|
153
|
-
- `/admin cancel` - in private chat, cancel a pending admin handoff code.
|
|
154
|
-
- `/project` - show the current supergroup's project binding.
|
|
155
|
-
- `/project bind <absolute-path>` - bind the current supergroup to a project root.
|
|
156
|
-
- `/project unbind` - remove the current supergroup's project binding.
|
|
157
|
-
- `/thread` - in a topic, show the current attached thread id.
|
|
158
|
-
- `/thread list` - list saved Codex threads whose working directory is inside the current project root.
|
|
159
|
-
- `/thread new <topic-name>` - create a new topic for a fresh Codex thread.
|
|
160
|
-
- `/thread resume <threadId>` - create a new topic and bind it to an existing saved Codex thread id from the current project.
|
|
161
|
-
- Normal text in a topic - send that message to the current Codex thread.
|
|
162
|
-
- `/stop` - interrupt the active SDK run.
|
|
163
|
-
- `/cwd <absolute-path>` - switch the topic working directory inside the current project root.
|
|
164
|
-
- `/mode read|write|danger|yolo` - switch runtime presets for the current topic.
|
|
165
|
-
- `/sandbox <read-only|workspace-write|danger-full-access>` - set sandbox explicitly for the current topic.
|
|
166
|
-
- `/approval <on-request|on-failure|never>` - set approval policy explicitly for the current topic.
|
|
167
|
-
- `/yolo on|off` - quick toggle for `danger-full-access + never` on the current topic.
|
|
168
|
-
- `/model <model-id>` - set model for the current topic.
|
|
169
|
-
- `/effort default|minimal|low|medium|high|xhigh` - set model reasoning effort for the current topic.
|
|
170
|
-
- `/web default|disabled|cached|live` - set Codex SDK web search mode.
|
|
171
|
-
- `/network on|off` - set workspace network access for Codex SDK runs.
|
|
172
|
-
- `/gitcheck skip|enforce` - control Codex SDK git repository checks.
|
|
173
|
-
- `/adddir list|add <path-inside-project>|add-external <absolute-path>|drop <index>|clear` - manage Codex SDK additional directories. `add` stays inside the project root; `add-external` is the explicit escape hatch.
|
|
174
|
-
- `/schema show|set <JSON object>|clear` - manage Codex SDK output schema for the current topic.
|
|
175
|
-
- `/codexconfig show|set <JSON object>|clear` - manage global non-auth Codex SDK config overrides for future runs.
|
|
176
|
-
- Image messages in a topic - download the Telegram image locally and send it as SDK `local_image` input.
|
|
177
|
-
|
|
178
|
-
## Notes
|
|
179
|
-
|
|
180
|
-
- Long polling is managed by `@grammyjs/runner`.
|
|
181
|
-
- Streaming updates are throttled before editing Telegram messages.
|
|
182
|
-
- Final answers are rendered from Markdown to Telegram-safe HTML.
|
|
183
|
-
- Project-scoped path checks resolve symlinks before enforcing the root boundary, so topic cwd changes cannot escape the bound project through symlink paths.
|
|
184
|
-
- Because the SDK run and pending queue are in-process, a telecodex restart cannot resume a partially streamed Telegram turn and clears queued follow-up messages.
|
|
185
|
-
- Authentication and provider switching remain owned by the local Codex installation; telecodex does not manage API keys or login state.
|
|
186
|
-
- Interactive terminal stdin bridging and native Codex approval UI are intentionally not part of the Telegram contract. For unattended remote work, use the topic's sandbox/approval preset deliberately.
|
package/dist/bot/createBot.js
CHANGED
|
@@ -37,6 +37,7 @@ export function wireBot(input) {
|
|
|
37
37
|
});
|
|
38
38
|
void (async () => {
|
|
39
39
|
try {
|
|
40
|
+
await syncBotCommands(bot, logger);
|
|
40
41
|
await cleanupMissingTopicBindings({
|
|
41
42
|
bot,
|
|
42
43
|
store,
|
|
@@ -62,3 +63,45 @@ export function createBot(input) {
|
|
|
62
63
|
});
|
|
63
64
|
return bot;
|
|
64
65
|
}
|
|
66
|
+
async function syncBotCommands(bot, logger) {
|
|
67
|
+
try {
|
|
68
|
+
await bot.api.setMyCommands(privateCommands, {
|
|
69
|
+
scope: { type: "all_private_chats" },
|
|
70
|
+
});
|
|
71
|
+
await bot.api.setMyCommands(groupCommands, {
|
|
72
|
+
scope: { type: "all_group_chats" },
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
logger?.warn("failed to sync telegram bot commands", {
|
|
77
|
+
error: error instanceof Error ? error.message : String(error),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const privateCommands = [
|
|
82
|
+
{ command: "start", description: "Show help" },
|
|
83
|
+
{ command: "help", description: "Show help" },
|
|
84
|
+
{ command: "status", description: "Show bot status" },
|
|
85
|
+
{ command: "admin", description: "Show or hand off admin access" },
|
|
86
|
+
];
|
|
87
|
+
const groupCommands = [
|
|
88
|
+
{ command: "help", description: "Show help" },
|
|
89
|
+
{ command: "status", description: "Show project or topic status" },
|
|
90
|
+
{ command: "project", description: "Show, bind, or unbind project" },
|
|
91
|
+
{ command: "thread", description: "List, resume, or create topics" },
|
|
92
|
+
{ command: "queue", description: "List, drop, or clear queued inputs" },
|
|
93
|
+
{ command: "stop", description: "Stop the active run" },
|
|
94
|
+
{ command: "cwd", description: "Show or set topic directory" },
|
|
95
|
+
{ command: "mode", description: "Switch preset mode" },
|
|
96
|
+
{ command: "sandbox", description: "Show or set sandbox mode" },
|
|
97
|
+
{ command: "approval", description: "Show or set approval mode" },
|
|
98
|
+
{ command: "yolo", description: "Enable or disable YOLO mode" },
|
|
99
|
+
{ command: "model", description: "Show or set model" },
|
|
100
|
+
{ command: "effort", description: "Show or set reasoning effort" },
|
|
101
|
+
{ command: "web", description: "Show or set web search" },
|
|
102
|
+
{ command: "network", description: "Show or set network access" },
|
|
103
|
+
{ command: "gitcheck", description: "Show or set git repo check" },
|
|
104
|
+
{ command: "adddir", description: "List or manage extra directories" },
|
|
105
|
+
{ command: "schema", description: "Show or set output schema" },
|
|
106
|
+
{ command: "codexconfig", description: "Show or set Codex config" },
|
|
107
|
+
];
|