codex-telegram 0.4.4__tar.gz → 0.4.6__tar.gz
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.
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/PKG-INFO +1 -1
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/client.py +1 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram/__init__.py +1 -1
- codex-telegram-0.4.6/codex_telegram/cli.py +102 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/PKG-INFO +1 -1
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/SOURCES.txt +2 -2
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/main.py +7 -1
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/pyproject.toml +4 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_pypi_check.py +3 -2
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_web_server_local_command.py +5 -6
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/config.py +3 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/server.py +3 -1
- codex-telegram-0.4.6/web/static/dist/assets/index-B6IQl7AZ.js +53 -0
- codex-telegram-0.4.4/web/static/dist/assets/index-BOEE4EML.css → codex-telegram-0.4.6/web/static/dist/assets/index-Czx9yv3Y.css +1 -1
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/index.html +2 -2
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/workspace.py +1 -1
- codex-telegram-0.4.4/codex_telegram/cli.py +0 -23
- codex-telegram-0.4.4/web/static/dist/assets/index-Cn5g2YDL.js +0 -53
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/LICENSE +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/MANIFEST.in +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/README.md +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/TELEGRAM.md +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/WEB.md +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/bootstrap.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/telegram_app.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/web_server.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/callbacks.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/features_ui.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/handlers.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/keyboard.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/projects_ui.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/skills_ui.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/thread_ui.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/approval_flow.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/approval_guardian.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/collaboration_mode.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/common.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/context.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/contracts.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/core.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/projects.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/review.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/system.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/threads.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/commands.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/event_forwarding.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/events.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/protocol.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/dependency_links.txt +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/entry_points.txt +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/requires.txt +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/top_level.txt +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/conf.toml.example +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/state.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/thread.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/user.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/setup.cfg +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_approval_guardian.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_approval_policy.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_callbacks_results.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_cli_entrypoint.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_codex_client.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_command_router.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_guardian_config.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_handlers_results.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_keyboard.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_main_approval_flow.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_normalize.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_single_instance.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_telegram_bot_config.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_thread_history.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_web_runtime.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/approval_policy.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/local_command.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/logger.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/normalize.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/pypi_check.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/single_instance.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/web_config.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/__init__.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/dependencies.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/routes.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/runtime.py +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/icons-tab-add.svg +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/icons-tab-close.svg +0 -0
- {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/thread_history.py +0 -0
|
@@ -125,6 +125,7 @@ class CodexClient:
|
|
|
125
125
|
logger.debug("app-server stdin: %s", data)
|
|
126
126
|
if self._proc and self._proc.stdin:
|
|
127
127
|
self._proc.stdin.write(data.encode() + b"\n")
|
|
128
|
+
self._proc.stdin.flush()
|
|
128
129
|
|
|
129
130
|
def _fail_pending(self, exc: Exception) -> None:
|
|
130
131
|
for future in self._pending.values():
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from importlib.util import module_from_spec, spec_from_file_location
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from types import ModuleType
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _get_version() -> str:
|
|
11
|
+
from codex_telegram import __version__
|
|
12
|
+
|
|
13
|
+
return __version__
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _load_root_main_module() -> ModuleType:
|
|
17
|
+
root_main = Path(__file__).resolve().parent.parent / "main.py"
|
|
18
|
+
spec = spec_from_file_location("codex_telegram_root_main", root_main)
|
|
19
|
+
if spec is None or spec.loader is None:
|
|
20
|
+
raise RuntimeError(f"Failed to load entrypoint module from {root_main}")
|
|
21
|
+
module = module_from_spec(spec)
|
|
22
|
+
spec.loader.exec_module(module)
|
|
23
|
+
return module
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> int:
|
|
27
|
+
parser = argparse.ArgumentParser(
|
|
28
|
+
prog="codex-telegram",
|
|
29
|
+
description="Codex Telegram Bot - Bridges Codex App Server with Telegram and Web UI.",
|
|
30
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
31
|
+
epilog="""
|
|
32
|
+
Examples:
|
|
33
|
+
codex-telegram Run with default config
|
|
34
|
+
codex-telegram --config /path/to/conf.toml
|
|
35
|
+
codex-telegram --web-only Run web UI only (no Telegram polling)
|
|
36
|
+
codex-telegram --validate-config Validate configuration and exit
|
|
37
|
+
codex-telegram --debug Enable debug logging
|
|
38
|
+
""",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"-c",
|
|
42
|
+
"--config",
|
|
43
|
+
type=str,
|
|
44
|
+
metavar="PATH",
|
|
45
|
+
help="Path to configuration file (default: ~/.config/codex-telegram/conf.toml or ./conf.toml)",
|
|
46
|
+
)
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"--web-only",
|
|
49
|
+
action="store_true",
|
|
50
|
+
help="Run web UI only, without Telegram bot polling",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--debug",
|
|
54
|
+
action="store_true",
|
|
55
|
+
help="Enable debug level logging",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--validate-config",
|
|
59
|
+
action="store_true",
|
|
60
|
+
help="Validate configuration file and exit (no startup)",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--version",
|
|
64
|
+
action="version",
|
|
65
|
+
version=f"%(prog)s {_get_version()}",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
args = parser.parse_args()
|
|
69
|
+
|
|
70
|
+
if args.config:
|
|
71
|
+
os.environ["CODEX_CONFIG_PATH"] = args.config
|
|
72
|
+
|
|
73
|
+
if args.debug:
|
|
74
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
75
|
+
|
|
76
|
+
if args.validate_config:
|
|
77
|
+
return _validate_config()
|
|
78
|
+
|
|
79
|
+
if args.web_only:
|
|
80
|
+
os.environ["CODEX_WEB_ONLY"] = "1"
|
|
81
|
+
|
|
82
|
+
module = _load_root_main_module()
|
|
83
|
+
target = getattr(module, "main", None)
|
|
84
|
+
if not callable(target):
|
|
85
|
+
raise RuntimeError("Entrypoint module does not expose callable main()")
|
|
86
|
+
runner = target
|
|
87
|
+
return int(runner())
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _validate_config() -> int:
|
|
91
|
+
try:
|
|
92
|
+
from utils.config import load
|
|
93
|
+
from utils.config import get_config_path
|
|
94
|
+
|
|
95
|
+
config_path = get_config_path()
|
|
96
|
+
print(f"Validating config file: {config_path}")
|
|
97
|
+
config = load()
|
|
98
|
+
print(f"Config loaded successfully: {len(config)} top-level keys")
|
|
99
|
+
return 0
|
|
100
|
+
except Exception as e:
|
|
101
|
+
print(f"Config validation failed: {e}", file=sys.stderr)
|
|
102
|
+
return 1
|
|
@@ -84,5 +84,5 @@ web/workspace.py
|
|
|
84
84
|
web/static/dist/icons-tab-add.svg
|
|
85
85
|
web/static/dist/icons-tab-close.svg
|
|
86
86
|
web/static/dist/index.html
|
|
87
|
-
web/static/dist/assets/index-
|
|
88
|
-
web/static/dist/assets/index-
|
|
87
|
+
web/static/dist/assets/index-B6IQl7AZ.js
|
|
88
|
+
web/static/dist/assets/index-Czx9yv3Y.css
|
|
@@ -186,7 +186,13 @@ def main():
|
|
|
186
186
|
logger.info("Using config file %s", get_config_path())
|
|
187
187
|
|
|
188
188
|
web_enabled, web_host, web_port, web_endpoint, ssl_enabled, ssl_certfile, ssl_keyfile = _parse_web_endpoint()
|
|
189
|
-
|
|
189
|
+
telegram_enabled_env = os.environ.get("CODEX_WEB_ONLY", "").lower()
|
|
190
|
+
if telegram_enabled_env == "1":
|
|
191
|
+
telegram_enabled = False
|
|
192
|
+
if not web_enabled:
|
|
193
|
+
web_enabled = True
|
|
194
|
+
else:
|
|
195
|
+
telegram_enabled = parse_bool(get("telegram.enabled", True), default=True)
|
|
190
196
|
logger.info("Web endpoint configured: %s (enabled=%s)", web_endpoint, web_enabled)
|
|
191
197
|
logger.info("Telegram channel enabled=%s", telegram_enabled)
|
|
192
198
|
|
|
@@ -47,3 +47,7 @@ where = ["."]
|
|
|
47
47
|
include = ["app_runtime", "bot", "codex", "codex.*", "codex_telegram", "models", "utils", "web"]
|
|
48
48
|
exclude = ["tests*"]
|
|
49
49
|
namespaces = false
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
norecursedirs = ["codex_source", "web/frontend", "node_modules"]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
from unittest.mock import AsyncMock, patch, MagicMock
|
|
3
3
|
|
|
4
|
+
from codex_telegram import __version__
|
|
4
5
|
from utils.pypi_check import _compare_versions, check_latest_version, format_update_message, VersionInfo
|
|
5
6
|
|
|
6
7
|
|
|
@@ -61,7 +62,7 @@ class CheckLatestVersionTests(unittest.TestCase):
|
|
|
61
62
|
result = asyncio.run(check_latest_version())
|
|
62
63
|
|
|
63
64
|
self.assertIsNotNone(result)
|
|
64
|
-
self.assertEqual(result.current,
|
|
65
|
+
self.assertEqual(result.current, __version__)
|
|
65
66
|
self.assertEqual(result.latest, "0.5.0")
|
|
66
67
|
self.assertTrue(result.is_outdated)
|
|
67
68
|
|
|
@@ -91,7 +92,7 @@ class CheckLatestVersionTests(unittest.TestCase):
|
|
|
91
92
|
result = asyncio.run(check_latest_version())
|
|
92
93
|
|
|
93
94
|
self.assertIsNotNone(result)
|
|
94
|
-
self.assertEqual(result.current,
|
|
95
|
+
self.assertEqual(result.current, __version__)
|
|
95
96
|
self.assertEqual(result.latest, "0.4.1")
|
|
96
97
|
self.assertFalse(result.is_outdated)
|
|
97
98
|
|
|
@@ -102,11 +102,9 @@ class WebServerLocalCommandTests(unittest.TestCase):
|
|
|
102
102
|
response = asyncio.run(endpoint())
|
|
103
103
|
body = response.body.decode("utf-8")
|
|
104
104
|
|
|
105
|
-
self.assertIn(
|
|
106
|
-
self.assertIn("
|
|
107
|
-
self.assertIn(
|
|
108
|
-
self.assertRegex(body, r'/assets/styles\.css\?v=\d+')
|
|
109
|
-
self.assertRegex(body, r'/assets/app\.jsx\?v=\d+')
|
|
105
|
+
self.assertIn("<!doctype html>", body)
|
|
106
|
+
self.assertIn("<title>Codex Web</title>", body)
|
|
107
|
+
self.assertIn("/assets/", body)
|
|
110
108
|
|
|
111
109
|
def test_chat_messages_propagates_turn_start_failures(self):
|
|
112
110
|
app = create_web_app()
|
|
@@ -378,12 +376,13 @@ class WebServerLocalCommandTests(unittest.TestCase):
|
|
|
378
376
|
self.assertEqual("thread-1", body["thread_id"])
|
|
379
377
|
self.assertEqual(
|
|
380
378
|
[
|
|
381
|
-
{"role": "user", "text": "Plan this", "thread_id": "thread-1"},
|
|
379
|
+
{"role": "user", "text": "Plan this", "thread_id": "thread-1", "turn_id": "turn-1"},
|
|
382
380
|
{
|
|
383
381
|
"role": "assistant",
|
|
384
382
|
"text": "# Final plan\n- first\n- second",
|
|
385
383
|
"kind": "plan",
|
|
386
384
|
"thread_id": "thread-1",
|
|
385
|
+
"turn_id": "turn-1",
|
|
387
386
|
},
|
|
388
387
|
],
|
|
389
388
|
body["messages"],
|
|
@@ -85,6 +85,9 @@ threads_list_limit = 20
|
|
|
85
85
|
"""
|
|
86
86
|
|
|
87
87
|
def _get_config_path() -> Path:
|
|
88
|
+
env_config_path = os.environ.get("CODEX_CONFIG_PATH")
|
|
89
|
+
if env_config_path:
|
|
90
|
+
return Path(env_config_path)
|
|
88
91
|
config_dir = Path.home() / ".config" / "codex-telegram"
|
|
89
92
|
return config_dir / "conf.toml"
|
|
90
93
|
|
|
@@ -7,7 +7,9 @@ from codex_telegram import __version__
|
|
|
7
7
|
from utils.config import get_guardian_settings, save_guardian_settings
|
|
8
8
|
from utils.local_command import run_bang_command
|
|
9
9
|
from web import routes as route_module
|
|
10
|
-
from web.dependencies import resolved_assets_dir
|
|
10
|
+
from web.dependencies import COOKIE_NAME, resolved_assets_dir
|
|
11
|
+
|
|
12
|
+
__all__ = ["create_web_app", "COOKIE_NAME"]
|
|
11
13
|
|
|
12
14
|
logger = logging.getLogger("codex-telegram.web")
|
|
13
15
|
|