portacode 1.3.31__tar.gz → 1.3.32__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.
- {portacode-1.3.31 → portacode-1.3.32}/PKG-INFO +1 -1
- {portacode-1.3.31 → portacode-1.3.32}/portacode/_version.py +2 -2
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/git_manager.py +11 -3
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/handlers.py +9 -9
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/manager.py +25 -11
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-1.3.31 → portacode-1.3.32}/.claude/agents/communication-manager.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/.claude/settings.local.json +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/.gitignore +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/.gitmodules +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/LICENSE +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/MANIFEST.in +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/Makefile +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/backup.sh +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/connect.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/connect.sh +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/docker-compose.yaml +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/__main__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/cli.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/client.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/base.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/registry.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/session.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/multiplex.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/connection/terminal.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/data.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/keypair.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/logging_categories.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/service.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/utils/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode/utils/ntp_clock.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/SOURCES.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/requires.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/portacode.egg-info/top_level.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/pyproject.toml +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/restore.sh +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/run_tests.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/setup.cfg +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/setup.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test.sh +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_device_online.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_file_operations.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_git_status_ui.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_login_flow.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_modules/test_terminal_start.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/test_request_id.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/.env.example +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/README.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/cli.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/__init__.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/base_test.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/cli_manager.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/runner.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/core/test_discovery.py +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/testing_framework/requirements.txt +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/agent_context_management.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-1.3.31 → portacode-1.3.32}/tools/test_python_ntp_clock.py +0 -0
|
@@ -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 = '1.3.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 3,
|
|
31
|
+
__version__ = version = '1.3.32'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 3, 32)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/git_manager.py
RENAMED
|
@@ -350,9 +350,18 @@ class GitManager:
|
|
|
350
350
|
status_output = self.repo.git.status(*rel_paths, porcelain=True)
|
|
351
351
|
if status_output.strip():
|
|
352
352
|
for line in status_output.strip().split('\n'):
|
|
353
|
+
# Git porcelain format: XY path (X=index, Y=worktree, then space, then path)
|
|
354
|
+
# Some files may have renamed format: XY path -> new_path
|
|
353
355
|
if len(line) >= 3:
|
|
354
|
-
|
|
355
|
-
|
|
356
|
+
# Skip first 3 characters (2 status + 1 space) to get the file path
|
|
357
|
+
# But git uses exactly 2 chars for status then space, so position 3 onwards is path
|
|
358
|
+
parts = line.split(None, 1) # Split on first whitespace to separate status from path
|
|
359
|
+
if len(parts) >= 2:
|
|
360
|
+
file_path_from_status = parts[1]
|
|
361
|
+
# Handle renames (format: "old_path -> new_path")
|
|
362
|
+
if ' -> ' in file_path_from_status:
|
|
363
|
+
file_path_from_status = file_path_from_status.split(' -> ')[1]
|
|
364
|
+
status_map[file_path_from_status] = line
|
|
356
365
|
except Exception as e:
|
|
357
366
|
logger.debug("Error getting batch status: %s", e)
|
|
358
367
|
|
|
@@ -469,7 +478,6 @@ class GitManager:
|
|
|
469
478
|
elif index_status == 'D' or worktree_status == 'D':
|
|
470
479
|
has_deleted = True
|
|
471
480
|
|
|
472
|
-
# Priority order: untracked > modified/deleted > clean
|
|
473
481
|
if has_untracked:
|
|
474
482
|
return {"is_tracked": False, "status": "untracked", "is_ignored": False, "is_staged": is_staged}
|
|
475
483
|
elif has_deleted:
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/handlers.py
RENAMED
|
@@ -408,10 +408,10 @@ class ProjectStateGitStageHandler(AsyncHandler):
|
|
|
408
408
|
success = git_manager.stage_file(file_paths_to_stage[0])
|
|
409
409
|
else:
|
|
410
410
|
success = git_manager.stage_files(file_paths_to_stage)
|
|
411
|
-
|
|
411
|
+
|
|
412
412
|
if success:
|
|
413
|
-
# Refresh
|
|
414
|
-
await manager._refresh_project_state(source_client_session)
|
|
413
|
+
# Refresh git status only (no filesystem changes from staging)
|
|
414
|
+
await manager._refresh_project_state(source_client_session, git_only=True)
|
|
415
415
|
|
|
416
416
|
# Build response
|
|
417
417
|
response = {
|
|
@@ -482,10 +482,10 @@ class ProjectStateGitUnstageHandler(AsyncHandler):
|
|
|
482
482
|
success = git_manager.unstage_file(file_paths_to_unstage[0])
|
|
483
483
|
else:
|
|
484
484
|
success = git_manager.unstage_files(file_paths_to_unstage)
|
|
485
|
-
|
|
485
|
+
|
|
486
486
|
if success:
|
|
487
|
-
# Refresh
|
|
488
|
-
await manager._refresh_project_state(source_client_session)
|
|
487
|
+
# Refresh git status only (no filesystem changes from unstaging)
|
|
488
|
+
await manager._refresh_project_state(source_client_session, git_only=True)
|
|
489
489
|
|
|
490
490
|
# Build response
|
|
491
491
|
response = {
|
|
@@ -620,9 +620,9 @@ class ProjectStateGitCommitHandler(AsyncHandler):
|
|
|
620
620
|
if success:
|
|
621
621
|
# Get the commit hash of the new commit
|
|
622
622
|
commit_hash = git_manager.get_head_commit_hash()
|
|
623
|
-
|
|
624
|
-
# Refresh
|
|
625
|
-
await manager._refresh_project_state(source_client_session)
|
|
623
|
+
|
|
624
|
+
# Refresh git status only (no filesystem changes from commit)
|
|
625
|
+
await manager._refresh_project_state(source_client_session, git_only=True)
|
|
626
626
|
except Exception as e:
|
|
627
627
|
error_message = str(e)
|
|
628
628
|
logger.error("Error during commit: %s", error_message)
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/manager.py
RENAMED
|
@@ -152,7 +152,8 @@ class ProjectStateManager:
|
|
|
152
152
|
async def git_change_callback():
|
|
153
153
|
"""Callback when git status changes are detected."""
|
|
154
154
|
logger.debug("Git change detected, refreshing project state for %s", client_session_id)
|
|
155
|
-
|
|
155
|
+
# Git directory changes only affect git status, not filesystem
|
|
156
|
+
await self._refresh_project_state(client_session_id, git_only=True)
|
|
156
157
|
|
|
157
158
|
git_manager = GitManager(project_folder_path, change_callback=git_change_callback)
|
|
158
159
|
self.git_managers[client_session_id] = git_manager
|
|
@@ -877,9 +878,17 @@ class ProjectStateManager:
|
|
|
877
878
|
self._pending_changes.clear()
|
|
878
879
|
logger.debug("🔍 [TRACE] ✅ Finished processing file changes")
|
|
879
880
|
|
|
880
|
-
async def _refresh_project_state(self, client_session_id: str):
|
|
881
|
-
"""Refresh project state after file changes.
|
|
882
|
-
|
|
881
|
+
async def _refresh_project_state(self, client_session_id: str, git_only: bool = False):
|
|
882
|
+
"""Refresh project state after file changes.
|
|
883
|
+
|
|
884
|
+
Args:
|
|
885
|
+
client_session_id: The client session ID
|
|
886
|
+
git_only: If True, only git status changed (skip filesystem operations like
|
|
887
|
+
detecting new directories and syncing file state). Use this for
|
|
888
|
+
git operations (stage, unstage, revert) to avoid unnecessary work.
|
|
889
|
+
"""
|
|
890
|
+
logger.debug("🔍 [TRACE] _refresh_project_state called for session: %s (git_only=%s)",
|
|
891
|
+
client_session_id, git_only)
|
|
883
892
|
|
|
884
893
|
if client_session_id not in self.projects:
|
|
885
894
|
logger.debug("🔍 [TRACE] ❌ Session not found in projects: %s", client_session_id)
|
|
@@ -930,15 +939,20 @@ class ProjectStateManager:
|
|
|
930
939
|
old_status_summary, project_state.git_status_summary)
|
|
931
940
|
else:
|
|
932
941
|
logger.debug("🔍 [TRACE] ❌ No git manager found for session: %s", client_session_id)
|
|
933
|
-
|
|
934
|
-
#
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
942
|
+
|
|
943
|
+
# For git-only operations, skip scanning for new directories
|
|
944
|
+
# but still sync items to update git attributes for UI
|
|
945
|
+
if not git_only:
|
|
946
|
+
# Detect and add new directories in expanded folders before syncing
|
|
947
|
+
logger.debug("🔍 [TRACE] Detecting and adding new directories...")
|
|
948
|
+
await self._detect_and_add_new_directories(project_state)
|
|
949
|
+
else:
|
|
950
|
+
logger.debug("🔍 [TRACE] Skipping directory detection (git_only=True)")
|
|
951
|
+
|
|
952
|
+
# Always sync state to update git attributes on items (needed for UI updates)
|
|
939
953
|
logger.debug("🔍 [TRACE] Syncing all state with monitored folders...")
|
|
940
954
|
await self._sync_all_state_with_monitored_folders(project_state)
|
|
941
|
-
|
|
955
|
+
|
|
942
956
|
# Send update to clients
|
|
943
957
|
logger.debug("🔍 [TRACE] About to send project state update...")
|
|
944
958
|
await self._send_project_state_update(project_state)
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_aware_file_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{portacode-1.3.31 → portacode-1.3.32}/portacode/connection/handlers/project_state_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
|
|
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
|
|
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
|
|
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
|