minder-cli 0.6.0__tar.gz → 0.6.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.
Files changed (166) hide show
  1. {minder_cli-0.6.0 → minder_cli-0.6.2}/PKG-INFO +1 -1
  2. {minder_cli-0.6.0 → minder_cli-0.6.2}/pyproject.toml +1 -1
  3. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/application/admin/use_cases.py +1 -1
  4. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/service.py +2 -1
  5. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/bootstrap/transport.py +20 -6
  6. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/session_graph.py +2 -0
  7. minder_cli-0.6.2/src/minder/presentation/cli/commands/agent.py +236 -0
  8. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/resources/__init__.py +10 -0
  9. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/registry.py +7 -0
  10. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/session.py +15 -6
  11. minder_cli-0.6.0/src/minder/presentation/cli/commands/agent.py +0 -180
  12. {minder_cli-0.6.0 → minder_cli-0.6.2}/.gitignore +0 -0
  13. {minder_cli-0.6.0 → minder_cli-0.6.2}/LICENSE +0 -0
  14. {minder_cli-0.6.0 → minder_cli-0.6.2}/README-pypi.md +0 -0
  15. {minder_cli-0.6.0 → minder_cli-0.6.2}/README.md +0 -0
  16. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/__init__.py +0 -0
  17. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/api/routers/prompts.py +0 -0
  18. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/application/__init__.py +0 -0
  19. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/application/admin/__init__.py +0 -0
  20. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/application/admin/dto.py +0 -0
  21. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/application/admin/jobs.py +0 -0
  22. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/__init__.py +0 -0
  23. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/context.py +0 -0
  24. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/middleware.py +0 -0
  25. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/principal.py +0 -0
  26. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/rate_limiter.py +0 -0
  27. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/auth/rbac.py +0 -0
  28. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/bootstrap/__init__.py +0 -0
  29. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/bootstrap/agent_seeder.py +0 -0
  30. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/bootstrap/providers.py +0 -0
  31. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/bootstrap/workflow_seeder.py +0 -0
  32. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/cache/__init__.py +0 -0
  33. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/cache/providers.py +0 -0
  34. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/chunking/__init__.py +0 -0
  35. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/chunking/code_splitter.py +0 -0
  36. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/chunking/splitter.py +0 -0
  37. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/cli.py +0 -0
  38. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/config.py +0 -0
  39. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/context_compactor.py +0 -0
  40. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/continuity.py +0 -0
  41. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/dev.py +0 -0
  42. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/embedding/__init__.py +0 -0
  43. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/embedding/base.py +0 -0
  44. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/embedding/local.py +0 -0
  45. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/embedding/openai.py +0 -0
  46. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/__init__.py +0 -0
  47. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/checkpoint.py +0 -0
  48. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/edges.py +0 -0
  49. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/executor.py +0 -0
  50. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/graph.py +0 -0
  51. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/memory_graph.py +0 -0
  52. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/__init__.py +0 -0
  53. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/clarification.py +0 -0
  54. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/evaluator.py +0 -0
  55. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/guard.py +0 -0
  56. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/llm.py +0 -0
  57. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/parallel_retriever.py +0 -0
  58. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/planning.py +0 -0
  59. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/reasoning.py +0 -0
  60. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/reflection.py +0 -0
  61. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/reranker.py +0 -0
  62. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/retriever.py +0 -0
  63. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/verification.py +0 -0
  64. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/nodes/workflow_planner.py +0 -0
  65. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/runtime.py +0 -0
  66. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/state.py +0 -0
  67. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/graph/supervisor.py +0 -0
  68. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/learning/__init__.py +0 -0
  69. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/learning/error_learner.py +0 -0
  70. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/learning/pattern_extractor.py +0 -0
  71. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/learning/quality_optimizer.py +0 -0
  72. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/learning/skill_synthesizer.py +0 -0
  73. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/llm/__init__.py +0 -0
  74. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/llm/base.py +0 -0
  75. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/llm/factory.py +0 -0
  76. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/llm/llama_cpp_llm.py +0 -0
  77. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/llm/openai.py +0 -0
  78. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/model_bootstrap.py +0 -0
  79. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/__init__.py +0 -0
  80. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/agent.py +0 -0
  81. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/base.py +0 -0
  82. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/checkpoint.py +0 -0
  83. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/client.py +0 -0
  84. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/document.py +0 -0
  85. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/error.py +0 -0
  86. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/graph.py +0 -0
  87. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/history.py +0 -0
  88. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/job.py +0 -0
  89. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/prompt.py +0 -0
  90. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/repository.py +0 -0
  91. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/rule.py +0 -0
  92. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/session.py +0 -0
  93. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/skill.py +0 -0
  94. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/user.py +0 -0
  95. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/models/workflow.py +0 -0
  96. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/observability/__init__.py +0 -0
  97. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/observability/audit.py +0 -0
  98. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/observability/logging.py +0 -0
  99. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/observability/metrics.py +0 -0
  100. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/observability/tracing.py +0 -0
  101. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/__init__.py +0 -0
  102. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/__init__.py +0 -0
  103. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/commands/auth.py +0 -0
  104. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/commands/mcp.py +0 -0
  105. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/commands/sync.py +0 -0
  106. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/commands/update.py +0 -0
  107. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/main.py +0 -0
  108. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/utils/common.py +0 -0
  109. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/utils/config.py +0 -0
  110. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/utils/git.py +0 -0
  111. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/cli/utils/version.py +0 -0
  112. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/__init__.py +0 -0
  113. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/__init__.py +0 -0
  114. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/agents.py +0 -0
  115. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/api.py +0 -0
  116. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/context.py +0 -0
  117. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/dashboard.py +0 -0
  118. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/jobs.py +0 -0
  119. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/memories.py +0 -0
  120. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/prompts.py +0 -0
  121. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/routes.py +0 -0
  122. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/runtime.py +0 -0
  123. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/search.py +0 -0
  124. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/presentation/http/admin/skills.py +0 -0
  125. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/prompts/__init__.py +0 -0
  126. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/prompts/formatter.py +0 -0
  127. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/retrieval/__init__.py +0 -0
  128. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/retrieval/hybrid.py +0 -0
  129. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/retrieval/mmr.py +0 -0
  130. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/retrieval/multi_hop.py +0 -0
  131. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/runtime.py +0 -0
  132. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/server.py +0 -0
  133. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/__init__.py +0 -0
  134. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/document.py +0 -0
  135. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/error.py +0 -0
  136. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/feedback.py +0 -0
  137. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/graph.py +0 -0
  138. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/history.py +0 -0
  139. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/interfaces.py +0 -0
  140. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/__init__.py +0 -0
  141. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/client.py +0 -0
  142. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/crud.py +0 -0
  143. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/graph_store.py +0 -0
  144. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/operational_store.py +0 -0
  145. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/qdrant/vector_store.py +0 -0
  146. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/relational.py +0 -0
  147. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/repo_state.py +0 -0
  148. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/rule.py +0 -0
  149. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/store/vector.py +0 -0
  150. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/__init__.py +0 -0
  151. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/agents.py +0 -0
  152. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/auth.py +0 -0
  153. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/graph.py +0 -0
  154. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/ingest.py +0 -0
  155. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/memory.py +0 -0
  156. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/query.py +0 -0
  157. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/repo_scanner.py +0 -0
  158. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/seeds/__init__.py +0 -0
  159. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/seeds/default_agents.py +0 -0
  160. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/skills.py +0 -0
  161. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/tools/workflow.py +0 -0
  162. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/transport/__init__.py +0 -0
  163. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/transport/base.py +0 -0
  164. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/transport/sse.py +0 -0
  165. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/transport/stdio.py +0 -0
  166. {minder_cli-0.6.0 → minder_cli-0.6.2}/src/minder/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: minder-cli
3
- Version: 0.6.0
3
+ Version: 0.6.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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "minder-cli"
7
- version = "0.6.0"
7
+ version = "0.6.2"
8
8
  description = "Minder CLI is the command-line interface for the Minder self-hosted MCP platform."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -368,7 +368,7 @@ class AdminConsoleUseCases:
368
368
  'http_headers = { "X-Minder-Client-Key" = "<mkc_...>" }'
369
369
  ),
370
370
  "vscode": (
371
- f'{{"servers":{{"minder":{{"type":"sse","url":"{base_url}/sse","headers":{{"X-Minder-Client-Key":"<mkc_...>"}}}}}},"inputs":[]}}'
371
+ f'{{"servers":{{"minder":{{"type":"sse","url":"{base_url}/sse","headers":{{"X-Minder-Client-Key":"<mkc_...>"}},"tools":["*"]}}}},"inputs":[]}}'
372
372
  ),
373
373
  "copilot_cli": (
374
374
  f'{{"mcpServers":{{"minder":{{"type":"sse","url":"{base_url}/sse","headers":{{"X-Minder-Client-Key":"<mkc_...>"}},"tools":["*"]}}}}}}'
@@ -25,6 +25,7 @@ from minder.auth.principal import AdminUserPrincipal, ClientPrincipal, Principal
25
25
  from minder.config import MinderConfig
26
26
  from minder.models.user import User
27
27
  from minder.store.interfaces import ICacheProvider, IOperationalStore
28
+ from minder.tools.registry import DEFAULT_AGENT_TOOL_SCOPES
28
29
 
29
30
  # ---------------------------------------------------------------------------
30
31
  # Role hierarchy
@@ -256,7 +257,7 @@ class AuthService:
256
257
  created_by_user_id=created_by_user_id,
257
258
  owner_team=owner_team,
258
259
  transport_modes=transport_modes or ["sse", "stdio"],
259
- tool_scopes=tool_scopes or [],
260
+ tool_scopes=tool_scopes if tool_scopes is not None else list(DEFAULT_AGENT_TOOL_SCOPES),
260
261
  repo_scopes=repo_scopes or [],
261
262
  workflow_scopes=workflow_scopes or [],
262
263
  rate_limit_policy=rate_limit_policy or {},
@@ -94,6 +94,17 @@ def build_transport(
94
94
  )
95
95
  )
96
96
 
97
+ async def _resolve_repo_uuid(repo_id: str) -> uuid.UUID:
98
+ """Accept a UUID string or a repo name/slug; return the UUID."""
99
+ try:
100
+ return uuid.UUID(repo_id)
101
+ except ValueError:
102
+ pass
103
+ repo = await store.get_repository_by_name(repo_id)
104
+ if repo is None:
105
+ raise ValueError(f"Repository not found: {repo_id!r}")
106
+ return repo.id
107
+
97
108
  def ensure_client_repo_access(
98
109
  principal: Principal | None,
99
110
  *,
@@ -204,18 +215,19 @@ def build_transport(
204
215
  repo_id: str | None = None,
205
216
  project_context: dict[str, Any] | None = None,
206
217
  ) -> dict[str, Any]:
218
+ resolved_repo_id = await _resolve_repo_uuid(repo_id) if repo_id else None
207
219
  if isinstance(principal, ClientPrincipal):
208
220
  return await session_tools.minder_session_create(
209
221
  client_id=principal.client_id,
210
222
  name=name,
211
- repo_id=uuid.UUID(repo_id) if repo_id else None,
223
+ repo_id=resolved_repo_id,
212
224
  project_context=project_context,
213
225
  )
214
226
  authenticated_user = require_authenticated_user(user)
215
227
  return await session_tools.minder_session_create(
216
228
  user_id=authenticated_user.id,
217
229
  name=name,
218
- repo_id=uuid.UUID(repo_id) if repo_id else None,
230
+ repo_id=resolved_repo_id,
219
231
  project_context=project_context,
220
232
  )
221
233
 
@@ -254,12 +266,14 @@ def build_transport(
254
266
  session_id: str,
255
267
  state: dict[str, Any] | None = None,
256
268
  active_skills: dict[str, Any] | None = None, # noqa: ANN001
269
+ repo_id: str | None = None,
257
270
  ) -> dict[str, Any]:
258
271
  del user
259
272
  return await session_tools.minder_session_save(
260
273
  uuid.UUID(session_id),
261
274
  state=state,
262
275
  active_skills=active_skills,
276
+ repo_id=await _resolve_repo_uuid(repo_id) if repo_id else None,
263
277
  )
264
278
 
265
279
  async def minder_session_restore(
@@ -305,7 +319,7 @@ def build_transport(
305
319
  ) -> dict[str, Any]: # noqa: ANN001
306
320
  del user
307
321
  return await workflow_tools.minder_workflow_get(
308
- repo_id=uuid.UUID(repo_id),
322
+ repo_id=await _resolve_repo_uuid(repo_id),
309
323
  repo_path=repo_path,
310
324
  )
311
325
 
@@ -319,7 +333,7 @@ def build_transport(
319
333
  ) -> dict[str, Any]: # noqa: ANN001
320
334
  del user
321
335
  return await workflow_tools.minder_workflow_step(
322
- repo_id=uuid.UUID(repo_id) if repo_id else None,
336
+ repo_id=await _resolve_repo_uuid(repo_id) if repo_id else None,
323
337
  repo_path=repo_path,
324
338
  session_id=uuid.UUID(session_id) if session_id else None,
325
339
  decision=decision,
@@ -336,7 +350,7 @@ def build_transport(
336
350
  ) -> dict[str, Any]: # noqa: ANN001
337
351
  del user
338
352
  return await workflow_tools.minder_workflow_update(
339
- repo_id=uuid.UUID(repo_id),
353
+ repo_id=await _resolve_repo_uuid(repo_id),
340
354
  repo_path=repo_path,
341
355
  completed_step=completed_step,
342
356
  artifact_name=artifact_name,
@@ -348,7 +362,7 @@ def build_transport(
348
362
  ) -> dict[str, Any]: # noqa: ANN001
349
363
  del user
350
364
  return await workflow_tools.minder_workflow_guard(
351
- repo_id=uuid.UUID(repo_id),
365
+ repo_id=await _resolve_repo_uuid(repo_id),
352
366
  requested_step=requested_step,
353
367
  action=action,
354
368
  )
@@ -177,9 +177,11 @@ class SessionContextGraph:
177
177
  for memory_id in coherence.get("stale_memories", [])
178
178
  if memory_id
179
179
  )
180
+ repo_id = state.get("workflow_context", {}).get("repo_id") or None
180
181
  payload: dict[str, Any] = {
181
182
  "session_id": state["session_id"],
182
183
  "name": state.get("session_name"),
184
+ "repo_id": repo_id,
183
185
  "state": state.get("session_state", {}),
184
186
  "active_skills": state.get("active_skills", {}),
185
187
  "project_context": state.get("project_context", {}),
@@ -0,0 +1,236 @@
1
+ from __future__ import annotations
2
+
3
+ # Minder agent orchestration prompt — source of truth.
4
+ # The dashboard at /dashboard/instruction distributes this to all IDEs.
5
+ # This constant is kept here for programmatic use (e.g. tests, scripted bootstrap).
6
+
7
+ MINDER_AGENT_PROMPT = """# Minder Agent Orchestration Rules
8
+
9
+ You are an AI software engineer using **Minder** for repo-aware development.
10
+ These rules are **mandatory**. Every tool call has a precise precondition. Calling a tool before its preconditions are met causes UUID errors, stale bindings, or corrupt workflow state.
11
+
12
+ Emit `[TRACE] <phase> | <action> | <tool> | <outcome>` after every tool call.
13
+
14
+ ---
15
+
16
+ ## PRE-FLIGHT — Run before ANY code, proposal, or workflow action
17
+
18
+ Pre-flight has two branches. Execute **exactly one** based on ledger state.
19
+
20
+ ---
21
+
22
+ ### Branch A — RESUME (use when `.minder/agent.json` exists AND contains a valid `repo_id` UUID AND `session_id` UUID)
23
+
24
+ ```
25
+ A1. Read .minder/agent.json
26
+ → Load: repo_path, repo_id (UUID), repo_path, session_name, session_id (UUID), workflow.current_step
27
+ → HARD CHECK: repo_id must match the pattern xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
28
+ If repo_id is a name/slug (e.g. "omi-channel-be"), treat ledger as INCOMPLETE → switch to Branch B.
29
+
30
+ A2. minder_session_find(name=<session_name from ledger>)
31
+ Precondition: session_name from ledger.
32
+ Returns: session_id, repo_id (UUID or null), project_context, state, active_skills.
33
+ → Cache returned session_id (overrides ledger value).
34
+ → If returned repo_id is a UUID, use it (overrides ledger repo_id).
35
+ → If returned repo_id is null and ledger repo_id is not a UUID → switch to Branch B.
36
+ → On error (session not found): switch to Branch B.
37
+ [TRACE] PRE-FLIGHT:A2 | session_find | minder_session_find | <found|not_found>
38
+
39
+ A3. minder_auth_whoami
40
+ Precondition: none.
41
+ Returns: principal_type, principal_id, role, scopes, repo_scope.
42
+ → STOP if role or scopes are unexpected.
43
+ [TRACE] PRE-FLIGHT:A3 | verify_identity | minder_auth_whoami | principal=<id>
44
+
45
+ A4. minder_workflow_step(repo_id=<repo_id UUID>, repo_path=<repo_path>)
46
+ Precondition: repo_id UUID confirmed in A1/A2.
47
+ Returns: current_step, completed_steps, instruction_envelope.
48
+ → Cache current_step and instruction_envelope for the rest of this session.
49
+ → Update .minder/agent.json: workflow.current_step = returned current_step.
50
+ [TRACE] PRE-FLIGHT:A4 | load_workflow | minder_workflow_step | step=<step>
51
+
52
+ A5. Context recall — see "Context Recall Rules" section below.
53
+ ```
54
+
55
+ > GATE A: Do not proceed past A5 until `session_id`, `repo_id` (UUID), and `current_step` are all confirmed in memory.
56
+
57
+ ---
58
+
59
+ ### Branch B — INIT (use when ledger is absent, incomplete, or repo_id is not a UUID)
60
+
61
+ ```
62
+ B1. Read minder://repos resource
63
+ Precondition: none — this is always the first call when repo_id is unknown.
64
+ Returns: array of { id (UUID), name, path (absolute filesystem path), url, workflow_state }
65
+ → Find the entry whose `path` matches the current working directory,
66
+ OR whose `name` matches the current repository directory name,
67
+ OR whose `url` matches the git remote origin.
68
+ → Extract: repo_id = entry.id ← UUID only, NEVER a name or slug
69
+ → Extract: repo_path = entry.path ← absolute filesystem path from the resource
70
+ → If no matching entry: STOP. Tell user: "Run `minder sync` first, then retry."
71
+ Do NOT proceed and do NOT guess a repo_id.
72
+ [TRACE] PRE-FLIGHT:B1 | resolve_repo | minder://repos | repo_id=<uuid>
73
+
74
+ B2. minder_session_find(name=<stable-slug>)
75
+ Precondition: repo_id UUID from B1.
76
+ Slug rule: "<repo-name>--<client-or-user-identifier>", all lowercase, hyphens only.
77
+ Returns: session_id, project_context.
78
+ → Found: cache session_id. Verify project_context.repo_id matches B1 repo_id.
79
+ → Not found: call minder_session_create (see B2a).
80
+ [TRACE] PRE-FLIGHT:B2 | session_find | minder_session_find | <found|not_found>
81
+
82
+ B2a. (only if B2 not found) minder_session_create(name=<same-slug>, repo_id=<UUID from B1>)
83
+ Precondition: repo_id UUID from B1, slug from B2.
84
+ Returns: session_id, name.
85
+ → Cache session_id.
86
+ [TRACE] PRE-FLIGHT:B2a | session_create | minder_session_create | session_id=<id>
87
+
88
+ B3. minder_auth_whoami
89
+ (same as A3)
90
+ [TRACE] PRE-FLIGHT:B3 | verify_identity | minder_auth_whoami | principal=<id>
91
+
92
+ B4. minder_workflow_step(repo_id=<UUID from B1>, repo_path=<repo_path>)
93
+ Precondition: repo_id UUID confirmed in B1. session_id confirmed in B2/B2a.
94
+ Returns: current_step, completed_steps, instruction_envelope.
95
+ → Cache current_step and instruction_envelope.
96
+ [TRACE] PRE-FLIGHT:B4 | load_workflow | minder_workflow_step | step=<step>
97
+
98
+ B4b. (only if B2 returned repo_id=null) minder_session_save(session_id=<UUID from B2>, repo_id=<UUID from B1>, state={})
99
+ Links the existing session to the repository permanently.
100
+ After this call, future minder_session_find calls will return repo_id correctly.
101
+ [TRACE] PRE-FLIGHT:B4b | link_repo | minder_session_save | repo_id=<uuid>
102
+
103
+ B5. Write .minder/agent.json with confirmed values:
104
+ {
105
+ "repo_path": "<absolute path>",
106
+ "repo_id": "<UUID from B1>",
107
+ "session_name": "<slug from B2>",
108
+ "session_id": "<UUID from B2/B2a>",
109
+ "workflow": { "id": "", "name": "", "current_step": "<from B4>" },
110
+ "updated_at": "<ISO-8601 now>",
111
+ "notes": ""
112
+ }
113
+ [TRACE] PRE-FLIGHT:B5 | write_ledger | none | ok
114
+
115
+ B6. Context recall — see "Context Recall Rules" section below.
116
+ ```
117
+
118
+ > GATE B: Do not proceed past B6 until `session_id`, `repo_id` (UUID), and `current_step` are all confirmed and ledger is written.
119
+
120
+ ---
121
+
122
+ ## Context Recall Rules (A5 / B6)
123
+
124
+ Read `instruction_envelope.current_step` before choosing tools. Call only what the step requires.
125
+
126
+ | What you need | Tool | Required input | Call when |
127
+ |---|---|---|---|
128
+ | Project facts, past decisions, constraints | `minder_memory_recall(query=<task>)` | query | Task may depend on prior project context |
129
+ | Step patterns, checklists, conventions | `minder_skill_recall(query=<task>, current_step=<step>)` | query, current_step | Always at step start |
130
+ | File locations, symbol definitions | `minder_search_code(query=<...>, repo_path=<repo_path>)` | query, repo_path | Before touching any file |
131
+ | Structural/relational graph queries | `minder_search_graph(query=<...>, repo_path=<repo_path>)` | query, repo_path | Cross-module or dependency questions |
132
+ | Prior error resolutions | `minder_search_errors(query=<...>)` | query | When investigating failures |
133
+ | Blast radius before changing shared code | `minder_find_impact(target=<...>, repo_path=<repo_path>)` | target, repo_path | Always before modifying shared modules |
134
+
135
+ **Decision rule — memory vs skills**: "How do *we* do X in THIS project?" → `minder_memory_recall`. "How to do X in general?" → `minder_skill_recall`. Never call both with the same query.
136
+
137
+ `[TRACE] PRE-FLIGHT:A5/B6 | <purpose> | <tool> | <summary>`
138
+
139
+ ---
140
+
141
+ ## Session Ledger
142
+
143
+ `.minder/agent.json` must always contain valid values — no placeholders, no slugs in UUID fields:
144
+
145
+ ```json
146
+ {
147
+ "repo_path": "/absolute/path/to/repo",
148
+ "repo_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
149
+ "session_name": "repo-name--client-slug",
150
+ "session_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
151
+ "workflow": { "id": "", "name": "", "current_step": "" },
152
+ "updated_at": "ISO-8601",
153
+ "notes": ""
154
+ }
155
+ ```
156
+
157
+ Rules:
158
+ - `repo_id` and `session_id` must be UUID format — never a name or slug.
159
+ - `repo_path` must be an absolute filesystem path — never a relative path.
160
+ - `session_name` must be stable and unique across machines for the same project.
161
+ - Refresh `workflow.current_step` after every `minder_workflow_*` call.
162
+ - Never use `minder_session_list` for routine recovery — use `minder_session_find`.
163
+ - Never mix ledger values across different repositories.
164
+
165
+ ---
166
+
167
+ ## Phase C — Implementation
168
+
169
+ 1. Verify `(repo_path, repo_id UUID, session_id UUID, current_step)` tuple before every tool write.
170
+ 2. Never guess file paths or symbols — always confirm with `minder_search_code` or `minder_search_graph` first.
171
+ 3. Follow recalled skill patterns exactly. Deviation → `[TRACE] PHASE-C | skill_deviation | none | reason=<why>`.
172
+ 4. Before each significant action:
173
+ `minder_workflow_guard(repo_id=<UUID>, requested_step=<current_step>)`
174
+ - `allowed: true` → proceed.
175
+ - `allowed: false` → **STOP**, surface `reason` and `violations`, wait for user.
176
+ `[TRACE] PHASE-C | guard_check | minder_workflow_guard | allowed=<t/f>`
177
+ 5. `minder_session_save(session_id=<UUID>, state={"task":..., "step":..., "next_steps":[...]})` after each significant change. Do not batch.
178
+ `[TRACE] PHASE-C | checkpoint | minder_session_save | ok`
179
+
180
+ ---
181
+
182
+ ## Phase D — Finalization (all required, in order)
183
+
184
+ **D1** `minder_workflow_update(repo_id=<UUID>, repo_path=<path>, completed_step=<step>, artifact_name=<name>, artifact_content=<content>)` — one call per required artifact.
185
+ `[TRACE] PHASE-D | artifact_submit | minder_workflow_update | artifact=<name>`
186
+
187
+ **D2** `minder_workflow_update` to advance the step (completed_step=<current>, no artifact).
188
+ `[TRACE] PHASE-D | advance_workflow | minder_workflow_update | new_step=<next>`
189
+
190
+ **D3** `minder_memory_store` for each project-specific item learned: decisions, constraints, confirmed paths/symbols, gotchas, wrong assumptions, mapped dependencies.
191
+ If nothing: `[TRACE] PHASE-D | memory_store | skipped | reason=<specific>`
192
+
193
+ **D4** `minder_skill_store` / `minder_skill_update` for each cross-project reusable pattern written or confirmed effective.
194
+ If nothing: `[TRACE] PHASE-D | skill_store | skipped | reason=<specific>`
195
+
196
+ **D5** `minder_session_save` `[TRACE] PHASE-D | session_save | minder_session_save | ok`
197
+
198
+ **D6** `minder_session_context(session_id=<UUID>, branch=<branch>, open_files=[...])` — update open files and branch.
199
+ `[TRACE] PHASE-D | session_context | minder_session_context | ok`
200
+
201
+ **D7** Write `.minder/agent.json` with updated `workflow.current_step` and `updated_at`.
202
+ `[TRACE] PHASE-D | update_ledger | none | current_step=<step>`
203
+
204
+ **D8 — Checklist** (output verbatim before final response):
205
+ ```
206
+ □ D1 artifact_submit □ D2 advance_workflow □ D3 memory_store
207
+ □ D4 skill_store □ D5 session_save □ D6 session_context □ D7 ledger_updated
208
+ ```
209
+
210
+ ---
211
+
212
+ ## SubAgent Delegation (required for review and test steps)
213
+
214
+ When `current_step` is `review`, `write_tests`, or `verify_tests` — delegate, never self-execute.
215
+
216
+ | Step | Subagent | Required artifacts |
217
+ |---|---|---|
218
+ | `review` | `code_reviewer` | `review_notes`, `approval_summary` |
219
+ | `write_tests` | `tester` | `failing_tests`, `test_plan` |
220
+ | `verify_tests` | `tester` | `test_results` |
221
+
222
+ Delegation sequence:
223
+ 1. `minder_agent_list(workflow_step=<step>)` → find available agents for this step.
224
+ `[TRACE] SUBAGENT | list | minder_agent_list | step=<step>`
225
+ 2. `minder_agent_get(name=<name>)` → load full `system_prompt` and `tools` list. Always read before spawning.
226
+ `[TRACE] SUBAGENT | fetch | minder_agent_get | name=<name>`
227
+ 3. Spawn subagent with returned `system_prompt`. Restrict to returned `tools` list only. Pass: `session_id`, `repo_id` (UUID), `repo_path`, `current_step`, `instruction_envelope`.
228
+ `[TRACE] SUBAGENT | spawn | <name> | session_id=<id>, step=<step>`
229
+
230
+ If no agent exists for the step, create one first:
231
+ ```
232
+ minder_agent_store(name=<slug>, title=..., description=..., system_prompt=...,
233
+ tools=[...], workflow_steps=[<step>], artifact_types=[...], is_default=False)
234
+ ```
235
+ `[TRACE] SUBAGENT | create | minder_agent_store | name=<name>`
236
+ """
@@ -194,6 +194,8 @@ class ResourceRegistry:
194
194
  mime_type="application/json",
195
195
  )
196
196
  async def repos_resource() -> str:
197
+ from pathlib import Path as _Path
198
+
197
199
  repos = await store.list_repositories()
198
200
  result: list[dict[str, Any]] = []
199
201
  for repo in repos:
@@ -205,10 +207,18 @@ class ResourceRegistry:
205
207
  "completed_steps": list(state.completed_steps),
206
208
  "blocked_by": list(state.blocked_by),
207
209
  }
210
+ # Derive repo_path from state_path (e.g. /repo/.minder → /repo)
211
+ state_path = str(getattr(repo, "state_path", "") or "")
212
+ if state_path:
213
+ sp = _Path(state_path)
214
+ repo_path = str(sp.parent) if sp.name == ".minder" else state_path
215
+ else:
216
+ repo_path = None
208
217
  result.append(
209
218
  {
210
219
  "id": str(repo.id),
211
220
  "name": repo.repo_name,
221
+ "path": repo_path,
212
222
  "url": getattr(repo, "repo_url", ""),
213
223
  "workflow_state": workflow_info,
214
224
  }
@@ -246,6 +246,7 @@ ALL_TOOLS: list[ToolMeta] = [
246
246
  "Only call to verify authentication is working — not during normal workflows."
247
247
  ),
248
248
  scopeable=False,
249
+ always_available=True,
249
250
  ),
250
251
  ToolMeta(
251
252
  name="minder_auth_login",
@@ -323,6 +324,12 @@ ALWAYS_AVAILABLE_FOR_CLIENTS: frozenset[str] = frozenset(
323
324
  tool.name for tool in ALL_TOOLS if tool.always_available
324
325
  )
325
326
 
327
+ # Default tool_scopes for new agent clients — all scopeable tools.
328
+ # Admin-only non-scopeable tools (auth_login, auth_manage, skill_import_git) are excluded by design.
329
+ DEFAULT_AGENT_TOOL_SCOPES: frozenset[str] = frozenset(
330
+ tool.name for tool in SCOPEABLE_TOOLS
331
+ )
332
+
326
333
 
327
334
  TOOL_USAGE_PATTERNS: dict[str, str] = {
328
335
  # ── Session lifecycle ──────────────────────────────────────────────────────
@@ -186,6 +186,7 @@ class SessionTools:
186
186
  return {
187
187
  "session_id": str(session.id),
188
188
  "name": session.name,
189
+ "repo_id": str(session.repo_id) if session.repo_id else None,
189
190
  "state": session.state,
190
191
  "active_skills": session.active_skills,
191
192
  "project_context": session.project_context,
@@ -242,6 +243,7 @@ class SessionTools:
242
243
  *,
243
244
  state: dict[str, Any] | None = None,
244
245
  active_skills: dict[str, Any] | None = None,
246
+ repo_id: uuid.UUID | None = None,
245
247
  ) -> dict[str, Any]:
246
248
  """Persist the LLM's current task state and active skill set.
247
249
 
@@ -254,19 +256,25 @@ class SessionTools:
254
256
  - Files modified / in progress
255
257
  - Next planned steps
256
258
  - Open questions / blockers
259
+
260
+ Pass ``repo_id`` to permanently link this session to a repository when
261
+ the session was created without one (e.g. during Branch B init).
257
262
  """
258
263
  await self._require_active_session(session_id)
259
- session = await self._store.update_session(
260
- session_id,
261
- state=state or {},
262
- active_skills=active_skills or {},
263
- last_active=datetime.now(UTC),
264
- )
264
+ updates: dict[str, Any] = {
265
+ "state": state or {},
266
+ "active_skills": active_skills or {},
267
+ "last_active": datetime.now(UTC),
268
+ }
269
+ if repo_id is not None:
270
+ updates["repo_id"] = repo_id
271
+ session = await self._store.update_session(session_id, **updates)
265
272
  if session is None:
266
273
  raise ValueError(f"Session not found: {session_id}")
267
274
  return {
268
275
  "session_id": str(session.id),
269
276
  "name": session.name,
277
+ "repo_id": str(session.repo_id) if session.repo_id else None,
270
278
  "state": session.state,
271
279
  "active_skills": session.active_skills,
272
280
  }
@@ -312,6 +320,7 @@ class SessionTools:
312
320
  payload = {
313
321
  "session_id": str(session.id),
314
322
  "name": session.name,
323
+ "repo_id": str(session.repo_id) if session.repo_id else None,
315
324
  "state": session.state,
316
325
  "active_skills": session.active_skills,
317
326
  "project_context": session.project_context,