gitcast 1.0.12__tar.gz → 1.0.13__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 (88) hide show
  1. {gitcast-1.0.12/gitcast.egg-info → gitcast-1.0.13}/PKG-INFO +1 -1
  2. {gitcast-1.0.12 → gitcast-1.0.13}/api/payload.py +65 -64
  3. {gitcast-1.0.12 → gitcast-1.0.13}/cli/gitcast.py +2 -0
  4. {gitcast-1.0.12 → gitcast-1.0.13}/core/ocr.py +5 -1
  5. {gitcast-1.0.12 → gitcast-1.0.13}/core/trigger.py +9 -2
  6. {gitcast-1.0.12 → gitcast-1.0.13/gitcast.egg-info}/PKG-INFO +1 -1
  7. {gitcast-1.0.12 → gitcast-1.0.13}/setup.py +1 -1
  8. {gitcast-1.0.12 → gitcast-1.0.13}/.env.example +0 -0
  9. {gitcast-1.0.12 → gitcast-1.0.13}/LICENSE +0 -0
  10. {gitcast-1.0.12 → gitcast-1.0.13}/MANIFEST.in +0 -0
  11. {gitcast-1.0.12 → gitcast-1.0.13}/README.md +0 -0
  12. {gitcast-1.0.12 → gitcast-1.0.13}/ai/__init__.py +0 -0
  13. {gitcast-1.0.12 → gitcast-1.0.13}/ai/formatter.py +0 -0
  14. {gitcast-1.0.12 → gitcast-1.0.13}/ai/generator.py +0 -0
  15. {gitcast-1.0.12 → gitcast-1.0.13}/ai/prompts.py +0 -0
  16. {gitcast-1.0.12 → gitcast-1.0.13}/ai/viral_patterns.py +0 -0
  17. {gitcast-1.0.12 → gitcast-1.0.13}/api/__init__.py +0 -0
  18. {gitcast-1.0.12 → gitcast-1.0.13}/api/analytics.py +0 -0
  19. {gitcast-1.0.12 → gitcast-1.0.13}/api/auth.py +0 -0
  20. {gitcast-1.0.12 → gitcast-1.0.13}/api/auth_middleware.py +0 -0
  21. {gitcast-1.0.12 → gitcast-1.0.13}/api/auth_routes.py +0 -0
  22. {gitcast-1.0.12 → gitcast-1.0.13}/api/monitoring.py +0 -0
  23. {gitcast-1.0.12 → gitcast-1.0.13}/api/ratelimit.py +0 -0
  24. {gitcast-1.0.12 → gitcast-1.0.13}/api/routes.py +0 -0
  25. {gitcast-1.0.12 → gitcast-1.0.13}/api/server.py +0 -0
  26. {gitcast-1.0.12 → gitcast-1.0.13}/api/validators.py +0 -0
  27. {gitcast-1.0.12 → gitcast-1.0.13}/assets/__init__.py +0 -0
  28. {gitcast-1.0.12 → gitcast-1.0.13}/assets/favicon-16x16.png +0 -0
  29. {gitcast-1.0.12 → gitcast-1.0.13}/assets/favicon-32x32.png +0 -0
  30. {gitcast-1.0.12 → gitcast-1.0.13}/assets/favicon-64x64.png +0 -0
  31. {gitcast-1.0.12 → gitcast-1.0.13}/assets/favicon.ico +0 -0
  32. {gitcast-1.0.12 → gitcast-1.0.13}/assets/icon.png +0 -0
  33. {gitcast-1.0.12 → gitcast-1.0.13}/cli/.env.example +0 -0
  34. {gitcast-1.0.12 → gitcast-1.0.13}/cli/__init__.py +0 -0
  35. {gitcast-1.0.12 → gitcast-1.0.13}/config/__init__.py +0 -0
  36. {gitcast-1.0.12 → gitcast-1.0.13}/config/settings.py +0 -0
  37. {gitcast-1.0.12 → gitcast-1.0.13}/core/__init__.py +0 -0
  38. {gitcast-1.0.12 → gitcast-1.0.13}/core/capture.py +0 -0
  39. {gitcast-1.0.12 → gitcast-1.0.13}/core/codebase_reader.py +0 -0
  40. {gitcast-1.0.12 → gitcast-1.0.13}/core/framing.py +0 -0
  41. {gitcast-1.0.12 → gitcast-1.0.13}/core/hotkey.py +0 -0
  42. {gitcast-1.0.12 → gitcast-1.0.13}/core/log_stream.py +0 -0
  43. {gitcast-1.0.12 → gitcast-1.0.13}/core/screenshot_session.py +0 -0
  44. {gitcast-1.0.12 → gitcast-1.0.13}/core/security.py +0 -0
  45. {gitcast-1.0.12 → gitcast-1.0.13}/core/tray.py +0 -0
  46. {gitcast-1.0.12 → gitcast-1.0.13}/docs/api-keys.md +0 -0
  47. {gitcast-1.0.12 → gitcast-1.0.13}/docs/article-generator.md +0 -0
  48. {gitcast-1.0.12 → gitcast-1.0.13}/docs/capture-flow.md +0 -0
  49. {gitcast-1.0.12 → gitcast-1.0.13}/docs/changelog.md +0 -0
  50. {gitcast-1.0.12 → gitcast-1.0.13}/docs/contributing.md +0 -0
  51. {gitcast-1.0.12 → gitcast-1.0.13}/docs/dashboard.md +0 -0
  52. {gitcast-1.0.12 → gitcast-1.0.13}/docs/insights.md +0 -0
  53. {gitcast-1.0.12 → gitcast-1.0.13}/docs/introduction.md +0 -0
  54. {gitcast-1.0.12 → gitcast-1.0.13}/docs/post-formats.md +0 -0
  55. {gitcast-1.0.12 → gitcast-1.0.13}/docs/providers.md +0 -0
  56. {gitcast-1.0.12 → gitcast-1.0.13}/docs/pypi-errors.md +0 -0
  57. {gitcast-1.0.12 → gitcast-1.0.13}/docs/quickstart.md +0 -0
  58. {gitcast-1.0.12 → gitcast-1.0.13}/docs/sprint-mode.md +0 -0
  59. {gitcast-1.0.12 → gitcast-1.0.13}/gitcast.egg-info/SOURCES.txt +0 -0
  60. {gitcast-1.0.12 → gitcast-1.0.13}/gitcast.egg-info/dependency_links.txt +0 -0
  61. {gitcast-1.0.12 → gitcast-1.0.13}/gitcast.egg-info/entry_points.txt +0 -0
  62. {gitcast-1.0.12 → gitcast-1.0.13}/gitcast.egg-info/requires.txt +0 -0
  63. {gitcast-1.0.12 → gitcast-1.0.13}/gitcast.egg-info/top_level.txt +0 -0
  64. {gitcast-1.0.12 → gitcast-1.0.13}/publisher/__init__.py +0 -0
  65. {gitcast-1.0.12 → gitcast-1.0.13}/publisher/clipboard.py +0 -0
  66. {gitcast-1.0.12 → gitcast-1.0.13}/publisher/twitter.py +0 -0
  67. {gitcast-1.0.12 → gitcast-1.0.13}/pyproject.toml +0 -0
  68. {gitcast-1.0.12 → gitcast-1.0.13}/requirements.txt +0 -0
  69. {gitcast-1.0.12 → gitcast-1.0.13}/setup.cfg +0 -0
  70. {gitcast-1.0.12 → gitcast-1.0.13}/storage/__init__.py +0 -0
  71. {gitcast-1.0.12 → gitcast-1.0.13}/storage/cleanup.py +0 -0
  72. {gitcast-1.0.12 → gitcast-1.0.13}/storage/engagement.py +0 -0
  73. {gitcast-1.0.12 → gitcast-1.0.13}/storage/insights.py +0 -0
  74. {gitcast-1.0.12 → gitcast-1.0.13}/storage/key_manager.py +0 -0
  75. {gitcast-1.0.12 → gitcast-1.0.13}/storage/logger.py +0 -0
  76. {gitcast-1.0.12 → gitcast-1.0.13}/storage/metrics.py +0 -0
  77. {gitcast-1.0.12 → gitcast-1.0.13}/storage/sprint.py +0 -0
  78. {gitcast-1.0.12 → gitcast-1.0.13}/storage/streak.py +0 -0
  79. {gitcast-1.0.12 → gitcast-1.0.13}/storage/supabase_client.py +0 -0
  80. {gitcast-1.0.12 → gitcast-1.0.13}/storage/tone_memory.py +0 -0
  81. {gitcast-1.0.12 → gitcast-1.0.13}/tests/test_keys.py +0 -0
  82. {gitcast-1.0.12 → gitcast-1.0.13}/tests/test_ocr_fix.py +0 -0
  83. {gitcast-1.0.12 → gitcast-1.0.13}/ui/__init__.py +0 -0
  84. {gitcast-1.0.12 → gitcast-1.0.13}/ui/popup.py +0 -0
  85. {gitcast-1.0.12 → gitcast-1.0.13}/ui/review.py +0 -0
  86. {gitcast-1.0.12 → gitcast-1.0.13}/web/__init__.py +0 -0
  87. {gitcast-1.0.12 → gitcast-1.0.13}/web/index.html +0 -0
  88. {gitcast-1.0.12 → gitcast-1.0.13}/web/landing.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitcast
3
- Version: 1.0.12
3
+ Version: 1.0.13
4
4
  Summary: git diff → published post. under 60 seconds.
5
5
  Home-page: https://github.com/drizzy765/gitcast
6
6
  Author: Timilehin Agoro
@@ -121,76 +121,77 @@ def _build_user_message(
121
121
  diff_text = git_diff.get("diff", "") if isinstance(git_diff, dict) else ""
122
122
  if diff_text:
123
123
  parts.append(f"## Git diff (recent code changes)\n```\n{diff_text.strip()}\n```")
124
-
125
- # project narrative
126
- if narrative:
127
- parts.append(f"## Project context\n{narrative}")
128
-
129
- parts.append(
130
- "\nUsing the context above, generate the post now. "
131
- "Follow the format and rules in the system prompt exactly."
132
- )
133
-
134
- return "\n\n".join(parts)
135
-
136
-
137
- # ── Sprint Mode payload ───────────────────────────────────────────────────────
138
-
124
+ # project narrative
125
+ if narrative:
126
+ parts.append(f"## Project context\n{narrative}")
127
+
128
+ parts.append(
129
+ "\nUsing the context above, generate the post now. "
130
+ "Follow the format and rules in the system prompt exactly."
131
+ )
132
+
133
+ return "\n\n".join(parts)
134
+
135
+
136
+ # ── Sprint Mode payload ───────────────────────────────────────────────────────
137
+
139
138
  def build_sprint_payload(sprint_log_entries: list) -> dict:
140
- """
141
- Builds the payload for Sprint Mode — takes the full list of
142
- silent captures and assembles them into one batched message
143
- for the sprint summary prompt.
144
- """
145
- parts = ["You have been given a log of captures from a coding sprint.\n"]
146
-
147
- for i, entry in enumerate(sprint_log_entries, 1):
148
- parts.append(f"--- Capture {i} of {len(sprint_log_entries)} ---")
149
-
150
- if entry.get("raw_thought"):
151
- parts.append(f"Developer thought: {entry['raw_thought']}")
152
-
153
- if entry.get("git_diff"):
154
- parts.append(f"Code changes:\n```\n{entry['git_diff'][:500]}\n```")
155
-
156
- if entry.get("ocr_text"):
157
- parts.append(f"Screen context: {entry['ocr_text'][:300]}")
158
-
159
- if entry.get("timestamp"):
160
- parts.append(f"Time: {entry['timestamp']}")
161
-
162
- parts.append(
163
- "\nSynthesize all of the above into a compelling sprint thread. "
164
- "Follow the format and rules in the system prompt exactly."
165
- )
166
-
167
- narrative = get_project_narrative()
168
-
169
- return {
170
- "user_message": "\n\n".join(parts),
171
- "format_keys": ["sprint_summary"],
172
- "narrative": narrative,
173
- "num_captures": len(sprint_log_entries),
174
- "use_vision_fallback": False,
175
- "screenshot_b64": None,
176
- }
177
-
178
-
179
- # ── Image encoder ─────────────────────────────────────────────────────────────
180
-
181
- def _encode_image(image_path: str) -> str:
182
- """
183
- Encodes an image file as a base64 string for the Gemini vision API.
184
- Returns empty string if encoding fails.
185
- """
139
+ """
140
+ Builds the payload for Sprint Mode — takes the full list of
141
+ silent captures and assembles them into one batched message
142
+ for the sprint summary prompt.
143
+ """
144
+ parts = ["You have been given a log of captures from a coding sprint.\n"]
145
+
146
+ for i, entry in enumerate(sprint_log_entries, 1):
147
+ parts.append(f"--- Capture {i} of {len(sprint_log_entries)} ---")
148
+
149
+ if entry.get("raw_thought"):
150
+ parts.append(f"Developer thought: {entry['raw_thought']}")
151
+
152
+ if entry.get("git_diff"):
153
+ parts.append(f"Code changes:\n```\n{entry['git_diff'][:500]}\n```")
154
+
155
+ if entry.get("ocr_text"):
156
+ parts.append(f"Screen context: {entry['ocr_text'][:300]}")
157
+
158
+ if entry.get("timestamp"):
159
+ parts.append(f"Time: {entry['timestamp']}")
160
+
161
+ parts.append(
162
+ "\nSynthesize all of the above into a compelling sprint thread. "
163
+ "Follow the format and rules in the system prompt exactly."
164
+ )
165
+
166
+ narrative = get_project_narrative()
167
+
168
+ return {
169
+ "user_message": "\n\n".join(parts),
170
+ "format_keys": ["sprint_summary"],
171
+ "narrative": narrative,
172
+ "num_captures": len(sprint_log_entries),
173
+ "use_vision_fallback": False,
174
+ "screenshot_b64": None,
175
+ }
176
+
177
+
178
+ # ── Image encoder ─────────────────────────────────────────────────────────────
179
+
180
+ def _encode_image(image_path: str) -> str:
181
+ """
182
+ Encodes an image file as a base64 string for the Gemini vision API.
183
+ Returns empty string if encoding fails.
184
+ """
186
185
  try:
187
- with open(image_path, "rb") as f:
186
+ from config.settings import BASE_DIR
187
+ path = Path(image_path)
188
+ if not path.is_absolute():
189
+ path = BASE_DIR / path
190
+ with open(path, "rb") as f:
188
191
  return base64.b64encode(f.read()).decode("utf-8")
189
192
  except Exception as e:
190
193
  stream_log("Payload", "WARN", f"image encoding failed: {e}")
191
194
  return ""
192
-
193
-
194
195
  # ── Payload validator ─────────────────────────────────────────────────────────
195
196
 
196
197
  def validate_payload(payload: dict) -> tuple[bool, list[str]]:
@@ -87,6 +87,8 @@ def main():
87
87
 
88
88
  print("[OK] server running at http://localhost:8000")
89
89
  print("[OK] browser opened")
90
+ print("\n> [OK] Gitcast daemon is listening globally.")
91
+ print("> Press Ctrl+Alt+S (or Ctrl+Shift+P) while coding to capture a screenshot + git diff and generate posts.\n")
90
92
 
91
93
  from core.tray import run_tray
92
94
  from core.trigger import on_trigger
@@ -32,7 +32,11 @@ def run_ocr(image_path: str) -> dict:
32
32
  threshold = get_ocr_threshold() # default 60, set in config/settings.py
33
33
 
34
34
  try:
35
- img = Image.open(image_path)
35
+ from config.settings import BASE_DIR
36
+ path = Path(image_path)
37
+ if not path.is_absolute():
38
+ path = BASE_DIR / path
39
+ img = Image.open(path)
36
40
 
37
41
  # get detailed output including confidence scores per word
38
42
  data = pytesseract.image_to_data(
@@ -12,6 +12,8 @@ from storage.logger import log_post
12
12
  import asyncio
13
13
  import webbrowser
14
14
 
15
+ _browser_opened = False
16
+
15
17
 
16
18
  def on_trigger():
17
19
  """
@@ -57,8 +59,13 @@ def on_trigger():
57
59
  for k, v in variations.items():
58
60
  print(f'[Trigger] {k}: {v[:50]}...')
59
61
 
60
- print("[Trigger] opening review window")
61
- webbrowser.open("http://localhost:8000")
62
+ global _browser_opened
63
+ if not _browser_opened:
64
+ print("[Trigger] opening review window")
65
+ webbrowser.open("http://localhost:8000")
66
+ _browser_opened = True
67
+ else:
68
+ print("> [OK] Posts generated. Refresh or check your active dashboard tab at http://localhost:8000")
62
69
 
63
70
  def on_publish(post_text, format_key,
64
71
  screenshot_path):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitcast
3
- Version: 1.0.12
3
+ Version: 1.0.13
4
4
  Summary: git diff → published post. under 60 seconds.
5
5
  Home-page: https://github.com/drizzy765/gitcast
6
6
  Author: Timilehin Agoro
@@ -51,7 +51,7 @@ if os.path.exists(requirements_path):
51
51
 
52
52
  setup(
53
53
  name="gitcast",
54
- version="1.0.12",
54
+ version="1.0.13",
55
55
  description="git diff → published post. under 60 seconds.",
56
56
  long_description=long_description,
57
57
  long_description_content_type="text/markdown",
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
File without changes
File without changes
File without changes
File without changes
File without changes