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.
Files changed (92) hide show
  1. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/PKG-INFO +1 -1
  2. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/client.py +1 -0
  3. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram/__init__.py +1 -1
  4. codex-telegram-0.4.6/codex_telegram/cli.py +102 -0
  5. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/PKG-INFO +1 -1
  6. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/SOURCES.txt +2 -2
  7. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/main.py +7 -1
  8. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/pyproject.toml +4 -0
  9. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_pypi_check.py +3 -2
  10. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_web_server_local_command.py +5 -6
  11. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/config.py +3 -0
  12. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/server.py +3 -1
  13. codex-telegram-0.4.6/web/static/dist/assets/index-B6IQl7AZ.js +53 -0
  14. 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
  15. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/index.html +2 -2
  16. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/workspace.py +1 -1
  17. codex-telegram-0.4.4/codex_telegram/cli.py +0 -23
  18. codex-telegram-0.4.4/web/static/dist/assets/index-Cn5g2YDL.js +0 -53
  19. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/LICENSE +0 -0
  20. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/MANIFEST.in +0 -0
  21. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/README.md +0 -0
  22. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/TELEGRAM.md +0 -0
  23. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/WEB.md +0 -0
  24. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/__init__.py +0 -0
  25. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/bootstrap.py +0 -0
  26. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/telegram_app.py +0 -0
  27. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/app_runtime/web_server.py +0 -0
  28. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/__init__.py +0 -0
  29. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/callbacks.py +0 -0
  30. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/features_ui.py +0 -0
  31. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/handlers.py +0 -0
  32. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/keyboard.py +0 -0
  33. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/projects_ui.py +0 -0
  34. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/skills_ui.py +0 -0
  35. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/bot/thread_ui.py +0 -0
  36. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/__init__.py +0 -0
  37. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/approval_flow.py +0 -0
  38. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/approval_guardian.py +0 -0
  39. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/collaboration_mode.py +0 -0
  40. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/__init__.py +0 -0
  41. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/common.py +0 -0
  42. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/context.py +0 -0
  43. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/contracts.py +0 -0
  44. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/core.py +0 -0
  45. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/projects.py +0 -0
  46. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/review.py +0 -0
  47. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/system.py +0 -0
  48. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/command_router/threads.py +0 -0
  49. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/commands.py +0 -0
  50. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/event_forwarding.py +0 -0
  51. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/events.py +0 -0
  52. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex/protocol.py +0 -0
  53. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/dependency_links.txt +0 -0
  54. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/entry_points.txt +0 -0
  55. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/requires.txt +0 -0
  56. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/codex_telegram.egg-info/top_level.txt +0 -0
  57. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/conf.toml.example +0 -0
  58. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/__init__.py +0 -0
  59. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/state.py +0 -0
  60. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/thread.py +0 -0
  61. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/models/user.py +0 -0
  62. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/setup.cfg +0 -0
  63. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_approval_guardian.py +0 -0
  64. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_approval_policy.py +0 -0
  65. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_callbacks_results.py +0 -0
  66. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_cli_entrypoint.py +0 -0
  67. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_codex_client.py +0 -0
  68. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_command_router.py +0 -0
  69. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_guardian_config.py +0 -0
  70. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_handlers_results.py +0 -0
  71. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_keyboard.py +0 -0
  72. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_main_approval_flow.py +0 -0
  73. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_normalize.py +0 -0
  74. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_single_instance.py +0 -0
  75. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_telegram_bot_config.py +0 -0
  76. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_thread_history.py +0 -0
  77. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/tests/test_web_runtime.py +0 -0
  78. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/__init__.py +0 -0
  79. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/approval_policy.py +0 -0
  80. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/local_command.py +0 -0
  81. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/logger.py +0 -0
  82. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/normalize.py +0 -0
  83. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/pypi_check.py +0 -0
  84. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/single_instance.py +0 -0
  85. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/utils/web_config.py +0 -0
  86. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/__init__.py +0 -0
  87. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/dependencies.py +0 -0
  88. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/routes.py +0 -0
  89. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/runtime.py +0 -0
  90. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/icons-tab-add.svg +0 -0
  91. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/static/dist/icons-tab-close.svg +0 -0
  92. {codex-telegram-0.4.4 → codex-telegram-0.4.6}/web/thread_history.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codex-telegram
3
- Version: 0.4.4
3
+ Version: 0.4.6
4
4
  Summary: Bridge for controlling the Codex App Server from Telegram and Web UI
5
5
  Author: heungtae
6
6
  License: Apache License
@@ -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():
@@ -1,3 +1,3 @@
1
1
  """codex-telegram package."""
2
2
 
3
- __version__ = "0.4.4"
3
+ __version__ = "0.4.6"
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codex-telegram
3
- Version: 0.4.4
3
+ Version: 0.4.6
4
4
  Summary: Bridge for controlling the Codex App Server from Telegram and Web UI
5
5
  Author: heungtae
6
6
  License: Apache License
@@ -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-BOEE4EML.css
88
- web/static/dist/assets/index-Cn5g2YDL.js
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
- telegram_enabled = parse_bool(get("telegram.enabled", True), default=True)
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, "0.4.1")
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, "0.4.1")
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('const storageKey = "codex-web-theme";', body)
106
- self.assertIn("window.localStorage.getItem(storageKey)", body)
107
- self.assertIn('document.documentElement.dataset.theme = theme;', body)
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