overcode 0.1.0__py3-none-any.whl

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 (43) hide show
  1. overcode/__init__.py +5 -0
  2. overcode/cli.py +812 -0
  3. overcode/config.py +72 -0
  4. overcode/daemon.py +1184 -0
  5. overcode/daemon_claude_skill.md +180 -0
  6. overcode/daemon_state.py +113 -0
  7. overcode/data_export.py +257 -0
  8. overcode/dependency_check.py +227 -0
  9. overcode/exceptions.py +219 -0
  10. overcode/history_reader.py +448 -0
  11. overcode/implementations.py +214 -0
  12. overcode/interfaces.py +49 -0
  13. overcode/launcher.py +434 -0
  14. overcode/logging_config.py +193 -0
  15. overcode/mocks.py +152 -0
  16. overcode/monitor_daemon.py +808 -0
  17. overcode/monitor_daemon_state.py +358 -0
  18. overcode/pid_utils.py +225 -0
  19. overcode/presence_logger.py +454 -0
  20. overcode/protocols.py +143 -0
  21. overcode/session_manager.py +606 -0
  22. overcode/settings.py +412 -0
  23. overcode/standing_instructions.py +276 -0
  24. overcode/status_constants.py +190 -0
  25. overcode/status_detector.py +339 -0
  26. overcode/status_history.py +164 -0
  27. overcode/status_patterns.py +264 -0
  28. overcode/summarizer_client.py +136 -0
  29. overcode/summarizer_component.py +312 -0
  30. overcode/supervisor_daemon.py +1000 -0
  31. overcode/supervisor_layout.sh +50 -0
  32. overcode/tmux_manager.py +228 -0
  33. overcode/tui.py +2549 -0
  34. overcode/tui_helpers.py +495 -0
  35. overcode/web_api.py +279 -0
  36. overcode/web_server.py +138 -0
  37. overcode/web_templates.py +563 -0
  38. overcode-0.1.0.dist-info/METADATA +87 -0
  39. overcode-0.1.0.dist-info/RECORD +43 -0
  40. overcode-0.1.0.dist-info/WHEEL +5 -0
  41. overcode-0.1.0.dist-info/entry_points.txt +2 -0
  42. overcode-0.1.0.dist-info/licenses/LICENSE +21 -0
  43. overcode-0.1.0.dist-info/top_level.txt +1 -0
overcode/mocks.py ADDED
@@ -0,0 +1,152 @@
1
+ """
2
+ Mock implementations of protocol interfaces for testing.
3
+
4
+ These mocks allow unit tests to run without real tmux sessions,
5
+ file system access, or subprocess calls.
6
+ """
7
+
8
+ import json
9
+ from pathlib import Path
10
+ from typing import Optional, List, Dict, Any
11
+
12
+
13
+ class MockTmux:
14
+ """Mock implementation of TmuxInterface for testing"""
15
+
16
+ def __init__(self):
17
+ self.sessions: Dict[str, Dict[int, str]] = {} # session -> {window: content}
18
+ self.sent_keys: List[tuple] = [] # Record of sent keys
19
+ self._next_window = 1
20
+
21
+ def set_pane_content(self, session: str, window: int, content: str):
22
+ """Set up mock pane content for testing"""
23
+ if session not in self.sessions:
24
+ self.sessions[session] = {}
25
+ self.sessions[session][window] = content
26
+
27
+ def capture_pane(self, session: str, window: int, lines: int = 100) -> Optional[str]:
28
+ if session in self.sessions and window in self.sessions[session]:
29
+ content = self.sessions[session][window]
30
+ # Simulate line limit
31
+ content_lines = content.split('\n')
32
+ return '\n'.join(content_lines[-lines:])
33
+ return None
34
+
35
+ def send_keys(self, session: str, window: int, keys: str, enter: bool = True) -> bool:
36
+ self.sent_keys.append((session, window, keys, enter))
37
+ return session in self.sessions
38
+
39
+ def has_session(self, session: str) -> bool:
40
+ return session in self.sessions
41
+
42
+ def new_session(self, session: str) -> bool:
43
+ if session not in self.sessions:
44
+ self.sessions[session] = {}
45
+ return True
46
+ return False
47
+
48
+ def new_window(self, session: str, name: str, command: Optional[List[str]] = None,
49
+ cwd: Optional[str] = None) -> Optional[int]:
50
+ if session not in self.sessions:
51
+ return None
52
+ window = self._next_window
53
+ self._next_window += 1
54
+ self.sessions[session][window] = ""
55
+ return window
56
+
57
+ def kill_window(self, session: str, window: int) -> bool:
58
+ if session in self.sessions and window in self.sessions[session]:
59
+ del self.sessions[session][window]
60
+ return True
61
+ return False
62
+
63
+ def kill_session(self, session: str) -> bool:
64
+ if session in self.sessions:
65
+ del self.sessions[session]
66
+ return True
67
+ return False
68
+
69
+ def list_windows(self, session: str) -> List[Dict[str, Any]]:
70
+ if session not in self.sessions:
71
+ return []
72
+ return [
73
+ {'index': idx, 'name': f'window-{idx}', 'active': False}
74
+ for idx in self.sessions[session].keys()
75
+ ]
76
+
77
+ def attach(self, session: str) -> None:
78
+ pass # No-op in tests
79
+
80
+
81
+ class MockFileSystem:
82
+ """Mock implementation of FileSystemInterface for testing"""
83
+
84
+ def __init__(self):
85
+ self.files: Dict[str, Any] = {} # path_str -> content
86
+ self.dirs: set = set()
87
+
88
+ def read_json(self, path: Path) -> Optional[Dict[str, Any]]:
89
+ content = self.files.get(str(path))
90
+ if content is None:
91
+ return None
92
+ if isinstance(content, dict):
93
+ return content
94
+ try:
95
+ return json.loads(content)
96
+ except json.JSONDecodeError:
97
+ return None
98
+
99
+ def write_json(self, path: Path, data: Dict[str, Any]) -> bool:
100
+ self.files[str(path)] = data
101
+ return True
102
+
103
+ def exists(self, path: Path) -> bool:
104
+ return str(path) in self.files or str(path) in self.dirs
105
+
106
+ def mkdir(self, path: Path, parents: bool = True) -> bool:
107
+ self.dirs.add(str(path))
108
+ return True
109
+
110
+ def read_text(self, path: Path) -> Optional[str]:
111
+ content = self.files.get(str(path))
112
+ if content is None:
113
+ return None
114
+ return str(content)
115
+
116
+ def write_text(self, path: Path, content: str) -> bool:
117
+ self.files[str(path)] = content
118
+ return True
119
+
120
+
121
+ class MockSubprocess:
122
+ """Mock implementation of SubprocessInterface for testing"""
123
+
124
+ def __init__(self):
125
+ self.commands: List[List[str]] = [] # Record of run commands
126
+ self.responses: Dict[str, Dict[str, Any]] = {} # cmd_key -> response
127
+
128
+ def set_response(self, cmd_prefix: str, returncode: int = 0,
129
+ stdout: str = "", stderr: str = ""):
130
+ """Set up a mock response for commands starting with prefix"""
131
+ self.responses[cmd_prefix] = {
132
+ 'returncode': returncode,
133
+ 'stdout': stdout,
134
+ 'stderr': stderr
135
+ }
136
+
137
+ def run(self, cmd: List[str], timeout: Optional[int] = None,
138
+ capture_output: bool = True) -> Optional[Dict[str, Any]]:
139
+ self.commands.append(cmd)
140
+ cmd_str = ' '.join(cmd)
141
+
142
+ # Check for matching response
143
+ for prefix, response in self.responses.items():
144
+ if cmd_str.startswith(prefix):
145
+ return response
146
+
147
+ # Default response
148
+ return {'returncode': 0, 'stdout': '', 'stderr': ''}
149
+
150
+ def popen(self, cmd: List[str], cwd: Optional[str] = None) -> Any:
151
+ self.commands.append(cmd)
152
+ return None