portacode 0.3.19.dev1__tar.gz → 0.3.19.dev2__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 (45) hide show
  1. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/PKG-INFO +1 -1
  2. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/_version.py +2 -2
  3. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/project_state_handlers.py +89 -39
  4. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/PKG-INFO +1 -1
  5. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/.claude/agents/communication-manager.md +0 -0
  6. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/.claude/settings.local.json +0 -0
  7. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/.gitignore +0 -0
  8. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/.gitmodules +0 -0
  9. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/LICENSE +0 -0
  10. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/MANIFEST.in +0 -0
  11. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/Makefile +0 -0
  12. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/README.md +0 -0
  13. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/backup.sh +0 -0
  14. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/docker-compose.yaml +0 -0
  15. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/README.md +0 -0
  16. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/__init__.py +0 -0
  17. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/__main__.py +0 -0
  18. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/cli.py +0 -0
  19. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/README.md +0 -0
  20. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/__init__.py +0 -0
  21. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/client.py +0 -0
  22. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/README.md +0 -0
  23. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +0 -0
  24. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/__init__.py +0 -0
  25. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/base.py +0 -0
  26. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/file_handlers.py +0 -0
  27. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/registry.py +0 -0
  28. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/session.py +0 -0
  29. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/system_handlers.py +0 -0
  30. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/tab_factory.py +0 -0
  31. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/handlers/terminal_handlers.py +0 -0
  32. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/multiplex.py +0 -0
  33. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/connection/terminal.py +0 -0
  34. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/data.py +0 -0
  35. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/keypair.py +0 -0
  36. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode/service.py +0 -0
  37. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/SOURCES.txt +0 -0
  38. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/dependency_links.txt +0 -0
  39. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/entry_points.txt +0 -0
  40. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/requires.txt +0 -0
  41. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/portacode.egg-info/top_level.txt +0 -0
  42. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/pyproject.toml +0 -0
  43. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/restore.sh +0 -0
  44. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/setup.cfg +0 -0
  45. {portacode-0.3.19.dev1 → portacode-0.3.19.dev2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: portacode
3
- Version: 0.3.19.dev1
3
+ Version: 0.3.19.dev2
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.19.dev1'
21
- __version_tuple__ = version_tuple = (0, 3, 19, 'dev1')
20
+ __version__ = version = '0.3.19.dev2'
21
+ __version_tuple__ = version_tuple = (0, 3, 19, 'dev2')
@@ -401,7 +401,7 @@ class GitManager:
401
401
  return None
402
402
 
403
403
  def _generate_html_diff(self, original_content: str, modified_content: str, file_path: str) -> Optional[str]:
404
- """Generate HTML diff with syntax highlighting using Pygments and diff-match-patch."""
404
+ """Generate unified HTML diff with syntax highlighting using Pygments and diff-match-patch."""
405
405
  if not DIFF_MATCH_PATCH_AVAILABLE or not PYGMENTS_AVAILABLE:
406
406
  logger.debug("Required libraries not available for HTML diff generation")
407
407
  return None
@@ -415,24 +415,12 @@ class GitManager:
415
415
  # Get Pygments lexer for syntax highlighting
416
416
  lexer = self._get_pygments_lexer(file_path)
417
417
 
418
- # Create HTML formatter with custom CSS classes
419
- formatter = HtmlFormatter(
420
- style='monokai',
421
- noclasses=False,
422
- cssclass='highlight',
423
- linenos=True,
424
- lineanchors='line',
425
- anchorlinenos=True,
426
- hl_lines=[]
427
- )
428
-
429
- # Split content into lines for line-by-line processing
430
- original_lines = original_content.splitlines(keepends=True)
431
- modified_lines = modified_content.splitlines(keepends=True)
418
+ # Convert diffs to line-based unified diff
419
+ unified_diff_lines = self._create_unified_diff_lines(diffs, original_content, modified_content)
432
420
 
433
- # Build HTML diff content
421
+ # Build HTML
434
422
  html_parts = []
435
- html_parts.append('<div class="pygments-diff-container">')
423
+ html_parts.append('<div class="unified-diff-container">')
436
424
 
437
425
  # Add stats header
438
426
  char_additions = sum(len(text) for op, text in diffs if op == 1)
@@ -446,31 +434,45 @@ class GitManager:
446
434
  </div>
447
435
  ''')
448
436
 
449
- # Add side-by-side diff
450
- html_parts.append('<div class="diff-sides">')
437
+ # Generate unified diff view
438
+ html_parts.append('<div class="diff-content">')
439
+ html_parts.append('<table class="diff-table">')
451
440
 
452
- # Left side (original)
453
- html_parts.append('<div class="diff-side original">')
454
- html_parts.append('<h4>Original</h4>')
455
- if lexer and original_content.strip():
456
- highlighted = highlight(original_content, lexer, formatter)
457
- html_parts.append(highlighted)
458
- else:
459
- html_parts.append(f'<pre class="highlight"><code>{self._escape_html(original_content)}</code></pre>')
460
- html_parts.append('</div>')
441
+ for line_info in unified_diff_lines:
442
+ line_type = line_info['type'] # 'context', 'delete', 'add', 'header'
443
+ old_line_num = line_info.get('old_line_num', '')
444
+ new_line_num = line_info.get('new_line_num', '')
445
+ content = line_info['content']
446
+
447
+ # Apply syntax highlighting to the content
448
+ if lexer and content.strip() and line_type != 'header':
449
+ try:
450
+ # Remove the +/- prefix for highlighting, then add it back
451
+ clean_content = content[1:] if content and content[0] in '+-' else content
452
+ highlighted = highlight(clean_content, lexer, HtmlFormatter(nowrap=True, noclasses=False))
453
+ # Add the prefix back
454
+ if content and content[0] in '+-':
455
+ highlighted = content[0] + highlighted[len(clean_content):]
456
+ content = highlighted
457
+ except Exception:
458
+ content = self._escape_html(content)
459
+ else:
460
+ content = self._escape_html(content)
461
+
462
+ # CSS classes for different line types
463
+ row_class = f'diff-line diff-{line_type}'
464
+
465
+ html_parts.append(f'''
466
+ <tr class="{row_class}">
467
+ <td class="line-num old-line-num">{old_line_num}</td>
468
+ <td class="line-num new-line-num">{new_line_num}</td>
469
+ <td class="line-content">{content}</td>
470
+ </tr>
471
+ ''')
461
472
 
462
- # Right side (modified)
463
- html_parts.append('<div class="diff-side modified">')
464
- html_parts.append('<h4>Modified</h4>')
465
- if lexer and modified_content.strip():
466
- highlighted = highlight(modified_content, lexer, formatter)
467
- html_parts.append(highlighted)
468
- else:
469
- html_parts.append(f'<pre class="highlight"><code>{self._escape_html(modified_content)}</code></pre>')
473
+ html_parts.append('</table>')
474
+ html_parts.append('</div>')
470
475
  html_parts.append('</div>')
471
-
472
- html_parts.append('</div>') # Close diff-sides
473
- html_parts.append('</div>') # Close container
474
476
 
475
477
  return ''.join(html_parts)
476
478
 
@@ -478,6 +480,54 @@ class GitManager:
478
480
  logger.error("Error generating HTML diff: %s", e)
479
481
  return None
480
482
 
483
+ def _create_unified_diff_lines(self, diffs, original_content: str, modified_content: str):
484
+ """Create unified diff lines from diff-match-patch output."""
485
+ lines = []
486
+
487
+ # Split content into lines
488
+ original_lines = original_content.splitlines()
489
+ modified_lines = modified_content.splitlines()
490
+
491
+ old_line_num = 1
492
+ new_line_num = 1
493
+
494
+ # Process each diff operation
495
+ for op, text in diffs:
496
+ text_lines = text.splitlines()
497
+
498
+ if op == 0: # EQUAL - context lines
499
+ for line in text_lines:
500
+ lines.append({
501
+ 'type': 'context',
502
+ 'old_line_num': old_line_num,
503
+ 'new_line_num': new_line_num,
504
+ 'content': ' ' + line
505
+ })
506
+ old_line_num += 1
507
+ new_line_num += 1
508
+
509
+ elif op == -1: # DELETE
510
+ for line in text_lines:
511
+ lines.append({
512
+ 'type': 'delete',
513
+ 'old_line_num': old_line_num,
514
+ 'new_line_num': '',
515
+ 'content': '-' + line
516
+ })
517
+ old_line_num += 1
518
+
519
+ elif op == 1: # INSERT
520
+ for line in text_lines:
521
+ lines.append({
522
+ 'type': 'add',
523
+ 'old_line_num': '',
524
+ 'new_line_num': new_line_num,
525
+ 'content': '+' + line
526
+ })
527
+ new_line_num += 1
528
+
529
+ return lines
530
+
481
531
  def _escape_html(self, text: str) -> str:
482
532
  """Escape HTML special characters."""
483
533
  return (text.replace('&', '&amp;')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: portacode
3
- Version: 0.3.19.dev1
3
+ Version: 0.3.19.dev2
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