omega-code 0.4.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 (73) hide show
  1. omega/__init__.py +0 -0
  2. omega/__main__.py +589 -0
  3. omega/artifacts.py +151 -0
  4. omega/checkpoint.py +246 -0
  5. omega/compact.py +106 -0
  6. omega/config.py +285 -0
  7. omega/eval/__init__.py +3 -0
  8. omega/eval/cli.py +127 -0
  9. omega/eval/examples/plan-version-flag.yaml +11 -0
  10. omega/eval/examples/relative-age-negative-delta.yaml +14 -0
  11. omega/eval/examples/version-flag.yaml +10 -0
  12. omega/eval/manifest.py +129 -0
  13. omega/eval/prices.py +29 -0
  14. omega/eval/report.py +135 -0
  15. omega/eval/runner.py +199 -0
  16. omega/eval/tasks.py +97 -0
  17. omega/events.py +145 -0
  18. omega/export.py +80 -0
  19. omega/gitlog.py +229 -0
  20. omega/hooks.py +63 -0
  21. omega/instructions.py +103 -0
  22. omega/integrations.py +284 -0
  23. omega/keys.py +173 -0
  24. omega/llm.py +442 -0
  25. omega/loop.py +510 -0
  26. omega/mcp.py +490 -0
  27. omega/memory/__init__.py +5 -0
  28. omega/memory/consolidate.py +103 -0
  29. omega/memory/curate.py +69 -0
  30. omega/memory/store.py +321 -0
  31. omega/memory/tools.py +175 -0
  32. omega/migrate.py +40 -0
  33. omega/onboarding.py +242 -0
  34. omega/permissions.py +137 -0
  35. omega/secrets.py +173 -0
  36. omega/server/__init__.py +7 -0
  37. omega/server/__main__.py +18 -0
  38. omega/server/app.py +71 -0
  39. omega/server/auth.py +73 -0
  40. omega/server/manager.py +287 -0
  41. omega/server/models.py +123 -0
  42. omega/server/tasks_api.py +311 -0
  43. omega/server/terminals.py +245 -0
  44. omega/server/worker.py +186 -0
  45. omega/session.py +209 -0
  46. omega/setup.html +281 -0
  47. omega/setup_server.py +452 -0
  48. omega/skills.py +158 -0
  49. omega/subagent.py +98 -0
  50. omega/tasks.py +195 -0
  51. omega/tools.py +590 -0
  52. omega/trace.py +156 -0
  53. omega/trajectory.py +146 -0
  54. omega/ui/__init__.py +0 -0
  55. omega/ui/composer.py +140 -0
  56. omega/ui/format.py +708 -0
  57. omega/ui/plain.py +141 -0
  58. omega/ui/tui/__init__.py +9 -0
  59. omega/ui/tui/app.py +958 -0
  60. omega/ui/tui/history.py +50 -0
  61. omega/ui/tui/modals.py +292 -0
  62. omega/ui/tui/onboarding.py +367 -0
  63. omega/ui/tui/prefs.py +25 -0
  64. omega/ui/tui/sidebar.py +510 -0
  65. omega/ui/tui/status.py +115 -0
  66. omega/ui/tui/theme.py +91 -0
  67. omega/ui/tui/transcript.py +783 -0
  68. omega/verify.py +133 -0
  69. omega_code-0.4.0.dist-info/METADATA +479 -0
  70. omega_code-0.4.0.dist-info/RECORD +73 -0
  71. omega_code-0.4.0.dist-info/WHEEL +4 -0
  72. omega_code-0.4.0.dist-info/entry_points.txt +2 -0
  73. omega_code-0.4.0.dist-info/licenses/LICENSE +21 -0
omega/ui/plain.py ADDED
@@ -0,0 +1,141 @@
1
+ import asyncio
2
+ from typing import Any
3
+
4
+ from rich.console import Console
5
+
6
+ from .. import events, loop, permissions, trace
7
+ from ..config import Config
8
+ from ..session import Message, Session
9
+ from . import format
10
+
11
+ _Checkpoint = getattr(events, "Checkpoint", None)
12
+ _Verified = getattr(events, "Verified", None)
13
+ _JobStarted = getattr(events, "JobStarted", None)
14
+ _JobFinished = getattr(events, "JobFinished", None)
15
+
16
+ console = Console()
17
+
18
+
19
+ async def confirm(name: str, args: dict[str, Any], why: str) -> bool:
20
+ detail = str(args.get("command") or args.get("path")
21
+ or args.get("name") or "")[:200]
22
+ console.print(f"\n[yellow]⏸ {name}[/yellow] [dim]{format.esc(why)}[/dim]")
23
+ if detail:
24
+ console.print(f" [bold]{format.esc(detail)}[/bold]", highlight=False)
25
+ try:
26
+ answer = (await asyncio.to_thread(
27
+ input, " allow? [y]es / [N]o / [a]lways: ")).strip().lower()
28
+ except (EOFError, KeyboardInterrupt):
29
+ return False
30
+ if answer == "a":
31
+ permissions.remember(permissions.rule_for(name, args), permissions.ALLOW)
32
+ return True
33
+ return answer.startswith("y")
34
+
35
+
36
+ async def ask_user(question: str, options: list[events.Option], multi_select: bool = False) -> str:
37
+ console.print(f"\n[yellow]?[/yellow] {format.esc(question)}", highlight=False)
38
+ labels = [opt.get("label", "") for opt in options]
39
+ for i, opt in enumerate(options, 1):
40
+ desc = opt.get("description", "")
41
+ line = f" {i}. {format.esc(opt.get('label', ''))}" + (f" — {format.esc(desc)}" if desc else "")
42
+ console.print(line, highlight=False)
43
+ prompt = (" answer (comma-separated numbers): " if multi_select
44
+ else " answer: ")
45
+ try:
46
+ answer = (await asyncio.to_thread(input, prompt)).strip()
47
+ except (EOFError, KeyboardInterrupt):
48
+ return "(no answer)"
49
+ if not answer:
50
+ return "(no answer)"
51
+
52
+ def resolve(token: str) -> str:
53
+ token = token.strip()
54
+ if token.isdigit() and 1 <= int(token) <= len(labels):
55
+ return labels[int(token) - 1]
56
+ return token
57
+
58
+ if multi_select:
59
+ return ", ".join(resolve(t) for t in answer.split(",") if t.strip())
60
+ return resolve(answer)
61
+
62
+
63
+ def render(ev: events.Event) -> None:
64
+ match ev:
65
+ case events.TextDelta(text=text):
66
+ console.print(text, end="", markup=False, highlight=False)
67
+ case events.ToolStart():
68
+ # Width-aware here too: `describe_call` hands over the whole
69
+ # command now (the TUI has the room to wrap it), so without a
70
+ # budget a long bash line would run past the terminal instead of
71
+ # being middle-truncated to fit.
72
+ console.print("\n" + format.tool_start(ev, width=max(20, console.width - 24)),
73
+ highlight=False)
74
+ case events.ToolEnd():
75
+ end_text = format.tool_end(ev)
76
+ if end_text is not None:
77
+ console.print(end_text, highlight=False)
78
+ case events.SubagentSpawned():
79
+ console.print("\n" + format.subagent_spawned(ev), highlight=False)
80
+ case events.SubagentDone():
81
+ console.print(format.subagent_done(ev), highlight=False)
82
+ case events.Compacted():
83
+ console.print("\n" + format.compacted(ev), highlight=False)
84
+ case events.MemoryWrite():
85
+ console.print(format.memory_write(ev), highlight=False)
86
+ case events.MemoryConsolidated():
87
+ console.print(format.memory_consolidated(ev), highlight=False)
88
+ case events.Error():
89
+ console.print("\n" + format.error(ev), highlight=False)
90
+ case events.Done():
91
+ pass
92
+ case events.Usage():
93
+ pass
94
+ case events.ModelUsed():
95
+ pass
96
+ case _ if _Checkpoint is not None and isinstance(ev, _Checkpoint):
97
+ console.print(format.checkpoint(ev), highlight=False)
98
+ case _ if _Verified is not None and isinstance(ev, _Verified):
99
+ console.print(format.verified(ev), highlight=False)
100
+ case _ if _JobStarted is not None and isinstance(ev, _JobStarted):
101
+ console.print(format.job_started(ev), highlight=False)
102
+ case _ if _JobFinished is not None and isinstance(ev, _JobFinished):
103
+ console.print(format.job_finished(ev), highlight=False)
104
+
105
+
106
+ async def run_prompt(cfg: Config, history: list[Message], prompt: str, mode: str,
107
+ sess: Session | None = None, model: str | None = None) -> None:
108
+ history.append({"role": "user", "content": prompt})
109
+
110
+ def emit(ev: events.Event) -> None:
111
+ # A rendering bug (an unescaped model string hitting rich's markup
112
+ # parser, say) must never abort the turn the model is mid-way through
113
+ # -- log it to the trace and keep going instead of letting it propagate.
114
+ try:
115
+ render(ev)
116
+ except Exception as e:
117
+ console.print(f"\n[yellow]⚠ render error: {type(e).__name__}: "
118
+ f"{format.esc(str(e)[:120])}[/yellow]", highlight=False)
119
+ if sess:
120
+ trace.append(sess.id, ev, sess.turns)
121
+ if (isinstance(ev, events.Compacted)
122
+ and not ev.note.startswith("compaction skipped")):
123
+ sess.compactions += 1
124
+
125
+ interrupted = False
126
+ try:
127
+ await loop.run_turn(cfg, history, mode=mode, emit=emit, model=model)
128
+ except KeyboardInterrupt:
129
+ # BaseException, so a bare `except Exception` misses it entirely and the
130
+ # process dies before the session is ever written.
131
+ interrupted = True
132
+ console.print("\n[dim]interrupted[/dim]")
133
+ except Exception as e:
134
+ console.print(f"\n[red]error:[/red] {type(e).__name__}: {format.esc(str(e))}")
135
+ finally:
136
+ if sess:
137
+ try:
138
+ sess.close_turn(history, mode, interrupted)
139
+ except Exception as e:
140
+ console.print(f"[red]could not save session:[/red] {format.esc(str(e))}")
141
+ console.print()
@@ -0,0 +1,9 @@
1
+ from pathlib import Path
2
+
3
+ from .app import OmegaApp
4
+
5
+ # Module-level so tests can `monkeypatch.setattr(tui, "HISTORY", tmp_path / "history")`
6
+ # before constructing an OmegaApp; app.py re-reads this via a deferred import.
7
+ HISTORY: Path = Path.home() / ".omega" / "history"
8
+
9
+ __all__ = ["OmegaApp", "HISTORY"]