velune-cli 0.9.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.
- velune/__init__.py +5 -0
- velune/__main__.py +6 -0
- velune/cli/__init__.py +5 -0
- velune/cli/app.py +208 -0
- velune/cli/autocomplete.py +80 -0
- velune/cli/banner.py +60 -0
- velune/cli/commands/__init__.py +32 -0
- velune/cli/commands/ask.py +175 -0
- velune/cli/commands/base.py +16 -0
- velune/cli/commands/chat.py +228 -0
- velune/cli/commands/config.py +224 -0
- velune/cli/commands/daemon.py +88 -0
- velune/cli/commands/doctor.py +721 -0
- velune/cli/commands/init.py +170 -0
- velune/cli/commands/mcp.py +82 -0
- velune/cli/commands/memory.py +293 -0
- velune/cli/commands/models.py +683 -0
- velune/cli/commands/preflight.py +95 -0
- velune/cli/commands/run.py +270 -0
- velune/cli/commands/setup.py +184 -0
- velune/cli/commands/workspace.py +249 -0
- velune/cli/context.py +36 -0
- velune/cli/councilmodel_ui.py +199 -0
- velune/cli/display/council_view.py +254 -0
- velune/cli/display/memory_view.py +126 -0
- velune/cli/display/panels.py +35 -0
- velune/cli/display/progress.py +25 -0
- velune/cli/display/themes.py +25 -0
- velune/cli/main.py +15 -0
- velune/cli/model_selector.py +51 -0
- velune/cli/modes.py +86 -0
- velune/cli/pull_ui.py +123 -0
- velune/cli/registry.py +80 -0
- velune/cli/rendering/__init__.py +5 -0
- velune/cli/rendering/error_panel.py +79 -0
- velune/cli/rendering/markdown.py +63 -0
- velune/cli/repl.py +1855 -0
- velune/cli/session_manager.py +71 -0
- velune/cli/slash_commands.py +37 -0
- velune/cli/theme.py +8 -0
- velune/cognition/__init__.py +23 -0
- velune/cognition/agents/__init__.py +7 -0
- velune/cognition/agents/coder.py +209 -0
- velune/cognition/agents/planner.py +156 -0
- velune/cognition/agents/reviewer.py +195 -0
- velune/cognition/arbitrator.py +220 -0
- velune/cognition/architecture.py +415 -0
- velune/cognition/budget.py +65 -0
- velune/cognition/council/__init__.py +47 -0
- velune/cognition/council/base.py +217 -0
- velune/cognition/council/challenger.py +74 -0
- velune/cognition/council/coder.py +79 -0
- velune/cognition/council/critic_agent.py +43 -0
- velune/cognition/council/critic_configs.py +111 -0
- velune/cognition/council/critics.py +41 -0
- velune/cognition/council/debate.py +46 -0
- velune/cognition/council/factory.py +140 -0
- velune/cognition/council/messages.py +56 -0
- velune/cognition/council/planner.py +124 -0
- velune/cognition/council/reviewer.py +74 -0
- velune/cognition/council/synthesizer.py +67 -0
- velune/cognition/council/tiers.py +188 -0
- velune/cognition/council_orchestrator.py +282 -0
- velune/cognition/firewall.py +354 -0
- velune/cognition/module.py +46 -0
- velune/cognition/orchestrator.py +1205 -0
- velune/cognition/personality.py +238 -0
- velune/cognition/state.py +104 -0
- velune/cognition/style_resolver.py +64 -0
- velune/cognition/verification.py +205 -0
- velune/context/__init__.py +28 -0
- velune/context/assembler.py +240 -0
- velune/context/budget.py +97 -0
- velune/context/extractive.py +95 -0
- velune/context/prompt_adaptation.py +480 -0
- velune/context/sections.py +99 -0
- velune/context/token_counter.py +134 -0
- velune/context/utilization.py +33 -0
- velune/context/window.py +63 -0
- velune/core/__init__.py +89 -0
- velune/core/background.py +5 -0
- velune/core/config/__init__.py +37 -0
- velune/core/errors/__init__.py +90 -0
- velune/core/errors/catalog.py +188 -0
- velune/core/errors/execution.py +31 -0
- velune/core/errors/memory.py +25 -0
- velune/core/errors/orchestration.py +31 -0
- velune/core/errors/provider.py +37 -0
- velune/core/event_loop.py +35 -0
- velune/core/logging.py +83 -0
- velune/core/paths.py +165 -0
- velune/core/runtime.py +113 -0
- velune/core/startup_profiler.py +56 -0
- velune/core/task_registry.py +117 -0
- velune/core/trace.py +83 -0
- velune/core/types/__init__.py +48 -0
- velune/core/types/agent.py +53 -0
- velune/core/types/context.py +42 -0
- velune/core/types/inference.py +38 -0
- velune/core/types/memory.py +42 -0
- velune/core/types/model.py +70 -0
- velune/core/types/provider.py +62 -0
- velune/core/types/repository.py +38 -0
- velune/core/types/task.py +61 -0
- velune/core/types/workspace.py +28 -0
- velune/daemon/client.py +13 -0
- velune/daemon/server.py +127 -0
- velune/daemon/transport.py +179 -0
- velune/events.py +204 -0
- velune/execution/__init__.py +22 -0
- velune/execution/benchmarker.py +315 -0
- velune/execution/cancellation.py +53 -0
- velune/execution/checkpointer.py +130 -0
- velune/execution/command_spec.py +165 -0
- velune/execution/diff_preview.py +197 -0
- velune/execution/executor.py +181 -0
- velune/execution/module.py +18 -0
- velune/execution/multi_diff.py +67 -0
- velune/execution/path_guard.py +74 -0
- velune/execution/planner.py +91 -0
- velune/execution/rollback.py +89 -0
- velune/execution/sandbox.py +268 -0
- velune/execution/validator.py +115 -0
- velune/hardware/__init__.py +1 -0
- velune/hardware/detector.py +192 -0
- velune/kernel/__init__.py +55 -0
- velune/kernel/bootstrap.py +125 -0
- velune/kernel/config.py +426 -0
- velune/kernel/entrypoint.py +78 -0
- velune/kernel/health.py +54 -0
- velune/kernel/lifecycle.py +143 -0
- velune/kernel/module.py +17 -0
- velune/kernel/modules.py +23 -0
- velune/kernel/registry.py +96 -0
- velune/kernel/schemas.py +28 -0
- velune/main.py +9 -0
- velune/mcp/__init__.py +9 -0
- velune/mcp/client.py +115 -0
- velune/mcp/config.py +19 -0
- velune/mcp/server.py +624 -0
- velune/memory/__init__.py +32 -0
- velune/memory/compaction.py +506 -0
- velune/memory/embedding_pipeline.py +241 -0
- velune/memory/lifecycle.py +680 -0
- velune/memory/module.py +218 -0
- velune/memory/prioritizer.py +67 -0
- velune/memory/storage/episodic_schema.sql +53 -0
- velune/memory/storage/lancedb_store.py +282 -0
- velune/memory/storage/sqlite_manager.py +369 -0
- velune/memory/storage/sqlite_pool.py +149 -0
- velune/memory/tiers/episodic.py +588 -0
- velune/memory/tiers/graph.py +378 -0
- velune/memory/tiers/lineage.py +416 -0
- velune/memory/tiers/semantic.py +475 -0
- velune/memory/tiers/working.py +168 -0
- velune/memory/vitality.py +132 -0
- velune/models/__init__.py +15 -0
- velune/models/family.py +76 -0
- velune/models/module.py +20 -0
- velune/models/probes.py +192 -0
- velune/models/profile_cache.py +84 -0
- velune/models/profiler.py +108 -0
- velune/models/registry.py +251 -0
- velune/models/scorer.py +233 -0
- velune/models/specializations.py +205 -0
- velune/orchestration/__init__.py +19 -0
- velune/orchestration/engine.py +239 -0
- velune/orchestration/module.py +15 -0
- velune/orchestration/role_assignments.py +82 -0
- velune/orchestration/schemas.py +98 -0
- velune/plugins/__init__.py +20 -0
- velune/plugins/hooks.py +50 -0
- velune/plugins/loader.py +161 -0
- velune/plugins/registry.py +56 -0
- velune/plugins/schemas.py +21 -0
- velune/providers/__init__.py +23 -0
- velune/providers/adapters/anthropic.py +257 -0
- velune/providers/adapters/fireworks.py +115 -0
- velune/providers/adapters/google.py +234 -0
- velune/providers/adapters/groq.py +151 -0
- velune/providers/adapters/huggingface.py +210 -0
- velune/providers/adapters/llamacpp.py +208 -0
- velune/providers/adapters/lmstudio.py +175 -0
- velune/providers/adapters/ollama.py +233 -0
- velune/providers/adapters/openai.py +213 -0
- velune/providers/adapters/openrouter.py +81 -0
- velune/providers/adapters/together.py +134 -0
- velune/providers/adapters/xai.py +60 -0
- velune/providers/base.py +86 -0
- velune/providers/benchmarker.py +138 -0
- velune/providers/discovery/__init__.py +33 -0
- velune/providers/discovery/anthropic.py +79 -0
- velune/providers/discovery/benchmarks.py +44 -0
- velune/providers/discovery/classifier.py +69 -0
- velune/providers/discovery/fireworks.py +95 -0
- velune/providers/discovery/gguf.py +88 -0
- velune/providers/discovery/google.py +95 -0
- velune/providers/discovery/gpu.py +117 -0
- velune/providers/discovery/groq.py +21 -0
- velune/providers/discovery/huggingface.py +67 -0
- velune/providers/discovery/lmstudio.py +80 -0
- velune/providers/discovery/ollama.py +162 -0
- velune/providers/discovery/openai.py +96 -0
- velune/providers/discovery/openrouter.py +113 -0
- velune/providers/discovery/scanner.py +115 -0
- velune/providers/discovery/together.py +114 -0
- velune/providers/discovery/xai.py +57 -0
- velune/providers/health.py +67 -0
- velune/providers/health_monitor.py +169 -0
- velune/providers/keystore.py +142 -0
- velune/providers/local_paths.py +49 -0
- velune/providers/local_resolver.py +229 -0
- velune/providers/module.py +51 -0
- velune/providers/ollama_manager.py +193 -0
- velune/providers/registry.py +220 -0
- velune/providers/router.py +255 -0
- velune/providers/task_classifier.py +288 -0
- velune/py.typed +0 -0
- velune/repository/__init__.py +33 -0
- velune/repository/analyzer.py +127 -0
- velune/repository/ast_parser.py +822 -0
- velune/repository/blast_radius.py +298 -0
- velune/repository/boundary_classifier.py +295 -0
- velune/repository/cognition.py +316 -0
- velune/repository/grapher.py +179 -0
- velune/repository/import_graph.py +263 -0
- velune/repository/incremental_indexer.py +275 -0
- velune/repository/index_state.py +96 -0
- velune/repository/indexer.py +243 -0
- velune/repository/module.py +17 -0
- velune/repository/parser.py +474 -0
- velune/repository/project_type.py +300 -0
- velune/repository/rename_journal.py +287 -0
- velune/repository/scanner.py +193 -0
- velune/repository/schemas.py +102 -0
- velune/repository/symbol_registry.py +365 -0
- velune/repository/tracker.py +252 -0
- velune/retrieval/__init__.py +27 -0
- velune/retrieval/cache.py +110 -0
- velune/retrieval/fast_path.py +391 -0
- velune/retrieval/graph.py +124 -0
- velune/retrieval/hybrid.py +271 -0
- velune/retrieval/keyword.py +131 -0
- velune/retrieval/module.py +26 -0
- velune/retrieval/pipeline.py +303 -0
- velune/retrieval/reranker.py +102 -0
- velune/retrieval/schemas.py +59 -0
- velune/retrieval/slow_path.py +364 -0
- velune/retrieval/vector.py +203 -0
- velune/telemetry/__init__.py +59 -0
- velune/telemetry/cognition.py +267 -0
- velune/telemetry/cost_estimator.py +92 -0
- velune/telemetry/debug.py +304 -0
- velune/telemetry/doctor.py +244 -0
- velune/telemetry/logging.py +286 -0
- velune/telemetry/spans.py +277 -0
- velune/telemetry/token_tracker.py +140 -0
- velune/telemetry/usage_tracker.py +340 -0
- velune/tools/__init__.py +41 -0
- velune/tools/base/registry.py +87 -0
- velune/tools/base/tool.py +63 -0
- velune/tools/code/navigate.py +116 -0
- velune/tools/code/search.py +123 -0
- velune/tools/filesystem/read.py +75 -0
- velune/tools/filesystem/search.py +136 -0
- velune/tools/filesystem/write.py +163 -0
- velune/tools/git/history.py +177 -0
- velune/tools/git/operations.py +122 -0
- velune/tools/git/state.py +121 -0
- velune/tools/module.py +81 -0
- velune/tools/terminal/execute.py +72 -0
- velune/tools/terminal/history.py +47 -0
- velune/tools/web/fetch.py +55 -0
- velune/tools/web/validator.py +122 -0
- velune_cli-0.9.0.dist-info/METADATA +518 -0
- velune_cli-0.9.0.dist-info/RECORD +279 -0
- velune_cli-0.9.0.dist-info/WHEEL +4 -0
- velune_cli-0.9.0.dist-info/entry_points.txt +2 -0
- velune_cli-0.9.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Rich terminal visualization of the Reasoning Council debate, scoring, and votes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from rich.box import ROUNDED
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.panel import Panel
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
13
|
+
from velune.cognition.council.planner import TaskPlan
|
|
14
|
+
from velune.models.specializations import CouncilRole
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CouncilDisplayView:
|
|
18
|
+
"""Beautiful Rich-based UI components to visualize Reasoning Council deliberations."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, console: Console) -> None:
|
|
21
|
+
self.console = console
|
|
22
|
+
|
|
23
|
+
def render_header(self, task: str) -> None:
|
|
24
|
+
"""Display an eye-catching header for the council run."""
|
|
25
|
+
self.console.print()
|
|
26
|
+
self.console.print(
|
|
27
|
+
Panel(
|
|
28
|
+
Text.assemble(
|
|
29
|
+
(
|
|
30
|
+
"[bold magenta]VELUNE COGNITIVE OS[/bold magenta] — [cyan]Reasoning Council Active[/cyan]\n"
|
|
31
|
+
),
|
|
32
|
+
("[dim]Objective:[/dim] ", "[italic white]" + task + "[/italic white]"),
|
|
33
|
+
),
|
|
34
|
+
border_style="magenta",
|
|
35
|
+
box=ROUNDED,
|
|
36
|
+
title="[bold white]🧠 Cognitive Deliberation[/bold white]",
|
|
37
|
+
title_align="left",
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def render_role_assignments(self, assignments: dict[CouncilRole, Any]) -> None:
|
|
42
|
+
"""Render a table displaying mapped specialized models for the council."""
|
|
43
|
+
table = Table(
|
|
44
|
+
title="[bold cyan]Mapped Council Specializations[/bold cyan]",
|
|
45
|
+
box=ROUNDED,
|
|
46
|
+
border_style="dim",
|
|
47
|
+
expand=True,
|
|
48
|
+
)
|
|
49
|
+
table.add_column("Council Seat", style="bold yellow")
|
|
50
|
+
table.add_column("Provider / Endpoint", style="green")
|
|
51
|
+
table.add_column("Target Model", style="cyan")
|
|
52
|
+
table.add_column("Key Skills / Tags", style="magenta")
|
|
53
|
+
|
|
54
|
+
for role, desc in assignments.items():
|
|
55
|
+
caps = []
|
|
56
|
+
if hasattr(desc, "capabilities") and desc.capabilities:
|
|
57
|
+
for cap_name in ["coding", "reasoning", "planning", "summarization", "tool_use"]:
|
|
58
|
+
level = getattr(desc.capabilities, cap_name, None)
|
|
59
|
+
if level and level > 0:
|
|
60
|
+
caps.append(f"{cap_name} ({level.name})")
|
|
61
|
+
tags = (
|
|
62
|
+
", ".join(caps)
|
|
63
|
+
if caps
|
|
64
|
+
else ", ".join(desc.tags)
|
|
65
|
+
if getattr(desc, "tags", None)
|
|
66
|
+
else "reasoning"
|
|
67
|
+
)
|
|
68
|
+
table.add_row(role.value.upper(), desc.provider_id.capitalize(), desc.model_id, tags)
|
|
69
|
+
self.console.print(table)
|
|
70
|
+
self.console.print()
|
|
71
|
+
|
|
72
|
+
def render_step_header(self, step_name: str, agent_emoji: str = "🤖") -> None:
|
|
73
|
+
"""Draw an elegant boundary indicating a change in agent active deliberation."""
|
|
74
|
+
self.console.print(
|
|
75
|
+
f"\n[bold magenta]●[/bold magenta] [bold white]{agent_emoji} {step_name}[/bold white] is deliberating..."
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def render_planner_dag(self, plan: TaskPlan) -> None:
|
|
79
|
+
"""Render the Planner's task plan DAG as a neat hierarchical or sequential table."""
|
|
80
|
+
table = Table(
|
|
81
|
+
title="[bold yellow]Execution Plan Compiled by Council Planner[/bold yellow]",
|
|
82
|
+
box=ROUNDED,
|
|
83
|
+
border_style="yellow",
|
|
84
|
+
expand=True,
|
|
85
|
+
)
|
|
86
|
+
table.add_column("ID", style="bold cyan", width=8)
|
|
87
|
+
table.add_column("Description", style="white")
|
|
88
|
+
table.add_column("Dependencies", style="magenta")
|
|
89
|
+
table.add_column("Validation Strategy", style="green")
|
|
90
|
+
|
|
91
|
+
for step in plan.steps:
|
|
92
|
+
deps = ", ".join(step.dependencies) if step.dependencies else "[dim]None[/dim]"
|
|
93
|
+
val = step.metadata.get("test_command") or "Syntax check + File existence"
|
|
94
|
+
table.add_row(step.id, step.description, deps, str(val))
|
|
95
|
+
self.console.print(table)
|
|
96
|
+
self.console.print()
|
|
97
|
+
|
|
98
|
+
def render_code_proposal(self, code_proposal: str) -> None:
|
|
99
|
+
"""Format the coder's proposed implementation code inside a syntax-focused block."""
|
|
100
|
+
self.console.print(
|
|
101
|
+
Panel(
|
|
102
|
+
Text(code_proposal, style="green"),
|
|
103
|
+
title="[bold green]💻 Coder Proposed Patch[/bold green]",
|
|
104
|
+
border_style="green",
|
|
105
|
+
box=ROUNDED,
|
|
106
|
+
expand=True,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def render_reviewer_report(self, report: Any) -> None:
|
|
111
|
+
"""Render the Reviewer's static audit, showing passed status and critical issues."""
|
|
112
|
+
if isinstance(report, dict):
|
|
113
|
+
passed = report.get("passed", True)
|
|
114
|
+
confidence = report.get("confidence_rating", 0.8)
|
|
115
|
+
issues = report.get("critical_issues", [])
|
|
116
|
+
else:
|
|
117
|
+
passed = report.passed
|
|
118
|
+
confidence = report.confidence_rating
|
|
119
|
+
issues = report.critical_issues
|
|
120
|
+
|
|
121
|
+
status_text = (
|
|
122
|
+
"[bold green]PASS[/bold green]" if passed else "[bold red]FAIL / BLOCKED[/bold red]"
|
|
123
|
+
)
|
|
124
|
+
border_style = "green" if passed else "red"
|
|
125
|
+
|
|
126
|
+
content = []
|
|
127
|
+
content.append(f"[bold]Verification Status:[/bold] {status_text}")
|
|
128
|
+
content.append(f"[bold]Confidence Rating:[/bold] {confidence:.2f}")
|
|
129
|
+
|
|
130
|
+
if issues:
|
|
131
|
+
content.append("\n[bold red]⚠️ Critical Issues Detected:[/bold red]")
|
|
132
|
+
for issue in issues:
|
|
133
|
+
content.append(f" [red]•[/red] {issue}")
|
|
134
|
+
else:
|
|
135
|
+
content.append(
|
|
136
|
+
"\n[green]✓ Static static checks passed. No syntactical or safety concerns raised.[/green]"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
self.console.print(
|
|
140
|
+
Panel(
|
|
141
|
+
"\n".join(content),
|
|
142
|
+
title="[bold]🔍 Reviewer Audit[/bold]",
|
|
143
|
+
border_style=border_style,
|
|
144
|
+
box=ROUNDED,
|
|
145
|
+
expand=True,
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def render_challenger_report(self, report: Any) -> None:
|
|
150
|
+
"""Render the Challenger's adversarial audit and failure vector probes."""
|
|
151
|
+
if isinstance(report, dict):
|
|
152
|
+
severity = report.get("severity_rating", 0.0)
|
|
153
|
+
vectors = report.get("failure_vectors", [])
|
|
154
|
+
else:
|
|
155
|
+
severity = report.severity_rating
|
|
156
|
+
vectors = report.failure_vectors
|
|
157
|
+
|
|
158
|
+
border_style = "yellow" if severity > 0.4 else "dim"
|
|
159
|
+
|
|
160
|
+
content = []
|
|
161
|
+
content.append(
|
|
162
|
+
f"[bold]Adversarial Severity Rating:[/bold] [bold red]{severity:.2f}[/bold red] / 1.00"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if vectors:
|
|
166
|
+
content.append("\n[bold yellow]⚡ Failure Vectors Simulated:[/bold yellow]")
|
|
167
|
+
for vec in vectors:
|
|
168
|
+
content.append(f" [yellow]•[/yellow] {vec}")
|
|
169
|
+
else:
|
|
170
|
+
content.append(
|
|
171
|
+
"\n[dim]No significant failure vectors or edge-case gaps simulated.[/dim]"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
self.console.print(
|
|
175
|
+
Panel(
|
|
176
|
+
"\n".join(content),
|
|
177
|
+
title="[bold]⚡ Challenger Adversarial Check[/bold]",
|
|
178
|
+
border_style=border_style,
|
|
179
|
+
box=ROUNDED,
|
|
180
|
+
expand=True,
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def render_arbitration_result(self, res: Any) -> None:
|
|
185
|
+
"""Display calibrated confidence score, contradiction matches, and human-review flags."""
|
|
186
|
+
if isinstance(res, dict):
|
|
187
|
+
confidence = res.get("overall_confidence", 0.8)
|
|
188
|
+
review_required = res.get("requires_human_review", False)
|
|
189
|
+
flags = res.get("flags", [])
|
|
190
|
+
winning_claims = res.get("winning_claims", [])
|
|
191
|
+
synthesis_inst = res.get("synthesis_instructions", "")
|
|
192
|
+
else:
|
|
193
|
+
confidence = res.overall_confidence
|
|
194
|
+
review_required = res.requires_human_review
|
|
195
|
+
flags = res.flags
|
|
196
|
+
winning_claims = res.winning_claims
|
|
197
|
+
synthesis_inst = res.synthesis_instructions
|
|
198
|
+
|
|
199
|
+
# Color calibrated confidence based on score
|
|
200
|
+
if confidence > 0.75:
|
|
201
|
+
conf_str = f"[bold green]{confidence * 100:.1f}% (High Confidence)[/bold green]"
|
|
202
|
+
border_style = "green"
|
|
203
|
+
elif confidence > 0.55:
|
|
204
|
+
conf_str = f"[bold yellow]{confidence * 100:.1f}% (Medium Confidence)[/bold yellow]"
|
|
205
|
+
border_style = "yellow"
|
|
206
|
+
else:
|
|
207
|
+
conf_str = (
|
|
208
|
+
f"[bold red]{confidence * 100:.1f}% (Low Confidence / High Volatility)[/bold red]"
|
|
209
|
+
)
|
|
210
|
+
border_style = "red"
|
|
211
|
+
|
|
212
|
+
status_text = (
|
|
213
|
+
"[bold red]YES (Blocked / Escalate)[/bold red]"
|
|
214
|
+
if review_required
|
|
215
|
+
else "[bold green]NO (Autonomous Pass)[/bold green]"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
content = []
|
|
219
|
+
content.append(f"[bold]Calibrated Council Confidence Score:[/bold] {conf_str}")
|
|
220
|
+
content.append(f"[bold]Escalate to Human-in-the-Loop Review:[/bold] {status_text}")
|
|
221
|
+
|
|
222
|
+
if flags:
|
|
223
|
+
content.append(f"[bold red]System Flags Raised:[/bold red] {', '.join(flags)}")
|
|
224
|
+
|
|
225
|
+
if winning_claims:
|
|
226
|
+
content.append("\n[bold cyan]Winning Claims & Arbitration Compromise:[/bold cyan]")
|
|
227
|
+
for claim in winning_claims:
|
|
228
|
+
content.append(f" [cyan]✓[/cyan] {claim}")
|
|
229
|
+
|
|
230
|
+
if synthesis_inst:
|
|
231
|
+
content.append("\n[bold dim]Arbitrator Instructions for Synthesizer:[/bold dim]")
|
|
232
|
+
content.append(f"[dim]{synthesis_inst}[/dim]")
|
|
233
|
+
|
|
234
|
+
self.console.print(
|
|
235
|
+
Panel(
|
|
236
|
+
"\n".join(content),
|
|
237
|
+
title="[bold white]⚖️ Council Arbitration Engine[/bold white]",
|
|
238
|
+
border_style=border_style,
|
|
239
|
+
box=ROUNDED,
|
|
240
|
+
expand=True,
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
def render_synthesized_response(self, text: str) -> None:
|
|
245
|
+
"""Display final walker walkthrough summary and accomplishments."""
|
|
246
|
+
self.console.print(
|
|
247
|
+
Panel(
|
|
248
|
+
Text(text, style="white"),
|
|
249
|
+
title="[bold magenta]🚀 Deliberated Walkthrough & Accomplishments[/bold magenta]",
|
|
250
|
+
border_style="magenta",
|
|
251
|
+
box=ROUNDED,
|
|
252
|
+
expand=True,
|
|
253
|
+
)
|
|
254
|
+
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Rich terminal rendering of hierarchical memory tiers, priority decays, and graph entities."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from rich.box import ROUNDED
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.panel import Panel
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
from rich.tree import Tree
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MemoryDisplayView:
|
|
16
|
+
"""Beautiful Rich-based UI components to visualize Velune's 5-tier Hierarchical Memory system."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, console: Console) -> None:
|
|
19
|
+
self.console = console
|
|
20
|
+
|
|
21
|
+
def render_memory_architecture(self, stats: dict[str, Any]) -> None:
|
|
22
|
+
"""Render a magnificent visual map of the memory tiers and active index statistics."""
|
|
23
|
+
self.console.print(
|
|
24
|
+
Panel(
|
|
25
|
+
Text.assemble(
|
|
26
|
+
("[bold magenta]VELUNE CORE HIERARCHICAL MEMORY MAP[/bold magenta]\n"),
|
|
27
|
+
(
|
|
28
|
+
"[dim]Active Workspace:[/dim] [italic cyan]"
|
|
29
|
+
+ str(stats.get("workspace", "current"))
|
|
30
|
+
+ "[/italic cyan]\n\n"
|
|
31
|
+
),
|
|
32
|
+
(
|
|
33
|
+
"[bold yellow]Tier 1: Working Memory[/bold yellow] ──► In-memory state, fast lookups (TTL: "
|
|
34
|
+
+ str(stats.get("working_memory_ttl", 3600))
|
|
35
|
+
+ "s)\n"
|
|
36
|
+
),
|
|
37
|
+
(
|
|
38
|
+
"[bold green]Tier 2: Episodic SQLite[/bold green] ──► Task runs, step histories (Retention: "
|
|
39
|
+
+ str(stats.get("episodic_retention_days", 30))
|
|
40
|
+
+ " days)\n"
|
|
41
|
+
),
|
|
42
|
+
(
|
|
43
|
+
"[bold blue]Tier 3: Semantic Qdrant[/bold blue] ──► Vector code snippet indices (Similarity Threshold: "
|
|
44
|
+
+ str(stats.get("semantic_threshold", 0.85))
|
|
45
|
+
+ ")\n"
|
|
46
|
+
),
|
|
47
|
+
(
|
|
48
|
+
"[bold cyan]Tier 4: Graphiti Graph[/bold cyan] ──► Entity relationships & AST Dependency Graph (Graphiti Enabled: "
|
|
49
|
+
+ str(stats.get("graph_enabled", True))
|
|
50
|
+
+ ")\n"
|
|
51
|
+
),
|
|
52
|
+
(
|
|
53
|
+
"[bold red]Tier 5: Archive Storage[/bold red] ──► Long-term zstd-compressed cold files"
|
|
54
|
+
),
|
|
55
|
+
),
|
|
56
|
+
title="[bold white]🧠 Memory Architecture Map[/bold white]",
|
|
57
|
+
border_style="magenta",
|
|
58
|
+
box=ROUNDED,
|
|
59
|
+
title_align="left",
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def render_memory_records_table(self, records: list[dict[str, Any]], memory_type: str) -> None:
|
|
64
|
+
"""Render a structured table showing registered records across specific memory tiers."""
|
|
65
|
+
table = Table(
|
|
66
|
+
title=f"[bold green]Registered Memory Records ({memory_type.capitalize()})[/bold green]",
|
|
67
|
+
box=ROUNDED,
|
|
68
|
+
border_style="green",
|
|
69
|
+
expand=True,
|
|
70
|
+
)
|
|
71
|
+
table.add_column("Record ID / Key", style="bold cyan", width=25)
|
|
72
|
+
table.add_column("Memory Tier", style="magenta")
|
|
73
|
+
table.add_column("Importance Score", style="yellow")
|
|
74
|
+
table.add_column("Content Preview", style="white")
|
|
75
|
+
table.add_column("Age (s) / Status", style="blue")
|
|
76
|
+
|
|
77
|
+
for rec in records:
|
|
78
|
+
importance = rec.get("importance", 1.0)
|
|
79
|
+
importance_bar = "★" * int(importance * 5)
|
|
80
|
+
table.add_row(
|
|
81
|
+
rec.get("id", "N/A"),
|
|
82
|
+
rec.get("tier", memory_type),
|
|
83
|
+
f"{importance:.2f} ({importance_bar})",
|
|
84
|
+
rec.get("content_preview", ""),
|
|
85
|
+
rec.get("status", "Active"),
|
|
86
|
+
)
|
|
87
|
+
self.console.print(table)
|
|
88
|
+
self.console.print()
|
|
89
|
+
|
|
90
|
+
def render_knowledge_graph(
|
|
91
|
+
self, entities: list[dict[str, Any]], relations: list[dict[str, Any]]
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Render a beautiful hierarchical tree of knowledge graph entities and their relational links."""
|
|
94
|
+
root = Tree("[bold cyan]🌐 Graphiti Knowledge Graph Root[/bold cyan]")
|
|
95
|
+
|
|
96
|
+
# Index entities by type for rendering
|
|
97
|
+
by_type: dict[str, list[dict[str, Any]]] = {}
|
|
98
|
+
for ent in entities:
|
|
99
|
+
etype = ent.get("type", "entity").upper()
|
|
100
|
+
if etype not in by_type:
|
|
101
|
+
by_type[etype] = []
|
|
102
|
+
by_type[etype].append(ent)
|
|
103
|
+
|
|
104
|
+
for etype, items in by_type.items():
|
|
105
|
+
type_node = root.add(f"[bold yellow]🏷️ {etype}[/bold yellow]")
|
|
106
|
+
for item in items:
|
|
107
|
+
name = item.get("name", item.get("id", "Unknown"))
|
|
108
|
+
importance = item.get("importance", 1.0)
|
|
109
|
+
item_node = type_node.add(f"[cyan]{name}[/cyan] [dim](imp: {importance:.2f})[/dim]")
|
|
110
|
+
|
|
111
|
+
# Find relations where this item is the source
|
|
112
|
+
for rel in relations:
|
|
113
|
+
if rel.get("source") == item.get("id"):
|
|
114
|
+
item_node.add(
|
|
115
|
+
f"──[magenta]{rel.get('relation', 'connected')}[/magenta]──► [white]{rel.get('target')}[/white]"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
self.console.print(
|
|
119
|
+
Panel(
|
|
120
|
+
root,
|
|
121
|
+
title="[bold white]Knowledge Graph Visualization[/bold white]",
|
|
122
|
+
border_style="cyan",
|
|
123
|
+
box=ROUNDED,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
self.console.print()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Rich-based terminal panels."""
|
|
2
|
+
|
|
3
|
+
from rich.console import Console
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from rich.table import Table
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DisplayPanels:
|
|
9
|
+
"""Utility class for creating rich display panels."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, console: Console):
|
|
12
|
+
self.console = console
|
|
13
|
+
|
|
14
|
+
def info_panel(self, title: str, content: str) -> None:
|
|
15
|
+
"""Display an info panel."""
|
|
16
|
+
self.console.print(Panel(content, title=title, border_style="blue"))
|
|
17
|
+
|
|
18
|
+
def success_panel(self, title: str, content: str) -> None:
|
|
19
|
+
"""Display a success panel."""
|
|
20
|
+
self.console.print(Panel(content, title=title, border_style="green"))
|
|
21
|
+
|
|
22
|
+
def warning_panel(self, title: str, content: str) -> None:
|
|
23
|
+
"""Display a warning panel."""
|
|
24
|
+
self.console.print(Panel(content, title=title, border_style="yellow"))
|
|
25
|
+
|
|
26
|
+
def error_panel(self, title: str, content: str) -> None:
|
|
27
|
+
"""Display an error panel."""
|
|
28
|
+
self.console.print(Panel(content, title=title, border_style="red"))
|
|
29
|
+
|
|
30
|
+
def create_table(self, title: str, columns: list[str]) -> Table:
|
|
31
|
+
"""Create a rich table."""
|
|
32
|
+
table = Table(title=title)
|
|
33
|
+
for column in columns:
|
|
34
|
+
table.add_column(column)
|
|
35
|
+
return table
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Rich-based progress display."""
|
|
2
|
+
|
|
3
|
+
from rich.console import Console
|
|
4
|
+
from rich.progress import BarColumn, Progress, SpinnerColumn, TaskProgressColumn, TextColumn
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ProgressDisplay:
|
|
8
|
+
"""Utility class for displaying progress."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, console: Console):
|
|
11
|
+
self.console = console
|
|
12
|
+
|
|
13
|
+
def create_progress(self) -> Progress:
|
|
14
|
+
"""Create a rich progress bar."""
|
|
15
|
+
return Progress(
|
|
16
|
+
SpinnerColumn(),
|
|
17
|
+
TextColumn("[progress.description]{task.description}"),
|
|
18
|
+
BarColumn(),
|
|
19
|
+
TaskProgressColumn(),
|
|
20
|
+
console=self.console,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def spinner(self, description: str):
|
|
24
|
+
"""Create a spinner context manager."""
|
|
25
|
+
return self.console.status(description)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Rich terminal themes."""
|
|
2
|
+
|
|
3
|
+
from rich.theme import Theme
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VeluneTheme:
|
|
7
|
+
"""Velune CLI theme — modern, restrained color palette."""
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
def get_theme() -> Theme:
|
|
11
|
+
"""Get the Velune theme with sophisticated color choices."""
|
|
12
|
+
return Theme(
|
|
13
|
+
{
|
|
14
|
+
"info": "blue", # Primary blue for info
|
|
15
|
+
"warning": "yellow", # Warm yellow for warnings
|
|
16
|
+
"error": "red", # Clear red for errors
|
|
17
|
+
"success": "green", # Green for success
|
|
18
|
+
"title": "bold blue", # Primary blue titles
|
|
19
|
+
"subtitle": "dim blue", # Subtle secondary blue
|
|
20
|
+
"key": "dim white", # Subtle key labels
|
|
21
|
+
"value": "white", # Clear values
|
|
22
|
+
"muted": "dim", # Background/muted text
|
|
23
|
+
"accent": "#d4af37", # Warm gold accent
|
|
24
|
+
}
|
|
25
|
+
)
|
velune/cli/main.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Backward-compatible CLI entry point."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
if sys.platform == "win32":
|
|
6
|
+
try:
|
|
7
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
8
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
9
|
+
except Exception:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
from velune.cli.app import app
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
app()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from velune.cli.modes import ModeConfig
|
|
2
|
+
from velune.core.types.model import ModelDescriptor
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ModeAwareModelSelector:
|
|
6
|
+
def __init__(self, model_registry, provider_registry) -> None:
|
|
7
|
+
self.model_registry = model_registry
|
|
8
|
+
self.provider_registry = provider_registry
|
|
9
|
+
|
|
10
|
+
def select_for_mode(
|
|
11
|
+
self,
|
|
12
|
+
config: ModeConfig,
|
|
13
|
+
current_model: ModelDescriptor | None,
|
|
14
|
+
) -> ModelDescriptor | None:
|
|
15
|
+
all_models = [
|
|
16
|
+
m
|
|
17
|
+
for m in self.model_registry.list_all()
|
|
18
|
+
if self.provider_registry.get(m.provider_id) is not None
|
|
19
|
+
]
|
|
20
|
+
if not all_models:
|
|
21
|
+
return current_model
|
|
22
|
+
|
|
23
|
+
if config.use_fastest_model:
|
|
24
|
+
# Smallest context window = fastest / lightest
|
|
25
|
+
# Prefer local 3B/7B over cloud in optimus
|
|
26
|
+
local = [m for m in all_models if m.is_local]
|
|
27
|
+
pool = local if local else all_models
|
|
28
|
+
return min(pool, key=lambda m: m.context_length)
|
|
29
|
+
|
|
30
|
+
if config.use_largest_model:
|
|
31
|
+
# Largest context + highest capability score
|
|
32
|
+
def capability_score(m: ModelDescriptor) -> int:
|
|
33
|
+
caps = m.capabilities
|
|
34
|
+
if not caps:
|
|
35
|
+
return 0
|
|
36
|
+
return sum(
|
|
37
|
+
[
|
|
38
|
+
getattr(caps, f, 0).value if hasattr(getattr(caps, f, None), "value") else 0
|
|
39
|
+
for f in [
|
|
40
|
+
"coding",
|
|
41
|
+
"reasoning",
|
|
42
|
+
"planning",
|
|
43
|
+
"summarization",
|
|
44
|
+
"instruction_following",
|
|
45
|
+
]
|
|
46
|
+
]
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return max(all_models, key=capability_score)
|
|
50
|
+
|
|
51
|
+
return current_model
|
velune/cli/modes.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SessionMode(Enum):
|
|
6
|
+
NORMAL = "normal"
|
|
7
|
+
OPTIMUS = "optimus"
|
|
8
|
+
GODLY = "godly"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ModeConfig:
|
|
13
|
+
mode: SessionMode
|
|
14
|
+
council_tier: str # "instant" | "minimal" | "standard" | "full" | "auto"
|
|
15
|
+
context_compression: bool # compress context before each call
|
|
16
|
+
max_context_tokens: int # hard cap on context sent per call
|
|
17
|
+
temperature: float
|
|
18
|
+
retrieval_depth: int # how many memory + repo chunks to pull
|
|
19
|
+
use_fastest_model: bool # optimus: pick smallest capable model
|
|
20
|
+
use_largest_model: bool # godly: pick largest available model
|
|
21
|
+
disable_critics: bool # optimus: skip critic agents
|
|
22
|
+
description: str
|
|
23
|
+
prompt_color: str # Rich color for prompt badge
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
MODE_CONFIGS: dict[SessionMode, ModeConfig] = {
|
|
27
|
+
SessionMode.NORMAL: ModeConfig(
|
|
28
|
+
mode=SessionMode.NORMAL,
|
|
29
|
+
council_tier="auto",
|
|
30
|
+
context_compression=False,
|
|
31
|
+
max_context_tokens=16384,
|
|
32
|
+
temperature=0.3,
|
|
33
|
+
retrieval_depth=8,
|
|
34
|
+
use_fastest_model=False,
|
|
35
|
+
use_largest_model=False,
|
|
36
|
+
disable_critics=False,
|
|
37
|
+
description="Balanced — auto-selects council tier per task",
|
|
38
|
+
prompt_color="cyan",
|
|
39
|
+
),
|
|
40
|
+
SessionMode.OPTIMUS: ModeConfig(
|
|
41
|
+
mode=SessionMode.OPTIMUS,
|
|
42
|
+
council_tier="instant",
|
|
43
|
+
context_compression=True,
|
|
44
|
+
max_context_tokens=4096,
|
|
45
|
+
temperature=0.1,
|
|
46
|
+
retrieval_depth=3,
|
|
47
|
+
use_fastest_model=True,
|
|
48
|
+
use_largest_model=False,
|
|
49
|
+
disable_critics=True,
|
|
50
|
+
description="Speed mode — smallest model, compressed context, instant tier",
|
|
51
|
+
prompt_color="yellow",
|
|
52
|
+
),
|
|
53
|
+
SessionMode.GODLY: ModeConfig(
|
|
54
|
+
mode=SessionMode.GODLY,
|
|
55
|
+
council_tier="full",
|
|
56
|
+
context_compression=False,
|
|
57
|
+
max_context_tokens=128000,
|
|
58
|
+
temperature=0.5,
|
|
59
|
+
retrieval_depth=20,
|
|
60
|
+
use_fastest_model=False,
|
|
61
|
+
use_largest_model=True,
|
|
62
|
+
disable_critics=False,
|
|
63
|
+
description="Maximum — largest model, full context, complete council",
|
|
64
|
+
prompt_color="magenta",
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ModeManager:
|
|
70
|
+
def __init__(self) -> None:
|
|
71
|
+
self._active = SessionMode.NORMAL
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def current(self) -> SessionMode:
|
|
75
|
+
return self._active
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def config(self) -> ModeConfig:
|
|
79
|
+
return MODE_CONFIGS[self._active]
|
|
80
|
+
|
|
81
|
+
def set_mode(self, mode: SessionMode) -> ModeConfig:
|
|
82
|
+
self._active = mode
|
|
83
|
+
return self.config
|
|
84
|
+
|
|
85
|
+
def is_normal(self) -> bool:
|
|
86
|
+
return self._active == SessionMode.NORMAL
|