openfish 1.0.0__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.
- openfish-1.0.0/PKG-INFO +115 -0
- openfish-1.0.0/README_PYPI.md +88 -0
- openfish-1.0.0/openfish.egg-info/PKG-INFO +115 -0
- openfish-1.0.0/openfish.egg-info/SOURCES.txt +88 -0
- openfish-1.0.0/openfish.egg-info/dependency_links.txt +1 -0
- openfish-1.0.0/openfish.egg-info/entry_points.txt +2 -0
- openfish-1.0.0/openfish.egg-info/requires.txt +5 -0
- openfish-1.0.0/openfish.egg-info/top_level.txt +1 -0
- openfish-1.0.0/pyproject.toml +58 -0
- openfish-1.0.0/setup.cfg +4 -0
- openfish-1.0.0/src/__init__.py +1 -0
- openfish-1.0.0/src/app.py +136 -0
- openfish-1.0.0/src/approval.py +57 -0
- openfish-1.0.0/src/approval_store.py +122 -0
- openfish-1.0.0/src/audit.py +81 -0
- openfish-1.0.0/src/audit_events.py +130 -0
- openfish-1.0.0/src/auth.py +7 -0
- openfish-1.0.0/src/chat_state_store.py +375 -0
- openfish-1.0.0/src/cli.py +1480 -0
- openfish-1.0.0/src/codex_runner.py +735 -0
- openfish-1.0.0/src/codex_session_service.py +290 -0
- openfish-1.0.0/src/config.py +197 -0
- openfish-1.0.0/src/db.py +108 -0
- openfish-1.0.0/src/event_consistency.py +90 -0
- openfish-1.0.0/src/formatters.py +674 -0
- openfish-1.0.0/src/github_repo_service.py +105 -0
- openfish-1.0.0/src/main.py +12 -0
- openfish-1.0.0/src/mcp_service.py +500 -0
- openfish-1.0.0/src/models.py +51 -0
- openfish-1.0.0/src/process_lock.py +73 -0
- openfish-1.0.0/src/progress_reporter.py +69 -0
- openfish-1.0.0/src/project_registry.py +188 -0
- openfish-1.0.0/src/project_state_store.py +384 -0
- openfish-1.0.0/src/redaction.py +47 -0
- openfish-1.0.0/src/repo_inspector.py +65 -0
- openfish-1.0.0/src/resources/env.example +53 -0
- openfish-1.0.0/src/resources/migrations/0002_chat_context.sql +12 -0
- openfish-1.0.0/src/resources/migrations/0003_scheduled_tasks.sql +22 -0
- openfish-1.0.0/src/resources/migrations/0004_chat_flows_and_recent_projects.sql +17 -0
- openfish-1.0.0/src/resources/migrations/0005_chat_ui_mode.sql +2 -0
- openfish-1.0.0/src/resources/migrations/0006_chat_delivery_state.sql +11 -0
- openfish-1.0.0/src/resources/migrations/0007_chat_codex_model.sql +2 -0
- openfish-1.0.0/src/resources/migrations/0008_system_notifications.sql +10 -0
- openfish-1.0.0/src/resources/schema.sql +191 -0
- openfish-1.0.0/src/router.py +2447 -0
- openfish-1.0.0/src/schedule_store.py +222 -0
- openfish-1.0.0/src/scheduler.py +92 -0
- openfish-1.0.0/src/security_guard.py +39 -0
- openfish-1.0.0/src/skills_service.py +206 -0
- openfish-1.0.0/src/system_notification_store.py +103 -0
- openfish-1.0.0/src/task_runtime_store.py +322 -0
- openfish-1.0.0/src/task_store.py +810 -0
- openfish-1.0.0/src/telegram_adapter.py +1829 -0
- openfish-1.0.0/src/telegram_messages.py +124 -0
- openfish-1.0.0/src/telegram_sink.py +383 -0
- openfish-1.0.0/src/telegram_views.py +452 -0
- openfish-1.0.0/src/update_service.py +174 -0
- openfish-1.0.0/tests/test_approval.py +33 -0
- openfish-1.0.0/tests/test_approval_store.py +114 -0
- openfish-1.0.0/tests/test_audit.py +80 -0
- openfish-1.0.0/tests/test_cards_snapshot.py +59 -0
- openfish-1.0.0/tests/test_chat_state_store.py +134 -0
- openfish-1.0.0/tests/test_cli.py +661 -0
- openfish-1.0.0/tests/test_codex_runner.py +382 -0
- openfish-1.0.0/tests/test_config.py +92 -0
- openfish-1.0.0/tests/test_db.py +61 -0
- openfish-1.0.0/tests/test_event_consistency.py +34 -0
- openfish-1.0.0/tests/test_formatters.py +307 -0
- openfish-1.0.0/tests/test_github_repo_service.py +43 -0
- openfish-1.0.0/tests/test_mcp_service.py +130 -0
- openfish-1.0.0/tests/test_process_lock.py +38 -0
- openfish-1.0.0/tests/test_progress_reporter.py +63 -0
- openfish-1.0.0/tests/test_project_registry.py +91 -0
- openfish-1.0.0/tests/test_project_state_store.py +90 -0
- openfish-1.0.0/tests/test_redaction.py +22 -0
- openfish-1.0.0/tests/test_router.py +2028 -0
- openfish-1.0.0/tests/test_schedule_store.py +70 -0
- openfish-1.0.0/tests/test_scheduler.py +90 -0
- openfish-1.0.0/tests/test_security_guard.py +17 -0
- openfish-1.0.0/tests/test_skills_service.py +53 -0
- openfish-1.0.0/tests/test_system_notification_store.py +45 -0
- openfish-1.0.0/tests/test_task_events.py +128 -0
- openfish-1.0.0/tests/test_task_runtime_store.py +93 -0
- openfish-1.0.0/tests/test_task_store_context.py +463 -0
- openfish-1.0.0/tests/test_task_store_schedule.py +151 -0
- openfish-1.0.0/tests/test_telegram_adapter.py +1742 -0
- openfish-1.0.0/tests/test_telegram_messages.py +13 -0
- openfish-1.0.0/tests/test_telegram_sink.py +261 -0
- openfish-1.0.0/tests/test_telegram_views.py +219 -0
- openfish-1.0.0/tests/test_update_service.py +156 -0
openfish-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openfish
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: OpenFish: single-user Telegram-driven personal Codex assistant
|
|
5
|
+
Author: Re13orn
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Re13orn/openfish
|
|
8
|
+
Project-URL: Repository, https://github.com/Re13orn/openfish
|
|
9
|
+
Project-URL: Issues, https://github.com/Re13orn/openfish/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: telegram,codex,assistant,cli,self-hosted
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Communications :: Chat
|
|
19
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: PyYAML>=6.0
|
|
24
|
+
Requires-Dist: python-telegram-bot>=22.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
|
|
28
|
+
OpenFish
|
|
29
|
+
========
|
|
30
|
+
|
|
31
|
+
OpenFish is a single-user, Telegram-driven local Codex assistant.
|
|
32
|
+
|
|
33
|
+
It lets one trusted owner control local repositories from Telegram while execution, approvals, state, and audit data remain on the local machine.
|
|
34
|
+
|
|
35
|
+
Core capabilities
|
|
36
|
+
-----------------
|
|
37
|
+
|
|
38
|
+
- Project lifecycle: list, select, add, disable, archive
|
|
39
|
+
- Task lifecycle: ask, do, resume, retry, cancel
|
|
40
|
+
- Scheduling: periodic task add/list/run/pause/enable/delete
|
|
41
|
+
- Approval flow: approve/reject continuation
|
|
42
|
+
- Project memory: notes, recent summaries, paginated memory view
|
|
43
|
+
- Codex session browser: OpenFish sessions and local native sessions
|
|
44
|
+
- MCP management: list, inspect, enable, disable
|
|
45
|
+
- Service controls: restart, logs, update-check, self-update
|
|
46
|
+
- CLI runtime: `openfish install`, `configure`, `check`, `start`
|
|
47
|
+
|
|
48
|
+
Quick start
|
|
49
|
+
-----------
|
|
50
|
+
|
|
51
|
+
Install:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install openfish
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Repository mode:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
openfish install
|
|
61
|
+
openfish configure
|
|
62
|
+
openfish check
|
|
63
|
+
openfish start
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Home runtime mode:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
openfish init-home
|
|
70
|
+
export OPENFISH_HOME=~/.config/openfish
|
|
71
|
+
openfish install
|
|
72
|
+
openfish configure
|
|
73
|
+
openfish check
|
|
74
|
+
openfish start
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Common commands
|
|
78
|
+
---------------
|
|
79
|
+
|
|
80
|
+
- `openfish install`
|
|
81
|
+
- `openfish uninstall`
|
|
82
|
+
- `openfish configure`
|
|
83
|
+
- `openfish init-home`
|
|
84
|
+
- `openfish check`
|
|
85
|
+
- `openfish start`
|
|
86
|
+
- `openfish stop`
|
|
87
|
+
- `openfish restart`
|
|
88
|
+
- `openfish status`
|
|
89
|
+
- `openfish logs`
|
|
90
|
+
- `openfish update-check`
|
|
91
|
+
|
|
92
|
+
Scope
|
|
93
|
+
-----
|
|
94
|
+
|
|
95
|
+
OpenFish is built for:
|
|
96
|
+
|
|
97
|
+
- one trusted owner
|
|
98
|
+
- local-first execution
|
|
99
|
+
- project-scoped continuity
|
|
100
|
+
- Telegram as the primary control surface
|
|
101
|
+
|
|
102
|
+
OpenFish is not:
|
|
103
|
+
|
|
104
|
+
- a multi-user bot platform
|
|
105
|
+
- a public remote shell
|
|
106
|
+
- a cloud orchestration system
|
|
107
|
+
|
|
108
|
+
Links
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
- Homepage: https://github.com/Re13orn/openfish
|
|
112
|
+
- README: https://github.com/Re13orn/openfish/blob/main/README.md
|
|
113
|
+
- 中文说明: https://github.com/Re13orn/openfish/blob/main/README_CN.md
|
|
114
|
+
- Security: https://github.com/Re13orn/openfish/blob/main/SECURITY.md
|
|
115
|
+
- Changelog: https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
OpenFish
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
OpenFish is a single-user, Telegram-driven local Codex assistant.
|
|
5
|
+
|
|
6
|
+
It lets one trusted owner control local repositories from Telegram while execution, approvals, state, and audit data remain on the local machine.
|
|
7
|
+
|
|
8
|
+
Core capabilities
|
|
9
|
+
-----------------
|
|
10
|
+
|
|
11
|
+
- Project lifecycle: list, select, add, disable, archive
|
|
12
|
+
- Task lifecycle: ask, do, resume, retry, cancel
|
|
13
|
+
- Scheduling: periodic task add/list/run/pause/enable/delete
|
|
14
|
+
- Approval flow: approve/reject continuation
|
|
15
|
+
- Project memory: notes, recent summaries, paginated memory view
|
|
16
|
+
- Codex session browser: OpenFish sessions and local native sessions
|
|
17
|
+
- MCP management: list, inspect, enable, disable
|
|
18
|
+
- Service controls: restart, logs, update-check, self-update
|
|
19
|
+
- CLI runtime: `openfish install`, `configure`, `check`, `start`
|
|
20
|
+
|
|
21
|
+
Quick start
|
|
22
|
+
-----------
|
|
23
|
+
|
|
24
|
+
Install:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install openfish
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Repository mode:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
openfish install
|
|
34
|
+
openfish configure
|
|
35
|
+
openfish check
|
|
36
|
+
openfish start
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Home runtime mode:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
openfish init-home
|
|
43
|
+
export OPENFISH_HOME=~/.config/openfish
|
|
44
|
+
openfish install
|
|
45
|
+
openfish configure
|
|
46
|
+
openfish check
|
|
47
|
+
openfish start
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Common commands
|
|
51
|
+
---------------
|
|
52
|
+
|
|
53
|
+
- `openfish install`
|
|
54
|
+
- `openfish uninstall`
|
|
55
|
+
- `openfish configure`
|
|
56
|
+
- `openfish init-home`
|
|
57
|
+
- `openfish check`
|
|
58
|
+
- `openfish start`
|
|
59
|
+
- `openfish stop`
|
|
60
|
+
- `openfish restart`
|
|
61
|
+
- `openfish status`
|
|
62
|
+
- `openfish logs`
|
|
63
|
+
- `openfish update-check`
|
|
64
|
+
|
|
65
|
+
Scope
|
|
66
|
+
-----
|
|
67
|
+
|
|
68
|
+
OpenFish is built for:
|
|
69
|
+
|
|
70
|
+
- one trusted owner
|
|
71
|
+
- local-first execution
|
|
72
|
+
- project-scoped continuity
|
|
73
|
+
- Telegram as the primary control surface
|
|
74
|
+
|
|
75
|
+
OpenFish is not:
|
|
76
|
+
|
|
77
|
+
- a multi-user bot platform
|
|
78
|
+
- a public remote shell
|
|
79
|
+
- a cloud orchestration system
|
|
80
|
+
|
|
81
|
+
Links
|
|
82
|
+
-----
|
|
83
|
+
|
|
84
|
+
- Homepage: https://github.com/Re13orn/openfish
|
|
85
|
+
- README: https://github.com/Re13orn/openfish/blob/main/README.md
|
|
86
|
+
- 中文说明: https://github.com/Re13orn/openfish/blob/main/README_CN.md
|
|
87
|
+
- Security: https://github.com/Re13orn/openfish/blob/main/SECURITY.md
|
|
88
|
+
- Changelog: https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openfish
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: OpenFish: single-user Telegram-driven personal Codex assistant
|
|
5
|
+
Author: Re13orn
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Re13orn/openfish
|
|
8
|
+
Project-URL: Repository, https://github.com/Re13orn/openfish
|
|
9
|
+
Project-URL: Issues, https://github.com/Re13orn/openfish/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: telegram,codex,assistant,cli,self-hosted
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Communications :: Chat
|
|
19
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: PyYAML>=6.0
|
|
24
|
+
Requires-Dist: python-telegram-bot>=22.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
|
|
28
|
+
OpenFish
|
|
29
|
+
========
|
|
30
|
+
|
|
31
|
+
OpenFish is a single-user, Telegram-driven local Codex assistant.
|
|
32
|
+
|
|
33
|
+
It lets one trusted owner control local repositories from Telegram while execution, approvals, state, and audit data remain on the local machine.
|
|
34
|
+
|
|
35
|
+
Core capabilities
|
|
36
|
+
-----------------
|
|
37
|
+
|
|
38
|
+
- Project lifecycle: list, select, add, disable, archive
|
|
39
|
+
- Task lifecycle: ask, do, resume, retry, cancel
|
|
40
|
+
- Scheduling: periodic task add/list/run/pause/enable/delete
|
|
41
|
+
- Approval flow: approve/reject continuation
|
|
42
|
+
- Project memory: notes, recent summaries, paginated memory view
|
|
43
|
+
- Codex session browser: OpenFish sessions and local native sessions
|
|
44
|
+
- MCP management: list, inspect, enable, disable
|
|
45
|
+
- Service controls: restart, logs, update-check, self-update
|
|
46
|
+
- CLI runtime: `openfish install`, `configure`, `check`, `start`
|
|
47
|
+
|
|
48
|
+
Quick start
|
|
49
|
+
-----------
|
|
50
|
+
|
|
51
|
+
Install:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install openfish
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Repository mode:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
openfish install
|
|
61
|
+
openfish configure
|
|
62
|
+
openfish check
|
|
63
|
+
openfish start
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Home runtime mode:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
openfish init-home
|
|
70
|
+
export OPENFISH_HOME=~/.config/openfish
|
|
71
|
+
openfish install
|
|
72
|
+
openfish configure
|
|
73
|
+
openfish check
|
|
74
|
+
openfish start
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Common commands
|
|
78
|
+
---------------
|
|
79
|
+
|
|
80
|
+
- `openfish install`
|
|
81
|
+
- `openfish uninstall`
|
|
82
|
+
- `openfish configure`
|
|
83
|
+
- `openfish init-home`
|
|
84
|
+
- `openfish check`
|
|
85
|
+
- `openfish start`
|
|
86
|
+
- `openfish stop`
|
|
87
|
+
- `openfish restart`
|
|
88
|
+
- `openfish status`
|
|
89
|
+
- `openfish logs`
|
|
90
|
+
- `openfish update-check`
|
|
91
|
+
|
|
92
|
+
Scope
|
|
93
|
+
-----
|
|
94
|
+
|
|
95
|
+
OpenFish is built for:
|
|
96
|
+
|
|
97
|
+
- one trusted owner
|
|
98
|
+
- local-first execution
|
|
99
|
+
- project-scoped continuity
|
|
100
|
+
- Telegram as the primary control surface
|
|
101
|
+
|
|
102
|
+
OpenFish is not:
|
|
103
|
+
|
|
104
|
+
- a multi-user bot platform
|
|
105
|
+
- a public remote shell
|
|
106
|
+
- a cloud orchestration system
|
|
107
|
+
|
|
108
|
+
Links
|
|
109
|
+
-----
|
|
110
|
+
|
|
111
|
+
- Homepage: https://github.com/Re13orn/openfish
|
|
112
|
+
- README: https://github.com/Re13orn/openfish/blob/main/README.md
|
|
113
|
+
- 中文说明: https://github.com/Re13orn/openfish/blob/main/README_CN.md
|
|
114
|
+
- Security: https://github.com/Re13orn/openfish/blob/main/SECURITY.md
|
|
115
|
+
- Changelog: https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
README_PYPI.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
openfish.egg-info/PKG-INFO
|
|
4
|
+
openfish.egg-info/SOURCES.txt
|
|
5
|
+
openfish.egg-info/dependency_links.txt
|
|
6
|
+
openfish.egg-info/entry_points.txt
|
|
7
|
+
openfish.egg-info/requires.txt
|
|
8
|
+
openfish.egg-info/top_level.txt
|
|
9
|
+
src/__init__.py
|
|
10
|
+
src/app.py
|
|
11
|
+
src/approval.py
|
|
12
|
+
src/approval_store.py
|
|
13
|
+
src/audit.py
|
|
14
|
+
src/audit_events.py
|
|
15
|
+
src/auth.py
|
|
16
|
+
src/chat_state_store.py
|
|
17
|
+
src/cli.py
|
|
18
|
+
src/codex_runner.py
|
|
19
|
+
src/codex_session_service.py
|
|
20
|
+
src/config.py
|
|
21
|
+
src/db.py
|
|
22
|
+
src/event_consistency.py
|
|
23
|
+
src/formatters.py
|
|
24
|
+
src/github_repo_service.py
|
|
25
|
+
src/main.py
|
|
26
|
+
src/mcp_service.py
|
|
27
|
+
src/models.py
|
|
28
|
+
src/process_lock.py
|
|
29
|
+
src/progress_reporter.py
|
|
30
|
+
src/project_registry.py
|
|
31
|
+
src/project_state_store.py
|
|
32
|
+
src/redaction.py
|
|
33
|
+
src/repo_inspector.py
|
|
34
|
+
src/router.py
|
|
35
|
+
src/schedule_store.py
|
|
36
|
+
src/scheduler.py
|
|
37
|
+
src/security_guard.py
|
|
38
|
+
src/skills_service.py
|
|
39
|
+
src/system_notification_store.py
|
|
40
|
+
src/task_runtime_store.py
|
|
41
|
+
src/task_store.py
|
|
42
|
+
src/telegram_adapter.py
|
|
43
|
+
src/telegram_messages.py
|
|
44
|
+
src/telegram_sink.py
|
|
45
|
+
src/telegram_views.py
|
|
46
|
+
src/update_service.py
|
|
47
|
+
src/resources/env.example
|
|
48
|
+
src/resources/schema.sql
|
|
49
|
+
src/resources/migrations/0002_chat_context.sql
|
|
50
|
+
src/resources/migrations/0003_scheduled_tasks.sql
|
|
51
|
+
src/resources/migrations/0004_chat_flows_and_recent_projects.sql
|
|
52
|
+
src/resources/migrations/0005_chat_ui_mode.sql
|
|
53
|
+
src/resources/migrations/0006_chat_delivery_state.sql
|
|
54
|
+
src/resources/migrations/0007_chat_codex_model.sql
|
|
55
|
+
src/resources/migrations/0008_system_notifications.sql
|
|
56
|
+
tests/test_approval.py
|
|
57
|
+
tests/test_approval_store.py
|
|
58
|
+
tests/test_audit.py
|
|
59
|
+
tests/test_cards_snapshot.py
|
|
60
|
+
tests/test_chat_state_store.py
|
|
61
|
+
tests/test_cli.py
|
|
62
|
+
tests/test_codex_runner.py
|
|
63
|
+
tests/test_config.py
|
|
64
|
+
tests/test_db.py
|
|
65
|
+
tests/test_event_consistency.py
|
|
66
|
+
tests/test_formatters.py
|
|
67
|
+
tests/test_github_repo_service.py
|
|
68
|
+
tests/test_mcp_service.py
|
|
69
|
+
tests/test_process_lock.py
|
|
70
|
+
tests/test_progress_reporter.py
|
|
71
|
+
tests/test_project_registry.py
|
|
72
|
+
tests/test_project_state_store.py
|
|
73
|
+
tests/test_redaction.py
|
|
74
|
+
tests/test_router.py
|
|
75
|
+
tests/test_schedule_store.py
|
|
76
|
+
tests/test_scheduler.py
|
|
77
|
+
tests/test_security_guard.py
|
|
78
|
+
tests/test_skills_service.py
|
|
79
|
+
tests/test_system_notification_store.py
|
|
80
|
+
tests/test_task_events.py
|
|
81
|
+
tests/test_task_runtime_store.py
|
|
82
|
+
tests/test_task_store_context.py
|
|
83
|
+
tests/test_task_store_schedule.py
|
|
84
|
+
tests/test_telegram_adapter.py
|
|
85
|
+
tests/test_telegram_messages.py
|
|
86
|
+
tests/test_telegram_sink.py
|
|
87
|
+
tests/test_telegram_views.py
|
|
88
|
+
tests/test_update_service.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
src
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "openfish"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "OpenFish: single-user Telegram-driven personal Codex assistant"
|
|
9
|
+
readme = "README_PYPI.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Re13orn" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["telegram", "codex", "assistant", "cli", "self-hosted"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Communications :: Chat",
|
|
24
|
+
"Topic :: Software Development :: Build Tools",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"PyYAML>=6.0",
|
|
29
|
+
"python-telegram-bot>=22.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/Re13orn/openfish"
|
|
34
|
+
Repository = "https://github.com/Re13orn/openfish"
|
|
35
|
+
Issues = "https://github.com/Re13orn/openfish/issues"
|
|
36
|
+
Changelog = "https://github.com/Re13orn/openfish/blob/main/CHANGELOG.md"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
openfish = "src.cli:main"
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
dev = [
|
|
43
|
+
"pytest>=8.0",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools]
|
|
47
|
+
packages = ["src"]
|
|
48
|
+
include-package-data = true
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.package-data]
|
|
51
|
+
src = [
|
|
52
|
+
"resources/schema.sql",
|
|
53
|
+
"resources/env.example",
|
|
54
|
+
"resources/migrations/*.sql",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
openfish-1.0.0/setup.cfg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""OpenFish assistant package."""
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""Application composition root."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from src.audit import AuditLogger
|
|
7
|
+
from src.approval import ApprovalService
|
|
8
|
+
from src.codex_runner import CodexRunner
|
|
9
|
+
from src.codex_session_service import CodexSessionService
|
|
10
|
+
from src.config import AppConfig, load_config
|
|
11
|
+
from src.db import Database
|
|
12
|
+
from src.github_repo_service import GitHubRepoService
|
|
13
|
+
from src.project_registry import ProjectRegistry
|
|
14
|
+
from src.process_lock import ProcessLock, acquire_process_lock
|
|
15
|
+
from src.repo_inspector import RepoInspector
|
|
16
|
+
from src.router import CommandRouter
|
|
17
|
+
from src.scheduler import ScheduledTaskService
|
|
18
|
+
from src.skills_service import SkillsService
|
|
19
|
+
from src.mcp_service import McpService
|
|
20
|
+
from src.task_store import TaskStore
|
|
21
|
+
from src.telegram_adapter import TelegramBotService
|
|
22
|
+
from src.update_service import UpdateService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Application:
|
|
29
|
+
"""Build and run the single-process assistant service."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, config: AppConfig) -> None:
|
|
32
|
+
self.config = config
|
|
33
|
+
self.process_lock: ProcessLock | None = None
|
|
34
|
+
self.db = Database(config.sqlite_path, config.schema_path, config.migrations_dir)
|
|
35
|
+
self.projects = ProjectRegistry(config.projects_config_path)
|
|
36
|
+
self.tasks = TaskStore(self.db)
|
|
37
|
+
self.audit = AuditLogger(self.db)
|
|
38
|
+
self.approvals = ApprovalService()
|
|
39
|
+
self.codex = CodexRunner(config)
|
|
40
|
+
self.codex_sessions = CodexSessionService(db=self.db, codex_home=config.codex_home)
|
|
41
|
+
self.skills = SkillsService(
|
|
42
|
+
codex_bin=config.codex_bin,
|
|
43
|
+
skills_root=config.codex_home / "skills",
|
|
44
|
+
enable_install=config.enable_skill_install,
|
|
45
|
+
timeout_seconds=config.skill_install_timeout_seconds,
|
|
46
|
+
)
|
|
47
|
+
self.mcp = McpService(
|
|
48
|
+
codex_bin=config.codex_bin,
|
|
49
|
+
timeout_seconds=config.codex_command_timeout_seconds,
|
|
50
|
+
config_path=config.codex_home / "config.toml",
|
|
51
|
+
)
|
|
52
|
+
self.updates = UpdateService(
|
|
53
|
+
repo_root=Path(__file__).resolve().parents[2],
|
|
54
|
+
script_path=Path(__file__).resolve().parents[1] / "scripts" / "install_start.sh",
|
|
55
|
+
)
|
|
56
|
+
self.github_repos = GitHubRepoService()
|
|
57
|
+
self.repo = RepoInspector()
|
|
58
|
+
self.router = CommandRouter(
|
|
59
|
+
config=config,
|
|
60
|
+
projects=self.projects,
|
|
61
|
+
tasks=self.tasks,
|
|
62
|
+
audit=self.audit,
|
|
63
|
+
codex=self.codex,
|
|
64
|
+
repo=self.repo,
|
|
65
|
+
approvals=self.approvals,
|
|
66
|
+
skills_service=self.skills,
|
|
67
|
+
mcp_service=self.mcp,
|
|
68
|
+
update_service=self.updates,
|
|
69
|
+
codex_sessions=self.codex_sessions,
|
|
70
|
+
github_repos=self.github_repos,
|
|
71
|
+
)
|
|
72
|
+
self.scheduler = ScheduledTaskService(
|
|
73
|
+
tasks=self.tasks,
|
|
74
|
+
router=self.router,
|
|
75
|
+
poll_interval_seconds=self.config.schedule_poll_interval_seconds,
|
|
76
|
+
enabled=self.config.enable_scheduler,
|
|
77
|
+
missed_run_policy=self.config.schedule_missed_run_policy,
|
|
78
|
+
)
|
|
79
|
+
self.bot = TelegramBotService(config=config, router=self.router)
|
|
80
|
+
|
|
81
|
+
def run(self) -> None:
|
|
82
|
+
self._configure_logging()
|
|
83
|
+
self.process_lock = acquire_process_lock(self.config.process_lock_path)
|
|
84
|
+
logger.info("Acquired process lock: %s", self.config.process_lock_path)
|
|
85
|
+
self.projects.load()
|
|
86
|
+
self._run_startup_health_checks()
|
|
87
|
+
self.db.connect()
|
|
88
|
+
self.db.initialize_schema()
|
|
89
|
+
self.tasks.sync_projects_from_registry(self.projects)
|
|
90
|
+
recovered_task_ids = self.tasks.recover_interrupted_tasks()
|
|
91
|
+
if recovered_task_ids:
|
|
92
|
+
logger.warning(
|
|
93
|
+
"Recovered %d interrupted task(s) on startup: %s",
|
|
94
|
+
len(recovered_task_ids),
|
|
95
|
+
", ".join(str(task_id) for task_id in recovered_task_ids),
|
|
96
|
+
)
|
|
97
|
+
self.scheduler.start()
|
|
98
|
+
try:
|
|
99
|
+
self.bot.run_polling()
|
|
100
|
+
finally:
|
|
101
|
+
self.scheduler.stop()
|
|
102
|
+
self.db.close_all()
|
|
103
|
+
if self.process_lock is not None:
|
|
104
|
+
self.process_lock.release()
|
|
105
|
+
self.process_lock = None
|
|
106
|
+
|
|
107
|
+
def _configure_logging(self) -> None:
|
|
108
|
+
logging.basicConfig(
|
|
109
|
+
level=getattr(logging, self.config.log_level.upper(), logging.INFO),
|
|
110
|
+
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def _run_startup_health_checks(self) -> None:
|
|
114
|
+
if not self.projects.projects:
|
|
115
|
+
logger.warning(
|
|
116
|
+
"Project registry is empty. Service will start, but you should add a project via /project-add."
|
|
117
|
+
)
|
|
118
|
+
return
|
|
119
|
+
|
|
120
|
+
for key, project in self.projects.projects.items():
|
|
121
|
+
if not project.is_active:
|
|
122
|
+
continue
|
|
123
|
+
if not self.projects.is_path_allowed(project, project.path):
|
|
124
|
+
raise ValueError(
|
|
125
|
+
f"Project '{key}' path is not in allowed_directories: {project.path}"
|
|
126
|
+
)
|
|
127
|
+
project_path = Path(project.path)
|
|
128
|
+
if not project_path.exists():
|
|
129
|
+
logger.warning("Project path does not exist for key=%s path=%s", key, project_path)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def create_app() -> Application:
|
|
133
|
+
"""Factory used by CLI entry points and tests."""
|
|
134
|
+
|
|
135
|
+
config = load_config()
|
|
136
|
+
return Application(config)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Approval policy helpers for Phase 3 workflow."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
from src.codex_runner import CodexRunResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
APPROVAL_PATTERNS = [
|
|
10
|
+
re.compile(r"\bneeds?\s+approval\b", re.IGNORECASE),
|
|
11
|
+
re.compile(r"\bwaiting\s+for\s+approval\b", re.IGNORECASE),
|
|
12
|
+
re.compile(r"\brequires?\s+approval\b", re.IGNORECASE),
|
|
13
|
+
re.compile(r"\bapprove\b", re.IGNORECASE),
|
|
14
|
+
re.compile(r"等待审批"),
|
|
15
|
+
re.compile(r"需要审批"),
|
|
16
|
+
re.compile(r"请批准"),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(slots=True)
|
|
21
|
+
class ApprovalAssessment:
|
|
22
|
+
requires_approval: bool
|
|
23
|
+
reason: str | None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ApprovalService:
|
|
27
|
+
"""Detects approval pauses from Codex output and builds follow-up instructions."""
|
|
28
|
+
|
|
29
|
+
def assess(self, result: CodexRunResult) -> ApprovalAssessment:
|
|
30
|
+
text_parts = [result.summary or "", result.stderr or "", result.stdout or ""]
|
|
31
|
+
combined = "\n".join(part for part in text_parts if part).strip()
|
|
32
|
+
if not combined:
|
|
33
|
+
return ApprovalAssessment(requires_approval=False, reason=None)
|
|
34
|
+
|
|
35
|
+
for pattern in APPROVAL_PATTERNS:
|
|
36
|
+
if pattern.search(combined):
|
|
37
|
+
reason = self._extract_reason(combined)
|
|
38
|
+
return ApprovalAssessment(requires_approval=True, reason=reason)
|
|
39
|
+
return ApprovalAssessment(requires_approval=False, reason=None)
|
|
40
|
+
|
|
41
|
+
def build_resume_instruction(self, requested_action: str, user_note: str | None = None) -> str:
|
|
42
|
+
base = (
|
|
43
|
+
"Approval granted. Continue the previously blocked task with conservative changes and concise summary. "
|
|
44
|
+
f"Approved action context: {requested_action}"
|
|
45
|
+
)
|
|
46
|
+
if user_note:
|
|
47
|
+
return f"{base}\nUser note: {user_note}"
|
|
48
|
+
return base
|
|
49
|
+
|
|
50
|
+
def _extract_reason(self, text: str, max_len: int = 240) -> str:
|
|
51
|
+
for line in text.splitlines():
|
|
52
|
+
candidate = line.strip()
|
|
53
|
+
if not candidate:
|
|
54
|
+
continue
|
|
55
|
+
if any(p.search(candidate) for p in APPROVAL_PATTERNS):
|
|
56
|
+
return candidate[:max_len]
|
|
57
|
+
return text[:max_len]
|