minder-cli 0.4.1__tar.gz → 0.4.2__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.
- {minder_cli-0.4.1 → minder_cli-0.4.2}/PKG-INFO +1 -1
- {minder_cli-0.4.1 → minder_cli-0.4.2}/pyproject.toml +1 -1
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/agent.py +108 -43
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/mcp.py +77 -8
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/main.py +84 -16
- {minder_cli-0.4.1 → minder_cli-0.4.2}/.gitignore +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/LICENSE +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/README-pypi.md +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/README.md +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/api/routers/prompts.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/application/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/application/admin/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/application/admin/dto.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/application/admin/jobs.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/application/admin/use_cases.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/context.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/middleware.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/principal.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/rate_limiter.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/rbac.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/auth/service.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/bootstrap/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/bootstrap/providers.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/bootstrap/transport.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/cache/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/cache/providers.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/chunking/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/chunking/code_splitter.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/chunking/splitter.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/cli.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/config.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/continuity.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/dev.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/embedding/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/embedding/base.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/embedding/local.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/embedding/openai.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/edges.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/executor.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/graph.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/evaluator.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/guard.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/llm.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/planning.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/reasoning.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/reranker.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/retriever.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/verification.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/nodes/workflow_planner.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/runtime.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/graph/state.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/llm/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/llm/base.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/llm/factory.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/llm/litert.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/llm/openai.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/base.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/client.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/document.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/error.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/graph.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/history.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/job.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/prompt.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/repository.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/rule.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/session.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/skill.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/user.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/models/workflow.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/observability/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/observability/audit.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/observability/logging.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/observability/metrics.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/observability/tracing.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/auth.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/ide.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/sync.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/commands/update.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/utils/common.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/utils/config.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/utils/git.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/cli/utils/version.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/api.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/context.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/dashboard.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/jobs.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/memories.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/prompts.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/routes.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/runtime.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/search.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/presentation/http/admin/skills.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/prompts/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/prompts/formatter.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/resources/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/retrieval/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/retrieval/hybrid.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/retrieval/mmr.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/retrieval/multi_hop.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/runtime.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/server.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/document.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/error.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/feedback.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/graph.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/history.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/interfaces.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/milvus/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/milvus/client.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/milvus/collections.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/milvus/vector_store.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/mongodb/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/mongodb/client.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/mongodb/indexes.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/mongodb/operational_store.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/relational.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/repo_state.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/rule.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/store/vector.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/auth.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/graph.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/ingest.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/memory.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/query.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/registry.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/repo_scanner.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/search.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/session.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/skills.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/tools/workflow.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/transport/__init__.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/transport/base.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/transport/sse.py +0 -0
- {minder_cli-0.4.1 → minder_cli-0.4.2}/src/minder/transport/stdio.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: minder-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Minder CLI is the command-line interface for the Minder self-hosted MCP platform.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hiimtrung/minder
|
|
6
6
|
Project-URL: Repository, https://github.com/hiimtrung/minder
|
|
@@ -7,6 +7,7 @@ from ..utils.common import (
|
|
|
7
7
|
upsert_managed_block,
|
|
8
8
|
remove_managed_block,
|
|
9
9
|
wrap_managed_block,
|
|
10
|
+
marker_pair,
|
|
10
11
|
)
|
|
11
12
|
from ..utils.version import installed_package_version
|
|
12
13
|
|
|
@@ -15,6 +16,11 @@ _ANTIGRAVITY_FRONT_MATTER = """---
|
|
|
15
16
|
description: Minder is your agentic engineering copilot for repo-aware development, workflow governance, and persistent session continuity.
|
|
16
17
|
---"""
|
|
17
18
|
|
|
19
|
+
_CLAUDE_CODE_FRONT_MATTER = """---
|
|
20
|
+
name: minder
|
|
21
|
+
description: Minder is your agentic engineering copilot for repo-aware development, workflow governance, and persistent session continuity.
|
|
22
|
+
---"""
|
|
23
|
+
|
|
18
24
|
MINDER_AGENT_PROMPT = """# Minder Agent Orchestration Rules
|
|
19
25
|
|
|
20
26
|
You are an expert AI software engineer equipped with **Minder**, an agentic development infrastructure. Your goal is to provide deep, grounded assistance by orchestrating Minder's tools effectively.
|
|
@@ -93,27 +99,48 @@ When implementing a feature or fix:
|
|
|
93
99
|
|
|
94
100
|
def _agent_instruction_path(target: str, cwd: Path) -> Path | None:
|
|
95
101
|
if target == "vscode":
|
|
96
|
-
return
|
|
102
|
+
return Path.home() / ".copilot" / "agents" / "minder.agent.md"
|
|
97
103
|
if target == "cursor":
|
|
98
|
-
return cwd / ".
|
|
104
|
+
return cwd / "AGENTS.md"
|
|
99
105
|
if target == "claude-code":
|
|
100
|
-
return
|
|
106
|
+
return Path.home() / ".claude" / "agents" / "minder.md"
|
|
101
107
|
if target == "antigravity":
|
|
102
|
-
return cwd / ".
|
|
108
|
+
return cwd / ".gemini" / "antigravity" / "global_workflows" / "minder.md"
|
|
103
109
|
if target == "codex":
|
|
104
110
|
return Path.home() / ".codex" / "AGENTS.md"
|
|
105
111
|
return None
|
|
106
112
|
|
|
107
113
|
|
|
108
|
-
def
|
|
114
|
+
def _get_installed_version(path: Path) -> str | None:
|
|
115
|
+
"""Extract the minder version embedded in an installed agent managed block."""
|
|
116
|
+
if not path.is_file():
|
|
117
|
+
return None
|
|
118
|
+
content = path.read_text(encoding="utf-8")
|
|
119
|
+
start, _ = marker_pair(path, _AGENT_INSTRUCTIONS_KEY)
|
|
120
|
+
if start not in content:
|
|
121
|
+
return None
|
|
122
|
+
_, after = content.split(start, 1)
|
|
123
|
+
first_line = after.lstrip("\n").split("\n")[0].strip()
|
|
124
|
+
prefix = "<!-- minder-agent-version:"
|
|
125
|
+
suffix = "-->"
|
|
126
|
+
if first_line.startswith(prefix) and first_line.endswith(suffix):
|
|
127
|
+
return first_line[len(prefix):-len(suffix)].strip()
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _agent_body_with_version(body: str, version: str) -> str:
|
|
132
|
+
return f"<!-- minder-agent-version: {version} -->\n{body}"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _upsert_with_front_matter(path: Path, front_matter: str, body: str) -> None:
|
|
109
136
|
# Migrate away legacy layout where managed marker was the first line.
|
|
110
137
|
remove_managed_block(path, _AGENT_INSTRUCTIONS_KEY)
|
|
111
138
|
existing = path.read_text(encoding="utf-8") if path.is_file() else ""
|
|
112
139
|
tail = existing
|
|
113
|
-
if tail.startswith(
|
|
114
|
-
tail = tail[len(
|
|
140
|
+
if tail.startswith(front_matter):
|
|
141
|
+
tail = tail[len(front_matter):].lstrip("\n")
|
|
115
142
|
managed = wrap_managed_block(path, _AGENT_INSTRUCTIONS_KEY, body).rstrip("\n")
|
|
116
|
-
updated = f"{
|
|
143
|
+
updated = f"{front_matter}\n\n{managed}"
|
|
117
144
|
tail = tail.strip("\n")
|
|
118
145
|
if tail:
|
|
119
146
|
updated = f"{updated}\n\n{tail}"
|
|
@@ -121,67 +148,105 @@ def _upsert_antigravity_workflow(path: Path, body: str) -> None:
|
|
|
121
148
|
path.write_text(updated + "\n", encoding="utf-8")
|
|
122
149
|
|
|
123
150
|
|
|
124
|
-
def
|
|
151
|
+
def _cleanup_front_matter(path: Path, front_matter: str) -> None:
|
|
125
152
|
if not path.is_file():
|
|
126
153
|
return
|
|
127
154
|
content = path.read_text(encoding="utf-8")
|
|
128
|
-
if not content.startswith(
|
|
155
|
+
if not content.startswith(front_matter):
|
|
129
156
|
return
|
|
130
|
-
tail = content[len(
|
|
157
|
+
tail = content[len(front_matter):].lstrip("\n")
|
|
131
158
|
if tail:
|
|
132
159
|
path.write_text(tail, encoding="utf-8")
|
|
133
160
|
else:
|
|
134
161
|
path.unlink(missing_ok=True)
|
|
135
162
|
|
|
163
|
+
|
|
164
|
+
def _display_path(path: Path, cwd: Path) -> str:
|
|
165
|
+
try:
|
|
166
|
+
return str(path.relative_to(cwd))
|
|
167
|
+
except ValueError:
|
|
168
|
+
return str(path)
|
|
169
|
+
|
|
136
170
|
def install_agent_command(args: argparse.Namespace) -> int:
|
|
137
171
|
cwd = Path(args.cwd).resolve()
|
|
138
172
|
targets = args.target or ["all"]
|
|
139
173
|
if "all" in targets:
|
|
140
174
|
targets = ["vscode", "cursor", "claude-code", "antigravity", "codex"]
|
|
141
|
-
|
|
175
|
+
|
|
142
176
|
version = installed_package_version() or "unknown"
|
|
143
|
-
|
|
177
|
+
installed_list: list[tuple[Path, str | None]] = []
|
|
178
|
+
skipped_list: list[tuple[Path, str]] = []
|
|
179
|
+
|
|
144
180
|
for target in targets:
|
|
145
181
|
path = _agent_instruction_path(target, cwd)
|
|
146
|
-
if path:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
182
|
+
if not path:
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
existing_version = _get_installed_version(path)
|
|
186
|
+
if existing_version == version:
|
|
187
|
+
skipped_list.append((path, version))
|
|
188
|
+
continue
|
|
189
|
+
|
|
190
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
191
|
+
body = _agent_body_with_version(MINDER_AGENT_PROMPT, version)
|
|
192
|
+
|
|
193
|
+
if target == "antigravity":
|
|
194
|
+
_upsert_with_front_matter(path, _ANTIGRAVITY_FRONT_MATTER, body)
|
|
195
|
+
elif target == "claude-code":
|
|
196
|
+
_upsert_with_front_matter(path, _CLAUDE_CODE_FRONT_MATTER, body)
|
|
197
|
+
else:
|
|
198
|
+
upsert_managed_block(path, _AGENT_INSTRUCTIONS_KEY, body)
|
|
199
|
+
|
|
200
|
+
installed_list.append((path, existing_version))
|
|
201
|
+
|
|
202
|
+
if not installed_list and not skipped_list:
|
|
165
203
|
print("No valid targets found for agent installation.")
|
|
166
204
|
return 1
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
205
|
+
|
|
206
|
+
for path, old_ver in installed_list:
|
|
207
|
+
display = _display_path(path, cwd)
|
|
208
|
+
if old_ver:
|
|
209
|
+
print(f" Updated {display} (v{old_ver} → v{version})")
|
|
210
|
+
else:
|
|
211
|
+
print(f" Installed {display} (v{version})")
|
|
212
|
+
|
|
213
|
+
for path, ver in skipped_list:
|
|
214
|
+
print(f" Already up to date: {_display_path(path, cwd)} (v{ver})")
|
|
215
|
+
|
|
216
|
+
if installed_list:
|
|
217
|
+
print(f"Minder Agent rules installed/updated in {len(installed_list)} location(s).")
|
|
218
|
+
else:
|
|
219
|
+
print(f"All {len(skipped_list)} agent file(s) already up to date (v{version}).")
|
|
220
|
+
|
|
171
221
|
return 0
|
|
172
222
|
|
|
223
|
+
|
|
173
224
|
def uninstall_agent_command(args: argparse.Namespace) -> int:
|
|
174
225
|
cwd = Path(args.cwd).resolve()
|
|
175
226
|
targets = args.target or ["all"]
|
|
176
227
|
if "all" in targets:
|
|
177
228
|
targets = ["vscode", "cursor", "claude-code", "antigravity", "codex"]
|
|
178
|
-
|
|
229
|
+
|
|
230
|
+
removed: list[Path] = []
|
|
179
231
|
for target in targets:
|
|
180
232
|
path = _agent_instruction_path(target, cwd)
|
|
181
|
-
if path:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
233
|
+
if not path:
|
|
234
|
+
continue
|
|
235
|
+
removed_block = remove_managed_block(path, _AGENT_INSTRUCTIONS_KEY)
|
|
236
|
+
if target == "antigravity":
|
|
237
|
+
_cleanup_front_matter(path, _ANTIGRAVITY_FRONT_MATTER)
|
|
238
|
+
elif target == "claude-code":
|
|
239
|
+
_cleanup_front_matter(path, _CLAUDE_CODE_FRONT_MATTER)
|
|
240
|
+
if removed_block:
|
|
241
|
+
removed.append(path)
|
|
242
|
+
|
|
243
|
+
if removed:
|
|
244
|
+
print(f"Removed Minder Agent rules from {len(removed)} location(s).")
|
|
245
|
+
for p in removed:
|
|
246
|
+
print(f" - {_display_path(p, cwd)}")
|
|
247
|
+
else:
|
|
248
|
+
print("No Minder Agent rules found to remove.")
|
|
187
249
|
return 0
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
remove_agent_command = uninstall_agent_command
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
4
|
import platform
|
|
5
|
+
import re
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
@@ -15,6 +16,11 @@ from ..utils.common import (
|
|
|
15
16
|
from ..utils.config import require_client_settings
|
|
16
17
|
|
|
17
18
|
_LOCAL_MCP_TARGETS = ("vscode", "cursor", "claude-code", "antigravity")
|
|
19
|
+
_ALL_MCP_TARGETS = (*_LOCAL_MCP_TARGETS, "codex")
|
|
20
|
+
|
|
21
|
+
# Matches [mcp_servers.minder] and all its key/value lines up to the next
|
|
22
|
+
# section header or end of file. [^\[] also matches newlines in Python.
|
|
23
|
+
_CODEX_SECTION_RE = re.compile(r"^\[mcp_servers\.minder\][^\[]*", re.MULTILINE)
|
|
18
24
|
|
|
19
25
|
|
|
20
26
|
def _global_target_path(target: str) -> Path:
|
|
@@ -39,9 +45,49 @@ def _global_target_path(target: str) -> Path:
|
|
|
39
45
|
return Path.home() / ".config" / "Claude" / "claude_desktop_config.json"
|
|
40
46
|
if target == "antigravity":
|
|
41
47
|
return Path.home() / ".gemini" / "antigravity" / "mcp_config.json"
|
|
48
|
+
if target == "codex":
|
|
49
|
+
return Path.home() / ".codex" / "config.toml"
|
|
42
50
|
raise ValueError(f"Unknown global target: {target}")
|
|
43
51
|
|
|
44
52
|
|
|
53
|
+
def _codex_mcp_section(url: str, client_key: str) -> str:
|
|
54
|
+
return (
|
|
55
|
+
"[mcp_servers.minder]\n"
|
|
56
|
+
f'url = "{url}"\n'
|
|
57
|
+
f'http_headers = {{ "X-Minder-Client-Key" = "{client_key}" }}\n'
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _install_codex_mcp(url: str, client_key: str) -> None:
|
|
62
|
+
path = _global_target_path("codex")
|
|
63
|
+
new_section = _codex_mcp_section(url, client_key)
|
|
64
|
+
existing = path.read_text(encoding="utf-8") if path.is_file() else ""
|
|
65
|
+
if _CODEX_SECTION_RE.search(existing):
|
|
66
|
+
updated = _CODEX_SECTION_RE.sub(new_section, existing)
|
|
67
|
+
else:
|
|
68
|
+
updated = existing.rstrip("\n")
|
|
69
|
+
if updated:
|
|
70
|
+
updated += "\n\n"
|
|
71
|
+
updated += new_section
|
|
72
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
73
|
+
path.write_text(updated, encoding="utf-8")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _uninstall_codex_mcp() -> bool:
|
|
77
|
+
path = _global_target_path("codex")
|
|
78
|
+
if not path.is_file():
|
|
79
|
+
return False
|
|
80
|
+
existing = path.read_text(encoding="utf-8")
|
|
81
|
+
if not _CODEX_SECTION_RE.search(existing):
|
|
82
|
+
return False
|
|
83
|
+
updated = _CODEX_SECTION_RE.sub("", existing).strip("\n")
|
|
84
|
+
if updated:
|
|
85
|
+
path.write_text(updated + "\n", encoding="utf-8")
|
|
86
|
+
else:
|
|
87
|
+
path.unlink(missing_ok=True)
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
|
|
45
91
|
def local_target_path(target: str, cwd: Path) -> Path:
|
|
46
92
|
if target == "vscode":
|
|
47
93
|
return cwd / ".vscode" / "mcp.json"
|
|
@@ -101,14 +147,25 @@ def _target_entry(
|
|
|
101
147
|
def install_mcp_command(args: argparse.Namespace) -> int:
|
|
102
148
|
config_path = Path(args.config_path).expanduser().resolve()
|
|
103
149
|
settings = require_client_settings(config_path)
|
|
104
|
-
|
|
150
|
+
|
|
105
151
|
targets = args.target or ["all"]
|
|
106
152
|
if "all" in targets:
|
|
107
|
-
targets = list(
|
|
108
|
-
|
|
153
|
+
targets = list(_ALL_MCP_TARGETS)
|
|
154
|
+
|
|
109
155
|
cwd = Path(args.cwd).resolve()
|
|
110
|
-
|
|
156
|
+
|
|
111
157
|
for target in targets:
|
|
158
|
+
if target == "codex":
|
|
159
|
+
try:
|
|
160
|
+
_install_codex_mcp(
|
|
161
|
+
sse_url(settings.get("server_url") or ""),
|
|
162
|
+
settings["client_api_key"],
|
|
163
|
+
)
|
|
164
|
+
print(f"Installed Minder MCP config for codex at {_global_target_path('codex')}")
|
|
165
|
+
except Exception as e:
|
|
166
|
+
print(f"Failed to install MCP for codex: {e}")
|
|
167
|
+
continue
|
|
168
|
+
|
|
112
169
|
try:
|
|
113
170
|
if args.global_install:
|
|
114
171
|
path = _global_target_path(target)
|
|
@@ -138,11 +195,20 @@ def install_mcp_command(args: argparse.Namespace) -> int:
|
|
|
138
195
|
def uninstall_mcp_command(args: argparse.Namespace) -> int:
|
|
139
196
|
targets = args.target or ["all"]
|
|
140
197
|
if "all" in targets:
|
|
141
|
-
targets = list(
|
|
142
|
-
|
|
198
|
+
targets = list(_ALL_MCP_TARGETS)
|
|
199
|
+
|
|
143
200
|
cwd = Path(args.cwd).resolve()
|
|
144
|
-
|
|
201
|
+
|
|
145
202
|
for target in targets:
|
|
203
|
+
if target == "codex":
|
|
204
|
+
try:
|
|
205
|
+
removed = _uninstall_codex_mcp()
|
|
206
|
+
if removed:
|
|
207
|
+
print(f"Removed Minder MCP config for codex from {_global_target_path('codex')}")
|
|
208
|
+
except Exception as e:
|
|
209
|
+
print(f"Failed to uninstall MCP for codex: {e}")
|
|
210
|
+
continue
|
|
211
|
+
|
|
146
212
|
try:
|
|
147
213
|
if args.global_install:
|
|
148
214
|
path = _global_target_path(target)
|
|
@@ -165,5 +231,8 @@ def uninstall_mcp_command(args: argparse.Namespace) -> int:
|
|
|
165
231
|
print(f"Removed Minder MCP config for {target} from {path}")
|
|
166
232
|
except Exception as e:
|
|
167
233
|
print(f"Failed to uninstall MCP for {target}: {e}")
|
|
168
|
-
|
|
234
|
+
|
|
169
235
|
return 0
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
remove_mcp_command = uninstall_mcp_command
|
|
@@ -5,9 +5,9 @@ import argparse
|
|
|
5
5
|
from .utils.version import installed_package_version
|
|
6
6
|
from .utils.common import client_config_path
|
|
7
7
|
from .commands.auth import login_command
|
|
8
|
-
from .commands.mcp import install_mcp_command, uninstall_mcp_command
|
|
8
|
+
from .commands.mcp import install_mcp_command, uninstall_mcp_command, remove_mcp_command, _global_target_path
|
|
9
9
|
from .commands.ide import install_ide_command, uninstall_ide_command
|
|
10
|
-
from .commands.agent import install_agent_command, uninstall_agent_command
|
|
10
|
+
from .commands.agent import install_agent_command, uninstall_agent_command, remove_agent_command
|
|
11
11
|
from .commands.update import version_command, check_update_command, update_command
|
|
12
12
|
from .commands.sync import sync_command
|
|
13
13
|
|
|
@@ -41,10 +41,29 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
41
41
|
install = subparsers.add_parser("install", help="Install Minder integration (MCP/IDE).")
|
|
42
42
|
install_subs = install.add_subparsers(dest="subcommand", required=True)
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
_cwd_placeholder = "<repo>"
|
|
45
|
+
_mcp_epilog = (
|
|
46
|
+
"targets:\n"
|
|
47
|
+
f" vscode per-repo: {_cwd_placeholder}/.vscode/mcp.json\n"
|
|
48
|
+
f" --global: {_global_target_path('vscode')}\n"
|
|
49
|
+
f" cursor per-repo: {_cwd_placeholder}/.cursor/mcp.json\n"
|
|
50
|
+
f" --global: {_global_target_path('cursor')}\n"
|
|
51
|
+
f" claude-code per-repo: {_cwd_placeholder}/.claude/mcp.json\n"
|
|
52
|
+
f" --global: {_global_target_path('claude-code')}\n"
|
|
53
|
+
f" antigravity always: {_global_target_path('antigravity')} [--global has no effect]\n"
|
|
54
|
+
f" codex always: {_global_target_path('codex')} [--global has no effect]\n"
|
|
55
|
+
" all all targets above (default)\n"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
mcp_in = install_subs.add_parser(
|
|
59
|
+
"mcp",
|
|
60
|
+
help="Install MCP server config.",
|
|
61
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
62
|
+
epilog=_mcp_epilog,
|
|
63
|
+
)
|
|
64
|
+
mcp_in.add_argument("--target", action="append", metavar="TARGET", help="Target to install (see targets below).")
|
|
65
|
+
mcp_in.add_argument("--global", dest="global_install", action="store_true", help="Write to the IDE's global config instead of the repo-local file.")
|
|
66
|
+
mcp_in.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
48
67
|
mcp_in.add_argument("--config-path", default=str(client_config_path()), help="Path to client config.")
|
|
49
68
|
mcp_in.set_defaults(func=install_mcp_command)
|
|
50
69
|
|
|
@@ -54,18 +73,37 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
54
73
|
ide_in.add_argument("--config-path", default=str(client_config_path()), help="Path to client config.")
|
|
55
74
|
ide_in.set_defaults(func=install_ide_command)
|
|
56
75
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
_agent_epilog = """\
|
|
77
|
+
targets (scope):
|
|
78
|
+
vscode ~/.copilot/agents/minder.agent.md [global – all repos]
|
|
79
|
+
claude-code ~/.claude/agents/minder.md [global – all repos]
|
|
80
|
+
codex ~/.codex/AGENTS.md [global – all repos]
|
|
81
|
+
cursor <repo>/AGENTS.md [per-repo]
|
|
82
|
+
antigravity <repo>/.gemini/antigravity/global_workflows/ [per-repo]
|
|
83
|
+
all all targets above (default)
|
|
84
|
+
"""
|
|
85
|
+
agent_in = install_subs.add_parser(
|
|
86
|
+
"agent",
|
|
87
|
+
help="Install Minder Agent rules.",
|
|
88
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
89
|
+
epilog=_agent_epilog,
|
|
90
|
+
)
|
|
91
|
+
agent_in.add_argument("--target", action="append", metavar="TARGET", help="Target to install (see targets below).")
|
|
92
|
+
agent_in.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
60
93
|
agent_in.set_defaults(func=install_agent_command)
|
|
61
94
|
|
|
62
95
|
uninstall = subparsers.add_parser("uninstall", help="Remove Minder integration.")
|
|
63
96
|
uninstall_subs = uninstall.add_subparsers(dest="subcommand", required=True)
|
|
64
97
|
|
|
65
|
-
mcp_un = uninstall_subs.add_parser(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
98
|
+
mcp_un = uninstall_subs.add_parser(
|
|
99
|
+
"mcp",
|
|
100
|
+
help="Remove MCP server config.",
|
|
101
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
102
|
+
epilog=_mcp_epilog,
|
|
103
|
+
)
|
|
104
|
+
mcp_un.add_argument("--target", action="append", metavar="TARGET", help="Target to remove (see targets below).")
|
|
105
|
+
mcp_un.add_argument("--global", dest="global_install", action="store_true", help="Remove from the IDE's global config instead of the repo-local file.")
|
|
106
|
+
mcp_un.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
69
107
|
mcp_un.set_defaults(func=uninstall_mcp_command)
|
|
70
108
|
|
|
71
109
|
ide_un = uninstall_subs.add_parser("ide", help="Remove IDE bootstrap assets.")
|
|
@@ -73,11 +111,41 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
73
111
|
ide_un.add_argument("--cwd", default=".", help="Workspace directory.")
|
|
74
112
|
ide_un.set_defaults(func=uninstall_ide_command)
|
|
75
113
|
|
|
76
|
-
agent_un = uninstall_subs.add_parser(
|
|
77
|
-
|
|
78
|
-
|
|
114
|
+
agent_un = uninstall_subs.add_parser(
|
|
115
|
+
"agent",
|
|
116
|
+
help="Remove Minder Agent rules.",
|
|
117
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
118
|
+
epilog=_agent_epilog,
|
|
119
|
+
)
|
|
120
|
+
agent_un.add_argument("--target", action="append", metavar="TARGET", help="Target to remove (see targets below).")
|
|
121
|
+
agent_un.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
79
122
|
agent_un.set_defaults(func=uninstall_agent_command)
|
|
80
123
|
|
|
124
|
+
# --- Remove (alias for uninstall) ---
|
|
125
|
+
remove = subparsers.add_parser("remove", help="Remove Minder integration (alias for uninstall).")
|
|
126
|
+
remove_subs = remove.add_subparsers(dest="subcommand", required=True)
|
|
127
|
+
|
|
128
|
+
remove_mcp = remove_subs.add_parser(
|
|
129
|
+
"mcp",
|
|
130
|
+
help="Remove MCP server config.",
|
|
131
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
132
|
+
epilog=_mcp_epilog,
|
|
133
|
+
)
|
|
134
|
+
remove_mcp.add_argument("--target", action="append", metavar="TARGET", help="Target to remove (see targets below).")
|
|
135
|
+
remove_mcp.add_argument("--global", dest="global_install", action="store_true", help="Remove from the IDE's global config instead of the repo-local file.")
|
|
136
|
+
remove_mcp.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
137
|
+
remove_mcp.set_defaults(func=remove_mcp_command)
|
|
138
|
+
|
|
139
|
+
remove_agent = remove_subs.add_parser(
|
|
140
|
+
"agent",
|
|
141
|
+
help="Remove Minder Agent rules.",
|
|
142
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
143
|
+
epilog=_agent_epilog,
|
|
144
|
+
)
|
|
145
|
+
remove_agent.add_argument("--target", action="append", metavar="TARGET", help="Target to remove (see targets below).")
|
|
146
|
+
remove_agent.add_argument("--cwd", default=".", help="Workspace directory (used for per-repo targets).")
|
|
147
|
+
remove_agent.set_defaults(func=remove_agent_command)
|
|
148
|
+
|
|
81
149
|
# --- Sync ---
|
|
82
150
|
sync = subparsers.add_parser("sync", help="Sync repository state with Minder server.")
|
|
83
151
|
sync.add_argument("--repo-id", help="Repository UUID.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|