researchloop 0.1.0__py3-none-any.whl

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 (63) hide show
  1. researchloop/__init__.py +1 -0
  2. researchloop/__main__.py +3 -0
  3. researchloop/cli.py +1138 -0
  4. researchloop/clusters/__init__.py +4 -0
  5. researchloop/clusters/monitor.py +199 -0
  6. researchloop/clusters/ssh.py +183 -0
  7. researchloop/comms/__init__.py +0 -0
  8. researchloop/comms/base.py +34 -0
  9. researchloop/comms/conversation.py +465 -0
  10. researchloop/comms/ntfy.py +95 -0
  11. researchloop/comms/router.py +71 -0
  12. researchloop/comms/slack.py +188 -0
  13. researchloop/core/__init__.py +0 -0
  14. researchloop/core/auth.py +78 -0
  15. researchloop/core/config.py +328 -0
  16. researchloop/core/credentials.py +38 -0
  17. researchloop/core/models.py +119 -0
  18. researchloop/core/orchestrator.py +910 -0
  19. researchloop/dashboard/__init__.py +0 -0
  20. researchloop/dashboard/app.py +15 -0
  21. researchloop/dashboard/auth.py +60 -0
  22. researchloop/dashboard/routes.py +912 -0
  23. researchloop/dashboard/templates/base.html +84 -0
  24. researchloop/dashboard/templates/login.html +12 -0
  25. researchloop/dashboard/templates/loop_detail.html +58 -0
  26. researchloop/dashboard/templates/loops.html +61 -0
  27. researchloop/dashboard/templates/setup.html +14 -0
  28. researchloop/dashboard/templates/sprint_detail.html +109 -0
  29. researchloop/dashboard/templates/sprints.html +48 -0
  30. researchloop/dashboard/templates/studies.html +18 -0
  31. researchloop/dashboard/templates/study_detail.html +64 -0
  32. researchloop/db/__init__.py +5 -0
  33. researchloop/db/database.py +86 -0
  34. researchloop/db/migrations.py +172 -0
  35. researchloop/db/queries.py +351 -0
  36. researchloop/runner/__init__.py +1 -0
  37. researchloop/runner/claude.py +169 -0
  38. researchloop/runner/job_templates/sge.sh.j2 +319 -0
  39. researchloop/runner/job_templates/slurm.sh.j2 +336 -0
  40. researchloop/runner/main.py +156 -0
  41. researchloop/runner/pipeline.py +272 -0
  42. researchloop/runner/templates/fix_issues.md.j2 +11 -0
  43. researchloop/runner/templates/idea_generator.md.j2 +16 -0
  44. researchloop/runner/templates/red_team.md.j2 +15 -0
  45. researchloop/runner/templates/report.md.j2 +31 -0
  46. researchloop/runner/templates/research_sprint.md.j2 +51 -0
  47. researchloop/runner/templates/summarizer.md.j2 +7 -0
  48. researchloop/runner/upload.py +153 -0
  49. researchloop/schedulers/__init__.py +11 -0
  50. researchloop/schedulers/base.py +43 -0
  51. researchloop/schedulers/local.py +188 -0
  52. researchloop/schedulers/sge.py +163 -0
  53. researchloop/schedulers/slurm.py +179 -0
  54. researchloop/sprints/__init__.py +0 -0
  55. researchloop/sprints/auto_loop.py +458 -0
  56. researchloop/sprints/manager.py +750 -0
  57. researchloop/studies/__init__.py +0 -0
  58. researchloop/studies/manager.py +102 -0
  59. researchloop-0.1.0.dist-info/METADATA +596 -0
  60. researchloop-0.1.0.dist-info/RECORD +63 -0
  61. researchloop-0.1.0.dist-info/WHEEL +4 -0
  62. researchloop-0.1.0.dist-info/entry_points.txt +3 -0
  63. researchloop-0.1.0.dist-info/licenses/LICENSE +21 -0
File without changes
@@ -0,0 +1,15 @@
1
+ """Dashboard FastAPI application -- used by ``researchloop serve``.
2
+
3
+ This module provides the ASGI ``app`` object that uvicorn imports.
4
+ It loads the configuration, creates an :class:`Orchestrator`, and
5
+ delegates to :func:`create_app` for route setup.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from researchloop.core.config import load_config
11
+ from researchloop.core.orchestrator import Orchestrator, create_app
12
+
13
+ _config = load_config()
14
+ _orchestrator = Orchestrator(_config)
15
+ app = create_app(_orchestrator)
@@ -0,0 +1,60 @@
1
+ """Simple password authentication for the dashboard."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import hmac
7
+ import secrets
8
+
9
+ import bcrypt
10
+ from itsdangerous import URLSafeTimedSerializer
11
+
12
+ SESSION_COOKIE = "researchloop_session"
13
+ SESSION_MAX_AGE = 86400 * 7 # 7 days
14
+
15
+
16
+ def check_password(password: str, password_hash: str) -> bool:
17
+ """Verify a password against a bcrypt hash."""
18
+ return bcrypt.checkpw(
19
+ password.encode("utf-8"),
20
+ password_hash.encode("utf-8"),
21
+ )
22
+
23
+
24
+ def hash_password(password: str) -> str:
25
+ """Hash a password with bcrypt."""
26
+ return bcrypt.hashpw(
27
+ password.encode("utf-8"),
28
+ bcrypt.gensalt(),
29
+ ).decode("utf-8")
30
+
31
+
32
+ def generate_csrf_token(session_token: str, secret: str) -> str:
33
+ """Derive a CSRF token from the session token and signing secret."""
34
+ return hmac.new(
35
+ secret.encode(), session_token.encode(), hashlib.sha256
36
+ ).hexdigest()[:32]
37
+
38
+
39
+ def verify_csrf_token(session_token: str, secret: str, token: str) -> bool:
40
+ """Verify that *token* matches the expected CSRF token."""
41
+ expected = generate_csrf_token(session_token, secret)
42
+ return hmac.compare_digest(expected, token)
43
+
44
+
45
+ class SessionManager:
46
+ """Manage signed session cookies."""
47
+
48
+ def __init__(self, secret_key: str | None = None) -> None:
49
+ self.secret_key = secret_key or secrets.token_hex(32)
50
+ self._serializer = URLSafeTimedSerializer(self.secret_key)
51
+
52
+ def create_token(self) -> str:
53
+ return self._serializer.dumps({"authenticated": True})
54
+
55
+ def verify_token(self, token: str) -> bool:
56
+ try:
57
+ data = self._serializer.loads(token, max_age=SESSION_MAX_AGE)
58
+ return data.get("authenticated", False)
59
+ except Exception:
60
+ return False