agent-notes 2.24.0__tar.gz → 2.25.0__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.
- {agent_notes-2.24.0 → agent_notes-2.25.0}/PKG-INFO +1 -1
- agent_notes-2.25.0/agent_notes/VERSION +1 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/cli.py +28 -6
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/config.py +23 -2
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/doctor.py +51 -17
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/hook.py +27 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/info.py +25 -2
- agent_notes-2.25.0/agent_notes/commands/install.py +225 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/regenerate.py +46 -19
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/__init__.py +42 -3
- agent_notes-2.25.0/agent_notes/commands/wizard/cost_report.py +41 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/execute.py +44 -15
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/orchestrator.py +20 -7
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/claude.yaml +1 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-7.yaml +2 -1
- agent_notes-2.25.0/agent_notes/data/models/claude-opus-4-8.yaml +15 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/reasoner.yaml +1 -1
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/cli_backend.py +9 -2
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/state.py +4 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/cli_registry.py +2 -1
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_claude_backend.py +46 -10
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/cost_report.py +16 -5
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_checks.py +17 -12
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/install_state_builder.py +36 -15
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/installer.py +46 -15
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/rendering.py +26 -18
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/state_store.py +87 -24
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/user_config.py +7 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/PKG-INFO +1 -1
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/SOURCES.txt +4 -0
- agent_notes-2.25.0/tests/unit/commands/wizard/test_cost_report_step.py +120 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_cost_report_scoping.py +10 -2
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_rendering_includes.py +5 -1
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_state_store.py +298 -0
- agent_notes-2.25.0/tests/unit/services/test_user_config_cost_report.py +330 -0
- agent_notes-2.24.0/agent_notes/VERSION +0 -1
- agent_notes-2.24.0/agent_notes/commands/install.py +0 -125
- {agent_notes-2.24.0 → agent_notes-2.25.0}/LICENSE +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/README.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/__main__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/_install_helpers.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/build.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/list.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/_common.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/migrate.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/notes.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/reset.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/transfer.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/vault.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/memory/wiki.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/set_role.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/uninstall.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/validate.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/commands/wizard/_common.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/config.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/constants.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/agents.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/analyst.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/api-reviewer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/architect.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/coder.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/database-specialist.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/debugger.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/devil.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/devops.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/explorer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/integrations.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/lead.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/performance-profiler.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/refactorer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/reviewer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/security-auditor.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/cost_reporting.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/execution.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/guardrails.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/hard_limits.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/phase0.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/pipelines.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/review.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/verification.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/shared/wiki_compile.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/system-auditor.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/tech-writer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/test-runner.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/test-writer.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/agents/wiki-compiler.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/copilot.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/cli/opencode.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/brainstorm.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/debug.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/commands/review.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-claude.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-copilot.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/global-opencode.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/hooks/session-context.md.tpl +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-haiku-4-5.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-1.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-5.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-opus-4-6.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4-5.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4-6.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/models/claude-sonnet-4.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/claude.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/opencode-index.js.template +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/plugin/opencode.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/pricing.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/orchestrator.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/scout.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/roles/worker.yaml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/rules/code-quality.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/rules/safety.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/brainstorming/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/caveman/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/code-review/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/debugging-protocol/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/compose.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/docker/dockerfile.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/git/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/grill-me/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/grill-with-docs/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/handoff/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/improve-codebase-architecture/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/ingest/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/migrate-memory/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/obsidian-memory/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/LOGIC.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/prototype/UI.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/controllers.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/frontend.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/infra.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/models.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/testing.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/rails/views.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/refactoring-protocol/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/setup-project-context/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/tdd/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/to-issues/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/to-prd/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/write-a-skill/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/skills/zoom-out/SKILL.md +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/claude.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/data/templates/frontmatter/opencode.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/doctor_checks.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/agent.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/diagnostics.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/diff.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/model.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/role.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/rule.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/domain/skill.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/_base.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/agent_registry.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/model_registry.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/role_registry.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/rule_registry.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/registries/skill_registry.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_formatting.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_opencode_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/scripts/_pricing.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/_memory_utils.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/counts.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/credentials.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_display.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diagnostics/_fix.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/diff.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/fs.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/local_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/memory_router.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/migrations/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/obsidian_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/session_context.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/settings_writer.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/ui.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/validation.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/_wiki_utils.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_index.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_ingest.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_lint.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_query.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki/wiki_storage.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes/services/wiki_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/dependency_links.txt +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/entry_points.txt +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/requires.txt +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/agent_notes.egg-info/top_level.txt +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/pyproject.toml +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/setup.cfg +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/conftest.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_config_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_doctor_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_info_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_install_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_list_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_regenerate_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_uninstall_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/commands/test_validate_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/memory/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/memory/test_memory_command.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/scripts/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/functional/scripts/test_release_script.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/build_output/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/build_output/test_build_output.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/install/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/install/test_install_methods.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/plugin_builders/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/integration/plugin_builders/test_plugin_builders.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/claude/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/claude/test_agents.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/plugins/test_skills.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_cost_report_subcommand.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_count_agents.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_info.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_add_description.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_imports.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_memory_migrate.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_imports.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_orchestrator_skip.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_preflight.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/commands/test_wizard_steps.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/registries/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/registries/test_registries.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_cost_report.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_formatting_tty.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/scripts/test_time_aggregation.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/__init__.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_build_functions.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_credential_filter.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_credentials.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_fs.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_installer_hooks.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_installer_plan.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_local_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_backend_io.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_memory_router.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_session_context.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_settings_writer.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_skill_filtering.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_validation.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_wiki_backend.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/services/test_wiki_imports.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/test_import_health.py +0 -0
- {agent_notes-2.24.0 → agent_notes-2.25.0}/tests/unit/test_memory_dir_for_backend.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.25.0
|
|
@@ -226,6 +226,12 @@ def main():
|
|
|
226
226
|
p_install.add_argument("--copy", action="store_true", help="Copy instead of symlink (with --local)")
|
|
227
227
|
p_install.add_argument("--reconfigure", action="store_true",
|
|
228
228
|
help="Clear existing state for this scope and re-run the wizard")
|
|
229
|
+
p_install.add_argument("--profile", metavar="LABEL",
|
|
230
|
+
help="Profile label for multi-subscription setups (e.g. work, personal)")
|
|
231
|
+
p_install.add_argument("--folder", metavar="DIR",
|
|
232
|
+
help="Local folder name override (e.g. .claude-work)")
|
|
233
|
+
p_install.add_argument("--global-home", metavar="DIR", dest="global_home",
|
|
234
|
+
help="Global home directory override (e.g. ~/.claude-work)")
|
|
229
235
|
|
|
230
236
|
# build
|
|
231
237
|
subparsers.add_parser("build", help="Build agent configuration files from source")
|
|
@@ -234,6 +240,11 @@ def main():
|
|
|
234
240
|
p_uninstall = subparsers.add_parser("uninstall", help="Remove installed components")
|
|
235
241
|
p_uninstall.add_argument("--local", action="store_true", help="Remove from current project only")
|
|
236
242
|
p_uninstall.add_argument("--global", action="store_true", dest="global_", help="Remove from global scope only")
|
|
243
|
+
profile_group = p_uninstall.add_mutually_exclusive_group()
|
|
244
|
+
profile_group.add_argument("--profile", metavar="LABEL",
|
|
245
|
+
help="Profile label to uninstall (e.g. work)")
|
|
246
|
+
profile_group.add_argument("--all-profiles", action="store_true",
|
|
247
|
+
help="Uninstall all profiles for the target scope")
|
|
237
248
|
|
|
238
249
|
# doctor
|
|
239
250
|
p_doctor = subparsers.add_parser("doctor", help="Check installation health")
|
|
@@ -267,6 +278,7 @@ def main():
|
|
|
267
278
|
p_regen.add_argument("--scope", choices=["global", "local"], help="Install scope")
|
|
268
279
|
p_regen.add_argument("--cli", help="Regenerate specific CLI only")
|
|
269
280
|
p_regen.add_argument("--local", action="store_true", help="Use local scope")
|
|
281
|
+
p_regen.add_argument("--profile", metavar="LABEL", help="Profile label")
|
|
270
282
|
|
|
271
283
|
# memory
|
|
272
284
|
p_memory = subparsers.add_parser("memory", help="Manage agent memory")
|
|
@@ -279,7 +291,7 @@ def main():
|
|
|
279
291
|
|
|
280
292
|
# hook
|
|
281
293
|
p_hook = subparsers.add_parser("hook", help="Claude Code hook integrations")
|
|
282
|
-
p_hook.add_argument("subaction", choices=["memory-bridge"],
|
|
294
|
+
p_hook.add_argument("subaction", choices=["memory-bridge", "session-discover"],
|
|
283
295
|
help="Hook to run")
|
|
284
296
|
|
|
285
297
|
# cost-report
|
|
@@ -290,7 +302,7 @@ def main():
|
|
|
290
302
|
# config
|
|
291
303
|
p_config = subparsers.add_parser("config", help="Reconfigure role/agent/model/memory/skill assignments after install")
|
|
292
304
|
p_config.add_argument("action", nargs="?", default="wizard",
|
|
293
|
-
choices=["wizard", "show", "role-model", "role-agent", "provider", "providers", "memory"],
|
|
305
|
+
choices=["wizard", "show", "role-model", "role-agent", "provider", "providers", "memory", "cost-report"],
|
|
294
306
|
help="Config action (default: wizard)")
|
|
295
307
|
p_config.add_argument("extra", nargs="*", help="Additional positional args (role, model, agent)")
|
|
296
308
|
p_config.add_argument("--cli", help="Target CLI (claude / opencode / both)")
|
|
@@ -311,15 +323,24 @@ def main():
|
|
|
311
323
|
from .commands.build import build
|
|
312
324
|
build()
|
|
313
325
|
elif args.command == "install":
|
|
314
|
-
if args.local or args.copy:
|
|
326
|
+
if args.local or args.copy or args.profile or args.folder or args.global_home:
|
|
315
327
|
from .commands.install import install
|
|
316
|
-
install(
|
|
328
|
+
install(
|
|
329
|
+
local=args.local, copy=args.copy, reconfigure=args.reconfigure,
|
|
330
|
+
profile_label=args.profile or "",
|
|
331
|
+
folder=args.folder or "",
|
|
332
|
+
global_home=args.global_home or "",
|
|
333
|
+
)
|
|
317
334
|
else:
|
|
318
335
|
from .commands.wizard import interactive_install
|
|
319
336
|
interactive_install()
|
|
320
337
|
elif args.command == "uninstall":
|
|
338
|
+
all_profiles = getattr(args, 'all_profiles', False)
|
|
339
|
+
profile_label = getattr(args, 'profile', '') or ""
|
|
321
340
|
from .commands.install import uninstall
|
|
322
|
-
uninstall(local=args.local, global_=args.global_
|
|
341
|
+
uninstall(local=args.local, global_=args.global_,
|
|
342
|
+
profile_label=profile_label,
|
|
343
|
+
all_profiles=all_profiles)
|
|
323
344
|
elif args.command == "doctor":
|
|
324
345
|
from .commands.doctor import doctor
|
|
325
346
|
doctor(local=args.local, fix=args.fix)
|
|
@@ -338,7 +359,8 @@ def main():
|
|
|
338
359
|
set_role(args.role_name, args.model_id, cli=args.cli, scope=args.scope, local=args.local)
|
|
339
360
|
elif args.command == "regenerate":
|
|
340
361
|
from .commands.regenerate import regenerate
|
|
341
|
-
regenerate(scope=args.scope, cli=args.cli, local=args.local
|
|
362
|
+
regenerate(scope=args.scope, cli=args.cli, local=args.local,
|
|
363
|
+
profile_label=getattr(args, 'profile', '') or "")
|
|
342
364
|
elif args.command == "memory":
|
|
343
365
|
from .commands.memory import memory
|
|
344
366
|
memory(args.action, args.name, getattr(args, "extra", None), description=getattr(args, "description", ""))
|
|
@@ -194,8 +194,13 @@ def show(state=None) -> None:
|
|
|
194
194
|
else:
|
|
195
195
|
mem_label = "Disabled"
|
|
196
196
|
|
|
197
|
+
from ..services.user_config import load_user_config
|
|
198
|
+
cost_report_enabled = load_user_config().get("cost_report_enabled", False)
|
|
199
|
+
cost_report_label = "enabled" if cost_report_enabled else "disabled"
|
|
200
|
+
|
|
197
201
|
print("Current configuration:")
|
|
198
|
-
print(f" Memory:
|
|
202
|
+
print(f" Memory: {mem_label}")
|
|
203
|
+
print(f" Cost report: {cost_report_label}")
|
|
199
204
|
|
|
200
205
|
# Scopes
|
|
201
206
|
scopes = []
|
|
@@ -465,6 +470,17 @@ def interactive_config_memory() -> None:
|
|
|
465
470
|
_wizard_memory(state, before)
|
|
466
471
|
|
|
467
472
|
|
|
473
|
+
def cost_report_toggle(value: str) -> None:
|
|
474
|
+
"""Enable or disable cost reporting in user config."""
|
|
475
|
+
from ..services.user_config import load_user_config, save_user_config
|
|
476
|
+
cfg = load_user_config()
|
|
477
|
+
cfg["cost_report_enabled"] = (value == "on")
|
|
478
|
+
save_user_config(cfg)
|
|
479
|
+
state_label = "enabled" if value == "on" else "disabled"
|
|
480
|
+
print(f"Cost reporting {state_label}.")
|
|
481
|
+
print("Run 'agent-notes regenerate' to update generated rules.")
|
|
482
|
+
|
|
483
|
+
|
|
468
484
|
# ── Entry point ──────────────────────────────────────────────────────────────
|
|
469
485
|
|
|
470
486
|
def config(action: str = "wizard", args: Optional[list] = None, cli_filter: Optional[str] = None) -> None:
|
|
@@ -497,7 +513,12 @@ def config(action: str = "wizard", args: Optional[list] = None, cli_filter: Opti
|
|
|
497
513
|
_wizard_provider_status(args[0])
|
|
498
514
|
elif action == "memory":
|
|
499
515
|
interactive_config_memory()
|
|
516
|
+
elif action == "cost-report":
|
|
517
|
+
if len(args) != 1 or args[0] not in ("on", "off"):
|
|
518
|
+
print("Usage: agent-notes config cost-report <on|off>")
|
|
519
|
+
sys.exit(1)
|
|
520
|
+
cost_report_toggle(args[0])
|
|
500
521
|
else:
|
|
501
522
|
print(f"Unknown config action: {action}")
|
|
502
|
-
print("Actions: wizard, show, role-model, role-agent, providers, provider, memory")
|
|
523
|
+
print("Actions: wizard, show, role-model, role-agent, providers, provider, memory, cost-report")
|
|
503
524
|
sys.exit(1)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Health check for agent-notes installation."""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
3
5
|
# Re-export for backward compatibility. New code should import from agent_notes.domain.
|
|
4
6
|
from ..domain.diagnostics import Issue, FixAction # noqa: F401
|
|
5
7
|
|
|
@@ -53,19 +55,33 @@ def _check_session_hook(scope: str, issues: list) -> None:
|
|
|
53
55
|
except KeyError:
|
|
54
56
|
return
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
issues.append(Issue(
|
|
59
|
-
"missing_hook",
|
|
60
|
-
str(settings_path),
|
|
61
|
-
"SessionStart hook not found — run: agent-notes install to re-add the hook",
|
|
62
|
-
))
|
|
58
|
+
from ..services.state_store import load_state, get_profiles_for_project
|
|
59
|
+
state = load_state()
|
|
63
60
|
|
|
61
|
+
# Check all profiles for the current project (local scope) or default (global)
|
|
62
|
+
backends_to_check = [claude_backend]
|
|
63
|
+
if state and scope == "local":
|
|
64
|
+
for _key, ss in get_profiles_for_project(state, Path.cwd()):
|
|
65
|
+
bs = ss.clis.get("claude")
|
|
66
|
+
if bs and bs.local_dir_override:
|
|
67
|
+
backends_to_check.append(claude_backend.with_local_dir(bs.local_dir_override))
|
|
68
|
+
|
|
69
|
+
for backend in backends_to_check:
|
|
70
|
+
settings_path, _context_file, hook_command = _session_hook_paths(backend, scope)
|
|
71
|
+
if not settings_path.exists():
|
|
72
|
+
continue
|
|
73
|
+
if not has_hook(settings_path, "SessionStart", hook_command):
|
|
74
|
+
issues.append(Issue(
|
|
75
|
+
"missing_hook",
|
|
76
|
+
str(settings_path),
|
|
77
|
+
"SessionStart hook not found — run: agent-notes install to re-add the hook",
|
|
78
|
+
))
|
|
79
|
+
|
|
80
|
+
# Memory bridge check on the default backend only
|
|
81
|
+
settings_path, _, _ = _session_hook_paths(claude_backend, scope)
|
|
64
82
|
from ..constants import Hooks
|
|
65
|
-
from ..services.state_store import load_state
|
|
66
|
-
state = load_state()
|
|
67
83
|
if state and state.memory.backend in ("obsidian", "wiki"):
|
|
68
|
-
if not has_hook(settings_path, "SessionStart", Hooks.MEMORY_BRIDGE):
|
|
84
|
+
if settings_path.exists() and not has_hook(settings_path, "SessionStart", Hooks.MEMORY_BRIDGE):
|
|
69
85
|
issues.append(Issue(
|
|
70
86
|
"missing_hook",
|
|
71
87
|
str(settings_path),
|
|
@@ -111,12 +127,31 @@ def diagnose(scope: str, fix: bool = False) -> bool:
|
|
|
111
127
|
issues = []
|
|
112
128
|
fix_actions = []
|
|
113
129
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
130
|
+
from ..services.state_store import load_current_state, get_profiles_for_project
|
|
131
|
+
from ..services.state_store import label_from_key
|
|
132
|
+
|
|
133
|
+
# For local scope, run checks against each installed profile
|
|
134
|
+
if scope == "local":
|
|
135
|
+
state = load_current_state()
|
|
136
|
+
profiles = []
|
|
137
|
+
if state:
|
|
138
|
+
profiles = get_profiles_for_project(state, Path.cwd().resolve())
|
|
139
|
+
# Fall back to default profile if none recorded
|
|
140
|
+
if not profiles:
|
|
141
|
+
profiles = [("", None)]
|
|
142
|
+
for key, _ss in profiles:
|
|
143
|
+
label = label_from_key(key, Path.cwd())
|
|
144
|
+
check_stale_files(scope, issues, fix_actions, profile_label=label)
|
|
145
|
+
check_broken_symlinks(scope, issues, fix_actions, profile_label=label)
|
|
146
|
+
check_shadowed_files(scope, issues, fix_actions, profile_label=label)
|
|
147
|
+
check_missing_files(scope, issues, fix_actions, profile_label=label)
|
|
148
|
+
check_content_drift(scope, issues, fix_actions, profile_label=label)
|
|
149
|
+
else:
|
|
150
|
+
check_stale_files(scope, issues, fix_actions)
|
|
151
|
+
check_broken_symlinks(scope, issues, fix_actions)
|
|
152
|
+
check_shadowed_files(scope, issues, fix_actions)
|
|
153
|
+
check_missing_files(scope, issues, fix_actions)
|
|
154
|
+
check_content_drift(scope, issues, fix_actions)
|
|
120
155
|
|
|
121
156
|
# Build freshness check (scope-independent)
|
|
122
157
|
check_build_freshness(issues, fix_actions)
|
|
@@ -128,7 +163,6 @@ def diagnose(scope: str, fix: bool = False) -> bool:
|
|
|
128
163
|
_check_session_hook(scope, issues)
|
|
129
164
|
|
|
130
165
|
# Print role→model assignments
|
|
131
|
-
from ..services.state_store import load_current_state
|
|
132
166
|
state = load_current_state()
|
|
133
167
|
if state is not None:
|
|
134
168
|
_check_role_models(state)
|
|
@@ -7,6 +7,33 @@ def hook(subaction: str) -> None:
|
|
|
7
7
|
"""Handle hook subactions."""
|
|
8
8
|
if subaction == "memory-bridge":
|
|
9
9
|
_memory_bridge()
|
|
10
|
+
elif subaction == "session-discover":
|
|
11
|
+
_session_discover()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _session_discover() -> None:
|
|
15
|
+
"""Discover all agent-notes profiles for the current project and emit combined context."""
|
|
16
|
+
try:
|
|
17
|
+
from ..services.state_store import load_state, get_profiles_for_project
|
|
18
|
+
from ..registries.cli_registry import load_registry
|
|
19
|
+
|
|
20
|
+
state = load_state()
|
|
21
|
+
if state is None:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
registry = load_registry()
|
|
25
|
+
default_local_dirs = {b.name: b.local_dir for b in registry.all()}
|
|
26
|
+
|
|
27
|
+
for key, scope_state in get_profiles_for_project(state, Path.cwd()):
|
|
28
|
+
for cli_name, backend_state in scope_state.clis.items():
|
|
29
|
+
local_dir = backend_state.local_dir_override or default_local_dirs.get(cli_name, ".claude")
|
|
30
|
+
context_file = Path(local_dir) / "agent-notes-context.md"
|
|
31
|
+
if context_file.exists():
|
|
32
|
+
label = scope_state.profile_label or "default"
|
|
33
|
+
print(f"<!-- agent-notes profile: {label} -->")
|
|
34
|
+
print(context_file.read_text(encoding="utf-8"))
|
|
35
|
+
except Exception:
|
|
36
|
+
return
|
|
10
37
|
|
|
11
38
|
|
|
12
39
|
def _memory_bridge() -> None:
|
|
@@ -73,10 +73,30 @@ def show_info() -> None:
|
|
|
73
73
|
else:
|
|
74
74
|
print(" Global: none")
|
|
75
75
|
|
|
76
|
+
# Named global profiles
|
|
77
|
+
if st.global_installs:
|
|
78
|
+
for label, gs in sorted(st.global_installs.items()):
|
|
79
|
+
print(f" Global [{label}]: installed {gs.installed_at}, {gs.mode}")
|
|
80
|
+
if gs.clis:
|
|
81
|
+
backend_summaries = []
|
|
82
|
+
for backend_name, bs in sorted(gs.clis.items()):
|
|
83
|
+
parts = []
|
|
84
|
+
for component_type, items in bs.installed.items():
|
|
85
|
+
if items:
|
|
86
|
+
parts.append(f"{len(items)} {component_type}")
|
|
87
|
+
if parts:
|
|
88
|
+
extra = ""
|
|
89
|
+
if bs.global_home_override:
|
|
90
|
+
extra = f", home={bs.global_home_override}"
|
|
91
|
+
backend_summaries.append(f"{backend_name} ({', '.join(parts)}{extra})")
|
|
92
|
+
if backend_summaries:
|
|
93
|
+
print(f" Storage: {', '.join(backend_summaries)}")
|
|
94
|
+
|
|
76
95
|
# Local installs
|
|
77
96
|
if st.local_installs:
|
|
78
97
|
for project_path, ls in sorted(st.local_installs.items()):
|
|
79
|
-
|
|
98
|
+
profile_hint = f" [{ls.profile_label}]" if ls.profile_label else ""
|
|
99
|
+
print(f" Local{profile_hint}: {project_path} (installed {ls.installed_at}, {ls.mode})")
|
|
80
100
|
if ls.clis:
|
|
81
101
|
backend_summaries = []
|
|
82
102
|
for backend_name, bs in sorted(ls.clis.items()):
|
|
@@ -85,7 +105,10 @@ def show_info() -> None:
|
|
|
85
105
|
if items:
|
|
86
106
|
counts.append(f"{len(items)} {component_type}")
|
|
87
107
|
if counts:
|
|
88
|
-
|
|
108
|
+
extra = ""
|
|
109
|
+
if bs.local_dir_override:
|
|
110
|
+
extra = f", folder={bs.local_dir_override}"
|
|
111
|
+
backend_summaries.append(f"{backend_name} ({', '.join(counts)}{extra})")
|
|
89
112
|
if backend_summaries:
|
|
90
113
|
print(f" Storage: {', '.join(backend_summaries)}")
|
|
91
114
|
else:
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""Install command."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from ..config import Color, PKG_DIR
|
|
6
|
+
from ..services.install_state_builder import build_install_state
|
|
7
|
+
from ..services.state_store import load_current_state, record_install_state, remove_install_state, label_from_key
|
|
8
|
+
from ._install_helpers import _verify_install
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def install(local: bool = False, copy: bool = False, reconfigure: bool = False,
|
|
12
|
+
profile_label: str = "", folder: str = "", global_home: str = "") -> None:
|
|
13
|
+
"""Build from source and install to targets."""
|
|
14
|
+
from ..services.state_store import get_scope, state_file
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
scope = "local" if local else "global"
|
|
18
|
+
project_path = Path.cwd().resolve() if local else None
|
|
19
|
+
|
|
20
|
+
# Build folder overrides from --folder / --profile
|
|
21
|
+
folder_overrides = None
|
|
22
|
+
if folder:
|
|
23
|
+
folder_overrides = {"claude": folder}
|
|
24
|
+
elif profile_label and not folder:
|
|
25
|
+
folder_overrides = {"claude": f".claude-{profile_label}"}
|
|
26
|
+
|
|
27
|
+
# Default --global-home from profile label if not explicit
|
|
28
|
+
if profile_label and not global_home:
|
|
29
|
+
global_home = f"~/.claude-{profile_label}"
|
|
30
|
+
|
|
31
|
+
state = load_current_state()
|
|
32
|
+
existing = get_scope(state, scope, project_path, profile_label=profile_label) if state else None
|
|
33
|
+
|
|
34
|
+
profile_hint = f" (profile: {profile_label})" if profile_label else ""
|
|
35
|
+
|
|
36
|
+
if existing and not reconfigure:
|
|
37
|
+
# Print existing-install summary
|
|
38
|
+
print(f"Found existing {scope} installation{profile_hint} at {state_file()}")
|
|
39
|
+
print(f" Installed: {existing.installed_at}")
|
|
40
|
+
cli_labels = []
|
|
41
|
+
from ..registries.cli_registry import load_registry
|
|
42
|
+
registry = load_registry()
|
|
43
|
+
for cli_name in existing.clis.keys():
|
|
44
|
+
try:
|
|
45
|
+
cli_labels.append(registry.get(cli_name).label)
|
|
46
|
+
except KeyError:
|
|
47
|
+
cli_labels.append(cli_name)
|
|
48
|
+
print(f" CLIs: {', '.join(cli_labels)}")
|
|
49
|
+
print(f" Mode: {existing.mode}")
|
|
50
|
+
print()
|
|
51
|
+
print("Verifying ...")
|
|
52
|
+
issues = _verify_install(existing, scope, project_path, registry)
|
|
53
|
+
if not issues:
|
|
54
|
+
print()
|
|
55
|
+
print("Installation is healthy.")
|
|
56
|
+
print()
|
|
57
|
+
print("Tip: To reinstall with different choices, run:")
|
|
58
|
+
print(" agent-notes uninstall")
|
|
59
|
+
print(" agent-notes install")
|
|
60
|
+
print()
|
|
61
|
+
print(" Or to re-run the wizard and overwrite in place:")
|
|
62
|
+
print(" agent-notes install --reconfigure")
|
|
63
|
+
else:
|
|
64
|
+
print()
|
|
65
|
+
print(f"Installation has {len(issues)} issue(s).")
|
|
66
|
+
print()
|
|
67
|
+
print("Tip: Run `agent-notes doctor --fix` to repair, or `agent-notes install --reconfigure` to rewizard.")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
if existing and reconfigure:
|
|
71
|
+
print(f"Clearing existing {scope} state{profile_hint} (--reconfigure) ...")
|
|
72
|
+
remove_install_state(scope, project_path, profile_label=profile_label)
|
|
73
|
+
# Fall through to normal install flow
|
|
74
|
+
|
|
75
|
+
# Validate args
|
|
76
|
+
if copy and not local:
|
|
77
|
+
print("Error: --copy is only valid with --local installs.")
|
|
78
|
+
print("Global installs always use symlinks.")
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
# Build first
|
|
82
|
+
print("Building from source...")
|
|
83
|
+
try:
|
|
84
|
+
from ..commands.build import build
|
|
85
|
+
build()
|
|
86
|
+
except Exception as e:
|
|
87
|
+
print(f"{Color.RED}Build failed: {e}{Color.NC}")
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
# Execute
|
|
91
|
+
label_msg = f", profile={profile_label}" if profile_label else ""
|
|
92
|
+
print(f"Installing ({'local' if local else 'global'}, {'copy' if copy else 'symlink'}{label_msg}) ...")
|
|
93
|
+
print("")
|
|
94
|
+
|
|
95
|
+
from ..services import installer
|
|
96
|
+
scope = "local" if local else "global"
|
|
97
|
+
copy_mode = copy
|
|
98
|
+
installer.install_all(scope, copy_mode,
|
|
99
|
+
folder_overrides=folder_overrides,
|
|
100
|
+
global_home_override=global_home or None)
|
|
101
|
+
|
|
102
|
+
print("")
|
|
103
|
+
print(f"{Color.GREEN}Done.{Color.NC} Restart Claude Code / OpenCode to pick up changes.")
|
|
104
|
+
|
|
105
|
+
# Record state
|
|
106
|
+
try:
|
|
107
|
+
project_path = Path.cwd() if local else None
|
|
108
|
+
st = build_install_state(
|
|
109
|
+
mode="copy" if copy else "symlink",
|
|
110
|
+
scope="local" if local else "global",
|
|
111
|
+
repo_root=PKG_DIR.parent,
|
|
112
|
+
project_path=project_path,
|
|
113
|
+
profile_label=profile_label,
|
|
114
|
+
folder_overrides=folder_overrides,
|
|
115
|
+
global_home_override=global_home or None,
|
|
116
|
+
)
|
|
117
|
+
record_install_state(st)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
print(f"{Color.YELLOW}Warning: failed to write state.json: {e}{Color.NC}")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _resolve_overrides_from_state(scope: str, project_path, profile_label: str = ""):
|
|
123
|
+
"""Read folder/global_home overrides from state.json for the target scope."""
|
|
124
|
+
from ..services.state_store import load_state, get_scope
|
|
125
|
+
|
|
126
|
+
folder_overrides = None
|
|
127
|
+
global_home_override = None
|
|
128
|
+
|
|
129
|
+
state = load_state()
|
|
130
|
+
if state is None:
|
|
131
|
+
return folder_overrides, global_home_override
|
|
132
|
+
|
|
133
|
+
ss = get_scope(state, scope, project_path, profile_label=profile_label)
|
|
134
|
+
if ss is None:
|
|
135
|
+
return folder_overrides, global_home_override
|
|
136
|
+
|
|
137
|
+
for cli_name, bs in ss.clis.items():
|
|
138
|
+
if bs.local_dir_override:
|
|
139
|
+
folder_overrides = folder_overrides or {}
|
|
140
|
+
folder_overrides[cli_name] = bs.local_dir_override
|
|
141
|
+
if bs.global_home_override:
|
|
142
|
+
global_home_override = bs.global_home_override
|
|
143
|
+
|
|
144
|
+
return folder_overrides, global_home_override
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def uninstall(local: bool = False, global_: bool = False,
|
|
148
|
+
profile_label: str = "", all_profiles: bool = False) -> None:
|
|
149
|
+
"""Remove installed components managed by agent-notes."""
|
|
150
|
+
from ..services import installer
|
|
151
|
+
from ..services.state_store import load_state, get_profiles_for_project
|
|
152
|
+
|
|
153
|
+
# Determine which scopes to uninstall
|
|
154
|
+
if local and not global_:
|
|
155
|
+
scopes = [("local", Path.cwd().resolve())]
|
|
156
|
+
elif global_ and not local:
|
|
157
|
+
scopes = [("global", None)]
|
|
158
|
+
else:
|
|
159
|
+
scopes = [("global", None), ("local", Path.cwd().resolve())]
|
|
160
|
+
|
|
161
|
+
if all_profiles:
|
|
162
|
+
state = load_state()
|
|
163
|
+
if state is None:
|
|
164
|
+
print("Nothing to uninstall — no agent-notes state found.")
|
|
165
|
+
return
|
|
166
|
+
for scope, project_path in scopes:
|
|
167
|
+
if scope == "local":
|
|
168
|
+
profiles = get_profiles_for_project(state, project_path) if state else []
|
|
169
|
+
if not profiles:
|
|
170
|
+
print(f" No profiles found for {project_path}")
|
|
171
|
+
continue
|
|
172
|
+
for key, _ss in profiles:
|
|
173
|
+
label = label_from_key(key, project_path)
|
|
174
|
+
folder_overrides, global_home_override = _resolve_overrides_from_state(
|
|
175
|
+
scope, project_path, label)
|
|
176
|
+
label_hint = f" profile={label}" if label else ""
|
|
177
|
+
print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
|
|
178
|
+
installer.uninstall_all(scope,
|
|
179
|
+
folder_overrides=folder_overrides,
|
|
180
|
+
global_home_override=global_home_override,
|
|
181
|
+
profile_label=label)
|
|
182
|
+
try:
|
|
183
|
+
remove_install_state(scope, project_path, profile_label=label)
|
|
184
|
+
except Exception as e:
|
|
185
|
+
print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
|
|
186
|
+
else:
|
|
187
|
+
# Global: uninstall default + all labeled profiles
|
|
188
|
+
global_labels = [""] if (state and state.global_install) else []
|
|
189
|
+
if state:
|
|
190
|
+
global_labels += list(state.global_installs.keys())
|
|
191
|
+
for label in global_labels:
|
|
192
|
+
folder_overrides, global_home_override = _resolve_overrides_from_state(
|
|
193
|
+
scope, None, label)
|
|
194
|
+
label_hint = f" profile={label}" if label else ""
|
|
195
|
+
print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
|
|
196
|
+
installer.uninstall_all(scope,
|
|
197
|
+
folder_overrides=folder_overrides,
|
|
198
|
+
global_home_override=global_home_override,
|
|
199
|
+
profile_label=label)
|
|
200
|
+
try:
|
|
201
|
+
remove_install_state(scope, None, profile_label=label)
|
|
202
|
+
except Exception as e:
|
|
203
|
+
print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
|
|
204
|
+
print(f"{Color.GREEN}Done.{Color.NC} agent-notes components removed.")
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
for scope, project_path in scopes:
|
|
208
|
+
# Always resolve overrides from state so we clean the right directories
|
|
209
|
+
folder_overrides, global_home_override = _resolve_overrides_from_state(
|
|
210
|
+
scope, project_path, profile_label)
|
|
211
|
+
|
|
212
|
+
label_hint = f" profile={profile_label}" if profile_label else ""
|
|
213
|
+
print(f"Uninstalling agent-notes ({scope}{label_hint}) ...")
|
|
214
|
+
installer.uninstall_all(scope,
|
|
215
|
+
folder_overrides=folder_overrides,
|
|
216
|
+
global_home_override=global_home_override,
|
|
217
|
+
profile_label=profile_label)
|
|
218
|
+
|
|
219
|
+
# Remove state entry for this scope
|
|
220
|
+
try:
|
|
221
|
+
remove_install_state(scope, project_path, profile_label=profile_label)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
print(f"{Color.YELLOW}Warning: failed to clear state.json: {e}{Color.NC}")
|
|
224
|
+
|
|
225
|
+
print(f"{Color.GREEN}Done.{Color.NC} agent-notes components removed.")
|