velune-cli 0.9.3.4__tar.gz → 0.9.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.
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/.gitignore +12 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/PKG-INFO +10 -6
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/README.md +9 -3
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/docs/CHANGELOG.md +125 -1
- velune_cli-0.9.4/ext/go/cmd/velune/daemon.go +190 -0
- velune_cli-0.9.4/ext/go/cmd/velune/daemon_test.go +85 -0
- velune_cli-0.9.4/ext/go/cmd/velune/main.go +336 -0
- velune_cli-0.9.4/ext/go/cmd/velune/main_test.go +74 -0
- velune_cli-0.9.4/ext/go/cmd/velune/process_unix.go +34 -0
- velune_cli-0.9.4/ext/go/cmd/velune/process_windows.go +47 -0
- velune_cli-0.9.4/ext/go/cmd/velune/update.go +130 -0
- velune_cli-0.9.4/ext/go/cmd/velune/update_test.go +94 -0
- velune_cli-0.9.4/ext/rust/velune-native/pyproject.toml +16 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/pyproject.toml +7 -3
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/__init__.py +1 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/analysis/type_inferrer.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/app.py +57 -111
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/autocomplete.py +15 -7
- velune_cli-0.9.4/velune/cli/banner.py +205 -0
- velune_cli-0.9.4/velune/cli/command_palette.py +336 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/ask.py +8 -8
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/chat.py +8 -18
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/config.py +1 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/context.py +6 -6
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/doctor.py +19 -18
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/init.py +7 -11
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/mcp.py +1 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/memory.py +7 -7
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/models.py +8 -10
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/preflight.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/providers.py +15 -25
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/retrieval.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/run.py +8 -8
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/session.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/setup.py +7 -9
- velune_cli-0.9.4/velune/cli/commands/trust.py +73 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/usage.py +37 -34
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/workspace.py +15 -18
- velune_cli-0.9.4/velune/cli/constants.py +13 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/councilmodel_ui.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/design.py +26 -3
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/dir_browser.py +4 -4
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/display/council_view.py +16 -15
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/display/dashboard.py +50 -40
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/display/memory_view.py +3 -3
- velune_cli-0.9.4/velune/cli/display/panels.py +37 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/display/pipeline.py +3 -3
- velune_cli-0.9.4/velune/cli/display/themes.py +74 -0
- velune_cli-0.9.4/velune/cli/handlers/__init__.py +6 -0
- velune_cli-0.9.4/velune/cli/handlers/code_intel.py +164 -0
- velune_cli-0.9.4/velune/cli/handlers/cognition.py +295 -0
- velune_cli-0.9.4/velune/cli/handlers/council.py +536 -0
- velune_cli-0.9.4/velune/cli/handlers/councilmodel.py +89 -0
- velune_cli-0.9.4/velune/cli/handlers/git.py +246 -0
- velune_cli-0.9.4/velune/cli/handlers/mcp.py +160 -0
- velune_cli-0.9.4/velune/cli/handlers/memory.py +117 -0
- velune_cli-0.9.4/velune/cli/handlers/mode.py +102 -0
- velune_cli-0.9.4/velune/cli/handlers/model.py +1096 -0
- velune_cli-0.9.4/velune/cli/handlers/plugins.py +168 -0
- velune_cli-0.9.4/velune/cli/handlers/providers.py +30 -0
- velune_cli-0.9.4/velune/cli/handlers/session.py +156 -0
- velune_cli-0.9.4/velune/cli/handlers/session_mgmt.py +231 -0
- velune_cli-0.9.4/velune/cli/handlers/settings.py +796 -0
- velune_cli-0.9.4/velune/cli/handlers/workspace.py +385 -0
- velune_cli-0.9.4/velune/cli/model_prefs.py +157 -0
- velune_cli-0.9.4/velune/cli/onboarding.py +972 -0
- velune_cli-0.9.4/velune/cli/provider_ui.py +916 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/pull_ui.py +1 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/registry.py +14 -2
- velune_cli-0.9.4/velune/cli/rendering/error_panel.py +55 -0
- velune_cli-0.9.4/velune/cli/repl.py +1147 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/slash_commands.py +5 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/slash_dispatcher.py +73 -35
- velune_cli-0.9.4/velune/cli/statusbar.py +151 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/stream_renderer.py +8 -2
- velune_cli-0.9.4/velune/cli/ui.py +703 -0
- velune_cli-0.9.4/velune/cli/ui_components.py +85 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/workspaces.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/base.py +10 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/challenger.py +2 -23
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/coder.py +2 -9
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/planner.py +2 -36
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/reviewer.py +2 -24
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/synthesizer.py +2 -15
- velune_cli-0.9.4/velune/cognition/prompts/__init__.py +102 -0
- velune_cli-0.9.4/velune/cognition/prompts/_baseline.py +174 -0
- velune_cli-0.9.4/velune/cognition/prompts/_premium.example.py +27 -0
- velune_cli-0.9.4/velune/cognition/subsystems.py +49 -0
- velune_cli-0.9.4/velune/context/cache/__init__.py +22 -0
- velune_cli-0.9.4/velune/context/cache/fingerprint.py +31 -0
- velune_cli-0.9.4/velune/context/cache/manager.py +194 -0
- velune_cli-0.9.4/velune/context/cache/metrics.py +73 -0
- velune_cli-0.9.4/velune/context/cache/providers.py +210 -0
- velune_cli-0.9.4/velune/context/cache/state.py +73 -0
- velune_cli-0.9.4/velune/core/trust.py +123 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/inference.py +8 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/sandbox.py +1 -1
- velune_cli-0.9.4/velune/execution/subsystems.py +18 -0
- velune_cli-0.9.4/velune/intelligence/__init__.py +67 -0
- velune_cli-0.9.4/velune/intelligence/engine.py +370 -0
- velune_cli-0.9.4/velune/intelligence/events.py +133 -0
- velune_cli-0.9.4/velune/intelligence/graph_patcher.py +229 -0
- velune_cli-0.9.4/velune/intelligence/module.py +58 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/modules.py +11 -11
- velune_cli-0.9.4/velune/kernel/subsystems.py +18 -0
- velune_cli-0.9.4/velune/knowledge/__init__.py +57 -0
- velune_cli-0.9.4/velune/knowledge/builder.py +226 -0
- velune_cli-0.9.4/velune/knowledge/graph.py +491 -0
- velune_cli-0.9.4/velune/knowledge/module.py +49 -0
- velune_cli-0.9.4/velune/knowledge/query.py +192 -0
- velune_cli-0.9.4/velune/knowledge/schemas.py +64 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/registry.py +27 -8
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/server.py +105 -6
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/__init__.py +6 -0
- velune_cli-0.9.4/velune/memory/module.py +257 -0
- velune_cli-0.9.4/velune/memory/three_brain.py +284 -0
- velune_cli-0.9.4/velune/models/subsystems.py +21 -0
- velune_cli-0.9.4/velune/observability/subsystems.py +60 -0
- velune_cli-0.9.4/velune/orchestration/subsystems.py +15 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/anthropic.py +53 -41
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/gpu.py +1 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/module.py +12 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/ollama_manager.py +2 -2
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/registry.py +99 -23
- velune_cli-0.9.4/velune/providers/subsystems.py +65 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/validation.py +3 -13
- velune_cli-0.9.4/velune/repository/_native.py +105 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/context_builder.py +3 -3
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/git_context.py +47 -58
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/grapher.py +6 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/indexer.py +6 -11
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/scanner.py +15 -13
- velune_cli-0.9.4/velune/repository/subsystems.py +17 -0
- velune_cli-0.9.4/velune/retrieval/subsystems.py +59 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/doctor.py +4 -4
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/usage_tracker.py +46 -6
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/base/tool.py +36 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/filesystem/read.py +7 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/filesystem/write.py +13 -4
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/git/history.py +90 -37
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/git/operations.py +31 -16
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/git/providers.py +35 -35
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/git/state.py +46 -30
- velune_cli-0.9.4/velune/tools/subsystems.py +81 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/terminal/execute.py +4 -1
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/web/fetch.py +4 -1
- velune_cli-0.9.3.4/velune/cli/banner.py +0 -269
- velune_cli-0.9.3.4/velune/cli/display/panels.py +0 -35
- velune_cli-0.9.3.4/velune/cli/display/themes.py +0 -29
- velune_cli-0.9.3.4/velune/cli/model_prefs.py +0 -66
- velune_cli-0.9.3.4/velune/cli/rendering/error_panel.py +0 -79
- velune_cli-0.9.3.4/velune/cli/repl.py +0 -4491
- velune_cli-0.9.3.4/velune/cli/statusbar.py +0 -168
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/LICENSE +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/__main__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/_compat.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/analysis/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/analysis/linter.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/analysis/refactor.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/analysis/symbol_search.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/base.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/daemon.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/file_commands.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/commands/trace.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/context.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/display/progress.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/interrupts.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/main.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/model_selector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/modes.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/picker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/rendering/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/rendering/markdown.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/session_manager.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/sessions.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/theme.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cli/validators.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/agents/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/agents/coder.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/agents/planner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/agents/reviewer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/arbitrator.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/architecture.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/budget.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/consensus.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/critic_agent.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/critic_configs.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/critics.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/debate.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/factory.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/messages.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/sampling.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/scheduler.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council/tiers.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council_orchestrator.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/council_runner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/firewall.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/intent.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/orchestrator.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/personality.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/state.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/style_resolver.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/cognition/verification.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/assembler.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/budget.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/extractive.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/mentions.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/prompt_adaptation.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/sections.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/token_counter.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/utilization.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/context/window.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/background.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/config/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/catalog.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/execution.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/memory.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/orchestration.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/errors/provider.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/event_loop.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/logging.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/loop_detector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/paths.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/redaction.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/retry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/runtime.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/startup_profiler.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/task_registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/trace.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/agent.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/context.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/memory.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/model.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/provider.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/repository.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/task.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/core/types/workspace.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/daemon/client.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/daemon/server.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/daemon/transport.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/events.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/benchmarker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/cancellation.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/checkpointer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/command_spec.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/diff_preview.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/docker_sandbox.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/applier.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/base.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/search_replace.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/udiff.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/edit_formats/whole_file.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/executor.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/hunk_review.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/multi_diff.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/path_guard.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/planner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/rollback.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/execution/validator.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hardware/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hardware/detector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hardware/profiles.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hardware/quick.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/config.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/dispatcher.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/executor.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/matcher.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/hooks/types.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/integrations/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/integrations/base.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/integrations/github.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/integrations/gitlab.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/bootstrap.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/config.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/entrypoint.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/health.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/lifecycle.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/kernel/schemas.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/main.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/client.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/config.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/security.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/base.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/factory.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/http.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/sse.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/stdio.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/mcp/transports/websocket.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/compaction.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/embedding_pipeline.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/lifecycle.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/prioritizer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/storage/episodic_schema.sql +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/storage/lancedb_store.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/storage/sqlite_manager.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/storage/sqlite_pool.py +0 -0
- /velune_cli-0.9.3.4/velune/memory/module.py → /velune_cli-0.9.4/velune/memory/subsystems.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/tiers/episodic.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/tiers/graph.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/tiers/lineage.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/tiers/semantic.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/tiers/working.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/memory/vitality.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/family.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/probes.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/profile_cache.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/profiler.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/scorer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/models/specializations.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/context_report.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/format.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/retrieval_report.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/trace_log.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/trace_sink.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/observability/workspace_graph.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/orchestration/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/orchestration/engine.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/orchestration/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/orchestration/role_assignments.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/orchestration/schemas.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/agent.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/command.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/manifest.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/scanner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/declarative/skill.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/hooks.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/loader.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/manager.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/runner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/sandbox.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/plugins/schemas.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/proactive/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/proactive/alerts.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/proactive/watcher.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/cohere.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/deepseek.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/fireworks.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/google.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/groq.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/huggingface.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/llamacpp.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/lmstudio.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/mistral.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/nvidia.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/ollama.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/openai.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/openai_compat.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/openrouter.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/together.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/adapters/xai.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/base.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/benchmarker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/anthropic.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/benchmarks.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/classifier.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/fireworks.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/gguf.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/google.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/groq.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/huggingface.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/lmstudio.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/ollama.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/openai.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/openai_compat.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/openrouter.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/scanner.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/together.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/discovery/xai.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/health.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/health_monitor.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/keystore.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/local_paths.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/local_resolver.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/ollama_locations.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/ollama_store.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/router.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/providers/task_classifier.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/py.typed +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/analyzer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/api_mapper.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/architecture_detector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/ast_parser.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/blast_radius.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/boundary_classifier.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/cognition.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/commit_message.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/config_intelligence.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/import_graph.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/incremental_indexer.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/index_state.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/parser.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/project_type.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/rename_journal.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/schemas.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/symbol_registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/technology_detector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/tracker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/repository/watcher.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/cache.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/fast_path.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/graph.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/hybrid.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/keyword.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/pipeline.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/reranker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/schemas.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/slow_path.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/retrieval/vector.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/cognition.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/cost_estimator.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/debug.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/logging.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/spans.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/telemetry/token_tracker.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/__init__.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/base/registry.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/code/navigate.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/code/search.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/filesystem/ignore.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/filesystem/search.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/module.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/safety.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/terminal/history.py +0 -0
- {velune_cli-0.9.3.4 → velune_cli-0.9.4}/velune/tools/web/validator.py +0 -0
|
@@ -58,6 +58,11 @@ Thumbs.db
|
|
|
58
58
|
# Velune runtime/cache
|
|
59
59
|
.velune/
|
|
60
60
|
|
|
61
|
+
# Velune private "house" system prompts — tuned prompts ship with builds but are
|
|
62
|
+
# never committed. The committed _baseline.py guarantees a working fallback, and
|
|
63
|
+
# _premium.example.py documents the contract. (See velune/cognition/prompts/.)
|
|
64
|
+
velune/cognition/prompts/_premium.py
|
|
65
|
+
|
|
61
66
|
# Dev container
|
|
62
67
|
.devcontainer/
|
|
63
68
|
|
|
@@ -99,6 +104,13 @@ temp/
|
|
|
99
104
|
RECORD
|
|
100
105
|
installer/
|
|
101
106
|
|
|
107
|
+
# Native build artifacts
|
|
108
|
+
*.pyd
|
|
109
|
+
ext/go/*.exe
|
|
110
|
+
ext/go/**/*.exe
|
|
111
|
+
ext/go/bin/
|
|
112
|
+
ext/rust/**/target/
|
|
113
|
+
|
|
102
114
|
# Profiling
|
|
103
115
|
*.prof
|
|
104
116
|
*.lprof
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: velune-cli
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.4
|
|
4
4
|
Summary: Local-first multi-model AI developer CLI — council-based agents, persistent memory, repository cognition
|
|
5
5
|
Project-URL: Homepage, https://github.com/Surya-Hariharan/Velune-CLI
|
|
6
6
|
Project-URL: Repository, https://github.com/Surya-Hariharan/Velune-CLI
|
|
@@ -250,7 +250,6 @@ Requires-Dist: typer>=0.9.0
|
|
|
250
250
|
Provides-Extra: all
|
|
251
251
|
Requires-Dist: docker>=7.0.0; extra == 'all'
|
|
252
252
|
Requires-Dist: gguf>=0.6.0; extra == 'all'
|
|
253
|
-
Requires-Dist: gitpython>=3.1.40; extra == 'all'
|
|
254
253
|
Requires-Dist: lancedb>=0.5.0; extra == 'all'
|
|
255
254
|
Requires-Dist: opentelemetry-api>=1.22.0; extra == 'all'
|
|
256
255
|
Requires-Dist: opentelemetry-exporter-otlp>=1.22.0; extra == 'all'
|
|
@@ -277,7 +276,6 @@ Requires-Dist: docker>=7.0.0; extra == 'docker'
|
|
|
277
276
|
Provides-Extra: gguf
|
|
278
277
|
Requires-Dist: gguf>=0.6.0; extra == 'gguf'
|
|
279
278
|
Provides-Extra: git
|
|
280
|
-
Requires-Dist: gitpython>=3.1.40; extra == 'git'
|
|
281
279
|
Provides-Extra: parsing
|
|
282
280
|
Requires-Dist: tree-sitter-go>=0.21.0; extra == 'parsing'
|
|
283
281
|
Requires-Dist: tree-sitter-python>=0.21.0; extra == 'parsing'
|
|
@@ -363,6 +361,11 @@ pip install velune-cli
|
|
|
363
361
|
velune --version
|
|
364
362
|
```
|
|
365
363
|
|
|
364
|
+
The Python package is the authoritative runtime. Optional Go and Rust native
|
|
365
|
+
components live under `ext/` and are validated in CI; Velune keeps pure-Python
|
|
366
|
+
fallbacks for the Rust-backed repository helpers, so the standard PyPI install
|
|
367
|
+
works without compiling native code.
|
|
368
|
+
|
|
366
369
|
If your shell reports **`velune: command not found`** (or, on Windows,
|
|
367
370
|
*"'velune' is not recognized…"*), the install succeeded but your Python
|
|
368
371
|
scripts directory is not on `PATH`. Two reliable fixes:
|
|
@@ -676,7 +679,7 @@ Velune works as both an MCP **server** and an MCP **client**:
|
|
|
676
679
|
supported. Servers can also be declared in `.mcp.json` and loaded automatically.
|
|
677
680
|
|
|
678
681
|
Outbound connections to external MCP servers are trust-gated — see
|
|
679
|
-
[MCP trust gating](
|
|
682
|
+
[MCP trust gating](SECURITY.md#mcp-trust-gating) in the security policy.
|
|
680
683
|
|
|
681
684
|
---
|
|
682
685
|
|
|
@@ -690,9 +693,10 @@ Velune runs natively on Windows (supporting native command execution sandboxing,
|
|
|
690
693
|
|
|
691
694
|
| Doc | What's inside |
|
|
692
695
|
| --- | --- |
|
|
693
|
-
| [
|
|
694
|
-
| [
|
|
696
|
+
| [SECURITY.md](SECURITY.md) | Security posture, trust boundaries, reporting |
|
|
697
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup and contribution workflow |
|
|
695
698
|
| [docs/CHANGELOG.md](docs/CHANGELOG.md) | Full version history |
|
|
699
|
+
| [docs/RELEASE_NOTES_v0.9.4.md](docs/RELEASE_NOTES_v0.9.4.md) | v0.9.4 release notes |
|
|
696
700
|
|
|
697
701
|
---
|
|
698
702
|
|
|
@@ -67,6 +67,11 @@ pip install velune-cli
|
|
|
67
67
|
velune --version
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
The Python package is the authoritative runtime. Optional Go and Rust native
|
|
71
|
+
components live under `ext/` and are validated in CI; Velune keeps pure-Python
|
|
72
|
+
fallbacks for the Rust-backed repository helpers, so the standard PyPI install
|
|
73
|
+
works without compiling native code.
|
|
74
|
+
|
|
70
75
|
If your shell reports **`velune: command not found`** (or, on Windows,
|
|
71
76
|
*"'velune' is not recognized…"*), the install succeeded but your Python
|
|
72
77
|
scripts directory is not on `PATH`. Two reliable fixes:
|
|
@@ -380,7 +385,7 @@ Velune works as both an MCP **server** and an MCP **client**:
|
|
|
380
385
|
supported. Servers can also be declared in `.mcp.json` and loaded automatically.
|
|
381
386
|
|
|
382
387
|
Outbound connections to external MCP servers are trust-gated — see
|
|
383
|
-
[MCP trust gating](
|
|
388
|
+
[MCP trust gating](SECURITY.md#mcp-trust-gating) in the security policy.
|
|
384
389
|
|
|
385
390
|
---
|
|
386
391
|
|
|
@@ -394,9 +399,10 @@ Velune runs natively on Windows (supporting native command execution sandboxing,
|
|
|
394
399
|
|
|
395
400
|
| Doc | What's inside |
|
|
396
401
|
| --- | --- |
|
|
397
|
-
| [
|
|
398
|
-
| [
|
|
402
|
+
| [SECURITY.md](SECURITY.md) | Security posture, trust boundaries, reporting |
|
|
403
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup and contribution workflow |
|
|
399
404
|
| [docs/CHANGELOG.md](docs/CHANGELOG.md) | Full version history |
|
|
405
|
+
| [docs/RELEASE_NOTES_v0.9.4.md](docs/RELEASE_NOTES_v0.9.4.md) | v0.9.4 release notes |
|
|
400
406
|
|
|
401
407
|
---
|
|
402
408
|
|
|
@@ -9,6 +9,129 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.9.4] - 2026-06-28
|
|
13
|
+
|
|
14
|
+
### New
|
|
15
|
+
|
|
16
|
+
- Go production launcher improvements for cross-platform startup and health checks.
|
|
17
|
+
- Rust native module foundation for optional hot-path repository operations.
|
|
18
|
+
- Repository Knowledge Graph for structured file, symbol, and relationship context.
|
|
19
|
+
- Repository Intelligence Engine for repository events and incremental graph updates.
|
|
20
|
+
- Native integration layer with pure-Python fallbacks when native wheels are unavailable.
|
|
21
|
+
- Cross-platform CI covering Python, Go, Rust, packaging, install smoke tests, and native benchmarks.
|
|
22
|
+
|
|
23
|
+
### Improved
|
|
24
|
+
|
|
25
|
+
- Faster startup paths for lightweight commands and launcher-assisted execution.
|
|
26
|
+
- More reliable native integration across supported operating systems.
|
|
27
|
+
- Stronger security checks, including dependency auditing, Bandit, and Gitleaks coverage.
|
|
28
|
+
- Broader CI/CD validation before release.
|
|
29
|
+
- Expanded tests for knowledge graph, intelligence engine, memory coordination, and native fallbacks.
|
|
30
|
+
- More reproducible build and artifact validation.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Cross-platform build issues in Go and Rust CI jobs.
|
|
35
|
+
- PyO3 compatibility for Rust unit-test linkage.
|
|
36
|
+
- Native fallback behavior when the Rust extension is not installed.
|
|
37
|
+
- CI failures from synthetic secret-like test fixtures.
|
|
38
|
+
- Release workflow checks for version/tag consistency and artifact validation.
|
|
39
|
+
|
|
40
|
+
## [0.9.3.5] - 2026-06-27
|
|
41
|
+
|
|
42
|
+
> Sprint 1 AI Foundation — Repository Knowledge Graph, Intelligence Engine, and
|
|
43
|
+
> Three-Brain Memory Coordinator, plus Go launcher, Rust native extensions,
|
|
44
|
+
> and a fully hardened cross-platform CI/CD pipeline.
|
|
45
|
+
|
|
46
|
+
### Added — Repository Knowledge Graph (`velune/knowledge/`)
|
|
47
|
+
|
|
48
|
+
- **SQLite-backed semantic graph** with typed nodes (file, module, class,
|
|
49
|
+
function, method) and typed edges (imports, contains, inherits, defines).
|
|
50
|
+
WAL mode + single `asyncio.Lock` write serialization + short-lived read
|
|
51
|
+
connections keep the store fast and safe under concurrent access.
|
|
52
|
+
- **`KnowledgeGraphBuilder`** — converts a `RepositorySnapshot` into a full
|
|
53
|
+
graph in a single atomic transaction; partial failures roll back cleanly.
|
|
54
|
+
- **`KnowledgeQuery`** — AI-optimized query layer: `context_for_file`,
|
|
55
|
+
`find_by_label`, `summary_text`. Output is designed for direct LLM injection
|
|
56
|
+
without post-processing.
|
|
57
|
+
|
|
58
|
+
### Added — Repository Intelligence Engine (`velune/intelligence/`)
|
|
59
|
+
|
|
60
|
+
- **Central coordinator** with event-driven change detection (3 s file-change
|
|
61
|
+
poll) and git-state tracking (10 s interval). All events ride `CognitiveBus`.
|
|
62
|
+
- **`KnowledgeGraphPatcher`** — surgical incremental node/edge updates via
|
|
63
|
+
`FK CASCADE`; avoids full graph rebuilds on every file change.
|
|
64
|
+
- **Typed `RepositoryEventType` constants** + factory helpers for subscribers
|
|
65
|
+
(`repository.files_changed`, `index_updated`, `kg_patched`,
|
|
66
|
+
`git_state_changed`, `profile_refreshed`, `engine_started/stopped`).
|
|
67
|
+
|
|
68
|
+
### Added — Three-Brain Memory Coordinator (`velune/memory/three_brain.py`)
|
|
69
|
+
|
|
70
|
+
- **Brain 1 Hot (Working)** — in-session `MemoryTurn` store.
|
|
71
|
+
- **Brain 2 Warm (Semantic)** — LanceDB ANN search via `SemanticMemory`.
|
|
72
|
+
- **Brain 3 Cold (Episodic)** — SQLite cross-session LIKE search via
|
|
73
|
+
`EpisodicMemory`.
|
|
74
|
+
- `asyncio.gather` fan-out across all three brains; `KnowledgeQuery` augments
|
|
75
|
+
warm-brain results with graph context.
|
|
76
|
+
- Subscribes to `repository.files_changed` → annotates `ThreeBrainResult`
|
|
77
|
+
with `stale_file_count`.
|
|
78
|
+
- `as_context_block()` renders compact, LLM-injectable text; registered as
|
|
79
|
+
`runtime.three_brain_coordinator`.
|
|
80
|
+
|
|
81
|
+
### Added — Go Launcher (`ext/go/`)
|
|
82
|
+
|
|
83
|
+
- Cross-platform Go launcher binary (`velune` executable) that discovers the
|
|
84
|
+
correct Python interpreter (sibling `.venv` → `VIRTUAL_ENV` → PATH), relays
|
|
85
|
+
OS signals (SIGINT/SIGTERM) to the child Python process, and manages the
|
|
86
|
+
Velune daemon lifecycle (`start` / `stop` / `status`).
|
|
87
|
+
- **`velune update`** — queries PyPI (`velune-cli`) for the latest version and
|
|
88
|
+
upgrades via pip if a newer release exists (`--check` mode for scripts).
|
|
89
|
+
- **`velune --health`** — structured health check: Python binary, Python
|
|
90
|
+
version, `velune` module importability, launcher version.
|
|
91
|
+
- Full test suite: version parsing, Python discovery, daemon PID file handling,
|
|
92
|
+
process-alive checks, PyPI mock server tests.
|
|
93
|
+
|
|
94
|
+
### Added — Rust Native Extensions (`ext/rust/velune-native/`)
|
|
95
|
+
|
|
96
|
+
- **`sha256_file(path)`** — SHA-256 hex digest of a file; O(1) memory via
|
|
97
|
+
64 KB streaming buffer; raises `OSError` on unreadable files.
|
|
98
|
+
- **`scan_directory(root, extensions, skip_names)`** — recursive directory
|
|
99
|
+
walker with extension filtering and directory pruning; returns sorted
|
|
100
|
+
absolute paths.
|
|
101
|
+
- Pure-Python fallbacks in `velune/repository/_native.py` — all callers use the
|
|
102
|
+
same API regardless of whether the Rust wheel is installed.
|
|
103
|
+
- Unit tests covering determinism, empty files, missing files, directory
|
|
104
|
+
skipping, and cross-implementation parity.
|
|
105
|
+
|
|
106
|
+
### Added — CI/CD
|
|
107
|
+
|
|
108
|
+
- **Go Launcher** jobs (ubuntu / windows / macos): `go build`, `go test -v`,
|
|
109
|
+
`go vet` for the full launcher package.
|
|
110
|
+
- **Rust Native** jobs (ubuntu / windows / macos): `cargo fmt --check`,
|
|
111
|
+
`cargo clippy -D warnings`, `cargo build --lib`, `cargo test --lib`.
|
|
112
|
+
- **Native benchmarks** (`benchmark-native`, `benchmark-scan`): build the
|
|
113
|
+
Rust wheel via maturin, install it, run sha256 and scan_directory benchmarks,
|
|
114
|
+
upload JSON results as artifacts (informational — never gates on perf
|
|
115
|
+
thresholds since CI hardware is shared and variable).
|
|
116
|
+
- **Wheel install + REPL smoke** matrix expanded to 3 OS × 4 Python versions
|
|
117
|
+
(3.10 – 3.13).
|
|
118
|
+
- **`ci-pass` gate job** — requires all matrix jobs before reporting green.
|
|
119
|
+
|
|
120
|
+
### Fixed
|
|
121
|
+
|
|
122
|
+
- Benchmark jobs no longer use `--ci` performance-threshold mode; benchmarks
|
|
123
|
+
are informational in CI and will never fail due to machine variance.
|
|
124
|
+
- Go setup action no longer references a nonexistent `go.sum` (this project has
|
|
125
|
+
no external Go dependencies — all imports are stdlib).
|
|
126
|
+
- Rust `crate-type` now includes `rlib` alongside `cdylib` so that
|
|
127
|
+
`cargo test --lib` can link the Rust test harness without a Python runtime.
|
|
128
|
+
- `velune update` PyPI URL corrected from `/pypi/velune/` to `/pypi/velune-cli/`.
|
|
129
|
+
|
|
130
|
+
### Tests
|
|
131
|
+
|
|
132
|
+
- 139 tests passing — 42 new for Three-Brain Memory, 41 for Intelligence Engine,
|
|
133
|
+
41 for Knowledge Graph, plus cross-platform CI matrix (3 OS × 4 Python).
|
|
134
|
+
|
|
12
135
|
## [0.9.3] - 2026-06-24
|
|
13
136
|
|
|
14
137
|
> Promotes `0.9.3-beta.1` to a stable release and lands a command-architecture
|
|
@@ -694,7 +817,8 @@ changes — `pip install --upgrade velune-cli` is a safe, drop-in update.
|
|
|
694
817
|
- Security sandbox: workspace write guards, network hygiene, secret scrubbing
|
|
695
818
|
- Full pytest suite: unit, integration, async, and benchmark tests
|
|
696
819
|
|
|
697
|
-
[Unreleased]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.
|
|
820
|
+
[Unreleased]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.4...HEAD
|
|
821
|
+
[0.9.4]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.3.5...v0.9.4
|
|
698
822
|
[0.9.3-beta.1]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.2...v0.9.3-beta.1
|
|
699
823
|
[0.9.2]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.1...v0.9.2
|
|
700
824
|
[0.9.1]: https://github.com/Surya-Hariharan/Velune-CLI/compare/v0.9.0...v0.9.1
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
// Daemon lifecycle management.
|
|
4
|
+
//
|
|
5
|
+
// Go owns the process lifecycle: starting, stopping, and health-checking the
|
|
6
|
+
// Python daemon process. Python owns everything inside that process: the IPC
|
|
7
|
+
// protocol, AI orchestration, and business logic.
|
|
8
|
+
//
|
|
9
|
+
// The daemon is identified by a PID file at ~/.velune/daemon.pid. Go never
|
|
10
|
+
// reads or speaks the IPC wire format — that belongs to Python.
|
|
11
|
+
|
|
12
|
+
import (
|
|
13
|
+
"errors"
|
|
14
|
+
"fmt"
|
|
15
|
+
"os"
|
|
16
|
+
"os/exec"
|
|
17
|
+
"path/filepath"
|
|
18
|
+
"strconv"
|
|
19
|
+
"strings"
|
|
20
|
+
"time"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// runDaemonCommand dispatches daemon sub-commands.
|
|
24
|
+
// velune daemon start [workspace]
|
|
25
|
+
// velune daemon stop
|
|
26
|
+
// velune daemon status
|
|
27
|
+
func runDaemonCommand(action string, rest []string) {
|
|
28
|
+
switch action {
|
|
29
|
+
case "start":
|
|
30
|
+
workspace := "."
|
|
31
|
+
if len(rest) > 0 {
|
|
32
|
+
workspace = rest[0]
|
|
33
|
+
}
|
|
34
|
+
if err := daemonStart(workspace); err != nil {
|
|
35
|
+
fmt.Fprintf(os.Stderr, "velune daemon: start failed: %v\n", err)
|
|
36
|
+
os.Exit(1)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
case "stop":
|
|
40
|
+
if err := daemonStop(); err != nil {
|
|
41
|
+
fmt.Fprintf(os.Stderr, "velune daemon: stop failed: %v\n", err)
|
|
42
|
+
os.Exit(1)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
case "status":
|
|
46
|
+
daemonStatus()
|
|
47
|
+
|
|
48
|
+
default:
|
|
49
|
+
fmt.Fprintf(os.Stderr, "velune daemon: unknown action %q\n", action)
|
|
50
|
+
fmt.Fprintln(os.Stderr, "usage: velune daemon <start|stop|status> [workspace]")
|
|
51
|
+
os.Exit(1)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ─── Start ────────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
func daemonStart(workspace string) error {
|
|
58
|
+
pidFile := daemonPidFile()
|
|
59
|
+
|
|
60
|
+
// If already running, report and exit cleanly.
|
|
61
|
+
if pid, err := readPid(pidFile); err == nil {
|
|
62
|
+
if processAlive(pid) {
|
|
63
|
+
fmt.Printf("velune daemon: already running (pid %d)\n", pid)
|
|
64
|
+
return nil
|
|
65
|
+
}
|
|
66
|
+
// Stale PID — clean it up before starting fresh.
|
|
67
|
+
_ = os.Remove(pidFile)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
python := discoverPython()
|
|
71
|
+
|
|
72
|
+
// Resolve workspace to an absolute path so the daemon process always has a
|
|
73
|
+
// stable working path regardless of where the launcher is invoked from.
|
|
74
|
+
absWorkspace, err := filepath.Abs(workspace)
|
|
75
|
+
if err != nil {
|
|
76
|
+
return fmt.Errorf("resolve workspace: %w", err)
|
|
77
|
+
}
|
|
78
|
+
if _, err := os.Stat(absWorkspace); err != nil {
|
|
79
|
+
return fmt.Errorf("workspace %q does not exist", absWorkspace)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
cmd := exec.Command(python, "-m", "velune.daemon.server", absWorkspace)
|
|
83
|
+
cmd.Env = os.Environ()
|
|
84
|
+
|
|
85
|
+
// Detach from the terminal so the daemon survives after the launcher exits.
|
|
86
|
+
setProcAttr(cmd)
|
|
87
|
+
|
|
88
|
+
if err := cmd.Start(); err != nil {
|
|
89
|
+
return fmt.Errorf("spawn: %w", err)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
pid := cmd.Process.Pid
|
|
93
|
+
fmt.Printf("velune daemon: started (pid %d, workspace %s)\n", pid, absWorkspace)
|
|
94
|
+
|
|
95
|
+
// The Python daemon writes its own PID file once it is ready. Poll for it
|
|
96
|
+
// so we can confirm a successful start before returning.
|
|
97
|
+
deadline := time.Now().Add(5 * time.Second)
|
|
98
|
+
for time.Now().Before(deadline) {
|
|
99
|
+
if _, err := readPid(pidFile); err == nil {
|
|
100
|
+
fmt.Println("velune daemon: ready")
|
|
101
|
+
return nil
|
|
102
|
+
}
|
|
103
|
+
time.Sleep(100 * time.Millisecond)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Daemon did not write PID file in time — may still be starting up.
|
|
107
|
+
fmt.Fprintf(os.Stderr,
|
|
108
|
+
"velune daemon: warning: PID file not seen after 5s (pid %d may still be starting)\n", pid)
|
|
109
|
+
return nil
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ─── Stop ─────────────────────────────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
func daemonStop() error {
|
|
115
|
+
pidFile := daemonPidFile()
|
|
116
|
+
pid, err := readPid(pidFile)
|
|
117
|
+
if err != nil {
|
|
118
|
+
fmt.Println("velune daemon: not running")
|
|
119
|
+
return nil
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
proc, err := os.FindProcess(pid)
|
|
123
|
+
if err != nil || !processAlive(pid) {
|
|
124
|
+
fmt.Println("velune daemon: not running (stale PID file removed)")
|
|
125
|
+
_ = os.Remove(pidFile)
|
|
126
|
+
return nil
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Graceful shutdown first.
|
|
130
|
+
if err := gracefulStop(proc); err != nil {
|
|
131
|
+
return fmt.Errorf("signal: %w", err)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Wait up to 5 s for clean exit.
|
|
135
|
+
deadline := time.Now().Add(5 * time.Second)
|
|
136
|
+
for time.Now().Before(deadline) {
|
|
137
|
+
if !processAlive(pid) {
|
|
138
|
+
_ = os.Remove(pidFile)
|
|
139
|
+
fmt.Println("velune daemon: stopped")
|
|
140
|
+
return nil
|
|
141
|
+
}
|
|
142
|
+
time.Sleep(100 * time.Millisecond)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Force-kill if still alive.
|
|
146
|
+
_ = proc.Kill()
|
|
147
|
+
_ = os.Remove(pidFile)
|
|
148
|
+
fmt.Println("velune daemon: killed (did not exit cleanly)")
|
|
149
|
+
return nil
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ─── Status ───────────────────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
func daemonStatus() {
|
|
155
|
+
pidFile := daemonPidFile()
|
|
156
|
+
pid, err := readPid(pidFile)
|
|
157
|
+
if err != nil {
|
|
158
|
+
fmt.Println("velune daemon: stopped")
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if processAlive(pid) {
|
|
163
|
+
fmt.Printf("velune daemon: running (pid %d)\n", pid)
|
|
164
|
+
} else {
|
|
165
|
+
fmt.Println("velune daemon: stopped (stale PID file)")
|
|
166
|
+
_ = os.Remove(pidFile)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
func daemonPidFile() string {
|
|
173
|
+
home, err := os.UserHomeDir()
|
|
174
|
+
if err != nil {
|
|
175
|
+
home = "."
|
|
176
|
+
}
|
|
177
|
+
return filepath.Join(home, ".velune", "daemon.pid")
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
func readPid(pidFile string) (int, error) {
|
|
181
|
+
data, err := os.ReadFile(pidFile)
|
|
182
|
+
if err != nil {
|
|
183
|
+
return 0, err
|
|
184
|
+
}
|
|
185
|
+
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
|
|
186
|
+
if err != nil {
|
|
187
|
+
return 0, errors.New("malformed PID file")
|
|
188
|
+
}
|
|
189
|
+
return pid, nil
|
|
190
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strconv"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
func TestReadPid_Valid(t *testing.T) {
|
|
11
|
+
tmp := t.TempDir()
|
|
12
|
+
pidFile := filepath.Join(tmp, "daemon.pid")
|
|
13
|
+
if err := os.WriteFile(pidFile, []byte("12345\n"), 0o644); err != nil {
|
|
14
|
+
t.Fatal(err)
|
|
15
|
+
}
|
|
16
|
+
pid, err := readPid(pidFile)
|
|
17
|
+
if err != nil {
|
|
18
|
+
t.Fatalf("readPid returned error: %v", err)
|
|
19
|
+
}
|
|
20
|
+
if pid != 12345 {
|
|
21
|
+
t.Fatalf("expected 12345, got %d", pid)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func TestReadPid_Missing(t *testing.T) {
|
|
26
|
+
_, err := readPid("/nonexistent/daemon.pid")
|
|
27
|
+
if err == nil {
|
|
28
|
+
t.Fatal("expected error for missing PID file")
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func TestReadPid_Malformed(t *testing.T) {
|
|
33
|
+
tmp := t.TempDir()
|
|
34
|
+
pidFile := filepath.Join(tmp, "daemon.pid")
|
|
35
|
+
if err := os.WriteFile(pidFile, []byte("not-a-number\n"), 0o644); err != nil {
|
|
36
|
+
t.Fatal(err)
|
|
37
|
+
}
|
|
38
|
+
_, err := readPid(pidFile)
|
|
39
|
+
if err == nil {
|
|
40
|
+
t.Fatal("expected error for malformed PID file")
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func TestProcessAlive_CurrentProcess(t *testing.T) {
|
|
45
|
+
// The current process is always alive.
|
|
46
|
+
if !processAlive(os.Getpid()) {
|
|
47
|
+
t.Fatal("processAlive returned false for the current process")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func TestProcessAlive_InvalidPid(t *testing.T) {
|
|
52
|
+
// PID 0 and negative PIDs are never valid targets.
|
|
53
|
+
if processAlive(0) {
|
|
54
|
+
t.Fatal("processAlive returned true for pid 0")
|
|
55
|
+
}
|
|
56
|
+
if processAlive(-1) {
|
|
57
|
+
t.Fatal("processAlive returned true for pid -1")
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func TestDaemonPidFile(t *testing.T) {
|
|
62
|
+
path := daemonPidFile()
|
|
63
|
+
if path == "" {
|
|
64
|
+
t.Fatal("daemonPidFile returned empty string")
|
|
65
|
+
}
|
|
66
|
+
// Must end with daemon.pid
|
|
67
|
+
if filepath.Base(path) != "daemon.pid" {
|
|
68
|
+
t.Fatalf("expected daemon.pid, got %q", filepath.Base(path))
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
func TestDaemonStatus_NotRunning(t *testing.T) {
|
|
73
|
+
// Override the pid file to a temp location with no running process.
|
|
74
|
+
tmp := t.TempDir()
|
|
75
|
+
pidFile := filepath.Join(tmp, "daemon.pid")
|
|
76
|
+
// Write a PID that is guaranteed not to be a running daemon.
|
|
77
|
+
// PID 999999999 is astronomically unlikely to exist.
|
|
78
|
+
if err := os.WriteFile(pidFile, []byte(strconv.Itoa(999999999)), 0o644); err != nil {
|
|
79
|
+
t.Fatal(err)
|
|
80
|
+
}
|
|
81
|
+
// If processAlive returns false for a non-existent PID this is working correctly.
|
|
82
|
+
if processAlive(999999999) {
|
|
83
|
+
t.Skip("PID 999999999 unexpectedly exists — skipping")
|
|
84
|
+
}
|
|
85
|
+
}
|