### install_bridge() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Installs the CDP binding bridge, registers Runtime.addBinding, injects bridge JS, and listens for rendering-side calls, returning results via callbacks. ```APIDOC ## install_bridge() ### Description Registers `Runtime.addBinding`, injects bridge JS (`window.__codexSessionDeleteBridge`), and continuously listens for rendering-side calls in a background thread, returning results via `__codexSessionDeleteResolve` / `__codexSessionDeleteReject`. ### Method ```python from codex_session_delete.cdp import install_bridge def bridge_handler(path: str, payload: dict) -> dict: print(f"收到桥接请求: {path}, payload: {payload}") return {"status": "ok"} ws = install_bridge( websocket_url="ws://127.0.0.1:9229/devtools/page/ABCDEF1234", binding_name="codexSessionDeleteV2", handler=bridge_handler, ) # ws 保持连接,后台线程持续处理渲染端消息 ``` ``` -------------------------------- ### Watcher Log Example Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Example log entries from the watcher. ```text [...] watcher started (interval=3.0s) [...] Codex running without CDP (pids=[...]); attempting takeover [...] takeover: killing 4 codex pid(s): [...] [...] takeover: CDP is up on 9229 (launcher pid=...) ``` -------------------------------- ### Unified CLI Entry Point Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Provides a single entry point for all Codex++ functionalities via the command line. Includes commands for launching, setup, updates, watcher management, and removal. ```bash # 启动(自动查找 Codex,使用默认端口) python -m codex_session_delete launch # 指定路径和端口启动 python -m codex_session_delete launch \ --app-dir "/Applications/OpenAI Codex.app" \ --debug-port 9229 \ --helper-port 57321 \ --db ~/.codex/state_5.sqlite \ --backup-dir ~/.codex-session-delete/backups # Windows 安装快捷方式 python -m codex_session_delete setup # macOS 生成 /Applications/Codex++.app python -m codex_session_delete setup # 卸载并删除全部数据 python -m codex_session_delete remove --remove-data # 检查更新 python -m codex_session_delete check-update # 从 GitHub Release 更新 python -m codex_session_delete update # Windows Watcher 管理 python -m codex_session_delete watch-install python -m codex_session_delete watch-disable python -m codex_session_delete watch-enable python -m codex_session_delete watch-remove ``` -------------------------------- ### launch_and_inject() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Launches the Codex App with a CDP debug port, starts a local Helper server, and injects the renderer-inject.js script into the rendering process. It returns the HelperServer and codex_proc objects. Handles cleanup on failure. ```APIDOC ## launch_and_inject() ### Description Launches Codex App with CDP debug port, starts local Helper server, and injects `renderer-inject.js` into the rendering process. Returns `(HelperServer, codex_proc)` tuple. Handles cleanup on failure. ### Method ```python launch_and_inject( app_dir=None, db_path: Path, backup_dir: Path, debug_port: int = 9229, helper_port: int = 57321 ) ``` ### Parameters - **app_dir** (Path | None) - Optional: Path to the Codex App directory. Defaults to auto-detection. - **db_path** (Path) - Required: Path to the SQLite database file. - **backup_dir** (Path) - Required: Directory for storing backups. - **debug_port** (int) - Optional: The CDP debug port to use. Defaults to 9229. - **helper_port** (int) - Optional: The port for the local Helper HTTP server. Defaults to 57321. ### Returns - **HelperServer**: The running Helper HTTP server instance. - **codex_proc**: The process object for the launched Codex App. ### Request Example ```python from pathlib import Path from codex_session_delete.launcher import launch_and_inject, shutdown_helper server, codex_proc = launch_and_inject( app_dir=None, db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", debug_port=9229, helper_port=57321, ) print(f"Helper 运行于 http://127.0.0.1:{server.port}") try: if codex_proc is not None: codex_proc.wait() finally: shutdown_helper(server) ``` ``` -------------------------------- ### Cross-Platform Installation and Uninstallation Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Manages the installation and uninstallation of Codex++ across different platforms (Windows and macOS). Supports default and custom installation paths, and options to remove associated data during uninstallation. ```python from pathlib import Path from codex_session_delete.installers import InstallOptions, install_codex_plus_plus, uninstall_codex_plus_plus # 安装(使用默认路径) install_codex_plus_plus(InstallOptions()) # 安装到自定义路径(仅 Windows) install_codex_plus_plus(InstallOptions( install_root=Path("D:/MyApps"), launcher_command=r'"C:\Python311\pythonw.exe" -m codex_session_delete launch', )) # 卸载并删除所有数据(备份、日志等) uninstall_codex_plus_plus(InstallOptions(remove_data=True)) ``` -------------------------------- ### Launch Codex App and Inject Scripts with launch_and_inject Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt The launch_and_inject function starts the Codex App with a CDP debug port, initializes a local Helper server, and injects the renderer-inject.js script into the rendering process. It returns the HelperServer and codex_proc, ensuring cleanup on failure. Specify app_dir, db_path, backup_dir, debug_port, and helper_port as needed. ```python from pathlib import Path from codex_session_delete.launcher import launch_and_inject, shutdown_helper server, codex_proc = launch_and_inject( app_dir=None, # None = 自动查找 Codex 安装目录 db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", debug_port=9229, helper_port=57321, ) print(f"Helper 运行于 http://127.0.0.1:{server.port}") # Helper 运行于 http://127.0.0.1:57321 try: # 保持进程存活,直到 Codex 退出 if codex_proc is not None: codex_proc.wait() finally: shutdown_helper(server) ``` -------------------------------- ### Check and Perform Updates Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Checks for new releases on GitHub, prints release information if found, and performs the update by downloading and installing the wheel package. Includes utility functions for version comparison and checking the execution mode. ```python from codex_session_delete import updater # 检查是否有新版本 release = updater.check_for_update() if release is not None: print(f"发现新版本: {release.version}") print(f"Release 页面: {release.url}") print(f"更新包: {release.asset_name}") # 执行更新(下载 wheel 并 pip install) result = updater.perform_update(release) print(f"已安装到: {result.installed_path}") else: print("当前已是最新版本") # 版本号比较工具 print(updater.is_newer_version("1.1.0", "1.0.4")) # True print(updater.is_newer_version("1.0.4", "1.0.4")) # False # 判断是否从源码目录运行 print(updater.is_source_tree_mode()) # True(存在 .git 目录时) ``` -------------------------------- ### Install CDP Binding Bridge Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Registers Runtime.addBinding to inject bridge JS and listen for rendering-side calls, returning results via callbacks. Ensure the websocket URL is correct for your environment. ```python from codex_session_delete.cdp import install_bridge def bridge_handler(path: str, payload: dict) -> dict: print(f"收到桥接请求: {path}, payload: {payload}") return {"status": "ok"} ws = install_bridge( websocket_url="ws://127.0.0.1:9229/devtools/page/ABCDEF1234", binding_name="codexSessionDeleteV2", handler=bridge_handler, ) # ws 保持连接,后台线程持续处理渲染端消息 ``` -------------------------------- ### Inject JavaScript and Setup CDP Binding with inject_file Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Use inject_file to inject a JavaScript file into the Codex rendering page via CDP WebSocket. It can also install the codexSessionDeleteV2 binding bridge. A handler callback is required to process requests like /delete, /undo, and /archived-thread from the renderer. ```python from pathlib import Path from codex_session_delete.cdp import inject_file def my_handler(path: str, payload: dict) -> dict: if path == "/delete": print(f"删除请求: {payload}") return {"status": "local_deleted", "session_id": payload["session_id"], "message": "OK", "undo_token": None, "backup_path": None} return {"status": "failed", "session_id": "", "message": "未知路径"} script_path = Path("codex_session_delete/inject/renderer-inject.js") bridge_ws = inject_file( port=9229, script_path=script_path, helper_port=57321, handler=my_handler, ) # bridge_ws 是一个保持连接的 WebSocket,用于接收渲染端 binding 调用 ``` -------------------------------- ### Resolve Codex Application Directory Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Automatically locates the Codex installation directory on both Windows and macOS. It uses platform-specific methods to find the application bundle or AppX package. ```python from pathlib import Path from codex_session_delete.app_paths import resolve_codex_app_dir # 自动解析(返回 Path 或 None) app_dir = resolve_codex_app_dir() print(app_dir) # macOS: /Applications/Codex.app # Windows: C:\Program Files\WindowsApps\OpenAI.Codex_1.2.3_x64__xxx\app # 指定路径(跳过自动查找) app_dir = resolve_codex_app_dir(Path("/Applications/OpenAI Codex.app")) print(app_dir) # /Applications/OpenAI Codex.app ``` -------------------------------- ### inject_file() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Injects a JavaScript file into the Codex rendering process via CDP WebSocket and optionally installs the `codexSessionDeleteV2` binding bridge. Handles requests from the renderer. ```APIDOC ## inject_file() ### Description Injects a JavaScript file into the Codex rendering process via CDP WebSocket. Optionally installs the `codexSessionDeleteV2` binding bridge. The `handler` callback processes requests from the renderer for `/delete`, `/undo`, and `/archived-thread`. ### Method ```python inject_file( port: int, script_path: Path, helper_port: int, handler: callable ) ``` ### Parameters - **port** (int) - Required: The CDP debug port of the Codex process. - **script_path** (Path) - Required: Path to the JavaScript file to inject. - **helper_port** (int) - Required: The port of the local Helper HTTP server. - **handler** (callable) - Required: A callback function to handle requests from the renderer. It should accept `path` (str) and `payload` (dict) and return a dict. ### Returns - **bridge_ws**: A WebSocket object that maintains the connection for binding calls from the renderer. ### Request Example ```python from pathlib import Path from codex_session_delete.cdp import inject_file def my_handler(path: str, payload: dict) -> dict: if path == "/delete": print(f"删除请求: {payload}") return {"status": "local_deleted", "session_id": payload["session_id"], "message": "OK", "undo_token": None, "backup_path": None} return {"status": "failed", "session_id": "", "message": "未知路径"} script_path = Path("codex_session_delete/inject/renderer-inject.js") bridge_ws = inject_file( port=9229, script_path=script_path, helper_port=57321, handler=my_handler, ) ``` ``` -------------------------------- ### Helper HTTP Server for Session Operations (Python) Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt A ThreadingHTTPServer subclass that listens on 127.0.0.1:{helper_port}, providing POST endpoints for /delete, /undo, /archived-thread and a GET endpoint for /health, with full CORS headers. This Python code sets up and runs the server. ```python from codex_session_delete.helper_server import HelperServer from codex_session_delete.launcher import ApiFirstDeleteService from codex_session_delete.api_adapter import UnavailableApiAdapter from pathlib import Path import threading service = ApiFirstDeleteService( api_adapter=UnavailableApiAdapter(), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) server = HelperServer("127.0.0.1", 57321, service) thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() print(f"Helper 监听端口: {server.port}") # 57321 server.shutdown() server.server_close() ``` -------------------------------- ### Launcher Log Path Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Location of the launcher log file for troubleshooting. ```text %USERPROFILE%\.codex-session-delete\launcher.log ``` -------------------------------- ### Project Structure Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Overview of the project's directory and file structure. ```text codex_session_delete/ cli.py CLI 入口 launcher.py 启动 Codex 并注入脚本 cdp.py CDP 通信与 bridge helper_server.py 本地 helper 服务 storage_adapter.py 本地 SQLite 删除/撤销 windows_installer.py Windows 快捷方式与卸载项 macos_installer.py macOS app bundle 安装 watcher.py Windows 常驻 watcher(可选,原生启动接管) inject/renderer-inject.js tests/ 自动化测试 ``` -------------------------------- ### Run Tests Command Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Command to execute automated tests for the project. ```bash python -m pytest -q ``` -------------------------------- ### ApiFirstDeleteService for Server-First Deletion Strategy Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Prioritizes calling the server API via ApiAdapter for deletion. Falls back to local SQLite deletion if the server is unavailable or returns a 404 (indicated by None). Use this to implement a robust deletion strategy. ```python from pathlib import Path from codex_session_delete.launcher import ApiFirstDeleteService from codex_session_delete.api_adapter import ConfirmedHttpDeleteAdapter, UnavailableApiAdapter from codex_session_delete.models import SessionRef # 情景一:有可用的服务端接口 service_with_api = ApiFirstDeleteService( api_adapter=ConfirmedHttpDeleteAdapter("http://127.0.0.1:8080/api/delete"), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) ``` -------------------------------- ### ApiFirstDeleteService Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Implements a server-first deletion strategy, attempting to use an ApiAdapter for server-side deletion and falling back to local SQLite deletion if the server is unavailable. ```APIDOC ## ApiFirstDeleteService ### Description Implements a server-first deletion strategy. It first attempts to call the server interface via `ApiAdapter`. If it returns `None` (server unavailable/404), it falls back to local SQLite deletion. ### Method ```python from pathlib import Path from codex_session_delete.launcher import ApiFirstDeleteService from codex_session_delete.api_adapter import ConfirmedHttpDeleteAdapter, UnavailableApiAdapter from codex_session_delete.models import SessionRef # 情景一:有可用的服务端接口 service_with_api = ApiFirstDeleteService( api_adapter=ConfirmedHttpDeleteAdapter("http://127.0.0.1:8080/api/delete"), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) ``` ``` -------------------------------- ### Local-Only Deletion Service Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Demonstrates using ApiFirstDeleteService for local deletion without affecting remote APIs. Shows how to delete a session and then undo the deletion using the provided undo token. ```python service_local_only = ApiFirstDeleteService( api_adapter=UnavailableApiAdapter(), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) session = SessionRef(session_id="thread-abc123", title="测试会话") result = service_local_only.delete(session) print(result.status) # DeleteStatus.LOCAL_DELETED # 撤销 undo = service_local_only.undo(result.undo_token) print(undo.status) # DeleteStatus.UNDONE ``` -------------------------------- ### Watcher Log Path Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Location of the watcher log file for troubleshooting. ```text %USERPROFILE%\.codex-session-delete\watcher.log ``` -------------------------------- ### SQLiteStorageAdapter for Local Deletion and Undo Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Automatically identifies Codex database schemas, backs up associated rows and rollout files before deletion, and returns an undo_token. Use this for local data management when server-side operations are not feasible. ```python from pathlib import Path from codex_session_delete.storage_adapter import SQLiteStorageAdapter from codex_session_delete.backup_store import BackupStore from codex_session_delete.models import SessionRef, DeleteStatus db_path = Path.home() / ".codex" / "state_5.sqlite" backup_dir = Path.home() / ".codex-session-delete" / "backups" adapter = SQLiteStorageAdapter(db_path, BackupStore(backup_dir)) if adapter.supports_schema(): session = SessionRef(session_id="thread-abc123", title="测试会话") result = adapter.delete_local(session) print(result.status) # DeleteStatus.LOCAL_DELETED print(result.undo_token) # "1717000000-a1b2c3d4e5f6..." # 撤销删除 undo_result = adapter.undo(result.undo_token) print(undo_result.status) # DeleteStatus.UNDONE # 按标题查找已归档线程 archived = adapter.find_archived_thread_by_title("我的归档会话") if archived: print(archived.session_id) # "thread-xyz" ``` -------------------------------- ### Uninstall/Reinstall Command Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Command to run for updating the system uninstall entry and reinstalling Codex++. ```bash python -m codex_session_delete setup ``` -------------------------------- ### Helper HTTP Server for Session Operations (Bash) Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Provides local REST API endpoints for health checks, deleting sessions, undoing deletions, and finding archived threads. Ensure the port is accessible and correctly configured. ```bash # 健康检查 curl http://127.0.0.1:57321/health # {"ok": true} # 删除会话 curl -X POST http://127.0.0.1:57321/delete \ -H "Content-Type: application/json" \ -d '{"session_id": "thread-abc123", "title": "测试会话"}' # {"status": "local_deleted", "session_id": "thread-abc123", "message": "已从本地存储删除", "undo_token": "1717000000-xxx", "backup_path": "..."} # 撤销删除 curl -X POST http://127.0.0.1:57321/undo \ -H "Content-Type: application/json" \ -d '{"undo_token": "1717000000-xxx"}' # {"status": "undone", "session_id": "thread-abc123", "message": "Local session restored from backup", "undo_token": "1717000000-xxx", "backup_path": null} # 按标题查找归档线程 curl -X POST http://127.0.0.1:57321/archived-thread \ -H "Content-Type: application/json" \ -d '{"title": "我的归档会话"}' # {"session_id": "thread-xyz", "title": "我的归档会话"} ``` -------------------------------- ### BackupStore Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Manages backup storage for deleted rows, writing them in JSON format with Base64 encoded associated files and providing token-indexed retrieval. ```APIDOC ## BackupStore ### Description Manages backup storage. It writes deleted rows in JSON format (including Base64 encoded associated files) to `~/.codex-session-delete/backups/` and provides token-indexed reading. ### Method ```python from pathlib import Path from codex_session_delete.backup_store import BackupStore store = BackupStore(backup_dir=Path.home() / ".codex-session-delete" / "backups") # 写入备份 token = store.write_backup( session_id="abc-123", source_db="/home/user/.codex/state_5.sqlite", tables={ "sessions": [{"id": "abc-123", "title": "测试会话"}], "messages": [{"id": "msg-1", "session_id": "abc-123", "content": "Hello"}], }, ) print(token) # "1717000000-a1b2c3d4e5f6..." # 读取备份 backup = store.read_backup(token) print(backup["session_id"]) # "abc-123" print(list(backup["tables"])) # ["sessions", "messages"] # 获取备份文件路径 path = store.path_for(token) print(path) # PosixPath('/home/user/.codex-session-delete/backups/1717000000-a1b2c3d4e5f6.json') ``` ``` -------------------------------- ### BackupStore for Managing Backup Storage Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Writes rows to be deleted in JSON format (including Base64 encoded associated files) to ~/.codex-session-delete/backups/ and provides token-indexed reading. Use this to manage backups for session data. ```python from pathlib import Path from codex_session_delete.backup_store import BackupStore store = BackupStore(backup_dir=Path.home() / ".codex-session-delete" / "backups") # 写入备份 token = store.write_backup( session_id="abc-123", source_db="/home/user/.codex/state_5.sqlite", tables={ "sessions": [{"id": "abc-123", "title": "测试会话"}], "messages": [{"id": "msg-1", "session_id": "abc-123", "content": "Hello"}], }, ) print(token) # "1717000000-a1b2c3d4e5f6..." # 读取备份 backup = store.read_backup(token) print(backup["session_id"]) # "abc-123" print(list(backup["tables"])) # ["sessions", "messages"] # 获取备份文件路径 path = store.path_for(token) print(path) # PosixPath('/home/user/.codex-session-delete/backups/1717000000-a1b2c3d4e5f6.json') ``` -------------------------------- ### HelperServer Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt A local REST API service providing endpoints for deletion, undo, archived thread lookup, and health checks with full CORS headers. ```APIDOC ## HelperServer ### Description A subclass of `ThreadingHTTPServer` that listens on `127.0.0.1:{helper_port}`. It provides `/delete`, `/undo`, and `/archived-thread` POST endpoints, along with a `/health` GET endpoint, and includes full CORS headers. ### Endpoints #### GET /health ##### Description Checks the health of the server. ##### Response Example ```json { "ok": true } ``` #### POST /delete ##### Description Deletes a session from local storage. ##### Request Body - **session_id** (string) - Required - The ID of the session to delete. - **title** (string) - Required - The title of the session. ##### Request Example ```json { "session_id": "thread-abc123", "title": "测试会话" } ``` ##### Response Example ```json { "status": "local_deleted", "session_id": "thread-abc123", "message": "已从本地存储删除", "undo_token": "1717000000-xxx", "backup_path": "..." } ``` #### POST /undo ##### Description Undoes a previous deletion operation. ##### Request Body - **undo_token** (string) - Required - The token obtained from a delete operation to undo. ##### Request Example ```json { "undo_token": "1717000000-xxx" } ``` ##### Response Example ```json { "status": "undone", "session_id": "thread-abc123", "message": "Local session restored from backup", "undo_token": "1717000000-xxx", "backup_path": null } ``` #### POST /archived-thread ##### Description Finds an archived thread by its title. ##### Request Body - **title** (string) - Required - The title of the archived thread to find. ##### Request Example ```json { "title": "我的归档会话" } ``` ##### Response Example ```json { "session_id": "thread-xyz", "title": "我的归档会话" } ``` ### Method ```python from codex_session_delete.helper_server import HelperServer from codex_session_delete.launcher import ApiFirstDeleteService from codex_session_delete.api_adapter import UnavailableApiAdapter from pathlib import Path import threading service = ApiFirstDeleteService( api_adapter=UnavailableApiAdapter(), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) server = HelperServer("127.0.0.1", 57321, service) thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() print(f"Helper 监听端口: {server.port}") # 57321 server.shutdown() server.server_close() ``` ``` -------------------------------- ### Windows Watcher for Process Takeover Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Implements a watcher service for Windows that monitors for Codex processes and their associated CDP ports. If a process is running without CDP, it attempts to take over by restarting the process with CDP enabled. ```python # 命令行注册 watcher 为登录启动项(Windows 专用) # python -m codex_session_delete watch-install --debug-port 9229 # 临时禁用/启用 # python -m codex_session_delete watch-disable # python -m codex_session_delete watch-enable # 卸载 watcher # python -m codex_session_delete watch-remove # 直接在代码中使用 from codex_session_delete import watcher # 手动执行一次接管尝试 success = watcher.takeover(debug_port=9229) print("接管成功" if success else "接管失败") # 查看日志路径 print(watcher.watcher_log_path()) # /home/user/.codex-session-delete/watcher.log # 禁用/启用 watcher(通过 flag 文件控制) watcher.disable_watcher() watcher.enable_watcher() ``` -------------------------------- ### SQLiteStorageAdapter Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Manages local SQLite deletion and undo operations, automatically recognizing Codex database schemas and backing up related rows before deletion. ```APIDOC ## SQLiteStorageAdapter ### Description Manages local SQLite deletion and undo operations. It automatically recognizes Codex database schemas (`codex_threads` or `generic_sessions`), backs up all associated rows and rollout files before deletion, and returns an `undo_token` for reversal. ### Method ```python from pathlib import Path from codex_session_delete.storage_adapter import SQLiteStorageAdapter from codex_session_delete.backup_store import BackupStore from codex_session_delete.models import SessionRef, DeleteStatus db_path = Path.home() / ".codex" / "state_5.sqlite" backup_dir = Path.home() / ".codex-session-delete" / "backups" adapter = SQLiteStorageAdapter(db_path, BackupStore(backup_dir)) if adapter.supports_schema(): session = SessionRef(session_id="thread-abc123", title="测试会话") result = adapter.delete_local(session) print(result.status) # DeleteStatus.LOCAL_DELETED print(result.undo_token) # "1717000000-a1b2c3d4e5f6..." # 撤销删除 undo_result = adapter.undo(result.undo_token) print(undo_result.status) # DeleteStatus.UNDONE # 按标题查找已归档线程 archived = adapter.find_archived_thread_by_title("我的归档会话") if archived: print(archived.session_id) # "thread-xyz" ``` ``` -------------------------------- ### Create SessionRef for Session Identification Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Use SessionRef to create immutable references for sessions, supporting regular sessions and local threads. Ensure session_id is a non-empty string. ```python from codex_session_delete.models import SessionRef # 普通会话 session = SessionRef(session_id="abc-123", title="我的第一个会话") # Codex 本地线程(带 local: 前缀也会被自动 normalize) session_local = SessionRef(session_id="local:thread-xyz", title="本地线程") print(session.session_id) # "abc-123" print(session.title) # "我的第一个会话" ``` -------------------------------- ### List Debugging Targets with list_targets Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt The list_targets function retrieves all available debugging targets from a given CDP port. The output is a list of dictionaries, each representing a target with its ID, type, title, and WebSocket debugger URL. ```python from codex_session_delete.cdp import list_targets, pick_page_target targets = list_targets(port=9229) # [{"id": "...", "type": "page", "title": "Codex", "webSocketDebuggerUrl": "ws://...", ...}] target = pick_page_target(targets) print(target["webSocketDebuggerUrl"]) # ws://127.0.0.1:9229/devtools/page/ABCDEF1234 ``` -------------------------------- ### CDP Debugging Port Argument Source: https://github.com/bigpizzav3/codexplusplus/blob/main/README.md Argument to check if Codex is launched with CDP enabled. ```text --remote-debugging-port=9229 ``` -------------------------------- ### list_targets() / pick_page_target() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Retrieves a list of available debugging targets from the CDP endpoint and filters them to find a specific page target related to Codex. ```APIDOC ## list_targets() / pick_page_target() ### Description `list_targets()` fetches all debugging targets from the CDP `/json` endpoint. `pick_page_target()` then filters these targets to find one of type `page` whose URL or title contains `codex`. ### Method ```python list_targets(port: int) -> list pick_page_target(targets: list) -> dict | None ``` ### Parameters - **port** (int) - Required: The CDP debug port to query. - **targets** (list) - Required: A list of debugging targets, typically obtained from `list_targets()`. ### Returns - **list_targets**: A list of dictionaries, each representing a debugging target. - **pick_page_target**: A dictionary representing the selected page target, or None if no suitable target is found. ### Request Example ```python from codex_session_delete.cdp import list_targets, pick_page_target targets = list_targets(port=9229) # targets might look like: [{'id': '...', 'type': 'page', 'title': 'Codex', 'webSocketDebuggerUrl': 'ws://...', ...}] target = pick_page_target(targets) if target: print(target["webSocketDebuggerUrl"]) # ws://127.0.0.1:9229/devtools/page/ABCDEF1234 ``` ``` -------------------------------- ### inject_with_retry() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Attempts to inject a script into the Codex rendering process, retrying up to a specified number of attempts with a delay between retries. Useful when the rendering process might not be immediately ready. ```APIDOC ## inject_with_retry() ### Description Injects a script into the Codex rendering process, retrying up to `attempts` times with a specified `delay`. This is useful when the rendering process might not be immediately ready after launch. ### Method ```python inject_with_retry( debug_port: int, script_path: Path, helper_port: int, service: object, attempts: int = 20, delay: float = 0.5 ) ``` ### Parameters - **debug_port** (int) - Required: The CDP debug port of the Codex process. - **script_path** (Path) - Required: Path to the JavaScript file to inject. - **helper_port** (int) - Required: The port of the local Helper HTTP server. - **service** (object) - Required: An object implementing the delete service logic. - **attempts** (int) - Optional: The maximum number of retry attempts. Defaults to 20. - **delay** (float) - Optional: The delay in seconds between retry attempts. Defaults to 0.5. ### Returns - **bridge_socket**: A WebSocket object representing the connection to the injected script. ### Request Example ```python from pathlib import Path from codex_session_delete.launcher import inject_with_retry from codex_session_delete.api_adapter import UnavailableApiAdapter # Assuming ApiFirstDeleteService and UnavailableApiAdapter are defined elsewhere # service = ApiFirstDeleteService(...) script_path = Path("codex_session_delete/inject/renderer-inject.js") bridge_socket = inject_with_retry( debug_port=9229, script_path=script_path, helper_port=57321, service=UnavailableApiAdapter(), # Replace with actual service instance attempts=20, delay=0.5, ) ``` ``` -------------------------------- ### evaluate_script() Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Executes arbitrary JavaScript code within a specified page context using the Chromium DevTools Protocol (CDP), bypassing Content Security Policy (CSP) restrictions. ```APIDOC ## evaluate_script() ### Description Executes arbitrary JavaScript code within a specified page context via CDP's `Runtime.evaluate`. It uses `allowUnsafeEvalBlockedByCSP: true` to bypass CSP restrictions. ### Method ```python evaluate_script( websocket_url: str, script: str ) ``` ### Parameters - **websocket_url** (str) - Required: The WebSocket URL of the target page's CDP connection. - **script** (str) - Required: The JavaScript code to execute. ### Returns - The result of the executed script. ### Request Example ```python from codex_session_delete.cdp import evaluate_script result = evaluate_script( websocket_url="ws://127.0.0.1:9229/devtools/page/ABCDEF1234", script="document.title", ) print(result) # Example output: "Codex" ``` ``` -------------------------------- ### Handle Delete Operation Results with DeleteResult Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt Utilize DeleteResult to carry the status, undo token, and backup path of a delete operation. The to_dict() method provides a JSON-serializable dictionary representation. DeleteStatus includes various states like LOCAL_DELETED, SERVER_DELETED, PARTIAL, FAILED, and UNDONE. ```python from codex_session_delete.models import DeleteResult, DeleteStatus result = DeleteResult( status=DeleteStatus.LOCAL_DELETED, session_id="abc-123", message="已从本地存储删除", undo_token="1717000000-a1b2c3d4e5f6", backup_path="/home/user/.codex-session-delete/backups/1717000000-a1b2c3d4e5f6.json", ) print(result.to_dict()) # { # "status": "local_deleted", # "session_id": "abc-123", # "message": "已从本地存储删除", # "undo_token": "1717000000-a1b2c3d4e5f6", # "backup_path": "/home/user/.codex-session-delete/backups/1717000000-a1b2c3d4e5f6.json" # } # DeleteStatus 枚举值: # SERVER_DELETED — 服务端删除成功 # LOCAL_DELETED — 本地 SQLite 删除成功 # PARTIAL — 部分删除 # FAILED — 删除失败 # UNDONE — 已撤销恢复 ``` -------------------------------- ### Retry Script Injection with inject_with_retry Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt The inject_with_retry function is used when the Codex rendering process might not be ready immediately. It attempts injection up to a specified number of times with a defined delay between attempts. This is useful for ensuring the script is injected after the CDP target is available. ```python from pathlib import Path from codex_session_delete.launcher import inject_with_retry, ApiFirstDeleteService from codex_session_delete.api_adapter import UnavailableApiAdapter service = ApiFirstDeleteService( api_adapter=UnavailableApiAdapter(), db_path=Path.home() / ".codex" / "state_5.sqlite", backup_dir=Path.home() / ".codex-session-delete" / "backups", ) script_path = Path("codex_session_delete/inject/renderer-inject.js") bridge_socket = inject_with_retry( debug_port=9229, script_path=script_path, helper_port=57321, service=service, attempts=20, delay=0.5, ) ``` -------------------------------- ### Execute JavaScript in Browser Context with evaluate_script Source: https://context7.com/bigpizzav3/codexplusplus/llms.txt The evaluate_script function executes arbitrary JavaScript code within a specified browser page's context using its WebSocket debugger URL. It bypasses CSP restrictions by setting allowUnsafeEvalBlockedByCSP: true, allowing for dynamic script execution and DOM manipulation. ```python from codex_session_delete.cdp import evaluate_script result = evaluate_script( websocket_url="ws://127.0.0.1:9229/devtools/page/ABCDEF1234", script="document.title", ) print(result) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.