ralphx 0.2.2__tar.gz → 0.3.4__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 (98) hide show
  1. {ralphx-0.2.2 → ralphx-0.3.4}/PKG-INFO +2 -1
  2. {ralphx-0.2.2 → ralphx-0.3.4}/README.md +1 -0
  3. {ralphx-0.2.2 → ralphx-0.3.4}/pyproject.toml +17 -3
  4. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/__init__.py +1 -1
  5. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/main.py +9 -1
  6. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/auth.py +56 -0
  7. ralphx-0.3.4/ralphx/api/routes/export_import.py +798 -0
  8. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/projects.py +84 -2
  9. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/templates.py +113 -0
  10. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/workflows.py +21 -0
  11. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/cli.py +17 -5
  12. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/database.py +27 -3
  13. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/loop_templates.py +66 -0
  14. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/project_db.py +51 -3
  15. ralphx-0.3.4/ralphx/core/project_export.py +473 -0
  16. ralphx-0.3.4/ralphx/core/project_import.py +685 -0
  17. ralphx-0.3.4/ralphx/core/sample_project.py +434 -0
  18. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/templates.py +37 -0
  19. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/workflow_executor.py +35 -5
  20. ralphx-0.3.4/ralphx/core/workflow_export.py +609 -0
  21. ralphx-0.3.4/ralphx/core/workflow_import.py +1173 -0
  22. ralphx-0.3.4/ralphx/examples/sample_project/DESIGN.md +345 -0
  23. ralphx-0.3.4/ralphx/examples/sample_project/README.md +37 -0
  24. ralphx-0.3.4/ralphx/examples/sample_project/guardrails.md +57 -0
  25. ralphx-0.3.4/ralphx/examples/sample_project/stories.jsonl +10 -0
  26. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/server.py +99 -29
  27. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/__init__.py +4 -0
  28. ralphx-0.3.4/ralphx/mcp/tools/help.py +204 -0
  29. ralphx-0.3.4/ralphx/static/assets/index-CcRDyY3b.css +1 -0
  30. ralphx-0.3.4/ralphx/static/assets/index-CcxfTosc.js +251 -0
  31. ralphx-0.3.4/ralphx/static/assets/index-CcxfTosc.js.map +1 -0
  32. ralphx-0.3.4/ralphx/static/index.html +14 -0
  33. {ralphx-0.2.2 → ralphx-0.3.4}/.gitignore +0 -0
  34. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/adapters/__init__.py +0 -0
  35. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/adapters/base.py +0 -0
  36. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/adapters/claude_cli.py +0 -0
  37. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/__init__.py +0 -0
  38. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/__init__.py +0 -0
  39. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/config.py +0 -0
  40. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/files.py +0 -0
  41. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/filesystem.py +0 -0
  42. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/imports.py +0 -0
  43. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/items.py +0 -0
  44. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/logs.py +0 -0
  45. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/loops.py +0 -0
  46. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/planning.py +0 -0
  47. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/resources.py +0 -0
  48. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/runs.py +0 -0
  49. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/api/routes/stream.py +0 -0
  50. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/__init__.py +0 -0
  51. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/auth.py +0 -0
  52. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/checkpoint.py +0 -0
  53. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/dependencies.py +0 -0
  54. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/display.py +0 -0
  55. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/doctor.py +0 -0
  56. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/executor.py +0 -0
  57. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/global_db.py +0 -0
  58. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/guardrails.py +0 -0
  59. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/import_manager.py +0 -0
  60. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/input_templates.py +0 -0
  61. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/logger.py +0 -0
  62. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/loop.py +0 -0
  63. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/oauth.py +0 -0
  64. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/permission_templates.py +0 -0
  65. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/permissions.py +0 -0
  66. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/planning_service.py +0 -0
  67. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/preview.py +0 -0
  68. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/project.py +0 -0
  69. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/resources.py +0 -0
  70. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/schemas.py +0 -0
  71. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/session.py +0 -0
  72. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/core/workspace.py +0 -0
  73. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/__init__.py +0 -0
  74. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/base.py +0 -0
  75. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/registry.py +0 -0
  76. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/diagnostics.py +0 -0
  77. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/guardrails.py +0 -0
  78. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/imports.py +0 -0
  79. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/items.py +0 -0
  80. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/loops.py +0 -0
  81. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/monitoring.py +0 -0
  82. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/permissions.py +0 -0
  83. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/projects.py +0 -0
  84. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/resources.py +0 -0
  85. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp/tools/workflows.py +0 -0
  86. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/mcp_server.py +0 -0
  87. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/__init__.py +0 -0
  88. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/guardrail.py +0 -0
  89. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/loop.py +0 -0
  90. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/project.py +0 -0
  91. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/run.py +0 -0
  92. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/session.py +0 -0
  93. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/models/work_item.py +0 -0
  94. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/stores/__init__.py +0 -0
  95. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/templates/guardrails/default.md +0 -0
  96. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/templates/loop_templates/consumer.md +0 -0
  97. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/templates/loop_templates/generator.md +0 -0
  98. {ralphx-0.2.2 → ralphx-0.3.4}/ralphx/templates/loop_templates/hybrid.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ralphx
3
- Version: 0.2.2
3
+ Version: 0.3.4
4
4
  Summary: Autonomous AI loop orchestration for Claude Code - define workflows in YAML, run autonomously, monitor in real-time
5
5
  Project-URL: Homepage, https://github.com/jackneil/ralphx
6
6
  Project-URL: Repository, https://github.com/jackneil/ralphx
@@ -296,6 +296,7 @@ Claude gets full access to RalphX:
296
296
  - [SDLC Workflows](design/SDLC_WORKFLOWS.md) - All workflow templates explained
297
297
  - [Design Overview](design/DESIGN.md) - Architecture deep dive
298
298
  - [Loop Schema](design/LOOP_SCHEMA.md) - Configuration reference
299
+ - [Backup & Import Guide](docs/BACKUP_AND_IMPORT.md) - Export workflows, import items
299
300
 
300
301
  ---
301
302
 
@@ -256,6 +256,7 @@ Claude gets full access to RalphX:
256
256
  - [SDLC Workflows](design/SDLC_WORKFLOWS.md) - All workflow templates explained
257
257
  - [Design Overview](design/DESIGN.md) - Architecture deep dive
258
258
  - [Loop Schema](design/LOOP_SCHEMA.md) - Configuration reference
259
+ - [Backup & Import Guide](docs/BACKUP_AND_IMPORT.md) - Export workflows, import items
259
260
 
260
261
  ---
261
262
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ralphx"
7
- version = "0.2.2"
7
+ version = "0.3.4"
8
8
  description = "Autonomous AI loop orchestration for Claude Code - define workflows in YAML, run autonomously, monitor in real-time"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -67,8 +67,18 @@ Documentation = "https://github.com/jackneil/ralphx#readme"
67
67
 
68
68
  [tool.hatch.build.targets.wheel]
69
69
  packages = ["ralphx"]
70
- # Include static files (frontend build) in the wheel
71
- artifacts = ["ralphx/static/**"]
70
+ # Exclude static and examples - they're added explicitly via force-include
71
+ # to avoid duplicate entries when these dirs exist during CI build
72
+ exclude = [
73
+ "ralphx/static",
74
+ "ralphx/static/**",
75
+ "ralphx/examples",
76
+ "ralphx/examples/**",
77
+ ]
78
+
79
+ [tool.hatch.build.targets.wheel.force-include]
80
+ "ralphx/static" = "ralphx/static"
81
+ "ralphx/examples" = "ralphx/examples"
72
82
 
73
83
  [tool.hatch.build.targets.sdist]
74
84
  include = [
@@ -77,6 +87,10 @@ include = [
77
87
  "/LICENSE",
78
88
  ]
79
89
 
90
+ [tool.hatch.build.targets.sdist.force-include]
91
+ "ralphx/static" = "ralphx/static"
92
+ "ralphx/examples" = "ralphx/examples"
93
+
80
94
  [tool.ruff]
81
95
  line-length = 100
82
96
  target-version = "py310"
@@ -1,6 +1,6 @@
1
1
  """RalphX - Generic agent loop orchestration system."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.3.4"
4
4
  __author__ = "Jack"
5
5
 
6
6
  # Package metadata
@@ -27,7 +27,7 @@ from fastapi.responses import FileResponse, JSONResponse
27
27
  from fastapi.staticfiles import StaticFiles
28
28
 
29
29
  from ralphx import __version__
30
- from ralphx.api.routes import auth, config, files, filesystem, imports, items, logs, loops, planning, projects, resources, runs, stream, templates, workflows
30
+ from ralphx.api.routes import auth, config, export_import, files, filesystem, imports, items, logs, loops, planning, projects, resources, runs, stream, templates, workflows
31
31
  from ralphx.core.auth import restore_orphaned_backup
32
32
  from ralphx.core.workspace import ensure_workspace
33
33
 
@@ -123,10 +123,17 @@ async def _stale_run_cleanup_loop():
123
123
  async def lifespan(app: FastAPI):
124
124
  """Application lifespan events."""
125
125
  from ralphx.core.logger import system_log
126
+ from ralphx.core.sample_project import ensure_sample_project_created
126
127
 
127
128
  # Startup
128
129
  ensure_workspace()
129
130
 
131
+ # Create sample project on first run
132
+ try:
133
+ ensure_sample_project_created()
134
+ except Exception as e:
135
+ logger.warning(f"Sample project creation failed: {e}")
136
+
130
137
  # Restore any orphaned credential backups from previous crashes
131
138
  # This ensures user's main credentials are ALWAYS restored
132
139
  restore_orphaned_backup()
@@ -278,6 +285,7 @@ app.include_router(logs.router, prefix="/api", tags=["logs"])
278
285
  app.include_router(config.router, prefix="/api/projects", tags=["config"])
279
286
  app.include_router(workflows.router, prefix="/api/projects/{slug}", tags=["workflows"])
280
287
  app.include_router(planning.router, prefix="/api/projects/{slug}", tags=["planning"])
288
+ app.include_router(export_import.router, prefix="/api/projects/{slug}", tags=["export-import"])
281
289
 
282
290
 
283
291
  # Root endpoint
@@ -181,6 +181,62 @@ async def validate_credentials(
181
181
  }
182
182
 
183
183
 
184
+ @router.get("/usage")
185
+ async def get_usage(
186
+ project_path: Optional[str] = Query(
187
+ None, description="Project path for scoped credentials"
188
+ ),
189
+ ):
190
+ """Get Claude API usage statistics.
191
+
192
+ Returns 5-hour and 7-day utilization percentages.
193
+ """
194
+ import httpx
195
+
196
+ project_id = _get_project_id(project_path)
197
+ db = Database()
198
+ creds = db.get_credentials(project_id)
199
+
200
+ if not creds or not creds.get("access_token"):
201
+ return {
202
+ "success": False,
203
+ "error": "No credentials found",
204
+ }
205
+
206
+ try:
207
+ async with httpx.AsyncClient() as client:
208
+ response = await client.get(
209
+ "https://api.anthropic.com/api/oauth/usage",
210
+ headers={
211
+ "Authorization": f"Bearer {creds['access_token']}",
212
+ "anthropic-beta": "oauth-2025-04-20",
213
+ },
214
+ timeout=10.0,
215
+ )
216
+
217
+ if response.status_code != 200:
218
+ return {
219
+ "success": False,
220
+ "error": f"API error: {response.status_code}",
221
+ }
222
+
223
+ data = response.json()
224
+ five_hour = data.get("five_hour", {})
225
+ seven_day = data.get("seven_day", {})
226
+ return {
227
+ "success": True,
228
+ "five_hour_utilization": five_hour.get("utilization"),
229
+ "five_hour_resets_at": five_hour.get("resets_at"),
230
+ "seven_day_utilization": seven_day.get("utilization"),
231
+ "seven_day_resets_at": seven_day.get("resets_at"),
232
+ }
233
+ except Exception as e:
234
+ return {
235
+ "success": False,
236
+ "error": str(e),
237
+ }
238
+
239
+
184
240
  @router.get("/credentials/export")
185
241
  async def export_credentials(
186
242
  scope: Literal["project", "global"] = Query("global"),