minder-cli 0.5.2__tar.gz → 0.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {minder_cli-0.5.2 → minder_cli-0.5.4}/PKG-INFO +1 -1
- {minder_cli-0.5.2 → minder_cli-0.5.4}/pyproject.toml +1 -1
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/application/admin/dto.py +24 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/application/admin/use_cases.py +137 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/embedding/local.py +1 -3
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/llm/llama_cpp_llm.py +1 -3
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/api.py +99 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/runtime.py +24 -13
- {minder_cli-0.5.2 → minder_cli-0.5.4}/.gitignore +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/LICENSE +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/README-pypi.md +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/README.md +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/api/routers/prompts.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/application/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/application/admin/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/application/admin/jobs.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/context.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/middleware.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/principal.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/rate_limiter.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/rbac.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/auth/service.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/bootstrap/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/bootstrap/agent_seeder.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/bootstrap/providers.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/bootstrap/transport.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/cache/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/cache/providers.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/chunking/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/chunking/code_splitter.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/chunking/splitter.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/cli.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/config.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/context_compactor.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/continuity.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/dev.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/embedding/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/embedding/base.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/embedding/openai.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/edges.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/executor.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/graph.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/clarification.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/evaluator.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/guard.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/llm.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/planning.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/reasoning.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/reflection.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/reranker.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/retriever.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/verification.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/nodes/workflow_planner.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/runtime.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/graph/state.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/learning/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/learning/error_learner.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/learning/pattern_extractor.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/learning/quality_optimizer.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/learning/skill_synthesizer.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/llm/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/llm/base.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/llm/factory.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/llm/openai.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/agent.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/base.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/client.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/document.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/error.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/graph.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/history.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/job.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/prompt.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/repository.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/rule.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/session.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/skill.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/user.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/models/workflow.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/observability/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/observability/audit.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/observability/logging.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/observability/metrics.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/observability/tracing.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/agent.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/auth.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/ide.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/mcp.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/sync.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/commands/update.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/main.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/utils/common.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/utils/config.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/utils/git.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/cli/utils/version.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/agents.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/context.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/dashboard.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/jobs.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/memories.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/prompts.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/routes.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/runtime.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/search.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/presentation/http/admin/skills.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/prompts/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/prompts/formatter.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/resources/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/retrieval/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/retrieval/hybrid.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/retrieval/mmr.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/retrieval/multi_hop.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/server.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/document.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/error.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/feedback.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/graph.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/history.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/interfaces.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/milvus/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/milvus/client.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/milvus/collections.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/milvus/vector_store.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/mongodb/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/mongodb/client.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/mongodb/graph_store.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/mongodb/indexes.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/mongodb/operational_store.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/relational.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/repo_state.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/rule.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/store/vector.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/agents.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/auth.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/graph.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/ingest.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/memory.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/query.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/registry.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/repo_scanner.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/seeds/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/seeds/default_agents.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/session.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/skills.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/tools/workflow.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/transport/__init__.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/transport/base.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/src/minder/transport/sse.py +0 -0
- {minder_cli-0.5.2 → minder_cli-0.5.4}/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.5.
|
|
3
|
+
Version: 0.5.4
|
|
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
|
|
@@ -479,3 +479,27 @@ class RepositoryLandscapePayload(TypedDict):
|
|
|
479
479
|
nodes: list[RepositoryLandscapeNodePayload]
|
|
480
480
|
edges: list[RepositoryLandscapeEdgePayload]
|
|
481
481
|
summary: dict[str, int]
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class AgentPayload(TypedDict):
|
|
486
|
+
id: str
|
|
487
|
+
name: str
|
|
488
|
+
title: str
|
|
489
|
+
description: str
|
|
490
|
+
system_prompt: str
|
|
491
|
+
tools: list[str]
|
|
492
|
+
workflow_steps: list[str]
|
|
493
|
+
artifact_types: list[str]
|
|
494
|
+
tags: list[str]
|
|
495
|
+
is_default: bool
|
|
496
|
+
created_at: str | None
|
|
497
|
+
updated_at: str | None
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
class AgentListPayload(TypedDict):
|
|
501
|
+
agents: list[AgentPayload]
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
class AgentDetailPayload(TypedDict):
|
|
505
|
+
agent: AgentPayload
|
|
@@ -13,6 +13,9 @@ from minder.application.admin.dto import (
|
|
|
13
13
|
ActivityEventPayload,
|
|
14
14
|
AdminLoginPayload,
|
|
15
15
|
AdminSessionPayload,
|
|
16
|
+
AgentDetailPayload,
|
|
17
|
+
AgentListPayload,
|
|
18
|
+
AgentPayload,
|
|
16
19
|
AuditEventPayload,
|
|
17
20
|
AuditListPayload,
|
|
18
21
|
ClientConnectionTestPayload,
|
|
@@ -651,6 +654,116 @@ class AdminConsoleUseCases:
|
|
|
651
654
|
),
|
|
652
655
|
}
|
|
653
656
|
|
|
657
|
+
# ------------------------------------------------------------------
|
|
658
|
+
# SubAgent management
|
|
659
|
+
# ------------------------------------------------------------------
|
|
660
|
+
|
|
661
|
+
async def list_agents(self) -> AgentListPayload:
|
|
662
|
+
agents = await self._store.list_agents()
|
|
663
|
+
return {"agents": [self.serialize_agent(a) for a in agents]}
|
|
664
|
+
|
|
665
|
+
async def get_agent_detail(self, agent_id: uuid.UUID) -> AgentDetailPayload:
|
|
666
|
+
agent = await self._store.get_agent_by_id(agent_id)
|
|
667
|
+
if agent is None:
|
|
668
|
+
raise LookupError(f"Agent {agent_id} not found")
|
|
669
|
+
return {"agent": self.serialize_agent(agent)}
|
|
670
|
+
|
|
671
|
+
async def create_agent(
|
|
672
|
+
self,
|
|
673
|
+
*,
|
|
674
|
+
name: str,
|
|
675
|
+
title: str = "",
|
|
676
|
+
description: str = "",
|
|
677
|
+
system_prompt: str = "",
|
|
678
|
+
tools: list[str] | None = None,
|
|
679
|
+
workflow_steps: list[str] | None = None,
|
|
680
|
+
artifact_types: list[str] | None = None,
|
|
681
|
+
tags: list[str] | None = None,
|
|
682
|
+
is_default: bool = False,
|
|
683
|
+
) -> AgentDetailPayload:
|
|
684
|
+
agent = await self._store.create_agent(
|
|
685
|
+
name=name,
|
|
686
|
+
title=title,
|
|
687
|
+
description=description,
|
|
688
|
+
system_prompt=system_prompt,
|
|
689
|
+
tools=tools or [],
|
|
690
|
+
workflow_steps=workflow_steps or [],
|
|
691
|
+
artifact_types=artifact_types or [],
|
|
692
|
+
tags=tags or [],
|
|
693
|
+
is_default=is_default,
|
|
694
|
+
)
|
|
695
|
+
return {"agent": self.serialize_agent(agent)}
|
|
696
|
+
|
|
697
|
+
async def update_agent(
|
|
698
|
+
self,
|
|
699
|
+
agent_id: uuid.UUID,
|
|
700
|
+
*,
|
|
701
|
+
name: str | None = None,
|
|
702
|
+
title: str | None = None,
|
|
703
|
+
description: str | None = None,
|
|
704
|
+
system_prompt: str | None = None,
|
|
705
|
+
tools: list[str] | None = None,
|
|
706
|
+
workflow_steps: list[str] | None = None,
|
|
707
|
+
artifact_types: list[str] | None = None,
|
|
708
|
+
tags: list[str] | None = None,
|
|
709
|
+
is_default: bool | None = None,
|
|
710
|
+
) -> AgentDetailPayload:
|
|
711
|
+
kwargs: dict[str, Any] = {}
|
|
712
|
+
if name is not None:
|
|
713
|
+
kwargs["name"] = name
|
|
714
|
+
if title is not None:
|
|
715
|
+
kwargs["title"] = title
|
|
716
|
+
if description is not None:
|
|
717
|
+
kwargs["description"] = description
|
|
718
|
+
if system_prompt is not None:
|
|
719
|
+
kwargs["system_prompt"] = system_prompt
|
|
720
|
+
if tools is not None:
|
|
721
|
+
kwargs["tools"] = tools
|
|
722
|
+
if workflow_steps is not None:
|
|
723
|
+
kwargs["workflow_steps"] = workflow_steps
|
|
724
|
+
if artifact_types is not None:
|
|
725
|
+
kwargs["artifact_types"] = artifact_types
|
|
726
|
+
if tags is not None:
|
|
727
|
+
kwargs["tags"] = tags
|
|
728
|
+
if is_default is not None:
|
|
729
|
+
kwargs["is_default"] = is_default
|
|
730
|
+
updated = await self._store.update_agent(agent_id, **kwargs)
|
|
731
|
+
if updated is None:
|
|
732
|
+
raise LookupError(f"Agent {agent_id} not found")
|
|
733
|
+
return {"agent": self.serialize_agent(updated)}
|
|
734
|
+
|
|
735
|
+
async def delete_agent(self, agent_id: uuid.UUID) -> dict[str, bool]:
|
|
736
|
+
existing = await self._store.get_agent_by_id(agent_id)
|
|
737
|
+
if existing is None:
|
|
738
|
+
raise LookupError(f"Agent {agent_id} not found")
|
|
739
|
+
await self._store.delete_agent(agent_id)
|
|
740
|
+
return {"deleted": True}
|
|
741
|
+
|
|
742
|
+
@staticmethod
|
|
743
|
+
def serialize_agent(agent: Any) -> AgentPayload:
|
|
744
|
+
return {
|
|
745
|
+
"id": str(agent.id),
|
|
746
|
+
"name": getattr(agent, "name", ""),
|
|
747
|
+
"title": getattr(agent, "title", ""),
|
|
748
|
+
"description": getattr(agent, "description", ""),
|
|
749
|
+
"system_prompt": getattr(agent, "system_prompt", ""),
|
|
750
|
+
"tools": list(getattr(agent, "tools", []) or []),
|
|
751
|
+
"workflow_steps": list(getattr(agent, "workflow_steps", []) or []),
|
|
752
|
+
"artifact_types": list(getattr(agent, "artifact_types", []) or []),
|
|
753
|
+
"tags": list(getattr(agent, "tags", []) or []),
|
|
754
|
+
"is_default": bool(getattr(agent, "is_default", False)),
|
|
755
|
+
"created_at": (
|
|
756
|
+
agent.created_at.isoformat()
|
|
757
|
+
if getattr(agent, "created_at", None)
|
|
758
|
+
else None
|
|
759
|
+
),
|
|
760
|
+
"updated_at": (
|
|
761
|
+
agent.updated_at.isoformat()
|
|
762
|
+
if getattr(agent, "updated_at", None)
|
|
763
|
+
else None
|
|
764
|
+
),
|
|
765
|
+
}
|
|
766
|
+
|
|
654
767
|
# ------------------------------------------------------------------
|
|
655
768
|
# Session management
|
|
656
769
|
# ------------------------------------------------------------------
|
|
@@ -788,19 +901,43 @@ class AdminConsoleUseCases:
|
|
|
788
901
|
if not normalized_path:
|
|
789
902
|
raise ValueError("Repository path is required")
|
|
790
903
|
updates["state_path"] = normalized_path
|
|
904
|
+
new_workflow_id: uuid.UUID | None = _UNSET # type: ignore[assignment]
|
|
791
905
|
if workflow_id is not _UNSET:
|
|
792
906
|
if workflow_id is None or str(workflow_id).strip() == "":
|
|
793
907
|
updates["workflow_id"] = None
|
|
908
|
+
new_workflow_id = None
|
|
794
909
|
else:
|
|
795
910
|
wf_id = uuid.UUID(str(workflow_id))
|
|
796
911
|
workflow = await self._store.get_workflow_by_id(wf_id)
|
|
797
912
|
if workflow is None:
|
|
798
913
|
raise LookupError(f"Workflow {wf_id} not found")
|
|
799
914
|
updates["workflow_id"] = str(wf_id)
|
|
915
|
+
new_workflow_id = wf_id
|
|
800
916
|
|
|
801
917
|
updated = await self._store.update_repository(repo_id, **updates)
|
|
802
918
|
if updated is None:
|
|
803
919
|
raise LookupError("Repository not found")
|
|
920
|
+
|
|
921
|
+
# Create workflow_state when a workflow is first assigned to a repo
|
|
922
|
+
if new_workflow_id is not _UNSET and new_workflow_id is not None: # type: ignore[comparison-overlap]
|
|
923
|
+
existing_state = await self._store.get_workflow_state_by_repo(repo_id)
|
|
924
|
+
if existing_state is None:
|
|
925
|
+
workflow_obj = await self._store.get_workflow_by_id(new_workflow_id)
|
|
926
|
+
steps = list(getattr(workflow_obj, "steps", []) or []) if workflow_obj else []
|
|
927
|
+
step_names = [
|
|
928
|
+
s["name"] for s in steps if isinstance(s, dict) and "name" in s
|
|
929
|
+
]
|
|
930
|
+
first_step = step_names[0] if step_names else ""
|
|
931
|
+
second_step = step_names[1] if len(step_names) > 1 else None
|
|
932
|
+
await self._store.create_workflow_state(
|
|
933
|
+
repo_id=repo_id,
|
|
934
|
+
current_step=first_step,
|
|
935
|
+
completed_steps=[],
|
|
936
|
+
blocked_by=[],
|
|
937
|
+
artifacts={},
|
|
938
|
+
next_step=second_step,
|
|
939
|
+
)
|
|
940
|
+
|
|
804
941
|
return await self.get_repository_detail(repo_id)
|
|
805
942
|
|
|
806
943
|
async def delete_repository(self, repo_id: uuid.UUID) -> DeleteRepositoryPayload:
|
|
@@ -54,9 +54,7 @@ class LocalEmbeddingProvider:
|
|
|
54
54
|
return
|
|
55
55
|
|
|
56
56
|
if not llama_cpp_usable():
|
|
57
|
-
logger.warning(
|
|
58
|
-
"CPU does not support AVX2; llama.cpp unavailable. Using mock embedding."
|
|
59
|
-
)
|
|
57
|
+
logger.warning("llama.cpp not usable on this host; embedding running in mock mode.")
|
|
60
58
|
return
|
|
61
59
|
|
|
62
60
|
try:
|
|
@@ -52,9 +52,7 @@ class LlamaCppLLM:
|
|
|
52
52
|
return
|
|
53
53
|
|
|
54
54
|
if not llama_cpp_usable():
|
|
55
|
-
logger.warning(
|
|
56
|
-
"CPU does not support AVX2; llama.cpp unavailable. Falling back to mock mode."
|
|
57
|
-
)
|
|
55
|
+
logger.warning("llama.cpp not usable on this host; LLM running in mock mode.")
|
|
58
56
|
return
|
|
59
57
|
|
|
60
58
|
cache_key = f"{self._model_repo}:{self._model_file}"
|
|
@@ -520,6 +520,98 @@ def build_admin_api_routes(context: AdminRouteContext) -> list[BaseRoute]:
|
|
|
520
520
|
|
|
521
521
|
return JSONResponse({"error": "Method not allowed"}, status_code=405)
|
|
522
522
|
|
|
523
|
+
# ------------------------------------------------------------------
|
|
524
|
+
# SubAgent management
|
|
525
|
+
# ------------------------------------------------------------------
|
|
526
|
+
|
|
527
|
+
async def admin_agents(request):
|
|
528
|
+
try:
|
|
529
|
+
await context.admin_user_from_request(request)
|
|
530
|
+
except PermissionError:
|
|
531
|
+
return JSONResponse({"error": "Admin role required"}, status_code=403)
|
|
532
|
+
except Exception as exc:
|
|
533
|
+
return JSONResponse({"error": str(exc)}, status_code=401)
|
|
534
|
+
|
|
535
|
+
if request.method == "GET":
|
|
536
|
+
return JSONResponse(await context.use_cases.list_agents())
|
|
537
|
+
|
|
538
|
+
if request.method == "POST":
|
|
539
|
+
try:
|
|
540
|
+
payload = await request.json()
|
|
541
|
+
except Exception:
|
|
542
|
+
return JSONResponse({"error": "Invalid JSON"}, status_code=400)
|
|
543
|
+
name = str(payload.get("name", "")).strip()
|
|
544
|
+
if not name:
|
|
545
|
+
return JSONResponse({"error": "name is required"}, status_code=400)
|
|
546
|
+
try:
|
|
547
|
+
return JSONResponse(
|
|
548
|
+
await context.use_cases.create_agent(
|
|
549
|
+
name=name,
|
|
550
|
+
title=str(payload.get("title", "")),
|
|
551
|
+
description=str(payload.get("description", "")),
|
|
552
|
+
system_prompt=str(payload.get("system_prompt", "")),
|
|
553
|
+
tools=payload.get("tools") or [],
|
|
554
|
+
workflow_steps=payload.get("workflow_steps") or [],
|
|
555
|
+
artifact_types=payload.get("artifact_types") or [],
|
|
556
|
+
tags=payload.get("tags") or [],
|
|
557
|
+
is_default=bool(payload.get("is_default", False)),
|
|
558
|
+
),
|
|
559
|
+
status_code=201,
|
|
560
|
+
)
|
|
561
|
+
except Exception as exc:
|
|
562
|
+
return JSONResponse({"error": str(exc)}, status_code=400)
|
|
563
|
+
|
|
564
|
+
return JSONResponse({"error": "Method not allowed"}, status_code=405)
|
|
565
|
+
|
|
566
|
+
async def agent_detail(request):
|
|
567
|
+
try:
|
|
568
|
+
await context.admin_user_from_request(request)
|
|
569
|
+
except PermissionError:
|
|
570
|
+
return JSONResponse({"error": "Admin role required"}, status_code=403)
|
|
571
|
+
except Exception as exc:
|
|
572
|
+
return JSONResponse({"error": str(exc)}, status_code=401)
|
|
573
|
+
|
|
574
|
+
agent_id = uuid.UUID(str(request.path_params["agent_id"]))
|
|
575
|
+
|
|
576
|
+
if request.method == "GET":
|
|
577
|
+
try:
|
|
578
|
+
return JSONResponse(await context.use_cases.get_agent_detail(agent_id))
|
|
579
|
+
except LookupError:
|
|
580
|
+
return JSONResponse({"error": "Agent not found"}, status_code=404)
|
|
581
|
+
|
|
582
|
+
if request.method == "PATCH":
|
|
583
|
+
try:
|
|
584
|
+
payload = await request.json()
|
|
585
|
+
except Exception:
|
|
586
|
+
return JSONResponse({"error": "Invalid JSON"}, status_code=400)
|
|
587
|
+
try:
|
|
588
|
+
return JSONResponse(
|
|
589
|
+
await context.use_cases.update_agent(
|
|
590
|
+
agent_id,
|
|
591
|
+
name=payload.get("name"),
|
|
592
|
+
title=payload.get("title"),
|
|
593
|
+
description=payload.get("description"),
|
|
594
|
+
system_prompt=payload.get("system_prompt"),
|
|
595
|
+
tools=payload.get("tools"),
|
|
596
|
+
workflow_steps=payload.get("workflow_steps"),
|
|
597
|
+
artifact_types=payload.get("artifact_types"),
|
|
598
|
+
tags=payload.get("tags"),
|
|
599
|
+
is_default=payload.get("is_default"),
|
|
600
|
+
)
|
|
601
|
+
)
|
|
602
|
+
except LookupError:
|
|
603
|
+
return JSONResponse({"error": "Agent not found"}, status_code=404)
|
|
604
|
+
except Exception as exc:
|
|
605
|
+
return JSONResponse({"error": str(exc)}, status_code=400)
|
|
606
|
+
|
|
607
|
+
if request.method == "DELETE":
|
|
608
|
+
try:
|
|
609
|
+
return JSONResponse(await context.use_cases.delete_agent(agent_id))
|
|
610
|
+
except LookupError:
|
|
611
|
+
return JSONResponse({"error": "Agent not found"}, status_code=404)
|
|
612
|
+
|
|
613
|
+
return JSONResponse({"error": "Method not allowed"}, status_code=405)
|
|
614
|
+
|
|
523
615
|
# ------------------------------------------------------------------
|
|
524
616
|
# Workflow management
|
|
525
617
|
# ------------------------------------------------------------------
|
|
@@ -1331,6 +1423,13 @@ def build_admin_api_routes(context: AdminRouteContext) -> list[BaseRoute]:
|
|
|
1331
1423
|
user_detail,
|
|
1332
1424
|
methods=["GET", "PATCH", "DELETE"],
|
|
1333
1425
|
),
|
|
1426
|
+
# SubAgent management
|
|
1427
|
+
Route("/v1/admin/agents", admin_agents, methods=["GET", "POST"]),
|
|
1428
|
+
Route(
|
|
1429
|
+
"/v1/admin/agents/{agent_id:uuid}",
|
|
1430
|
+
agent_detail,
|
|
1431
|
+
methods=["GET", "PATCH", "DELETE"],
|
|
1432
|
+
),
|
|
1334
1433
|
# Workflow management
|
|
1335
1434
|
Route("/v1/admin/workflows", admin_workflows, methods=["GET", "POST"]),
|
|
1336
1435
|
Route(
|
|
@@ -26,18 +26,22 @@ def load_attr(module_name: str, attr_name: str) -> Any | None:
|
|
|
26
26
|
def llama_cpp_usable() -> bool:
|
|
27
27
|
"""Return True only if llama.cpp can actually run on this CPU.
|
|
28
28
|
|
|
29
|
-
Some CI runners
|
|
30
|
-
|
|
31
|
-
a subprocess that initialises the
|
|
32
|
-
is killed by SIGILL (returncode == -signal.SIGILL) we mark
|
|
33
|
-
as unavailable and fall back to mock mode.
|
|
34
|
-
|
|
29
|
+
Some CI runners / VM hypervisors block AVX2 instructions even when
|
|
30
|
+
/proc/cpuinfo advertises them, causing an unrecoverable SIGILL. We
|
|
31
|
+
probe by running a subprocess that initialises the ggml backend; if the
|
|
32
|
+
subprocess is killed by SIGILL (returncode == -signal.SIGILL) we mark
|
|
33
|
+
the library as unavailable and fall back to mock mode.
|
|
34
|
+
|
|
35
|
+
Build the Docker image with CMAKE_ARGS containing -DGGML_AVX2=OFF (and
|
|
36
|
+
related flags) to compile a portable binary that avoids SIGILL entirely.
|
|
37
|
+
Result is cached for the lifetime of the process.
|
|
35
38
|
"""
|
|
36
39
|
global _LLAMA_CPP_PROBE
|
|
37
40
|
if _LLAMA_CPP_PROBE is not None:
|
|
38
41
|
return _LLAMA_CPP_PROBE
|
|
39
42
|
|
|
40
43
|
if not module_available("llama_cpp"):
|
|
44
|
+
logger.warning("llama-cpp-python is not installed. Falling back to mock mode.")
|
|
41
45
|
_LLAMA_CPP_PROBE = False
|
|
42
46
|
return False
|
|
43
47
|
|
|
@@ -48,19 +52,26 @@ def llama_cpp_usable() -> bool:
|
|
|
48
52
|
"-c",
|
|
49
53
|
# Instantiating Llama triggers ggml_backend_reg_count → ggml_cpu_init.
|
|
50
54
|
# /dev/null causes a model-load error (returncode 1) on healthy CPUs;
|
|
51
|
-
# SIGILL
|
|
55
|
+
# SIGILL (returncode -4) means the CPU doesn't support the compiled ISA.
|
|
52
56
|
"from llama_cpp import Llama; Llama(model_path='/dev/null', verbose=False)",
|
|
53
57
|
],
|
|
54
58
|
capture_output=True,
|
|
55
59
|
timeout=30,
|
|
56
60
|
)
|
|
57
|
-
|
|
61
|
+
if proc.returncode == -signal.SIGILL:
|
|
62
|
+
logger.warning(
|
|
63
|
+
"llama.cpp unavailable: CPU or hypervisor blocked an instruction "
|
|
64
|
+
"(SIGILL). Rebuild the image with CMAKE_ARGS containing "
|
|
65
|
+
"-DGGML_AVX2=OFF to fix this. Falling back to mock mode."
|
|
66
|
+
)
|
|
67
|
+
_LLAMA_CPP_PROBE = False
|
|
68
|
+
else:
|
|
69
|
+
_LLAMA_CPP_PROBE = True
|
|
70
|
+
except subprocess.TimeoutExpired:
|
|
71
|
+
logger.warning("llama.cpp usability probe timed out. Falling back to mock mode.")
|
|
72
|
+
_LLAMA_CPP_PROBE = False
|
|
58
73
|
except Exception as exc:
|
|
59
|
-
logger.warning("llama.cpp usability probe error: %s", exc)
|
|
74
|
+
logger.warning("llama.cpp usability probe error: %s. Falling back to mock mode.", exc)
|
|
60
75
|
_LLAMA_CPP_PROBE = False
|
|
61
76
|
|
|
62
|
-
if not _LLAMA_CPP_PROBE:
|
|
63
|
-
logger.warning(
|
|
64
|
-
"llama.cpp unavailable on this CPU (SIGILL probe). Falling back to mock mode."
|
|
65
|
-
)
|
|
66
77
|
return _LLAMA_CPP_PROBE
|
|
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
|
|
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
|