portacode 1.3.33__tar.gz → 1.3.34__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 (97) hide show
  1. {portacode-1.3.33 → portacode-1.3.34}/PKG-INFO +1 -1
  2. {portacode-1.3.33 → portacode-1.3.34}/portacode/_version.py +2 -2
  3. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/handlers.py +7 -8
  4. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/tab_factory.py +1 -47
  5. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/PKG-INFO +1 -1
  6. {portacode-1.3.33 → portacode-1.3.34}/test.sh +0 -0
  7. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/.env.example +4 -1
  8. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/playwright_manager.py +29 -9
  9. {portacode-1.3.33 → portacode-1.3.34}/.claude/agents/communication-manager.md +0 -0
  10. {portacode-1.3.33 → portacode-1.3.34}/.claude/settings.local.json +0 -0
  11. {portacode-1.3.33 → portacode-1.3.34}/.gitignore +0 -0
  12. {portacode-1.3.33 → portacode-1.3.34}/.gitmodules +0 -0
  13. {portacode-1.3.33 → portacode-1.3.34}/LICENSE +0 -0
  14. {portacode-1.3.33 → portacode-1.3.34}/MANIFEST.in +0 -0
  15. {portacode-1.3.33 → portacode-1.3.34}/Makefile +0 -0
  16. {portacode-1.3.33 → portacode-1.3.34}/README.md +0 -0
  17. {portacode-1.3.33 → portacode-1.3.34}/backup.sh +0 -0
  18. {portacode-1.3.33 → portacode-1.3.34}/connect.py +0 -0
  19. {portacode-1.3.33 → portacode-1.3.34}/connect.sh +0 -0
  20. {portacode-1.3.33 → portacode-1.3.34}/docker-compose.yaml +0 -0
  21. {portacode-1.3.33 → portacode-1.3.34}/portacode/README.md +0 -0
  22. {portacode-1.3.33 → portacode-1.3.34}/portacode/__init__.py +0 -0
  23. {portacode-1.3.33 → portacode-1.3.34}/portacode/__main__.py +0 -0
  24. {portacode-1.3.33 → portacode-1.3.34}/portacode/cli.py +0 -0
  25. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/README.md +0 -0
  26. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/__init__.py +0 -0
  27. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/client.py +0 -0
  28. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/README.md +0 -0
  29. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  30. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/__init__.py +0 -0
  31. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/base.py +0 -0
  32. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/chunked_content.py +0 -0
  33. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/file_handlers.py +0 -0
  34. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
  35. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/README.md +0 -0
  36. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/__init__.py +0 -0
  37. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
  38. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/git_manager.py +0 -0
  39. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/manager.py +0 -0
  40. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/models.py +0 -0
  41. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state/utils.py +0 -0
  42. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/project_state_handlers.py +0 -0
  43. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/registry.py +0 -0
  44. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/session.py +0 -0
  45. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/system_handlers.py +0 -0
  46. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/handlers/terminal_handlers.py +0 -0
  47. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/multiplex.py +0 -0
  48. {portacode-1.3.33 → portacode-1.3.34}/portacode/connection/terminal.py +0 -0
  49. {portacode-1.3.33 → portacode-1.3.34}/portacode/data.py +0 -0
  50. {portacode-1.3.33 → portacode-1.3.34}/portacode/keypair.py +0 -0
  51. {portacode-1.3.33 → portacode-1.3.34}/portacode/logging_categories.py +0 -0
  52. {portacode-1.3.33 → portacode-1.3.34}/portacode/service.py +0 -0
  53. {portacode-1.3.33 → portacode-1.3.34}/portacode/static/js/test-ntp-clock.html +0 -0
  54. {portacode-1.3.33 → portacode-1.3.34}/portacode/static/js/utils/ntp-clock.js +0 -0
  55. {portacode-1.3.33 → portacode-1.3.34}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
  56. {portacode-1.3.33 → portacode-1.3.34}/portacode/utils/__init__.py +0 -0
  57. {portacode-1.3.33 → portacode-1.3.34}/portacode/utils/ntp_clock.py +0 -0
  58. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/SOURCES.txt +0 -0
  59. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/dependency_links.txt +0 -0
  60. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/entry_points.txt +0 -0
  61. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/requires.txt +0 -0
  62. {portacode-1.3.33 → portacode-1.3.34}/portacode.egg-info/top_level.txt +0 -0
  63. {portacode-1.3.33 → portacode-1.3.34}/pyproject.toml +0 -0
  64. {portacode-1.3.33 → portacode-1.3.34}/restore.sh +0 -0
  65. {portacode-1.3.33 → portacode-1.3.34}/run_tests.py +0 -0
  66. {portacode-1.3.33 → portacode-1.3.34}/setup.cfg +0 -0
  67. {portacode-1.3.33 → portacode-1.3.34}/setup.py +0 -0
  68. {portacode-1.3.33 → portacode-1.3.34}/test_modules/README.md +0 -0
  69. {portacode-1.3.33 → portacode-1.3.34}/test_modules/__init__.py +0 -0
  70. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_device_online.py +0 -0
  71. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_file_operations.py +0 -0
  72. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_git_status_ui.py +0 -0
  73. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_login_flow.py +0 -0
  74. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_navigate_testing_folder.py +0 -0
  75. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_terminal_buffer_performance.py +0 -0
  76. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_terminal_interaction.py +0 -0
  77. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_terminal_loading_race_condition.py +0 -0
  78. {portacode-1.3.33 → portacode-1.3.34}/test_modules/test_terminal_start.py +0 -0
  79. {portacode-1.3.33 → portacode-1.3.34}/test_request_id.py +0 -0
  80. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/README.md +0 -0
  81. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/__init__.py +0 -0
  82. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/cli.py +0 -0
  83. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/__init__.py +0 -0
  84. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/base_test.py +0 -0
  85. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/cli_manager.py +0 -0
  86. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/hierarchical_runner.py +0 -0
  87. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/runner.py +0 -0
  88. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/shared_cli_manager.py +0 -0
  89. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/core/test_discovery.py +0 -0
  90. {portacode-1.3.33 → portacode-1.3.34}/testing_framework/requirements.txt +0 -0
  91. {portacode-1.3.33 → portacode-1.3.34}/todo/agent_context_management.md +0 -0
  92. {portacode-1.3.33 → portacode-1.3.34}/todo/issues/device_performance_degradation.md +0 -0
  93. {portacode-1.3.33 → portacode-1.3.34}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
  94. {portacode-1.3.33 → portacode-1.3.34}/todo/issues/indefinite_resource_loading.md +0 -0
  95. {portacode-1.3.33 → portacode-1.3.34}/todo/issues/premature_terminal_exit.md +0 -0
  96. {portacode-1.3.33 → portacode-1.3.34}/todo/issues/terminals_exit_upon_starting.md +0 -0
  97. {portacode-1.3.33 → portacode-1.3.34}/tools/test_python_ntp_clock.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.3.33
3
+ Version: 1.3.34
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 = '1.3.33'
32
- __version_tuple__ = version_tuple = (1, 3, 33)
31
+ __version__ = version = '1.3.34'
32
+ __version_tuple__ = version_tuple = (1, 3, 34)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -764,14 +764,13 @@ class ProjectStateDiffContentHandler(AsyncHandler):
764
764
  if content is None or (content_type == "all" and not all([matching_tab.original_content, matching_tab.modified_content])):
765
765
  if content_type in ["original", "modified", "all"]:
766
766
  # Re-generate the diff content if needed
767
- await manager.create_diff_tab(
768
- source_client_session,
769
- file_path,
770
- from_ref,
771
- to_ref,
772
- from_hash,
773
- to_hash,
774
- activate=False # Don't activate, just ensure content is loaded
767
+ await manager.open_diff_tab(
768
+ source_client_session,
769
+ file_path,
770
+ from_ref,
771
+ to_ref,
772
+ from_hash,
773
+ to_hash
775
774
  )
776
775
 
777
776
  # Try to get content again after regeneration (use same matching logic)
@@ -162,53 +162,7 @@ class TabFactory:
162
162
  await self._load_binary_content(file_path, tab_info, file_size)
163
163
 
164
164
  return TabInfo(**tab_info)
165
-
166
- async def create_diff_tab(self, file_path: str, original_content: str,
167
- modified_content: str, tab_id: Optional[str] = None,
168
- diff_details: Optional[Dict[str, Any]] = None) -> TabInfo:
169
- """Create a diff tab for comparing file versions.
170
-
171
- Args:
172
- file_path: Path to the file being compared
173
- original_content: Original version of the file
174
- modified_content: Modified version of the file
175
- tab_id: Optional tab ID, will generate UUID if not provided
176
- diff_details: Optional detailed diff information from diff-match-patch
177
-
178
- Returns:
179
- TabInfo object configured for diff viewing
180
- """
181
- if tab_id is None:
182
- tab_id = str(uuid.uuid4())
183
-
184
- file_path = Path(file_path)
185
-
186
- metadata = {'diff_mode': True}
187
- if diff_details:
188
- metadata['diff_details'] = diff_details
189
-
190
- # Cache diff content
191
- original_hash = generate_content_hash(original_content)
192
- modified_hash = generate_content_hash(modified_content)
193
- cache_content(original_hash, original_content)
194
- cache_content(modified_hash, modified_content)
195
-
196
- return TabInfo(
197
- tab_id=tab_id,
198
- tab_type='diff',
199
- title=f"{file_path.name} (diff)",
200
- file_path=str(file_path),
201
- content=None, # Diff tabs don't use regular content
202
- original_content=original_content,
203
- modified_content=modified_content,
204
- original_content_hash=original_hash,
205
- modified_content_hash=modified_hash,
206
- is_dirty=False,
207
- mime_type=None,
208
- encoding='utf-8',
209
- metadata=metadata
210
- )
211
-
165
+
212
166
  async def create_diff_tab_with_title(self, file_path: str, original_content: str,
213
167
  modified_content: str, title: str,
214
168
  tab_id: Optional[str] = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.3.33
3
+ Version: 1.3.34
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
@@ -15,4 +15,7 @@ TEST_HEADLESS=false # true for headless mode, false for visible browser
15
15
  # Optional: Test Output Directories
16
16
  TEST_RESULTS_DIR=test_results
17
17
  TEST_RECORDINGS_DIR=test_recordings
18
- TEST_LOGS_DIR=test_results
18
+ TEST_LOGS_DIR=test_results
19
+
20
+ # Automation testing token (used by the testing framework to bypass captcha. Same token must be defined in ../main.env)
21
+ TEST_RUNNER_BYPASS_TOKEN=same-as-in-main-env
@@ -8,6 +8,7 @@ import logging
8
8
  import json
9
9
  import time
10
10
  from datetime import datetime
11
+ from urllib.parse import urlparse
11
12
 
12
13
  try:
13
14
  from playwright.async_api import async_playwright, Browser, BrowserContext, Page
@@ -71,6 +72,7 @@ class PlaywrightManager:
71
72
  env_headless = os.getenv('TEST_HEADLESS', 'false').lower() in ('true', '1', 'yes')
72
73
  env_video_width = int(os.getenv('TEST_VIDEO_WIDTH', '1920'))
73
74
  env_video_height = int(os.getenv('TEST_VIDEO_HEIGHT', '1080'))
75
+ automation_token = os.getenv('TEST_RUNNER_BYPASS_TOKEN')
74
76
 
75
77
  # Use provided values or fall back to environment
76
78
  self.base_url = url or env_url
@@ -125,14 +127,32 @@ class PlaywrightManager:
125
127
 
126
128
  # Create context with recording enabled and proper viewport
127
129
  video_size = {"width": env_video_width, "height": env_video_height}
128
- self.context = await self.browser.new_context(
129
- record_video_dir=str(self.test_recordings_dir),
130
- record_video_size=video_size,
131
- record_har_path=str(self.har_path),
132
- record_har_omit_content=False,
133
- viewport=video_size
134
- )
135
-
130
+ context_kwargs = {
131
+ "record_video_dir": str(self.test_recordings_dir),
132
+ "record_video_size": video_size,
133
+ "record_har_path": str(self.har_path),
134
+ "record_har_omit_content": False,
135
+ "viewport": video_size
136
+ }
137
+ self.context = await self.browser.new_context(**context_kwargs)
138
+ if automation_token:
139
+ parsed_base = urlparse(self.base_url)
140
+ target_host = parsed_base.hostname
141
+ target_scheme = parsed_base.scheme or "http"
142
+ header_name = "X-Portacode-Automation"
143
+
144
+ async def automation_header_route(route, request):
145
+ headers = dict(request.headers)
146
+ parsed_request = urlparse(request.url)
147
+ if parsed_request.hostname == target_host and parsed_request.scheme == target_scheme:
148
+ headers[header_name] = automation_token
149
+ else:
150
+ headers.pop(header_name, None)
151
+ await route.continue_(headers=headers)
152
+
153
+ await self.context.route("**/*", automation_header_route)
154
+ self.logger.info("Automation bypass header restricted to same-origin requests")
155
+
136
156
  self.logger.info(f"Video recording configured: {env_video_width}x{env_video_height}")
137
157
 
138
158
  # Start tracing
@@ -178,7 +198,7 @@ class PlaywrightManager:
178
198
  """Perform login using provided credentials."""
179
199
  try:
180
200
  # Navigate to login page first
181
- login_url = f"{self.base_url}/accounts/login/"
201
+ login_url = f"{self.base_url}accounts/login/"
182
202
  await self.page.goto(login_url)
183
203
  await self.log_action("navigate_to_login", {"url": login_url})
184
204
  await self.take_screenshot("login_page")
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