onecoder 0.0.2__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 (73) hide show
  1. onecoder/agent.py +95 -0
  2. onecoder/agentic_tool_search/__init__.py +0 -0
  3. onecoder/agentic_tool_search/dynamic_tool_search.py +64 -0
  4. onecoder/agentic_tool_search/registry.py +33 -0
  5. onecoder/agents/__init__.py +7 -0
  6. onecoder/agents/documentation_agent.py +12 -0
  7. onecoder/agents/file_reader_agent.py +19 -0
  8. onecoder/agents/file_writer_agent.py +19 -0
  9. onecoder/agents/orchestrator_agent.py +51 -0
  10. onecoder/agents/refactoring_agent.py +12 -0
  11. onecoder/agents/research_agent.py +31 -0
  12. onecoder/agents/task_suggestion_agent.py +88 -0
  13. onecoder/alignment.py +236 -0
  14. onecoder/api.py +162 -0
  15. onecoder/api_client.py +112 -0
  16. onecoder/backends/base.py +22 -0
  17. onecoder/backends/local_tui.py +65 -0
  18. onecoder/blackboard.py +102 -0
  19. onecoder/cli.py +108 -0
  20. onecoder/commands/__init__.py +1 -0
  21. onecoder/commands/auth.py +78 -0
  22. onecoder/commands/ci.py +29 -0
  23. onecoder/commands/delegate.py +557 -0
  24. onecoder/commands/doctor.py +40 -0
  25. onecoder/commands/issue.py +136 -0
  26. onecoder/commands/logs.py +45 -0
  27. onecoder/commands/project.py +270 -0
  28. onecoder/commands/server.py +170 -0
  29. onecoder/config_manager.py +87 -0
  30. onecoder/constants.py +9 -0
  31. onecoder/diagnostics/__init__.py +2 -0
  32. onecoder/diagnostics/env_scan.py +207 -0
  33. onecoder/discovery.py +101 -0
  34. onecoder/distillation.py +236 -0
  35. onecoder/evaluation/__init__.py +1 -0
  36. onecoder/evaluation/ttu.py +176 -0
  37. onecoder/governance/__init__.py +0 -0
  38. onecoder/governance/probllm.py +91 -0
  39. onecoder/hooks.py +74 -0
  40. onecoder/ipc_auth.py +200 -0
  41. onecoder/issues.py +188 -0
  42. onecoder/jules_client.py +343 -0
  43. onecoder/knowledge.py +106 -0
  44. onecoder/llm.py +61 -0
  45. onecoder/logger.py +42 -0
  46. onecoder/metrics.py +129 -0
  47. onecoder/models/delegation.py +46 -0
  48. onecoder/onboarding.py +264 -0
  49. onecoder/review.py +233 -0
  50. onecoder/services/delegation_service.py +209 -0
  51. onecoder/services/validation_service.py +104 -0
  52. onecoder/sessions.py +186 -0
  53. onecoder/sprint_collector.py +165 -0
  54. onecoder/sync.py +167 -0
  55. onecoder/tmux.py +86 -0
  56. onecoder/tools/__init__.py +10 -0
  57. onecoder/tools/executor.py +53 -0
  58. onecoder/tools/external_tools.py +106 -0
  59. onecoder/tools/file_tools.py +77 -0
  60. onecoder/tools/interface.py +25 -0
  61. onecoder/tools/jules_tools.py +122 -0
  62. onecoder/tools/kit_tools.py +122 -0
  63. onecoder/tools/registry.py +32 -0
  64. onecoder/tui/__init__.py +5 -0
  65. onecoder/tui/app.py +263 -0
  66. onecoder/tui/commands.py +150 -0
  67. onecoder/tui/widgets.py +92 -0
  68. onecoder/worktree.py +186 -0
  69. onecoder-0.0.2.dist-info/METADATA +17 -0
  70. onecoder-0.0.2.dist-info/RECORD +73 -0
  71. onecoder-0.0.2.dist-info/WHEEL +5 -0
  72. onecoder-0.0.2.dist-info/entry_points.txt +2 -0
  73. onecoder-0.0.2.dist-info/top_level.txt +1 -0
onecoder/blackboard.py ADDED
@@ -0,0 +1,102 @@
1
+ import sqlite3
2
+ import json
3
+ import logging
4
+ import datetime
5
+ from pathlib import Path
6
+ from typing import Any, Optional, Dict, List
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class BlackboardMemory:
11
+ """
12
+ A SQLite-backed shared memory (Blackboard) for agents.
13
+ Allows persistent key-value storage with scoping.
14
+ """
15
+
16
+ def __init__(self, db_path: str = ".adk/blackboard.db"):
17
+ self.db_path = Path(db_path)
18
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
19
+ self._init_db()
20
+
21
+ def _init_db(self):
22
+ with sqlite3.connect(self.db_path) as conn:
23
+ conn.execute("""
24
+ CREATE TABLE IF NOT EXISTS blackboard (
25
+ scope TEXT,
26
+ namespace TEXT,
27
+ key TEXT,
28
+ value TEXT,
29
+ updated_at DATETIME,
30
+ PRIMARY KEY (scope, namespace, key)
31
+ )
32
+ """)
33
+ conn.commit()
34
+
35
+ def set(self, key: str, value: Any, scope: str = "global", namespace: str = "shared"):
36
+ """Sets a value in the blackboard."""
37
+ val_str = json.dumps(value)
38
+ now = datetime.datetime.now().isoformat()
39
+ with sqlite3.connect(self.db_path) as conn:
40
+ conn.execute("""
41
+ INSERT OR REPLACE INTO blackboard (scope, namespace, key, value, updated_at)
42
+ VALUES (?, ?, ?, ?, ?)
43
+ """, (scope, namespace, key, val_str, now))
44
+ conn.commit()
45
+
46
+ def get(self, key: str, scope: str = "global", namespace: str = "shared") -> Any:
47
+ """Gets a value from the blackboard."""
48
+ with sqlite3.connect(self.db_path) as conn:
49
+ row = conn.execute("""
50
+ SELECT value FROM blackboard WHERE scope = ? AND namespace = ? AND key = ?
51
+ """, (scope, namespace, key)).fetchone()
52
+ if row:
53
+ return json.loads(row[0])
54
+ return None
55
+
56
+ def delete(self, key: str, scope: str = "global", namespace: str = "shared"):
57
+ """Deletes a key from the blackboard."""
58
+ with sqlite3.connect(self.db_path) as conn:
59
+ conn.execute("""
60
+ DELETE FROM blackboard WHERE scope = ? AND namespace = ? AND key = ?
61
+ """, (scope, namespace, key))
62
+ conn.commit()
63
+
64
+ def list_keys(self, scope: Optional[str] = None, namespace: Optional[str] = None) -> List[Dict[str, str]]:
65
+ """Lists keys in the blackboard, optionally filtered by scope/namespace."""
66
+ query = "SELECT scope, namespace, key, updated_at FROM blackboard"
67
+ params = []
68
+ if scope and namespace:
69
+ query += " WHERE scope = ? AND namespace = ?"
70
+ params = [scope, namespace]
71
+ elif scope:
72
+ query += " WHERE scope = ?"
73
+ params = [scope]
74
+ elif namespace:
75
+ query += " WHERE namespace = ?"
76
+ params = [namespace]
77
+
78
+ with sqlite3.connect(self.db_path) as conn:
79
+ rows = conn.execute(query, params).fetchall()
80
+ return [
81
+ {"scope": r[0], "namespace": r[1], "key": r[2], "updated_at": r[3]}
82
+ for r in rows
83
+ ]
84
+
85
+ def get_all(self, scope: str = "global", namespace: str = "shared") -> Dict[str, Any]:
86
+ """Gets all key-value pairs for a specific scope and namespace."""
87
+ with sqlite3.connect(self.db_path) as conn:
88
+ rows = conn.execute("""
89
+ SELECT key, value FROM blackboard WHERE scope = ? AND namespace = ?
90
+ """, (scope, namespace)).fetchall()
91
+ return {r[0]: json.loads(r[1]) for r in rows}
92
+
93
+ if __name__ == "__main__":
94
+ # Quick test
95
+ bb = BlackboardMemory("test_blackboard.db")
96
+ bb.set("status", "scanning", scope="sprint-025")
97
+ print(f"Status: {bb.get('status', scope='sprint-025')}")
98
+ print(f"All keys: {bb.list_keys()}")
99
+ bb.delete("status", scope="sprint-025")
100
+ import os
101
+ if os.path.exists("test_blackboard.db"):
102
+ os.remove("test_blackboard.db")
onecoder/cli.py ADDED
@@ -0,0 +1,108 @@
1
+ import click
2
+ import sys
3
+ import os
4
+ from pathlib import Path
5
+ from dotenv import load_dotenv
6
+
7
+ # Load environment variables
8
+ # env_path = Path(__file__).resolve().parent.parent / ".env"
9
+ # load_dotenv(env_path)
10
+
11
+ from .commands.auth import login, logout, whoami
12
+ from .commands.server import serve, web, tui
13
+ from .commands.issue import issue
14
+ from .commands.logs import logs
15
+ from .commands.project import (
16
+ init, status, knowledge, distill, sync, alignment, sprint_suggest
17
+ )
18
+ from .commands.delegate import (
19
+ delegate, delegate_list, delegate_status, delegate_validate, delegate_finish, jules_sessions
20
+ )
21
+ from .commands.doctor import doctor
22
+ from .commands.ci import ci
23
+ from .review import CodeReviewer
24
+
25
+ from .logger import configure_logging
26
+
27
+ @click.group()
28
+ @click.version_option(version="0.0.2", prog_name="onecoder")
29
+ @click.option("--verbose", is_flag=True, help="Enable verbose logging.")
30
+ def cli(verbose):
31
+ """OneCoder: Unified Agent Architecture."""
32
+ configure_logging(verbose=verbose)
33
+
34
+ def main():
35
+ """Main entry point with telemetry wrapper."""
36
+ try:
37
+ cli()
38
+ except Exception as e:
39
+ # Don't capture Click-internal exit exceptions as failures
40
+ if isinstance(e, (click.exceptions.Exit, click.exceptions.Abort, click.exceptions.ClickException)):
41
+ raise e
42
+
43
+ from ai_sprint.telemetry import FailureModeCapture
44
+ capture = FailureModeCapture()
45
+ capture.capture(e, context={"command_args": sys.argv[1:]})
46
+ raise e
47
+
48
+ # Register Commands
49
+ def is_internal_features_enabled():
50
+ """Check if internal features should be enabled."""
51
+ return os.getenv("ONECODER_INTERNAL", "false").lower() == "true" or \
52
+ os.getenv("ONE_CODER_DEV", "false").lower() == "true"
53
+
54
+ # Register Commands
55
+ cli.add_command(login)
56
+ cli.add_command(logout)
57
+ cli.add_command(whoami)
58
+
59
+ cli.add_command(serve)
60
+ cli.add_command(web)
61
+ cli.add_command(tui)
62
+
63
+ cli.add_command(issue)
64
+ cli.add_command(logs)
65
+ cli.add_command(doctor)
66
+
67
+ cli.add_command(init)
68
+ cli.add_command(status)
69
+ cli.add_command(knowledge)
70
+ cli.add_command(distill)
71
+ cli.add_command(sync)
72
+ cli.add_command(alignment)
73
+ cli.add_command(ci)
74
+
75
+ if is_internal_features_enabled():
76
+ cli.add_command(delegate)
77
+ cli.add_command(delegate_list)
78
+ cli.add_command(delegate_status)
79
+ cli.add_command(delegate_validate)
80
+ cli.add_command(delegate_finish)
81
+ cli.add_command(jules_sessions)
82
+
83
+ @cli.command()
84
+ @click.argument("pr_id", required=False)
85
+ @click.option("--local", is_flag=True, help="Review local changes against main")
86
+ def review(pr_id, local):
87
+ """Run a policy-grounded AI review on a PR or local code."""
88
+ reviewer = CodeReviewer()
89
+ reviewer.review(pr_id=pr_id, local=local)
90
+
91
+ # Sprint Group Integration
92
+ if is_internal_features_enabled():
93
+ try:
94
+ from ai_sprint.cli import main as sprint_main
95
+ # Attempt to add the command to the existing group
96
+ if sprint_suggest not in sprint_main.commands.values():
97
+ sprint_main.add_command(sprint_suggest)
98
+ cli.add_command(sprint_main, name="sprint")
99
+ except ImportError:
100
+ @cli.group(name="sprint")
101
+ def sprint_group():
102
+ """Sprint management commands."""
103
+ pass
104
+ sprint_group.add_command(sprint_suggest)
105
+ cli.add_command(sprint_group)
106
+
107
+ if __name__ == "__main__":
108
+ cli()
@@ -0,0 +1 @@
1
+ # Command package
@@ -0,0 +1,78 @@
1
+ import click
2
+ import os
3
+ import asyncio
4
+ import webbrowser
5
+ from functools import wraps
6
+ from ..api_client import get_api_client
7
+ from ..config_manager import config_manager
8
+
9
+ def require_login(f):
10
+ """Decorator to enforce login."""
11
+ @wraps(f)
12
+ def wrapper(*args, **kwargs):
13
+ token = config_manager.get_token()
14
+ if not token:
15
+ click.echo("Error: You must be logged in to run this command.")
16
+ click.echo("Run 'onecoder login' first.")
17
+ return
18
+ return f(*args, **kwargs)
19
+ return wrapper
20
+
21
+ from ..constants import GITHUB_CLIENT_ID
22
+
23
+ @click.command()
24
+ def login():
25
+ """Authenticates with OneCoder via GitHub."""
26
+ client_id = GITHUB_CLIENT_ID
27
+
28
+ # Debug info
29
+ if client_id == "your_github_client_id":
30
+ click.secho(f"Debug: CWD is {os.getcwd()}", fg="yellow")
31
+ click.secho("Debug: GITHUB_CLIENT_ID is using placeholder!", fg="red")
32
+
33
+ auth_url = f"https://github.com/login/oauth/authorize?client_id={client_id}&scope=user:email"
34
+
35
+ click.echo("To authenticate, please visit the following URL in your browser:")
36
+ click.echo(f"\n {auth_url}\n")
37
+ click.secho("Note: If you haven't installed the OneCoder GitHub App yet, please do so from the App Profile page.", fg="yellow")
38
+
39
+ if click.confirm("Open browser automatically?", default=True):
40
+ webbrowser.open(auth_url)
41
+
42
+ code = click.prompt("Enter the authorization code provided by GitHub")
43
+
44
+ async def do_login():
45
+ try:
46
+ client = get_api_client()
47
+ result = await client.login_with_github(code)
48
+ config_manager.set_token(result["token"])
49
+ config_manager.set_user(result["user"])
50
+ click.echo(f"Successfully logged in as {result['user']['username']}!")
51
+
52
+ if "github" in result and result["github"].get("expiresIn"):
53
+ click.echo(f" (Token expires in {result['github']['expiresIn']} seconds)")
54
+
55
+ except Exception as e:
56
+ import logging
57
+ logging.exception("Login process failed")
58
+ click.echo(f"Error: Login failed: {e}")
59
+
60
+ asyncio.run(do_login())
61
+
62
+ @click.command()
63
+ def logout():
64
+ """Logs out of OneCoder."""
65
+ config_manager.clear_token()
66
+ click.echo("Successfully logged out.")
67
+
68
+ @click.command()
69
+ def whoami():
70
+ """Shows the currently authenticated user."""
71
+ user = config_manager.get_user()
72
+ if user:
73
+ click.echo(f"Logged in as: {user['username']}")
74
+ token = config_manager.get_token()
75
+ if token:
76
+ click.echo(f"Token: {token[:10]}...{token[-10:]}")
77
+ else:
78
+ click.echo("Not logged in.")
@@ -0,0 +1,29 @@
1
+ import click
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ @click.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True))
7
+ @click.argument("args", nargs=-1, type=click.UNPROCESSED)
8
+ def ci(args):
9
+ """Run local CI/CD workflows using OneCoder CI."""
10
+ # Assumption: User runs this from the repo root where `scripts/onecoder-ci.sh` exists.
11
+ # Future improvement: Auto-detect repo root.
12
+ script_path = Path("scripts/onecoder-ci.sh")
13
+
14
+ if not script_path.exists():
15
+ click.echo("❌ Error: 'scripts/onecoder-ci.sh' not found.")
16
+ click.echo(" Please run this command from the root of the 'platform' repository.")
17
+ sys.exit(1)
18
+
19
+ # Prepare command: bash scripts/onecoder-ci.sh [args]
20
+ cmd = ["bash", str(script_path)] + list(args)
21
+
22
+ try:
23
+ # Use subprocess.call or run to stream output directly
24
+ subprocess.run(cmd, check=True)
25
+ except subprocess.CalledProcessError as e:
26
+ sys.exit(e.returncode)
27
+ except Exception as e:
28
+ click.echo(f"❌ Error executing OneCoder CI: {str(e)}")
29
+ sys.exit(1)