mlx-code 0.0.13__tar.gz → 0.0.14__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 (26) hide show
  1. {mlx_code-0.0.13 → mlx_code-0.0.14}/PKG-INFO +1 -1
  2. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/gits.py +50 -1
  3. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/repl.py +38 -4
  4. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/PKG-INFO +1 -1
  5. {mlx_code-0.0.13 → mlx_code-0.0.14}/setup.py +1 -1
  6. {mlx_code-0.0.13 → mlx_code-0.0.14}/LICENSE +0 -0
  7. {mlx_code-0.0.13 → mlx_code-0.0.14}/README.md +0 -0
  8. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/__init__.py +0 -0
  9. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/apis.py +0 -0
  10. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/lsp_tool.py +0 -0
  11. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/main.py +0 -0
  12. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/mcb.py +0 -0
  13. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/mcb_tool.py +0 -0
  14. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/stream_log.py +0 -0
  15. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/tools.py +0 -0
  16. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/util.py +0 -0
  17. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/view_git.py +0 -0
  18. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code/view_log.py +0 -0
  19. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/SOURCES.txt +0 -0
  20. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/dependency_links.txt +0 -0
  21. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/entry_points.txt +0 -0
  22. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/requires.txt +0 -0
  23. {mlx_code-0.0.13 → mlx_code-0.0.14}/mlx_code.egg-info/top_level.txt +0 -0
  24. {mlx_code-0.0.13 → mlx_code-0.0.14}/setup.cfg +0 -0
  25. {mlx_code-0.0.13 → mlx_code-0.0.14}/tests/__init__.py +0 -0
  26. {mlx_code-0.0.13 → mlx_code-0.0.14}/tests/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlx-code
3
- Version: 0.0.13
3
+ Version: 0.0.14
4
4
  Summary: Coding Agent for Mac
5
5
  Home-page: https://josefalbers.github.io/mlx-code/
6
6
  Author: J Joe
@@ -177,4 +177,53 @@ def current_point(worktree_dir: str) -> LedgerPoint:
177
177
  worktree_dir = os.path.abspath(worktree_dir)
178
178
  branch = _git(worktree_dir, 'symbolic-ref', '--short', 'HEAD', check=False) or 'DETACHED'
179
179
  sha = _git(worktree_dir, 'rev-parse', 'HEAD', check=False)
180
- return LedgerPoint(branch=branch, commit=sha, worktree=worktree_dir)
180
+ return LedgerPoint(branch=branch, commit=sha, worktree=worktree_dir)
181
+
182
+ def get_commit_history_with_stats(worktree: str, limit: int=50) -> list[dict]:
183
+ try:
184
+ cmd = ['git', 'log', '--name-status', '--format=COMMIT:%H%nSHORT:%h%nREFS:%d%nSUBJECT:%s%nBODY_START%n%b%nBODY_END', f'-n{limit}']
185
+ result = subprocess.run(cmd, cwd=worktree, capture_output=True, text=True, check=True)
186
+ output = result.stdout.strip()
187
+ commits = []
188
+ current_commit = None
189
+ in_body = False
190
+ body_lines = []
191
+ for line in output.split('\n'):
192
+ if line.startswith('COMMIT:'):
193
+ if current_commit:
194
+ body_text = '\n'.join(body_lines)
195
+ current_commit['user_turns'] = body_text.count('"role": "user"')
196
+ commits.append(current_commit)
197
+ current_commit = {'sha': line[7:], 'short_sha': '', 'refs': '', 'subject': '', 'files': []}
198
+ in_body = False
199
+ body_lines = []
200
+ elif line.startswith('SHORT:'):
201
+ if current_commit:
202
+ current_commit['short_sha'] = line[6:]
203
+ elif line.startswith('REFS:'):
204
+ if current_commit:
205
+ current_commit['refs'] = line[5:].strip()
206
+ elif line.startswith('SUBJECT:'):
207
+ if current_commit:
208
+ current_commit['subject'] = line[8:]
209
+ elif line == 'BODY_START':
210
+ in_body = True
211
+ elif line == 'BODY_END':
212
+ in_body = False
213
+ elif current_commit:
214
+ if in_body:
215
+ body_lines.append(line)
216
+ elif line.strip():
217
+ parts = line.split('\t', 1)
218
+ if len(parts) == 2:
219
+ current_commit['files'].append(f'{parts[0]} {parts[1]}')
220
+ else:
221
+ current_commit['files'].append(line)
222
+ if current_commit:
223
+ body_text = '\n'.join(body_lines)
224
+ current_commit['user_turns'] = body_text.count('"role": "user"')
225
+ commits.append(current_commit)
226
+ return commits
227
+ except Exception as e:
228
+ logger.warning(f'get_commit_history_with_stats failed: {e}')
229
+ return []
@@ -12,7 +12,7 @@ import time
12
12
  import logging
13
13
  import urllib.parse
14
14
  from typing import Any, Callable, Literal
15
- from .gits import create_worktree, commit_worktree, resume_worktree, cleanup_worktree, git_new_branch, git_switch_branch, GitError
15
+ from .gits import create_worktree, commit_worktree, resume_worktree, cleanup_worktree, git_new_branch, git_switch_branch, GitError, get_commit_history_with_stats
16
16
  from .tools import Tool, validate_tool_call, DEFAULT_TOOLS
17
17
  from .apis import resolve_api
18
18
  logger = logging.getLogger(__name__)
@@ -561,14 +561,48 @@ class ReplApp(App[None]):
561
561
  tab.show_command(text, 'No prompts yet.')
562
562
  else:
563
563
  lines = []
564
+ gwt = tab.agent.ctx.get('gwt')
565
+ commit_stats = []
566
+ if gwt and getattr(gwt, 'worktree', None):
567
+ try:
568
+ commit_stats = get_commit_history_with_stats(gwt.worktree, limit=len(user_msgs) + 5)
569
+ except Exception as e:
570
+ logger.warning(f'Failed to get commit stats: {e}')
571
+ turn_commits = {}
572
+ for c in commit_stats:
573
+ turn = c.get('user_turns', 0)
574
+ if turn > 0:
575
+ if turn not in turn_commits:
576
+ turn_commits[turn] = []
577
+ turn_commits[turn].append(c)
564
578
  for i, m in enumerate(user_msgs, 1):
565
579
  content = m.get('content', '')
566
580
  if isinstance(content, list):
567
- content = ''.join((b.get('text', '') for b in content if isinstance(b, dict) and b.get('type') == 'text'))
568
- content = re.sub('\\s+', ' ', content).strip()
581
+ content = ' '.join((b.get('text', '') for b in content if isinstance(b, dict) and b.get('type') == 'text'))
582
+ content = re.sub('\\s+', ' ', content).strip()
569
583
  if len(content) > 100:
570
584
  content = content[:100] + '…'
571
- lines.append(f'{i}. {content}')
585
+ line = f'{i}. {content}'
586
+ if i in turn_commits:
587
+ for c in turn_commits[i]:
588
+ ref_str = c.get('refs', '').strip(' ()')
589
+ if ref_str.startswith('HEAD -> '):
590
+ ref_str = ref_str[8:]
591
+ ref_str = ref_str.replace('HEAD, ', '').strip()
592
+ hash_str = f'[{c['short_sha']}]'
593
+ if ref_str:
594
+ hash_str += f' on {ref_str}'
595
+ else:
596
+ hash_str += ' (detached)'
597
+ line += f'\n ↪ Commit {hash_str}'
598
+ seen = set()
599
+ unique_files = [f for f in c['files'] if not (f in seen or seen.add(f))]
600
+ if unique_files:
601
+ file_lines = '\n '.join(unique_files[:8])
602
+ if len(unique_files) > 8:
603
+ file_lines += f'\n ... and {len(unique_files) - 8} more'
604
+ line += f'\n {file_lines}'
605
+ lines.append(line)
572
606
  tab.show_command(text, '\n'.join(lines))
573
607
  elif cmd == '/errors':
574
608
  if not tab.errors:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlx-code
3
- Version: 0.0.13
3
+ Version: 0.0.14
4
4
  Summary: Coding Agent for Mac
5
5
  Home-page: https://josefalbers.github.io/mlx-code/
6
6
  Author: J Joe
@@ -11,7 +11,7 @@ setup(
11
11
  author_email="albersj66@gmail.com",
12
12
  author="J Joe",
13
13
  license="Apache-2.0",
14
- version="0.0.13",
14
+ version="0.0.14",
15
15
  readme="README.md",
16
16
  description="Coding Agent for Mac",
17
17
  long_description=open("README.md").read(),
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