portacode 0.3.20.dev4__tar.gz → 0.3.20.dev5__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.
Files changed (80) hide show
  1. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/PKG-INFO +1 -1
  2. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/_version.py +2 -2
  3. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/centralized_handlers.py +96 -0
  4. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/git_manager.py +16 -4
  5. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state_handlers.py +12 -12
  6. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/PKG-INFO +1 -1
  7. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/.claude/agents/communication-manager.md +0 -0
  8. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/.claude/settings.local.json +0 -0
  9. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/.gitignore +0 -0
  10. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/.gitmodules +0 -0
  11. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/LICENSE +0 -0
  12. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/MANIFEST.in +0 -0
  13. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/Makefile +0 -0
  14. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/README.md +0 -0
  15. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/backup.sh +0 -0
  16. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/docker-compose.yaml +0 -0
  17. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/README.md +0 -0
  18. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/__init__.py +0 -0
  19. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/__main__.py +0 -0
  20. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/cli.py +0 -0
  21. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/README.md +0 -0
  22. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/__init__.py +0 -0
  23. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/client.py +0 -0
  24. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/README.md +0 -0
  25. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  26. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/__init__.py +0 -0
  27. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/base.py +0 -0
  28. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/file_handlers.py +0 -0
  29. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/README.md +0 -0
  30. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/__init__.py +0 -0
  31. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/centralized_manager.py +0 -0
  32. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/centralized_state.py +0 -0
  33. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
  34. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/handlers.py +0 -0
  35. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/manager.py +0 -0
  36. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/models.py +0 -0
  37. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/simplified_file_watcher.py +0 -0
  38. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/project_state/utils.py +0 -0
  39. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/registry.py +0 -0
  40. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/session.py +0 -0
  41. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/system_handlers.py +0 -0
  42. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/tab_factory.py +0 -0
  43. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/handlers/terminal_handlers.py +0 -0
  44. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/multiplex.py +0 -0
  45. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/connection/terminal.py +0 -0
  46. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/data.py +0 -0
  47. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/keypair.py +0 -0
  48. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode/service.py +0 -0
  49. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/SOURCES.txt +0 -0
  50. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/dependency_links.txt +0 -0
  51. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/entry_points.txt +0 -0
  52. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/requires.txt +0 -0
  53. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/portacode.egg-info/top_level.txt +0 -0
  54. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/pyproject.toml +0 -0
  55. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/restore.sh +0 -0
  56. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/run_tests.py +0 -0
  57. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/setup.cfg +0 -0
  58. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/setup.py +0 -0
  59. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test.sh +0 -0
  60. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/README.md +0 -0
  61. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/__init__.py +0 -0
  62. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_device_online.py +0 -0
  63. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_file_operations.py +0 -0
  64. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_login_flow.py +0 -0
  65. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_navigate_testing_folder.py +0 -0
  66. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_terminal_interaction.py +0 -0
  67. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/test_modules/test_terminal_start.py +0 -0
  68. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/.env.example +0 -0
  69. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/README.md +0 -0
  70. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/__init__.py +0 -0
  71. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/cli.py +0 -0
  72. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/__init__.py +0 -0
  73. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/base_test.py +0 -0
  74. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/cli_manager.py +0 -0
  75. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/hierarchical_runner.py +0 -0
  76. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/playwright_manager.py +0 -0
  77. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/runner.py +0 -0
  78. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/shared_cli_manager.py +0 -0
  79. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/core/test_discovery.py +0 -0
  80. {portacode-0.3.20.dev4 → portacode-0.3.20.dev5}/testing_framework/requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: portacode
3
- Version: 0.3.20.dev4
3
+ Version: 0.3.20.dev5
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -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.20.dev4'
21
- __version_tuple__ = version_tuple = (0, 3, 20, 'dev4')
20
+ __version__ = version = '0.3.20.dev5'
21
+ __version_tuple__ = version_tuple = (0, 3, 20, 'dev5')
@@ -268,6 +268,102 @@ class CentralizedProjectStateGitRevertHandler(AsyncHandler):
268
268
  }
269
269
 
270
270
 
271
+ class CentralizedProjectStateSetActiveTabHandler(AsyncHandler):
272
+ """Handler for setting active tab using centralized state."""
273
+
274
+ @property
275
+ def command_name(self) -> str:
276
+ return "project_state_set_active_tab"
277
+
278
+ async def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
279
+ """Set active tab in project state."""
280
+ server_project_id = message.get("project_id")
281
+ tab_id = message.get("tab_id") # Can be None to clear active tab
282
+ source_client_session = message.get("source_client_session")
283
+
284
+ if not server_project_id:
285
+ raise ValueError("project_id is required")
286
+ if not source_client_session:
287
+ raise ValueError("source_client_session is required")
288
+
289
+ logger.info("Setting active tab %s for session %s", tab_id, source_client_session)
290
+
291
+ # Note: Active tab is deprecated in the new centralized system
292
+ # This handler maintains compatibility but does nothing
293
+ logger.info("Active tab functionality is deprecated in centralized system")
294
+
295
+ return {
296
+ "event": "project_state_set_active_tab_response",
297
+ "project_id": server_project_id,
298
+ "tab_id": tab_id,
299
+ "success": True
300
+ }
301
+
302
+
303
+ class CentralizedProjectStateDiffOpenHandler(AsyncHandler):
304
+ """Handler for opening diff tabs using centralized state."""
305
+
306
+ @property
307
+ def command_name(self) -> str:
308
+ return "project_state_diff_open"
309
+
310
+ async def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
311
+ """Open a diff tab comparing file versions at different git timeline points."""
312
+ server_project_id = message.get("project_id")
313
+ file_path = message.get("file_path")
314
+ from_ref = message.get("from_ref")
315
+ to_ref = message.get("to_ref")
316
+ from_hash = message.get("from_hash")
317
+ to_hash = message.get("to_hash")
318
+ source_client_session = message.get("source_client_session")
319
+
320
+ if not server_project_id:
321
+ raise ValueError("project_id is required")
322
+ if not file_path:
323
+ raise ValueError("file_path is required")
324
+ if not from_ref:
325
+ raise ValueError("from_ref is required")
326
+ if not to_ref:
327
+ raise ValueError("to_ref is required")
328
+ if not source_client_session:
329
+ raise ValueError("source_client_session is required")
330
+
331
+ # Validate reference types
332
+ valid_refs = {'head', 'staged', 'working', 'commit'}
333
+ if from_ref not in valid_refs:
334
+ raise ValueError(f"Invalid from_ref: {from_ref}. Must be one of {valid_refs}")
335
+ if to_ref not in valid_refs:
336
+ raise ValueError(f"Invalid to_ref: {to_ref}. Must be one of {valid_refs}")
337
+
338
+ # Validate commit hashes are provided when needed
339
+ if from_ref == 'commit' and not from_hash:
340
+ raise ValueError("from_hash is required when from_ref='commit'")
341
+ if to_ref == 'commit' and not to_hash:
342
+ raise ValueError("to_hash is required when to_ref='commit'")
343
+
344
+ logger.info("Opening diff tab %s (%s->%s) for session %s",
345
+ file_path, from_ref, to_ref, source_client_session)
346
+
347
+ # Get centralized manager
348
+ manager = get_or_create_centralized_manager(self.context, self.control_channel)
349
+
350
+ # For now, return success but don't actually implement diff tabs
351
+ # This would need to be implemented in the centralized manager
352
+ logger.info("Diff tab functionality not yet implemented in centralized system")
353
+
354
+ return {
355
+ "event": "project_state_diff_open_response",
356
+ "project_id": server_project_id,
357
+ "file_path": file_path,
358
+ "from_ref": from_ref,
359
+ "to_ref": to_ref,
360
+ "from_hash": from_hash,
361
+ "to_hash": to_hash,
362
+ "success": False, # Not implemented yet
363
+ "error": "Diff tab functionality not yet implemented in centralized system"
364
+ }
365
+
366
+
271
367
  # Handler for explicit client session cleanup
272
368
  async def handle_centralized_client_session_cleanup(handler, payload: Dict[str, Any],
273
369
  source_client_session: str) -> Dict[str, Any]:
@@ -1092,13 +1092,25 @@ class GitManager:
1092
1092
 
1093
1093
  if has_commits:
1094
1094
  # Repository has commits - use git restore --staged
1095
- self.repo.git.restore('--staged', rel_path)
1096
- logger.info("Successfully unstaged file using restore: %s", rel_path)
1095
+ try:
1096
+ self.repo.git.restore('--staged', rel_path)
1097
+ logger.info("Successfully unstaged file using restore: %s", rel_path)
1098
+ except Exception as restore_error:
1099
+ # If restore fails, try reset HEAD approach
1100
+ logger.debug("git restore failed, trying reset HEAD: %s", restore_error)
1101
+ self.repo.git.reset('HEAD', rel_path)
1102
+ logger.info("Successfully unstaged file using reset HEAD: %s", rel_path)
1097
1103
  else:
1098
1104
  # Repository has no commits - use git rm --cached
1099
1105
  # This handles the case where files are staged but no initial commit exists
1100
- self.repo.git.rm('--cached', rel_path)
1101
- logger.info("Successfully unstaged file using rm --cached (no HEAD): %s", rel_path)
1106
+ try:
1107
+ self.repo.git.rm('--cached', rel_path)
1108
+ logger.info("Successfully unstaged file using rm --cached (no HEAD): %s", rel_path)
1109
+ except Exception as rm_error:
1110
+ # If rm --cached fails, try with --force flag
1111
+ logger.debug("git rm --cached failed, trying with --force: %s", rm_error)
1112
+ self.repo.git.rm('--cached', '--force', rel_path)
1113
+ logger.info("Successfully unstaged file using rm --cached --force (no HEAD): %s", rel_path)
1102
1114
 
1103
1115
  return True
1104
1116
 
@@ -15,18 +15,18 @@ project_state/README.md
15
15
  # Import everything from the modular structure for backward compatibility
16
16
  from .project_state import *
17
17
 
18
- # Ensure all handlers are available at module level for existing imports
19
- from .project_state.handlers import (
20
- ProjectStateFolderExpandHandler,
21
- ProjectStateFolderCollapseHandler,
22
- ProjectStateFileOpenHandler,
23
- ProjectStateTabCloseHandler,
24
- ProjectStateSetActiveTabHandler,
25
- ProjectStateDiffOpenHandler,
26
- ProjectStateGitStageHandler,
27
- ProjectStateGitUnstageHandler,
28
- ProjectStateGitRevertHandler,
29
- handle_client_session_cleanup
18
+ # Use the new centralized handlers for better performance and reliability
19
+ from .project_state.centralized_handlers import (
20
+ CentralizedProjectStateFolderExpandHandler as ProjectStateFolderExpandHandler,
21
+ CentralizedProjectStateFolderCollapseHandler as ProjectStateFolderCollapseHandler,
22
+ CentralizedProjectStateFileOpenHandler as ProjectStateFileOpenHandler,
23
+ CentralizedProjectStateTabCloseHandler as ProjectStateTabCloseHandler,
24
+ CentralizedProjectStateSetActiveTabHandler as ProjectStateSetActiveTabHandler,
25
+ CentralizedProjectStateDiffOpenHandler as ProjectStateDiffOpenHandler,
26
+ CentralizedProjectStateGitStageHandler as ProjectStateGitStageHandler,
27
+ CentralizedProjectStateGitUnstageHandler as ProjectStateGitUnstageHandler,
28
+ CentralizedProjectStateGitRevertHandler as ProjectStateGitRevertHandler,
29
+ handle_centralized_client_session_cleanup as handle_client_session_cleanup
30
30
  )
31
31
 
32
32
  from .project_state.manager import (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: portacode
3
- Version: 0.3.20.dev4
3
+ Version: 0.3.20.dev5
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