portacode 0.3.20.dev7__tar.gz → 0.3.20.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.
Files changed (80) hide show
  1. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/PKG-INFO +1 -1
  2. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/_version.py +2 -2
  3. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/centralized_manager.py +147 -1
  4. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/file_system_watcher.py +6 -47
  5. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state_handlers.py +4 -4
  6. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/PKG-INFO +1 -1
  7. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/.claude/agents/communication-manager.md +0 -0
  8. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/.claude/settings.local.json +0 -0
  9. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/.gitignore +0 -0
  10. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/.gitmodules +0 -0
  11. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/LICENSE +0 -0
  12. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/MANIFEST.in +0 -0
  13. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/Makefile +0 -0
  14. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/README.md +0 -0
  15. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/backup.sh +0 -0
  16. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/docker-compose.yaml +0 -0
  17. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/README.md +0 -0
  18. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/__init__.py +0 -0
  19. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/__main__.py +0 -0
  20. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/cli.py +0 -0
  21. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/README.md +0 -0
  22. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/__init__.py +0 -0
  23. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/client.py +0 -0
  24. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/README.md +0 -0
  25. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  26. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/__init__.py +0 -0
  27. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/base.py +0 -0
  28. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/file_handlers.py +0 -0
  29. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/README.md +0 -0
  30. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/__init__.py +0 -0
  31. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/centralized_handlers.py +0 -0
  32. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/centralized_state.py +0 -0
  33. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/git_manager.py +0 -0
  34. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/handlers.py +0 -0
  35. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/manager.py +0 -0
  36. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/models.py +0 -0
  37. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/simplified_file_watcher.py +0 -0
  38. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/project_state/utils.py +0 -0
  39. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/registry.py +0 -0
  40. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/session.py +0 -0
  41. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/system_handlers.py +0 -0
  42. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/tab_factory.py +0 -0
  43. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/handlers/terminal_handlers.py +0 -0
  44. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/multiplex.py +0 -0
  45. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/connection/terminal.py +0 -0
  46. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/data.py +0 -0
  47. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/keypair.py +0 -0
  48. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode/service.py +0 -0
  49. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/SOURCES.txt +0 -0
  50. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/dependency_links.txt +0 -0
  51. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/entry_points.txt +0 -0
  52. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/requires.txt +0 -0
  53. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/portacode.egg-info/top_level.txt +0 -0
  54. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/pyproject.toml +0 -0
  55. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/restore.sh +0 -0
  56. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/run_tests.py +0 -0
  57. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/setup.cfg +0 -0
  58. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/setup.py +0 -0
  59. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test.sh +0 -0
  60. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/README.md +0 -0
  61. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/__init__.py +0 -0
  62. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_device_online.py +0 -0
  63. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_file_operations.py +0 -0
  64. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_login_flow.py +0 -0
  65. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_navigate_testing_folder.py +0 -0
  66. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_terminal_interaction.py +0 -0
  67. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/test_modules/test_terminal_start.py +0 -0
  68. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/.env.example +0 -0
  69. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/README.md +0 -0
  70. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/__init__.py +0 -0
  71. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/cli.py +0 -0
  72. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/__init__.py +0 -0
  73. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/base_test.py +0 -0
  74. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/cli_manager.py +0 -0
  75. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/hierarchical_runner.py +0 -0
  76. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/playwright_manager.py +0 -0
  77. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/runner.py +0 -0
  78. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/shared_cli_manager.py +0 -0
  79. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/testing_framework/core/test_discovery.py +0 -0
  80. {portacode-0.3.20.dev7 → portacode-0.3.20.dev8}/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.dev7
3
+ Version: 0.3.20.dev8
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.dev7'
21
- __version_tuple__ = version_tuple = (0, 3, 20, 'dev7')
20
+ __version__ = version = '0.3.20.dev8'
21
+ __version_tuple__ = version_tuple = (0, 3, 20, 'dev8')
@@ -413,4 +413,150 @@ def get_or_create_centralized_manager(context: Dict,
413
413
  _global_manager = CentralizedProjectStateManager(context, control_channel)
414
414
  logger.info("Created new centralized project state manager")
415
415
 
416
- return _global_manager
416
+ return _global_manager
417
+
418
+
419
+ def reset_global_centralized_manager():
420
+ """Reset the global centralized project state manager."""
421
+ global _global_manager
422
+
423
+ if _global_manager:
424
+ # Stop all monitoring
425
+ _global_manager._git_monitor.stop_monitoring()
426
+ if _global_manager._file_watcher:
427
+ _global_manager._file_watcher.stop_all()
428
+
429
+ logger.info("Reset centralized project state manager")
430
+
431
+ _global_manager = None
432
+
433
+
434
+ def debug_global_centralized_manager_state() -> dict:
435
+ """Get debug information about the global centralized manager state."""
436
+ global _global_manager
437
+
438
+ if _global_manager is None:
439
+ return {"error": "No global centralized manager instance"}
440
+
441
+ import os
442
+ debug_info = {
443
+ "_instance_info": {
444
+ "pid": os.getpid(),
445
+ "timestamp": __import__('time').time(),
446
+ "project_count": len(_global_manager._project_states)
447
+ }
448
+ }
449
+
450
+ # Add state for each project
451
+ for client_session_id, state in _global_manager._project_states.items():
452
+ debug_info[f"specific..inmemory!{client_session_id}"] = {
453
+ "project_folder_path": state.project_folder_path,
454
+ "is_git_repo": state.is_git_repo,
455
+ "git_branch": state.git_branch,
456
+ "git_status_summary": state.git_status_summary,
457
+ "git_detailed_status": {
458
+ "head_commit_hash": state.git_detailed_status.head_commit_hash,
459
+ "staged_changes": [
460
+ {
461
+ "file_repo_path": f.file_repo_path,
462
+ "file_name": f.file_name,
463
+ "file_abs_path": f.file_abs_path,
464
+ "change_type": f.change_type,
465
+ "content_hash": f.content_hash,
466
+ "is_staged": f.is_staged,
467
+ "diff_details": {
468
+ "diffs": f.diff_details.diffs if f.diff_details else [],
469
+ "stats": {
470
+ "char_additions": f.diff_details.stats.char_additions if f.diff_details else 0,
471
+ "char_deletions": f.diff_details.stats.char_deletions if f.diff_details else 0,
472
+ "char_unchanged": f.diff_details.stats.char_unchanged if f.diff_details else 0,
473
+ "total_changes": f.diff_details.stats.total_changes if f.diff_details else 0
474
+ },
475
+ "algorithm": f.diff_details.algorithm if f.diff_details else "diff-match-patch"
476
+ }
477
+ } for f in state.git_detailed_status.staged_changes
478
+ ],
479
+ "unstaged_changes": [
480
+ {
481
+ "file_repo_path": f.file_repo_path,
482
+ "file_name": f.file_name,
483
+ "file_abs_path": f.file_abs_path,
484
+ "change_type": f.change_type,
485
+ "content_hash": f.content_hash,
486
+ "is_staged": f.is_staged,
487
+ "diff_details": {
488
+ "diffs": f.diff_details.diffs if f.diff_details else [],
489
+ "stats": {
490
+ "char_additions": f.diff_details.stats.char_additions if f.diff_details else 0,
491
+ "char_deletions": f.diff_details.stats.char_deletions if f.diff_details else 0,
492
+ "char_unchanged": f.diff_details.stats.char_unchanged if f.diff_details else 0,
493
+ "total_changes": f.diff_details.stats.total_changes if f.diff_details else 0
494
+ },
495
+ "algorithm": f.diff_details.algorithm if f.diff_details else "diff-match-patch"
496
+ }
497
+ } for f in state.git_detailed_status.unstaged_changes
498
+ ],
499
+ "untracked_files": [
500
+ {
501
+ "file_repo_path": f.file_repo_path,
502
+ "file_name": f.file_name,
503
+ "file_abs_path": f.file_abs_path,
504
+ "change_type": f.change_type,
505
+ "content_hash": f.content_hash,
506
+ "is_staged": f.is_staged,
507
+ "diff_details": {
508
+ "diffs": f.diff_details.diffs if f.diff_details else [],
509
+ "stats": {
510
+ "char_additions": f.diff_details.stats.char_additions if f.diff_details else 0,
511
+ "char_deletions": f.diff_details.stats.char_deletions if f.diff_details else 0,
512
+ "char_unchanged": f.diff_details.stats.char_unchanged if f.diff_details else 0,
513
+ "total_changes": f.diff_details.stats.total_changes if f.diff_details else 0
514
+ },
515
+ "algorithm": f.diff_details.algorithm if f.diff_details else "diff-match-patch"
516
+ }
517
+ } for f in state.git_detailed_status.untracked_files
518
+ ]
519
+ },
520
+ "open_tabs": [
521
+ {
522
+ "tab_id": tab.tab_id,
523
+ "tab_type": tab.tab_type,
524
+ "title": tab.title,
525
+ "file_path": tab.file_path,
526
+ "content": tab.content,
527
+ "original_content": tab.original_content,
528
+ "modified_content": tab.modified_content,
529
+ "is_dirty": tab.is_dirty,
530
+ "mime_type": tab.mime_type,
531
+ "encoding": tab.encoding,
532
+ "metadata": tab.metadata
533
+ } for tab in state.open_tabs
534
+ ],
535
+ "active_tab": None, # Deprecated in centralized system
536
+ "monitored_folders": [
537
+ {
538
+ "folder_path": folder.folder_path,
539
+ "is_expanded": folder.is_expanded
540
+ } for folder in state.monitored_folders
541
+ ],
542
+ "items": [
543
+ {
544
+ "name": item.name,
545
+ "path": item.path,
546
+ "is_directory": item.is_directory,
547
+ "parent_path": item.parent_path,
548
+ "size": item.size,
549
+ "modified_time": item.modified_time,
550
+ "is_git_tracked": item.is_git_tracked,
551
+ "git_status": item.git_status,
552
+ "is_staged": item.is_staged,
553
+ "is_hidden": item.is_hidden,
554
+ "is_ignored": item.is_ignored,
555
+ "children": item.children,
556
+ "is_expanded": item.is_expanded,
557
+ "is_loaded": item.is_loaded
558
+ } for item in state.items
559
+ ]
560
+ }
561
+
562
+ return debug_info
@@ -75,37 +75,11 @@ class FileSystemWatcher:
75
75
  logger.info("🔍 [TRACE] Skipping opened/closed event: %s", event.event_type)
76
76
  return
77
77
 
78
- # Handle .git folder events separately for git status monitoring
78
+ # Skip all .git folder events - git monitoring is handled by centralized periodic polling
79
79
  path_parts = Path(event.src_path).parts
80
80
  if '.git' in path_parts:
81
- logger.info("🔍 [TRACE] Processing .git folder event: %s", event.src_path)
82
- # Get the relative path within .git directory
83
- try:
84
- git_index = path_parts.index('.git')
85
- git_relative_path = '/'.join(path_parts[git_index + 1:])
86
- git_file = Path(event.src_path).name
87
-
88
- logger.info("🔍 [TRACE] Git file details - relative_path: %s, file: %s", git_relative_path, git_file)
89
-
90
- # Monitor git files that indicate repository state changes
91
- should_monitor_git_file = (
92
- git_file == 'index' or # Staging area changes
93
- git_file == 'HEAD' or # Branch switches
94
- git_relative_path.startswith('refs/heads/') or # Branch updates
95
- git_relative_path.startswith('refs/remotes/') or # Remote tracking branches
96
- git_relative_path.startswith('logs/refs/heads/') or # Branch history
97
- git_relative_path.startswith('logs/HEAD') or # HEAD history
98
- (git_file == 'index.lock' and event.event_type in ['moved', 'deleted']) # Index updates via lock file
99
- )
100
-
101
- if should_monitor_git_file:
102
- logger.info("🔍 [TRACE] ✅ Git file matches monitoring criteria: %s", event.src_path)
103
- else:
104
- logger.info("🔍 [TRACE] ❌ Git file does NOT match monitoring criteria - SKIPPING: %s", event.src_path)
105
- return # Skip other .git files
106
- except (ValueError, IndexError):
107
- logger.info("🔍 [TRACE] ❌ Could not parse .git path - SKIPPING: %s", event.src_path)
108
- return # Skip if can't parse .git path
81
+ logger.debug("Skipping .git folder event (centralized monitoring active): %s", event.src_path)
82
+ return
109
83
  else:
110
84
  logger.info("🔍 [TRACE] Processing non-git file event: %s", event.src_path)
111
85
  # Only log significant file changes, not every single event
@@ -157,24 +131,9 @@ class FileSystemWatcher:
157
131
 
158
132
  def start_watching_git_directory(self, git_path: str):
159
133
  """Start watching a .git directory for git status changes."""
160
- if not WATCHDOG_AVAILABLE or not self.observer:
161
- logger.warning("Watchdog not available, cannot start watching git directory: %s", git_path)
162
- return
163
-
164
- if git_path not in self.watched_paths:
165
- try:
166
- # Watch .git directory recursively to catch changes in refs/, logs/, etc.
167
- self.observer.schedule(self.event_handler, git_path, recursive=True)
168
- self.watched_paths.add(git_path)
169
- logger.info("Started watching git directory (recursive): %s", git_path)
170
-
171
- if not self.observer.is_alive():
172
- self.observer.start()
173
- logger.info("Started file system observer")
174
- except Exception as e:
175
- logger.error("Error starting git directory watcher for %s: %s", git_path, e)
176
- else:
177
- logger.debug("Git directory already being watched: %s", git_path)
134
+ # DISABLED: Git monitoring is now handled by centralized hash-based periodic polling
135
+ logger.debug("Git directory monitoring disabled - using centralized periodic polling: %s", git_path)
136
+ return
178
137
 
179
138
  def stop_watching(self, path: str):
180
139
  """Stop watching a specific path."""
@@ -29,10 +29,10 @@ from .project_state.centralized_handlers import (
29
29
  handle_centralized_client_session_cleanup as handle_client_session_cleanup
30
30
  )
31
31
 
32
- from .project_state.manager import (
33
- get_or_create_project_state_manager,
34
- reset_global_project_state_manager,
35
- debug_global_manager_state
32
+ from .project_state.centralized_manager import (
33
+ get_or_create_centralized_manager as get_or_create_project_state_manager,
34
+ reset_global_centralized_manager as reset_global_project_state_manager,
35
+ debug_global_centralized_manager_state as debug_global_manager_state
36
36
  )
37
37
 
38
38
  from .project_state.utils import generate_tab_key
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: portacode
3
- Version: 0.3.20.dev7
3
+ Version: 0.3.20.dev8
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