portacode 0.3.24__tar.gz → 0.3.25__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.

Potentially problematic release.


This version of portacode might be problematic. Click here for more details.

Files changed (84) hide show
  1. {portacode-0.3.24 → portacode-0.3.25}/PKG-INFO +1 -1
  2. {portacode-0.3.24 → portacode-0.3.25}/portacode/_version.py +2 -2
  3. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/session.py +28 -1
  4. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/terminal.py +13 -4
  5. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/PKG-INFO +1 -1
  6. {portacode-0.3.24 → portacode-0.3.25}/.claude/agents/communication-manager.md +0 -0
  7. {portacode-0.3.24 → portacode-0.3.25}/.claude/settings.local.json +0 -0
  8. {portacode-0.3.24 → portacode-0.3.25}/.gitignore +0 -0
  9. {portacode-0.3.24 → portacode-0.3.25}/.gitmodules +0 -0
  10. {portacode-0.3.24 → portacode-0.3.25}/LICENSE +0 -0
  11. {portacode-0.3.24 → portacode-0.3.25}/MANIFEST.in +0 -0
  12. {portacode-0.3.24 → portacode-0.3.25}/Makefile +0 -0
  13. {portacode-0.3.24 → portacode-0.3.25}/README.md +0 -0
  14. {portacode-0.3.24 → portacode-0.3.25}/backup.sh +0 -0
  15. {portacode-0.3.24 → portacode-0.3.25}/connect.py +0 -0
  16. {portacode-0.3.24 → portacode-0.3.25}/connect.sh +0 -0
  17. {portacode-0.3.24 → portacode-0.3.25}/docker-compose.yaml +0 -0
  18. {portacode-0.3.24 → portacode-0.3.25}/portacode/README.md +0 -0
  19. {portacode-0.3.24 → portacode-0.3.25}/portacode/__init__.py +0 -0
  20. {portacode-0.3.24 → portacode-0.3.25}/portacode/__main__.py +0 -0
  21. {portacode-0.3.24 → portacode-0.3.25}/portacode/cli.py +0 -0
  22. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/README.md +0 -0
  23. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/__init__.py +0 -0
  24. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/client.py +0 -0
  25. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/README.md +0 -0
  26. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  27. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/__init__.py +0 -0
  28. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/base.py +0 -0
  29. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/chunked_content.py +0 -0
  30. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/file_handlers.py +0 -0
  31. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
  32. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/README.md +0 -0
  33. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/__init__.py +0 -0
  34. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
  35. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/git_manager.py +0 -0
  36. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/handlers.py +0 -0
  37. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/manager.py +0 -0
  38. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/models.py +0 -0
  39. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state/utils.py +0 -0
  40. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/project_state_handlers.py +0 -0
  41. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/registry.py +0 -0
  42. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/system_handlers.py +0 -0
  43. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/tab_factory.py +0 -0
  44. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/handlers/terminal_handlers.py +0 -0
  45. {portacode-0.3.24 → portacode-0.3.25}/portacode/connection/multiplex.py +0 -0
  46. {portacode-0.3.24 → portacode-0.3.25}/portacode/data.py +0 -0
  47. {portacode-0.3.24 → portacode-0.3.25}/portacode/keypair.py +0 -0
  48. {portacode-0.3.24 → portacode-0.3.25}/portacode/logging_categories.py +0 -0
  49. {portacode-0.3.24 → portacode-0.3.25}/portacode/service.py +0 -0
  50. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/SOURCES.txt +0 -0
  51. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/dependency_links.txt +0 -0
  52. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/entry_points.txt +0 -0
  53. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/requires.txt +0 -0
  54. {portacode-0.3.24 → portacode-0.3.25}/portacode.egg-info/top_level.txt +0 -0
  55. {portacode-0.3.24 → portacode-0.3.25}/pyproject.toml +0 -0
  56. {portacode-0.3.24 → portacode-0.3.25}/restore.sh +0 -0
  57. {portacode-0.3.24 → portacode-0.3.25}/run_tests.py +0 -0
  58. {portacode-0.3.24 → portacode-0.3.25}/setup.cfg +0 -0
  59. {portacode-0.3.24 → portacode-0.3.25}/setup.py +0 -0
  60. {portacode-0.3.24 → portacode-0.3.25}/test.sh +0 -0
  61. {portacode-0.3.24 → portacode-0.3.25}/test_modules/README.md +0 -0
  62. {portacode-0.3.24 → portacode-0.3.25}/test_modules/__init__.py +0 -0
  63. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_device_online.py +0 -0
  64. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_file_operations.py +0 -0
  65. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_git_status_ui.py +0 -0
  66. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_login_flow.py +0 -0
  67. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_navigate_testing_folder.py +0 -0
  68. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_terminal_buffer_performance.py +0 -0
  69. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_terminal_interaction.py +0 -0
  70. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_terminal_loading_race_condition.py +0 -0
  71. {portacode-0.3.24 → portacode-0.3.25}/test_modules/test_terminal_start.py +0 -0
  72. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/.env.example +0 -0
  73. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/README.md +0 -0
  74. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/__init__.py +0 -0
  75. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/cli.py +0 -0
  76. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/__init__.py +0 -0
  77. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/base_test.py +0 -0
  78. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/cli_manager.py +0 -0
  79. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/hierarchical_runner.py +0 -0
  80. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/playwright_manager.py +0 -0
  81. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/runner.py +0 -0
  82. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/shared_cli_manager.py +0 -0
  83. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/core/test_discovery.py +0 -0
  84. {portacode-0.3.24 → portacode-0.3.25}/testing_framework/requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 0.3.24
3
+ Version: 0.3.25
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.3.24'
32
- __version_tuple__ = version_tuple = (0, 3, 24)
31
+ __version__ = version = '0.3.25'
32
+ __version_tuple__ = version_tuple = (0, 3, 25)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -161,6 +161,10 @@ class TerminalSession:
161
161
  async def _send_terminal_data_now(self, data: str) -> None:
162
162
  """Send terminal data immediately and update last send time."""
163
163
  self._last_send_time = time.time()
164
+ data_size = len(data.encode('utf-8'))
165
+
166
+ logger.info("session: Attempting to send terminal_data for terminal %s (data_size=%d bytes)",
167
+ self.id, data_size)
164
168
 
165
169
  # Add to buffer for snapshots with size limiting
166
170
  self._add_to_buffer(data)
@@ -174,18 +178,25 @@ class TerminalSession:
174
178
  "data": data,
175
179
  "project_id": self.project_id
176
180
  }, project_id=self.project_id)
181
+ logger.info("session: Successfully queued terminal_data for terminal %s via terminal_manager", self.id)
177
182
  else:
178
183
  # Fallback to raw channel for backward compatibility
179
184
  await self.channel.send(data)
185
+ logger.info("session: Successfully sent terminal_data for terminal %s via raw channel", self.id)
180
186
  except Exception as exc:
181
- logger.warning("Failed to forward terminal output: %s", exc)
187
+ logger.warning("session: Failed to forward terminal output for terminal %s: %s", self.id, exc)
182
188
 
183
189
  async def _flush_pending_data(self) -> None:
184
190
  """Send accumulated pending data and reset pending buffer."""
185
191
  if self._pending_data:
192
+ pending_size = len(self._pending_data.encode('utf-8'))
193
+ logger.info("session: Flushing pending terminal_data for terminal %s (pending_size=%d bytes)",
194
+ self.id, pending_size)
186
195
  data_to_send = self._pending_data
187
196
  self._pending_data = ""
188
197
  await self._send_terminal_data_now(data_to_send)
198
+ else:
199
+ logger.debug("session: No pending data to flush for terminal %s", self.id)
189
200
 
190
201
  # Clear the debounce task
191
202
  self._debounce_task = None
@@ -194,6 +205,10 @@ class TerminalSession:
194
205
  """Handle new terminal data with rate limiting and debouncing."""
195
206
  current_time = time.time()
196
207
  time_since_last_send = (current_time - self._last_send_time) * 1000 # Convert to milliseconds
208
+ data_size = len(data.encode('utf-8'))
209
+
210
+ logger.info("session: Received terminal_data for terminal %s (data_size=%d bytes, time_since_last_send=%.1fms)",
211
+ self.id, data_size, time_since_last_send)
197
212
 
198
213
  # Add new data to pending buffer with simple size limiting
199
214
  # Always add the new data first
@@ -202,15 +217,19 @@ class TerminalSession:
202
217
  # Simple size limiting - only trim if we exceed the 30KB limit significantly
203
218
  pending_size = len(self._pending_data.encode('utf-8'))
204
219
  if pending_size > TERMINAL_BUFFER_SIZE_LIMIT_BYTES:
220
+ logger.info("session: Buffer size limit exceeded for terminal %s (pending_size=%d bytes, limit=%d bytes), trimming",
221
+ self.id, pending_size, TERMINAL_BUFFER_SIZE_LIMIT_BYTES)
205
222
  # Only do minimal ANSI-safe trimming from the beginning
206
223
  excess_bytes = pending_size - TERMINAL_BUFFER_SIZE_LIMIT_BYTES
207
224
  trim_pos = self._find_minimal_safe_trim_position(excess_bytes)
208
225
 
209
226
  if trim_pos > 0:
210
227
  self._pending_data = self._pending_data[trim_pos:]
228
+ logger.info("session: Trimmed %d bytes from pending buffer for terminal %s", trim_pos, self.id)
211
229
 
212
230
  # Cancel existing debounce task if any
213
231
  if self._debounce_task and not self._debounce_task.done():
232
+ logger.debug("session: Cancelling existing debounce task for terminal %s", self.id)
214
233
  self._debounce_task.cancel()
215
234
 
216
235
  # Always set up a debounce timer to catch rapid consecutive outputs
@@ -219,19 +238,27 @@ class TerminalSession:
219
238
  if time_since_last_send >= TERMINAL_DATA_RATE_LIMIT_MS:
220
239
  # Enough time has passed since last send, wait initial delay for more data
221
240
  wait_time = TERMINAL_DATA_INITIAL_WAIT_MS / 1000
241
+ logger.info("session: Rate limit satisfied for terminal %s, waiting %.1fms for more data",
242
+ self.id, wait_time * 1000)
222
243
  else:
223
244
  # Too soon since last send, wait for either the rate limit period or max wait time
224
245
  wait_time = min(
225
246
  (TERMINAL_DATA_RATE_LIMIT_MS - time_since_last_send) / 1000,
226
247
  TERMINAL_DATA_MAX_WAIT_MS / 1000
227
248
  )
249
+ logger.info("session: Rate limit active for terminal %s, waiting %.1fms before send (time_since_last=%.1fms, rate_limit=%dms)",
250
+ self.id, wait_time * 1000, time_since_last_send, TERMINAL_DATA_RATE_LIMIT_MS)
251
+
228
252
  await asyncio.sleep(wait_time)
253
+ logger.info("session: Debounce timer expired for terminal %s, flushing pending data", self.id)
229
254
  await self._flush_pending_data()
230
255
  except asyncio.CancelledError:
256
+ logger.debug("session: Debounce timer cancelled for terminal %s (new data arrived)", self.id)
231
257
  # Timer was cancelled, another data event came in
232
258
  pass
233
259
 
234
260
  self._debounce_task = asyncio.create_task(_debounce_timer())
261
+ logger.info("session: Started debounce timer for terminal %s", self.id)
235
262
 
236
263
  def _find_minimal_safe_trim_position(self, excess_bytes: int) -> int:
237
264
  """Find a minimal safe position to trim that only avoids breaking ANSI sequences."""
@@ -738,15 +738,17 @@ class TerminalManager:
738
738
  payload: The message payload to send
739
739
  project_id: Optional project filter for targeting specific sessions
740
740
  """
741
+ event_type = payload.get("event", "unknown")
742
+
741
743
  # Check if there are any interested clients
742
744
  if not self._client_session_manager.has_interested_clients():
743
- logger.debug("terminal_manager: No interested clients, skipping message send")
745
+ logger.info("terminal_manager: No interested clients for %s event, skipping send", event_type)
744
746
  return
745
747
 
746
748
  # Get target sessions
747
749
  target_sessions = self._client_session_manager.get_target_sessions(project_id)
748
750
  if not target_sessions:
749
- logger.debug("terminal_manager: No target sessions found, skipping message send")
751
+ logger.info("terminal_manager: No target sessions found for %s event (project_id=%s), skipping send", event_type, project_id)
750
752
  return
751
753
 
752
754
  # Add session targeting information
@@ -758,8 +760,15 @@ class TerminalManager:
758
760
  if reply_channel and "reply_channel" not in enhanced_payload:
759
761
  enhanced_payload["reply_channel"] = reply_channel
760
762
 
761
- logger.debug("terminal_manager: Sending to %d client sessions: %s",
762
- len(target_sessions), target_sessions)
763
+ # Log all event dispatches at INFO level, with data size for terminal_data
764
+ if event_type == "terminal_data":
765
+ data_size = len(payload.get("data", ""))
766
+ terminal_id = payload.get("channel", "unknown")
767
+ logger.info("terminal_manager: Dispatching %s event (terminal_id=%s, data_size=%d bytes) to %d client sessions",
768
+ event_type, terminal_id, data_size, len(target_sessions))
769
+ else:
770
+ logger.info("terminal_manager: Dispatching %s event to %d client sessions",
771
+ event_type, len(target_sessions))
763
772
 
764
773
  await self._control_channel.send(enhanced_payload)
765
774
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 0.3.24
3
+ Version: 0.3.25
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
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