portacode 0.3.12.dev7__tar.gz → 0.3.12.dev8__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.
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/PKG-INFO +1 -1
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/_version.py +2 -2
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/session.py +30 -8
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/terminal.py +3 -2
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/.claude/agents/communication-manager.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/.claude/settings.local.json +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/.gitignore +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/.gitmodules +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/LICENSE +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/MANIFEST.in +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/Makefile +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/README.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/backup.sh +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/docker-compose.yaml +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/README.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/__init__.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/__main__.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/cli.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/README.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/__init__.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/client.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/README.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/base.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/registry.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/multiplex.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/data.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/keypair.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/service.py +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/requires.txt +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode.egg-info/top_level.txt +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/pyproject.toml +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/restore.sh +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/setup.cfg +0 -0
- {portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/setup.py +0 -0
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.3.12.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 3, 12, '
|
|
20
|
+
__version__ = version = '0.3.12.dev8'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 3, 12, 'dev8')
|
|
@@ -36,11 +36,12 @@ def _build_child_env() -> Dict[str, str]:
|
|
|
36
36
|
class TerminalSession:
|
|
37
37
|
"""Represents a local shell subprocess bound to a mux channel."""
|
|
38
38
|
|
|
39
|
-
def __init__(self, session_id: str, proc: Process, channel: "Channel", project_id: Optional[str] = None):
|
|
39
|
+
def __init__(self, session_id: str, proc: Process, channel: "Channel", project_id: Optional[str] = None, terminal_manager: Optional["TerminalManager"] = None):
|
|
40
40
|
self.id = session_id
|
|
41
41
|
self.proc = proc
|
|
42
42
|
self.channel = channel
|
|
43
43
|
self.project_id = project_id
|
|
44
|
+
self.terminal_manager = terminal_manager
|
|
44
45
|
self._reader_task: Optional[asyncio.Task[None]] = None
|
|
45
46
|
self._buffer: deque[str] = deque(maxlen=400)
|
|
46
47
|
|
|
@@ -58,7 +59,17 @@ class TerminalSession:
|
|
|
58
59
|
logging.getLogger("portacode.terminal").debug(f"[MUX] Terminal {self.id} output: {text!r}")
|
|
59
60
|
self._buffer.append(text)
|
|
60
61
|
try:
|
|
61
|
-
|
|
62
|
+
# Send terminal data via control channel with client session targeting
|
|
63
|
+
if self.terminal_manager:
|
|
64
|
+
await self.terminal_manager._send_session_aware({
|
|
65
|
+
"event": "terminal_data",
|
|
66
|
+
"channel": self.id,
|
|
67
|
+
"data": text,
|
|
68
|
+
"project_id": self.project_id
|
|
69
|
+
}, project_id=self.project_id)
|
|
70
|
+
else:
|
|
71
|
+
# Fallback to raw channel for backward compatibility
|
|
72
|
+
await self.channel.send(text)
|
|
62
73
|
except Exception as exc:
|
|
63
74
|
logger.warning("Failed to forward terminal output: %s", exc)
|
|
64
75
|
await asyncio.sleep(0.5)
|
|
@@ -147,7 +158,7 @@ class TerminalSession:
|
|
|
147
158
|
class WindowsTerminalSession(TerminalSession):
|
|
148
159
|
"""Terminal session backed by a Windows ConPTY."""
|
|
149
160
|
|
|
150
|
-
def __init__(self, session_id: str, pty, channel: "Channel", project_id: Optional[str] = None):
|
|
161
|
+
def __init__(self, session_id: str, pty, channel: "Channel", project_id: Optional[str] = None, terminal_manager: Optional["TerminalManager"] = None):
|
|
151
162
|
# Create a proxy for the PTY process
|
|
152
163
|
class _WinPTYProxy:
|
|
153
164
|
def __init__(self, pty):
|
|
@@ -165,7 +176,7 @@ class WindowsTerminalSession(TerminalSession):
|
|
|
165
176
|
loop = asyncio.get_running_loop()
|
|
166
177
|
await loop.run_in_executor(None, self._pty.wait)
|
|
167
178
|
|
|
168
|
-
super().__init__(session_id, _WinPTYProxy(pty), channel, project_id)
|
|
179
|
+
super().__init__(session_id, _WinPTYProxy(pty), channel, project_id, terminal_manager)
|
|
169
180
|
self._pty = pty
|
|
170
181
|
|
|
171
182
|
async def start_io_forwarding(self) -> None:
|
|
@@ -188,7 +199,17 @@ class WindowsTerminalSession(TerminalSession):
|
|
|
188
199
|
logging.getLogger("portacode.terminal").debug(f"[MUX] Terminal {self.id} output: {text!r}")
|
|
189
200
|
self._buffer.append(text)
|
|
190
201
|
try:
|
|
191
|
-
|
|
202
|
+
# Send terminal data via control channel with client session targeting
|
|
203
|
+
if self.terminal_manager:
|
|
204
|
+
await self.terminal_manager._send_session_aware({
|
|
205
|
+
"event": "terminal_data",
|
|
206
|
+
"channel": self.id,
|
|
207
|
+
"data": text,
|
|
208
|
+
"project_id": self.project_id
|
|
209
|
+
}, project_id=self.project_id)
|
|
210
|
+
else:
|
|
211
|
+
# Fallback to raw channel for backward compatibility
|
|
212
|
+
await self.channel.send(text)
|
|
192
213
|
except Exception as exc:
|
|
193
214
|
logger.warning("Failed to forward terminal output: %s", exc)
|
|
194
215
|
await asyncio.sleep(0.5)
|
|
@@ -247,8 +268,9 @@ class WindowsTerminalSession(TerminalSession):
|
|
|
247
268
|
class SessionManager:
|
|
248
269
|
"""Manages terminal sessions."""
|
|
249
270
|
|
|
250
|
-
def __init__(self, mux):
|
|
271
|
+
def __init__(self, mux, terminal_manager=None):
|
|
251
272
|
self.mux = mux
|
|
273
|
+
self.terminal_manager = terminal_manager
|
|
252
274
|
self._sessions: Dict[str, TerminalSession] = {}
|
|
253
275
|
|
|
254
276
|
def _allocate_channel_id(self) -> str:
|
|
@@ -287,7 +309,7 @@ class SessionManager:
|
|
|
287
309
|
raise RuntimeError("pywinpty not installed on client")
|
|
288
310
|
|
|
289
311
|
pty_proc = PtyProcess.spawn(shell, cwd=cwd or None, env=_build_child_env())
|
|
290
|
-
session = WindowsTerminalSession(term_id, pty_proc, channel, project_id)
|
|
312
|
+
session = WindowsTerminalSession(term_id, pty_proc, channel, project_id, self.terminal_manager)
|
|
291
313
|
else:
|
|
292
314
|
# Unix: try real PTY for proper TTY semantics
|
|
293
315
|
try:
|
|
@@ -320,7 +342,7 @@ class SessionManager:
|
|
|
320
342
|
cwd=cwd,
|
|
321
343
|
env=_build_child_env(),
|
|
322
344
|
)
|
|
323
|
-
session = TerminalSession(term_id, proc, channel, project_id)
|
|
345
|
+
session = TerminalSession(term_id, proc, channel, project_id, self.terminal_manager)
|
|
324
346
|
|
|
325
347
|
self._sessions[term_id] = session
|
|
326
348
|
await session.start_io_forwarding()
|
|
@@ -167,11 +167,12 @@ class TerminalManager:
|
|
|
167
167
|
|
|
168
168
|
# Only create new session manager on initial setup, preserve existing one on reconnection
|
|
169
169
|
if is_initial or self._session_manager is None:
|
|
170
|
-
self._session_manager = SessionManager(mux)
|
|
170
|
+
self._session_manager = SessionManager(mux, terminal_manager=self)
|
|
171
171
|
logger.info("Created new SessionManager")
|
|
172
172
|
else:
|
|
173
|
-
# Update existing session manager's mux
|
|
173
|
+
# Update existing session manager's mux and terminal_manager references
|
|
174
174
|
self._session_manager.mux = mux
|
|
175
|
+
self._session_manager.terminal_manager = self
|
|
175
176
|
logger.info("Preserved existing SessionManager with %d sessions", len(self._session_manager._sessions))
|
|
176
177
|
|
|
177
178
|
# Create context for handlers
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/file_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
{portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/system_handlers.py
RENAMED
|
File without changes
|
{portacode-0.3.12.dev7 → portacode-0.3.12.dev8}/portacode/connection/handlers/terminal_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|