repr-cli 0.2.19__tar.gz → 0.2.21__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 (72) hide show
  1. {repr_cli-0.2.19 → repr_cli-0.2.21}/PKG-INFO +1 -1
  2. {repr_cli-0.2.19 → repr_cli-0.2.21}/pyproject.toml +1 -1
  3. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/cli.py +3 -0
  4. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/openai_analysis.py +61 -29
  5. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/story_synthesis.py +6 -4
  6. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/PKG-INFO +1 -1
  7. {repr_cli-0.2.19 → repr_cli-0.2.21}/LICENSE +0 -0
  8. {repr_cli-0.2.19 → repr_cli-0.2.21}/README.md +0 -0
  9. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/__init__.py +0 -0
  10. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/__main__.py +0 -0
  11. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/api.py +0 -0
  12. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/auth.py +0 -0
  13. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/change_synthesis.py +0 -0
  14. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/config.py +0 -0
  15. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/configure.py +0 -0
  16. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/cron.py +0 -0
  17. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/__init__.py +0 -0
  18. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/build.py +0 -0
  19. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-B-aCjaCw.js +0 -0
  20. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-BYFVbEev.css +0 -0
  21. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-BrrhyJFO.css +0 -0
  22. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-C7Gzxc4f.js +0 -0
  23. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-CQdMXo6g.js +0 -0
  24. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-CcEg74ts.js +0 -0
  25. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-Cerc-iA_.js +0 -0
  26. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-CjVcBW2L.css +0 -0
  27. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-Cs8ofFGd.js +0 -0
  28. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-Dfl3mR5E.js +0 -0
  29. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-DwN0SeMc.css +0 -0
  30. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/assets/index-YFch_e0S.js +0 -0
  31. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/favicon.svg +0 -0
  32. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/dist/index.html +0 -0
  33. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/manager.py +0 -0
  34. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/dashboard/server.py +0 -0
  35. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/db.py +0 -0
  36. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/discovery.py +0 -0
  37. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/doctor.py +0 -0
  38. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/extractor.py +0 -0
  39. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/hooks.py +0 -0
  40. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/keychain.py +0 -0
  41. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/llm.py +0 -0
  42. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/loaders/__init__.py +0 -0
  43. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/loaders/base.py +0 -0
  44. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/loaders/claude_code.py +0 -0
  45. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/loaders/clawdbot.py +0 -0
  46. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/loaders/gemini_antigravity.py +0 -0
  47. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/mcp_server.py +0 -0
  48. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/models.py +0 -0
  49. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/privacy.py +0 -0
  50. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/session_extractor.py +0 -0
  51. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/storage.py +0 -0
  52. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/telemetry.py +0 -0
  53. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/templates.py +0 -0
  54. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/timeline.py +0 -0
  55. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/tools.py +0 -0
  56. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/ui.py +0 -0
  57. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr/updater.py +0 -0
  58. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/SOURCES.txt +0 -0
  59. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/dependency_links.txt +0 -0
  60. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/entry_points.txt +0 -0
  61. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/requires.txt +0 -0
  62. {repr_cli-0.2.19 → repr_cli-0.2.21}/repr_cli.egg-info/top_level.txt +0 -0
  63. {repr_cli-0.2.19 → repr_cli-0.2.21}/setup.cfg +0 -0
  64. {repr_cli-0.2.19 → repr_cli-0.2.21}/setup.py +0 -0
  65. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_deduplication.py +0 -0
  66. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_environment_variables.py +0 -0
  67. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_network_sandboxing.py +0 -0
  68. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_privacy_guarantees.py +0 -0
  69. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_profile_export.py +0 -0
  70. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_repo_identity.py +0 -0
  71. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_stories_review.py +0 -0
  72. {repr_cli-0.2.19 → repr_cli-0.2.21}/tests/test_token_budget.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repr-cli
3
- Version: 0.2.19
3
+ Version: 0.2.21
4
4
  Summary: A beautiful, privacy-first CLI that analyzes your code repositories and generates a compelling developer profile
5
5
  Author-email: Repr <hello@repr.dev>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "repr-cli"
7
- version = "0.2.19"
7
+ version = "0.2.21"
8
8
  description = "A beautiful, privacy-first CLI that analyzes your code repositories and generates a compelling developer profile"
9
9
  readme = "README.md"
10
10
  license = {file = "LICENSE"}
@@ -1136,6 +1136,9 @@ def generate(
1136
1136
  story.public_show = result.show
1137
1137
  story.internal_show = result.show
1138
1138
  except Exception as e:
1139
+ # Print error for visibility
1140
+ if not json_output:
1141
+ print_warning(f" Post generation failed: {e}")
1139
1142
  # Fallback: build from story data
1140
1143
  from .story_synthesis import _build_fallback_codex
1141
1144
  result = _build_fallback_codex(story, "internal")
@@ -240,7 +240,9 @@ No corporate fluff. No "enhanced", "improved", "robust". Just say what happened.
240
240
 
241
241
  {commits_formatted}"""
242
242
 
243
- try:
243
+ async def make_request(use_temperature: bool = True):
244
+ """Make API request, optionally with temperature."""
245
+ temp_kwargs = {"temperature": EXTRACTION_TEMPERATURE} if use_temperature else {}
244
246
  if structured:
245
247
  # Use structured output with Pydantic model
246
248
  response = await client.beta.chat.completions.parse(
@@ -249,9 +251,9 @@ No corporate fluff. No "enhanced", "improved", "robust". Just say what happened.
249
251
  {"role": "system", "content": system_prompt},
250
252
  {"role": "user", "content": user_prompt},
251
253
  ],
252
- temperature=EXTRACTION_TEMPERATURE,
253
254
  max_tokens=16000,
254
255
  response_format=ExtractedCommitBatch,
256
+ **temp_kwargs,
255
257
  )
256
258
 
257
259
  parsed = response.choices[0].message.parsed
@@ -292,15 +294,23 @@ No corporate fluff. No "enhanced", "improved", "robust". Just say what happened.
292
294
  {"role": "system", "content": system_prompt},
293
295
  {"role": "user", "content": user_prompt},
294
296
  ],
295
- temperature=EXTRACTION_TEMPERATURE,
296
297
  max_tokens=16000,
298
+ **temp_kwargs,
297
299
  )
298
-
300
+
299
301
  return response.choices[0].message.content or ""
302
+
303
+ try:
304
+ return await make_request(use_temperature=True)
300
305
  except Exception as e:
301
- error_msg = str(e).lower()
306
+ error_msg = str(e)
307
+ error_lower = error_msg.lower()
308
+ # Handle models that don't support custom temperature
309
+ if "temperature" in error_lower and "unsupported" in error_lower:
310
+ # Retry without temperature parameter
311
+ return await make_request(use_temperature=False)
302
312
  # Handle content moderation blocks gracefully
303
- if "blocked" in error_msg or "content" in error_msg or "moderation" in error_msg:
313
+ if "blocked" in error_lower or "content" in error_lower or "moderation" in error_lower:
304
314
  # Skip this batch but continue with others
305
315
  if structured:
306
316
  return [
@@ -421,18 +431,29 @@ Synthesize this into a cohesive developer profile in Markdown format starting wi
421
431
 
422
432
  Focus on CONCRETE technical accomplishments AND the reasoning behind key decisions. For each major feature or system, explain WHY it was built that way—what problem it solved, what user need it addressed, or what technical constraint it navigated."""
423
433
 
424
- response = await client.chat.completions.create(
425
- model=model,
426
- messages=[
427
- {"role": "system", "content": system_prompt},
428
- {"role": "user", "content": user_prompt},
429
- ],
430
- temperature=SYNTHESIS_TEMPERATURE,
431
- max_tokens=16000, # Increased for reasoning models
432
- )
433
-
434
+ async def make_synthesis_request(use_temperature: bool = True):
435
+ temp_kwargs = {"temperature": SYNTHESIS_TEMPERATURE} if use_temperature else {}
436
+ return await client.chat.completions.create(
437
+ model=model,
438
+ messages=[
439
+ {"role": "system", "content": system_prompt},
440
+ {"role": "user", "content": user_prompt},
441
+ ],
442
+ max_tokens=16000, # Increased for reasoning models
443
+ **temp_kwargs,
444
+ )
445
+
446
+ try:
447
+ response = await make_synthesis_request(use_temperature=True)
448
+ except Exception as e:
449
+ error_msg = str(e).lower()
450
+ if "temperature" in error_msg and "unsupported" in error_msg:
451
+ response = await make_synthesis_request(use_temperature=False)
452
+ else:
453
+ raise
454
+
434
455
  llm_content = response.choices[0].message.content or ""
435
-
456
+
436
457
  # Prepend metadata header
437
458
  return f"{metadata_header}\n\n---\n\n{llm_content}"
438
459
 
@@ -731,16 +752,27 @@ Preserve and highlight the "why" explanations that demonstrate engineering judgm
731
752
  progress=95.0,
732
753
  )
733
754
 
734
- response = await client.chat.completions.create(
735
- model=final_synthesis_model,
736
- messages=[
737
- {"role": "system", "content": system_prompt},
738
- {"role": "user", "content": user_prompt},
739
- ],
740
- temperature=SYNTHESIS_TEMPERATURE,
741
- max_tokens=16000,
742
- )
743
-
755
+ async def make_final_request(use_temperature: bool = True):
756
+ temp_kwargs = {"temperature": SYNTHESIS_TEMPERATURE} if use_temperature else {}
757
+ return await client.chat.completions.create(
758
+ model=final_synthesis_model,
759
+ messages=[
760
+ {"role": "system", "content": system_prompt},
761
+ {"role": "user", "content": user_prompt},
762
+ ],
763
+ max_tokens=16000,
764
+ **temp_kwargs,
765
+ )
766
+
767
+ try:
768
+ response = await make_final_request(use_temperature=True)
769
+ except Exception as e:
770
+ error_msg = str(e).lower()
771
+ if "temperature" in error_msg and "unsupported" in error_msg:
772
+ response = await make_final_request(use_temperature=False)
773
+ else:
774
+ raise
775
+
744
776
  if progress_callback:
745
777
  progress_callback(
746
778
  step="Complete",
@@ -748,9 +780,9 @@ Preserve and highlight the "why" explanations that demonstrate engineering judgm
748
780
  repo="",
749
781
  progress=100.0,
750
782
  )
751
-
783
+
752
784
  llm_content = response.choices[0].message.content or ""
753
-
785
+
754
786
  # Prepend metadata header
755
787
  return f"{metadata_header}\n\n---\n\n{llm_content}"
756
788
 
@@ -683,10 +683,9 @@ class StorySynthesizer:
683
683
  analysis = BatchAnalysis.model_validate_json(content)
684
684
 
685
685
  except Exception as e:
686
- # Log the error for debugging
687
- import os
688
- if os.environ.get("REPR_DEBUG"):
689
- print(f"DEBUG: Exception in LLM call: {type(e).__name__}: {e}")
686
+ # Always print error for visibility
687
+ from rich.console import Console
688
+ Console(stderr=True).print(f"[yellow] LLM error: {type(e).__name__}: {e}[/]")
690
689
 
691
690
  # Fallback: each commit is its own story
692
691
  analysis = BatchAnalysis(stories=[
@@ -1095,6 +1094,9 @@ async def transform_story_for_feed(
1095
1094
  return result
1096
1095
 
1097
1096
  except Exception as e:
1097
+ # Print error for visibility
1098
+ from rich.console import Console
1099
+ Console(stderr=True).print(f"[yellow] Transform error: {type(e).__name__}: {e}[/]")
1098
1100
  # Fallback: construct structured content from available data
1099
1101
  return _build_fallback_codex(story, mode)
1100
1102
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: repr-cli
3
- Version: 0.2.19
3
+ Version: 0.2.21
4
4
  Summary: A beautiful, privacy-first CLI that analyzes your code repositories and generates a compelling developer profile
5
5
  Author-email: Repr <hello@repr.dev>
6
6
  License: MIT License
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