agent-devkit 0.2.0 → 0.3.1
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.
- package/README.md +66 -13
- package/bin/agent.mjs +133 -7
- package/package.json +1 -1
- package/runtime/README.md +205 -13
- package/runtime/agent +31 -5
- package/runtime/agents/README.md +18 -0
- package/runtime/agents/contribution-reviewer/AGENTS.md +8 -0
- package/runtime/agents/contribution-reviewer/README.md +8 -0
- package/runtime/agents/contribution-reviewer/agent.yaml +40 -0
- package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/capability.yaml +27 -0
- package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/decision-rules.md +5 -0
- package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/workflow.md +6 -0
- package/runtime/agents/contribution-reviewer/capabilities/review-contribution/capability.yaml +25 -0
- package/runtime/agents/contribution-reviewer/capabilities/review-contribution/decision-rules.md +5 -0
- package/runtime/agents/contribution-reviewer/capabilities/review-contribution/workflow.md +5 -0
- package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/capability.yaml +26 -0
- package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/decision-rules.md +5 -0
- package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/workflow.md +6 -0
- package/runtime/agents/contribution-reviewer/infra/README.md +6 -0
- package/runtime/agents/contribution-reviewer/knowledge/context.md +8 -0
- package/runtime/agents/contribution-reviewer/knowledge/system.md +8 -0
- package/runtime/agents/contribution-reviewer/templates/README.md +3 -0
- package/runtime/agents/knowledge-author/AGENTS.md +7 -0
- package/runtime/agents/knowledge-author/README.md +7 -0
- package/runtime/agents/knowledge-author/agent.yaml +37 -0
- package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/capability.yaml +30 -0
- package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/decision-rules.md +6 -0
- package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/workflow.md +7 -0
- package/runtime/agents/knowledge-author/infra/.gitkeep +1 -0
- package/runtime/agents/knowledge-author/knowledge/context.md +4 -0
- package/runtime/agents/knowledge-author/knowledge/system.md +4 -0
- package/runtime/agents/knowledge-author/templates/.gitkeep +1 -0
- package/runtime/agents/knowledge-curator/AGENTS.md +7 -0
- package/runtime/agents/knowledge-curator/README.md +6 -0
- package/runtime/agents/knowledge-curator/agent.yaml +37 -0
- package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/capability.yaml +29 -0
- package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/decision-rules.md +6 -0
- package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/workflow.md +7 -0
- package/runtime/agents/knowledge-curator/infra/.gitkeep +1 -0
- package/runtime/agents/knowledge-curator/knowledge/context.md +4 -0
- package/runtime/agents/knowledge-curator/knowledge/system.md +4 -0
- package/runtime/agents/knowledge-curator/templates/.gitkeep +1 -0
- package/runtime/agents/knowledge-infra-builder/AGENTS.md +8 -0
- package/runtime/agents/knowledge-infra-builder/README.md +8 -0
- package/runtime/agents/knowledge-infra-builder/agent.yaml +38 -0
- package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/capability.yaml +30 -0
- package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/decision-rules.md +6 -0
- package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/workflow.md +7 -0
- package/runtime/agents/knowledge-infra-builder/infra/.gitkeep +1 -0
- package/runtime/agents/knowledge-infra-builder/knowledge/context.md +4 -0
- package/runtime/agents/knowledge-infra-builder/knowledge/system.md +4 -0
- package/runtime/agents/knowledge-infra-builder/templates/.gitkeep +1 -0
- package/runtime/agents/knowledge-owner/AGENTS.md +7 -0
- package/runtime/agents/knowledge-owner/README.md +6 -0
- package/runtime/agents/knowledge-owner/agent.yaml +37 -0
- package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/capability.yaml +28 -0
- package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/decision-rules.md +6 -0
- package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/workflow.md +7 -0
- package/runtime/agents/knowledge-owner/infra/.gitkeep +1 -0
- package/runtime/agents/knowledge-owner/knowledge/context.md +4 -0
- package/runtime/agents/knowledge-owner/knowledge/system.md +4 -0
- package/runtime/agents/knowledge-owner/templates/.gitkeep +1 -0
- package/runtime/agents/knowledge-reviewer/AGENTS.md +7 -0
- package/runtime/agents/knowledge-reviewer/README.md +7 -0
- package/runtime/agents/knowledge-reviewer/agent.yaml +36 -0
- package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/capability.yaml +26 -0
- package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/decision-rules.md +6 -0
- package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/workflow.md +7 -0
- package/runtime/agents/knowledge-reviewer/infra/.gitkeep +1 -0
- package/runtime/agents/knowledge-reviewer/knowledge/context.md +4 -0
- package/runtime/agents/knowledge-reviewer/knowledge/system.md +4 -0
- package/runtime/agents/knowledge-reviewer/templates/.gitkeep +1 -0
- package/runtime/agents/local-memory-manager/AGENTS.md +5 -0
- package/runtime/agents/local-memory-manager/README.md +7 -0
- package/runtime/agents/local-memory-manager/agent.yaml +38 -0
- package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/capability.yaml +19 -0
- package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/decision-rules.md +5 -0
- package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/workflow.md +6 -0
- package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/capability.yaml +19 -0
- package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/decision-rules.md +5 -0
- package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/workflow.md +5 -0
- package/runtime/agents/local-memory-manager/infra/.gitkeep +1 -0
- package/runtime/agents/local-memory-manager/knowledge/context.md +4 -0
- package/runtime/agents/local-memory-manager/knowledge/system.md +4 -0
- package/runtime/agents/local-memory-manager/templates/.gitkeep +1 -0
- package/runtime/agents/memory-sync-manager/AGENTS.md +7 -0
- package/runtime/agents/memory-sync-manager/README.md +7 -0
- package/runtime/agents/memory-sync-manager/agent.yaml +37 -0
- package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/capability.yaml +29 -0
- package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/decision-rules.md +6 -0
- package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/workflow.md +7 -0
- package/runtime/agents/memory-sync-manager/infra/.gitkeep +1 -0
- package/runtime/agents/memory-sync-manager/knowledge/context.md +4 -0
- package/runtime/agents/memory-sync-manager/knowledge/system.md +4 -0
- package/runtime/agents/memory-sync-manager/templates/.gitkeep +1 -0
- package/runtime/agents/shared-memory-curator/AGENTS.md +5 -0
- package/runtime/agents/shared-memory-curator/README.md +6 -0
- package/runtime/agents/shared-memory-curator/agent.yaml +38 -0
- package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/capability.yaml +19 -0
- package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/decision-rules.md +5 -0
- package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/workflow.md +5 -0
- package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/capability.yaml +19 -0
- package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/decision-rules.md +5 -0
- package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/workflow.md +5 -0
- package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/capability.yaml +19 -0
- package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/decision-rules.md +5 -0
- package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/workflow.md +5 -0
- package/runtime/agents/shared-memory-curator/infra/.gitkeep +1 -0
- package/runtime/agents/shared-memory-curator/knowledge/context.md +5 -0
- package/runtime/agents/shared-memory-curator/knowledge/system.md +4 -0
- package/runtime/agents/shared-memory-curator/templates/.gitkeep +1 -0
- package/runtime/cli/README.md +47 -8
- package/runtime/cli/aikit/__init__.py +1 -1
- package/runtime/cli/aikit/agent_registry.py +4 -2
- package/runtime/cli/aikit/agentic_commands.py +158 -0
- package/runtime/cli/aikit/app_home.py +2 -0
- package/runtime/cli/aikit/audit.py +16 -6
- package/runtime/cli/aikit/catalog.py +278 -8
- package/runtime/cli/aikit/cli_dispatch.py +489 -13
- package/runtime/cli/aikit/cli_parser.py +146 -8
- package/runtime/cli/aikit/contribution.py +132 -2
- package/runtime/cli/aikit/doctor_runtime.py +85 -0
- package/runtime/cli/aikit/embedded_mini_brain.py +351 -0
- package/runtime/cli/aikit/eval.py +356 -10
- package/runtime/cli/aikit/human_output.py +310 -4
- package/runtime/cli/aikit/interactive_wizard.py +146 -0
- package/runtime/cli/aikit/knowledge_base.py +1067 -0
- package/runtime/cli/aikit/llm.py +40 -6
- package/runtime/cli/aikit/local_artifacts.py +444 -0
- package/runtime/cli/aikit/local_llm.py +176 -0
- package/runtime/cli/aikit/local_llm_operator.py +15 -5
- package/runtime/cli/aikit/main.py +15 -0
- package/runtime/cli/aikit/mcp_manifest.py +798 -0
- package/runtime/cli/aikit/mcp_tools.py +643 -5
- package/runtime/cli/aikit/memory.py +405 -0
- package/runtime/cli/aikit/mini_brain.py +56 -25
- package/runtime/cli/aikit/model_router.py +42 -9
- package/runtime/cli/aikit/natural_prompt_runtime.py +194 -2
- package/runtime/cli/aikit/ollama.py +64 -15
- package/runtime/cli/aikit/onboarding.py +551 -0
- package/runtime/cli/aikit/output.py +67 -0
- package/runtime/cli/aikit/prompt_injection.py +12 -1
- package/runtime/cli/aikit/review_gate.py +14 -2
- package/runtime/cli/aikit/roadmap_cli.py +1 -1
- package/runtime/cli/aikit/secrets.py +3 -2
- package/runtime/cli/aikit/setup_wizard_payload.py +3 -0
- package/runtime/cli/aikit/shared_memory.py +415 -0
- package/runtime/cli/aikit/specialist_readiness.py +152 -0
- package/runtime/cli/aikit/tasks.py +104 -1
- package/runtime/cli/aikit/team.py +380 -0
- package/runtime/cli/aikit/toolchain.py +7 -2
- package/runtime/cli/aikit/workflows.py +115 -14
- package/runtime/models/qwen2.5-0.5b-instruct/manifest.json +30 -0
- package/runtime/providers/knowledge-github.yaml +40 -0
- package/runtime/providers/knowledge-google-drive.yaml +32 -0
- package/runtime/providers/knowledge-local.yaml +26 -0
- package/runtime/providers/knowledge-notion.yaml +32 -0
- package/runtime/providers/knowledge-obsidian.yaml +24 -0
- package/runtime/providers/knowledge-onedrive.yaml +36 -0
- package/runtime/providers/knowledge-s3.yaml +45 -0
- package/runtime/providers/knowledge-sharepoint.yaml +39 -0
- package/runtime/providers/knowledge-supabase.yaml +43 -0
- package/runtime/providers/knowledge-vector.yaml +39 -0
- package/runtime/requirements.txt +6 -0
- package/runtime/scripts/docker-cli-qa.sh +453 -0
- package/runtime/scripts/release-catalog-snapshot.json +55 -4
- package/runtime/scripts/release-gate.py +54 -13
- package/runtime/tooling/toolchain.yaml +92 -0
- package/runtime/vendor/skills/napkin/napkin.md +21 -7
- package/runtime/workflows/azure-card-analysis/README.md +3 -0
- package/runtime/workflows/azure-card-analysis/workflow.yaml +30 -0
- package/runtime/workflows/daily-pr-review/README.md +3 -0
- package/runtime/workflows/daily-pr-review/workflow.yaml +31 -0
- package/runtime/workflows/incident-analysis/README.md +3 -0
- package/runtime/workflows/incident-analysis/workflow.yaml +33 -0
- package/runtime/workflows/release-prep/README.md +3 -0
- package/runtime/workflows/release-prep/workflow.yaml +30 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
"""Embedded mini-brain runtime backed by an on-demand GGUF model."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import os
|
|
7
|
+
import shutil
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
import urllib.error
|
|
11
|
+
import urllib.request
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from cli.aikit.app_home import app_path, ensure_app_home
|
|
16
|
+
from cli.aikit.identity import identity_system_prompt
|
|
17
|
+
from cli.aikit.runtime_paths import ROOT
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
EMBEDDED_BACKEND_ID = "embedded-mini-brain"
|
|
21
|
+
EMBEDDED_MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
|
|
22
|
+
EMBEDDED_MODEL_NAME = "qwen2.5-0.5b-instruct"
|
|
23
|
+
EMBEDDED_MODEL_SOURCE = "https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q2_k.gguf"
|
|
24
|
+
EMBEDDED_MODEL_SIZE_BYTES = 415182688
|
|
25
|
+
EMBEDDED_MODEL_PATH = app_path("models", EMBEDDED_MODEL_NAME)
|
|
26
|
+
EMBEDDED_MANIFEST_PATH = ROOT / "models" / EMBEDDED_MODEL_NAME / "manifest.json"
|
|
27
|
+
EMBEDDED_MODEL_FILE = EMBEDDED_MODEL_PATH / "qwen2.5-0.5b-instruct-q2_k.gguf"
|
|
28
|
+
EMBEDDED_MODEL_SHA256 = "9ee36184e616dfc76df4f5dd66f908dbde6979524ae36e6cefb67f532f798cb8"
|
|
29
|
+
EMBEDDED_RUNTIME = "llama-cpp-python"
|
|
30
|
+
EMBEDDED_RUNTIME_REQUIREMENT = "llama-cpp-python>=0.3.9"
|
|
31
|
+
EMBEDDED_MAX_RESPONSE_CHARS = 2000
|
|
32
|
+
DEFAULT_MAX_TOKENS = 220
|
|
33
|
+
DEFAULT_CONTEXT_TOKENS = 2048
|
|
34
|
+
SMOKE_RESPONSE_ENV = "AGENT_DEVKIT_EMBEDDED_SMOKE_RESPONSE"
|
|
35
|
+
SOURCE_ENV = "AGENT_DEVKIT_EMBEDDED_MODEL_SOURCE"
|
|
36
|
+
SKIP_DEP_INSTALL_ENV = "AGENT_DEVKIT_EMBEDDED_SKIP_DEP_INSTALL"
|
|
37
|
+
|
|
38
|
+
_LLAMA_CACHE: Any | None = None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def embedded_mini_brain_status() -> dict[str, Any]:
|
|
42
|
+
manifest_exists = EMBEDDED_MANIFEST_PATH.exists()
|
|
43
|
+
model_exists = EMBEDDED_MODEL_FILE.exists()
|
|
44
|
+
model_sha256 = sha256_file(EMBEDDED_MODEL_FILE) if model_exists else None
|
|
45
|
+
smoke_mode = bool(os.environ.get(SMOKE_RESPONSE_ENV))
|
|
46
|
+
model_file_valid = smoke_mode or (model_sha256 == EMBEDDED_MODEL_SHA256 if model_exists else False)
|
|
47
|
+
dependency = llama_cpp_dependency_status()
|
|
48
|
+
available = model_file_valid and dependency["status"] == "ok"
|
|
49
|
+
if available:
|
|
50
|
+
status = "ok"
|
|
51
|
+
elif not model_exists:
|
|
52
|
+
status = "not-installed"
|
|
53
|
+
elif not model_file_valid:
|
|
54
|
+
status = "invalid-model"
|
|
55
|
+
elif dependency["status"] != "ok":
|
|
56
|
+
status = "dependency-missing"
|
|
57
|
+
else:
|
|
58
|
+
status = "missing"
|
|
59
|
+
return {
|
|
60
|
+
"kind": "embedded-mini-brain",
|
|
61
|
+
"id": EMBEDDED_BACKEND_ID,
|
|
62
|
+
"status": status,
|
|
63
|
+
"available": available,
|
|
64
|
+
"configured": model_file_valid,
|
|
65
|
+
"provider": EMBEDDED_BACKEND_ID,
|
|
66
|
+
"runtime": EMBEDDED_RUNTIME,
|
|
67
|
+
"runtime_requirement": EMBEDDED_RUNTIME_REQUIREMENT,
|
|
68
|
+
"model": EMBEDDED_MODEL_ID,
|
|
69
|
+
"hf_model": EMBEDDED_MODEL_ID,
|
|
70
|
+
"model_name": EMBEDDED_MODEL_NAME,
|
|
71
|
+
"model_path": str(EMBEDDED_MODEL_PATH),
|
|
72
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
73
|
+
"model_file_present": model_exists,
|
|
74
|
+
"model_file_valid": model_file_valid,
|
|
75
|
+
"model_file_sha256": model_sha256,
|
|
76
|
+
"smoke_mode": smoke_mode,
|
|
77
|
+
"model_size_bytes": EMBEDDED_MODEL_SIZE_BYTES,
|
|
78
|
+
"download_url": model_source(),
|
|
79
|
+
"sha256": EMBEDDED_MODEL_SHA256,
|
|
80
|
+
"manifest_path": str(EMBEDDED_MANIFEST_PATH),
|
|
81
|
+
"manifest_present": manifest_exists,
|
|
82
|
+
"dependency": dependency,
|
|
83
|
+
"auth": "none",
|
|
84
|
+
"stored_secret": False,
|
|
85
|
+
"install_command": "agent setup mini-brain --yes",
|
|
86
|
+
"message": (
|
|
87
|
+
"Embedded Qwen2.5 mini-brain is available for real local inference."
|
|
88
|
+
if available
|
|
89
|
+
else "Embedded mini-brain model is not installed or llama_cpp runtime is missing."
|
|
90
|
+
),
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def invoke_embedded_mini_brain(prompt: str, *, public_name: str = "Agent DevKit") -> str:
|
|
95
|
+
status = embedded_mini_brain_status()
|
|
96
|
+
if not status["available"]:
|
|
97
|
+
raise EmbeddedMiniBrainError(status["message"])
|
|
98
|
+
smoke_response = os.environ.get(SMOKE_RESPONSE_ENV)
|
|
99
|
+
if smoke_response:
|
|
100
|
+
return f"{public_name}: {smoke_response}"[:EMBEDDED_MAX_RESPONSE_CHARS]
|
|
101
|
+
llama = load_llama()
|
|
102
|
+
payload = llama.create_chat_completion(
|
|
103
|
+
messages=[
|
|
104
|
+
{
|
|
105
|
+
"role": "system",
|
|
106
|
+
"content": embedded_system_prompt(public_name),
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"role": "user",
|
|
110
|
+
"content": prompt,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
max_tokens=int(os.environ.get("AGENT_DEVKIT_EMBEDDED_MAX_TOKENS", str(DEFAULT_MAX_TOKENS))),
|
|
114
|
+
temperature=float(os.environ.get("AGENT_DEVKIT_EMBEDDED_TEMPERATURE", "0.2")),
|
|
115
|
+
top_p=float(os.environ.get("AGENT_DEVKIT_EMBEDDED_TOP_P", "0.9")),
|
|
116
|
+
repeat_penalty=float(os.environ.get("AGENT_DEVKIT_EMBEDDED_REPEAT_PENALTY", "1.08")),
|
|
117
|
+
)
|
|
118
|
+
try:
|
|
119
|
+
content = str(payload["choices"][0]["message"]["content"]).strip()
|
|
120
|
+
except (KeyError, IndexError, TypeError) as exc:
|
|
121
|
+
raise EmbeddedMiniBrainError("Embedded mini-brain returned an unexpected response shape.") from exc
|
|
122
|
+
if not content:
|
|
123
|
+
raise EmbeddedMiniBrainError("Embedded mini-brain returned an empty response.")
|
|
124
|
+
return content[:EMBEDDED_MAX_RESPONSE_CHARS]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def embedded_backend_doctor() -> dict[str, Any]:
|
|
128
|
+
status = embedded_mini_brain_status()
|
|
129
|
+
return {
|
|
130
|
+
"id": EMBEDDED_BACKEND_ID,
|
|
131
|
+
"display_name": "Embedded mini-brain",
|
|
132
|
+
"kind": "embedded-local",
|
|
133
|
+
"status": status["status"],
|
|
134
|
+
"configured": status["configured"],
|
|
135
|
+
"model": EMBEDDED_MODEL_ID,
|
|
136
|
+
"model_file": status["model_file"],
|
|
137
|
+
"runtime": EMBEDDED_RUNTIME,
|
|
138
|
+
"auth_status": "none",
|
|
139
|
+
"message": status["message"],
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def embedded_backend_config() -> dict[str, Any]:
|
|
144
|
+
return {
|
|
145
|
+
"kind": "embedded-local",
|
|
146
|
+
"auth": "none",
|
|
147
|
+
"model": EMBEDDED_MODEL_ID,
|
|
148
|
+
"runtime": EMBEDDED_RUNTIME,
|
|
149
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def setup_embedded_mini_brain(*, dry_run: bool = False, yes: bool = False) -> dict[str, Any]:
|
|
154
|
+
before = embedded_mini_brain_status()
|
|
155
|
+
plan = embedded_install_plan()
|
|
156
|
+
if dry_run or not yes:
|
|
157
|
+
needs_confirmation = not dry_run and not yes
|
|
158
|
+
return {
|
|
159
|
+
"kind": "embedded-mini-brain-install",
|
|
160
|
+
"status": "planned" if dry_run else "needs-confirmation",
|
|
161
|
+
"ok": bool(dry_run),
|
|
162
|
+
"exit_code": 2 if needs_confirmation else 0,
|
|
163
|
+
"dry_run": dry_run,
|
|
164
|
+
"yes": yes,
|
|
165
|
+
"before": before,
|
|
166
|
+
"after": before,
|
|
167
|
+
"plan": plan,
|
|
168
|
+
"message": "Use --yes to download the embedded mini-brain model and install its local runtime.",
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
ensure_app_home()
|
|
172
|
+
EMBEDDED_MODEL_PATH.mkdir(parents=True, exist_ok=True)
|
|
173
|
+
download_result = ensure_model_file()
|
|
174
|
+
dependency_result = ensure_llama_cpp_dependency()
|
|
175
|
+
after = embedded_mini_brain_status()
|
|
176
|
+
ok = after.get("available") is True
|
|
177
|
+
return {
|
|
178
|
+
"kind": "embedded-mini-brain-install",
|
|
179
|
+
"status": "ok" if ok else "failed",
|
|
180
|
+
"ok": ok,
|
|
181
|
+
"exit_code": 0 if ok else 1,
|
|
182
|
+
"dry_run": False,
|
|
183
|
+
"yes": True,
|
|
184
|
+
"before": before,
|
|
185
|
+
"after": after,
|
|
186
|
+
"plan": plan,
|
|
187
|
+
"download": download_result,
|
|
188
|
+
"dependency_install": dependency_result,
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def embedded_install_plan() -> dict[str, Any]:
|
|
193
|
+
return {
|
|
194
|
+
"provider": EMBEDDED_BACKEND_ID,
|
|
195
|
+
"model": EMBEDDED_MODEL_ID,
|
|
196
|
+
"model_name": EMBEDDED_MODEL_NAME,
|
|
197
|
+
"download_url": model_source(),
|
|
198
|
+
"size_bytes": EMBEDDED_MODEL_SIZE_BYTES,
|
|
199
|
+
"sha256": EMBEDDED_MODEL_SHA256,
|
|
200
|
+
"destination": str(EMBEDDED_MODEL_FILE),
|
|
201
|
+
"runtime_requirement": EMBEDDED_RUNTIME_REQUIREMENT,
|
|
202
|
+
"writes": [
|
|
203
|
+
str(EMBEDDED_MODEL_FILE),
|
|
204
|
+
str(app_path("python")),
|
|
205
|
+
],
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def embedded_system_prompt(public_name: str) -> str:
|
|
210
|
+
return "\n".join(
|
|
211
|
+
[
|
|
212
|
+
identity_system_prompt(name=public_name),
|
|
213
|
+
"Voce e o mini cerebro local embarcado do Agent DevKit.",
|
|
214
|
+
"Responda em portugues claro quando o usuario escrever em portugues.",
|
|
215
|
+
"Voce pode conversar, orientar onboarding/setup, explicar capacidades e preparar tarefas simples.",
|
|
216
|
+
"Nao finja ser Claude, Codex, OpenAI ou Ollama.",
|
|
217
|
+
"Nao aprove escrita externa, operacoes destrutivas, decisoes finais de seguranca ou revisoes finais.",
|
|
218
|
+
"Quando a tarefa exigir alto julgamento, diga que pode acionar Claude, Codex, Ollama ou APIs se configurados.",
|
|
219
|
+
]
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def load_llama() -> Any:
|
|
224
|
+
global _LLAMA_CACHE
|
|
225
|
+
if _LLAMA_CACHE is not None:
|
|
226
|
+
return _LLAMA_CACHE
|
|
227
|
+
try:
|
|
228
|
+
from llama_cpp import Llama # type: ignore
|
|
229
|
+
except ImportError as exc:
|
|
230
|
+
raise EmbeddedMiniBrainError("llama-cpp-python is required for embedded mini-brain inference.") from exc
|
|
231
|
+
if not EMBEDDED_MODEL_FILE.exists():
|
|
232
|
+
raise EmbeddedMiniBrainError(f"Embedded model file not found: {EMBEDDED_MODEL_FILE}")
|
|
233
|
+
if sha256_file(EMBEDDED_MODEL_FILE) != EMBEDDED_MODEL_SHA256:
|
|
234
|
+
raise EmbeddedMiniBrainError(f"Embedded model file failed SHA-256 validation: {EMBEDDED_MODEL_FILE}")
|
|
235
|
+
_LLAMA_CACHE = Llama(
|
|
236
|
+
model_path=str(EMBEDDED_MODEL_FILE),
|
|
237
|
+
n_ctx=int(os.environ.get("AGENT_DEVKIT_EMBEDDED_N_CTX", str(DEFAULT_CONTEXT_TOKENS))),
|
|
238
|
+
n_threads=int(os.environ.get("AGENT_DEVKIT_EMBEDDED_THREADS", str(max(1, min(4, os.cpu_count() or 1))))),
|
|
239
|
+
verbose=os.environ.get("AGENT_DEVKIT_EMBEDDED_VERBOSE") == "1",
|
|
240
|
+
)
|
|
241
|
+
return _LLAMA_CACHE
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def llama_cpp_dependency_status() -> dict[str, Any]:
|
|
245
|
+
if os.environ.get(SMOKE_RESPONSE_ENV):
|
|
246
|
+
return {
|
|
247
|
+
"status": "ok",
|
|
248
|
+
"module": "llama_cpp",
|
|
249
|
+
"package": "llama-cpp-python",
|
|
250
|
+
"mode": "smoke",
|
|
251
|
+
}
|
|
252
|
+
try:
|
|
253
|
+
import llama_cpp # type: ignore
|
|
254
|
+
except ImportError:
|
|
255
|
+
return {
|
|
256
|
+
"status": "missing",
|
|
257
|
+
"module": "llama_cpp",
|
|
258
|
+
"package": "llama-cpp-python",
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
"status": "ok",
|
|
262
|
+
"module": "llama_cpp",
|
|
263
|
+
"package": "llama-cpp-python",
|
|
264
|
+
"version": getattr(llama_cpp, "__version__", None),
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def ensure_model_file() -> dict[str, Any]:
|
|
269
|
+
if os.environ.get(SMOKE_RESPONSE_ENV):
|
|
270
|
+
return {
|
|
271
|
+
"status": "skipped",
|
|
272
|
+
"ok": True,
|
|
273
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
274
|
+
"reason": "smoke-mode",
|
|
275
|
+
}
|
|
276
|
+
if EMBEDDED_MODEL_FILE.exists() and sha256_file(EMBEDDED_MODEL_FILE) == EMBEDDED_MODEL_SHA256:
|
|
277
|
+
return {
|
|
278
|
+
"status": "already-installed",
|
|
279
|
+
"ok": True,
|
|
280
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
281
|
+
"sha256": EMBEDDED_MODEL_SHA256,
|
|
282
|
+
}
|
|
283
|
+
partial = EMBEDDED_MODEL_FILE.with_suffix(EMBEDDED_MODEL_FILE.suffix + ".part")
|
|
284
|
+
source = model_source()
|
|
285
|
+
try:
|
|
286
|
+
if Path(source).expanduser().exists():
|
|
287
|
+
shutil.copyfile(Path(source).expanduser(), partial)
|
|
288
|
+
else:
|
|
289
|
+
with urllib.request.urlopen(source, timeout=120) as response, partial.open("wb") as target:
|
|
290
|
+
shutil.copyfileobj(response, target)
|
|
291
|
+
except (OSError, urllib.error.URLError) as exc:
|
|
292
|
+
return {
|
|
293
|
+
"status": "failed",
|
|
294
|
+
"ok": False,
|
|
295
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
296
|
+
"source": source,
|
|
297
|
+
"message": str(exc),
|
|
298
|
+
}
|
|
299
|
+
actual_sha = sha256_file(partial)
|
|
300
|
+
if actual_sha != EMBEDDED_MODEL_SHA256:
|
|
301
|
+
return {
|
|
302
|
+
"status": "failed",
|
|
303
|
+
"ok": False,
|
|
304
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
305
|
+
"source": source,
|
|
306
|
+
"sha256": actual_sha,
|
|
307
|
+
"expected_sha256": EMBEDDED_MODEL_SHA256,
|
|
308
|
+
"message": "Downloaded embedded model failed SHA-256 validation.",
|
|
309
|
+
}
|
|
310
|
+
partial.replace(EMBEDDED_MODEL_FILE)
|
|
311
|
+
return {
|
|
312
|
+
"status": "downloaded",
|
|
313
|
+
"ok": True,
|
|
314
|
+
"model_file": str(EMBEDDED_MODEL_FILE),
|
|
315
|
+
"source": source,
|
|
316
|
+
"sha256": EMBEDDED_MODEL_SHA256,
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def ensure_llama_cpp_dependency() -> dict[str, Any]:
|
|
321
|
+
current = llama_cpp_dependency_status()
|
|
322
|
+
if current.get("status") == "ok":
|
|
323
|
+
return {"status": "already-installed", "ok": True, "dependency": current}
|
|
324
|
+
if os.environ.get(SKIP_DEP_INSTALL_ENV) == "1":
|
|
325
|
+
return {"status": "skipped", "ok": True, "dependency": current, "reason": "disabled-by-env"}
|
|
326
|
+
command = [sys.executable, "-m", "pip", "install", EMBEDDED_RUNTIME_REQUIREMENT]
|
|
327
|
+
process = subprocess.run(command, check=False, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=900)
|
|
328
|
+
return {
|
|
329
|
+
"status": "installed" if process.returncode == 0 else "failed",
|
|
330
|
+
"ok": process.returncode == 0,
|
|
331
|
+
"command": command,
|
|
332
|
+
"exit_code": process.returncode,
|
|
333
|
+
"stdout": process.stdout[-4000:],
|
|
334
|
+
"stderr": process.stderr[-4000:],
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def model_source() -> str:
|
|
339
|
+
return os.environ.get(SOURCE_ENV) or EMBEDDED_MODEL_SOURCE
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def sha256_file(path: Path) -> str:
|
|
343
|
+
hash_obj = hashlib.sha256()
|
|
344
|
+
with path.open("rb") as file:
|
|
345
|
+
for chunk in iter(lambda: file.read(1024 * 1024), b""):
|
|
346
|
+
hash_obj.update(chunk)
|
|
347
|
+
return hash_obj.hexdigest()
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class EmbeddedMiniBrainError(RuntimeError):
|
|
351
|
+
"""Raised when embedded local inference cannot run."""
|