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.
Files changed (177) hide show
  1. package/README.md +66 -13
  2. package/bin/agent.mjs +133 -7
  3. package/package.json +1 -1
  4. package/runtime/README.md +205 -13
  5. package/runtime/agent +31 -5
  6. package/runtime/agents/README.md +18 -0
  7. package/runtime/agents/contribution-reviewer/AGENTS.md +8 -0
  8. package/runtime/agents/contribution-reviewer/README.md +8 -0
  9. package/runtime/agents/contribution-reviewer/agent.yaml +40 -0
  10. package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/capability.yaml +27 -0
  11. package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/decision-rules.md +5 -0
  12. package/runtime/agents/contribution-reviewer/capabilities/plan-contribution-pr/workflow.md +6 -0
  13. package/runtime/agents/contribution-reviewer/capabilities/review-contribution/capability.yaml +25 -0
  14. package/runtime/agents/contribution-reviewer/capabilities/review-contribution/decision-rules.md +5 -0
  15. package/runtime/agents/contribution-reviewer/capabilities/review-contribution/workflow.md +5 -0
  16. package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/capability.yaml +26 -0
  17. package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/decision-rules.md +5 -0
  18. package/runtime/agents/contribution-reviewer/capabilities/validate-local-contribution/workflow.md +6 -0
  19. package/runtime/agents/contribution-reviewer/infra/README.md +6 -0
  20. package/runtime/agents/contribution-reviewer/knowledge/context.md +8 -0
  21. package/runtime/agents/contribution-reviewer/knowledge/system.md +8 -0
  22. package/runtime/agents/contribution-reviewer/templates/README.md +3 -0
  23. package/runtime/agents/knowledge-author/AGENTS.md +7 -0
  24. package/runtime/agents/knowledge-author/README.md +7 -0
  25. package/runtime/agents/knowledge-author/agent.yaml +37 -0
  26. package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/capability.yaml +30 -0
  27. package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/decision-rules.md +6 -0
  28. package/runtime/agents/knowledge-author/capabilities/create-knowledge-snapshot/workflow.md +7 -0
  29. package/runtime/agents/knowledge-author/infra/.gitkeep +1 -0
  30. package/runtime/agents/knowledge-author/knowledge/context.md +4 -0
  31. package/runtime/agents/knowledge-author/knowledge/system.md +4 -0
  32. package/runtime/agents/knowledge-author/templates/.gitkeep +1 -0
  33. package/runtime/agents/knowledge-curator/AGENTS.md +7 -0
  34. package/runtime/agents/knowledge-curator/README.md +6 -0
  35. package/runtime/agents/knowledge-curator/agent.yaml +37 -0
  36. package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/capability.yaml +29 -0
  37. package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/decision-rules.md +6 -0
  38. package/runtime/agents/knowledge-curator/capabilities/curate-knowledge-base/workflow.md +7 -0
  39. package/runtime/agents/knowledge-curator/infra/.gitkeep +1 -0
  40. package/runtime/agents/knowledge-curator/knowledge/context.md +4 -0
  41. package/runtime/agents/knowledge-curator/knowledge/system.md +4 -0
  42. package/runtime/agents/knowledge-curator/templates/.gitkeep +1 -0
  43. package/runtime/agents/knowledge-infra-builder/AGENTS.md +8 -0
  44. package/runtime/agents/knowledge-infra-builder/README.md +8 -0
  45. package/runtime/agents/knowledge-infra-builder/agent.yaml +38 -0
  46. package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/capability.yaml +30 -0
  47. package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/decision-rules.md +6 -0
  48. package/runtime/agents/knowledge-infra-builder/capabilities/create-knowledge-base/workflow.md +7 -0
  49. package/runtime/agents/knowledge-infra-builder/infra/.gitkeep +1 -0
  50. package/runtime/agents/knowledge-infra-builder/knowledge/context.md +4 -0
  51. package/runtime/agents/knowledge-infra-builder/knowledge/system.md +4 -0
  52. package/runtime/agents/knowledge-infra-builder/templates/.gitkeep +1 -0
  53. package/runtime/agents/knowledge-owner/AGENTS.md +7 -0
  54. package/runtime/agents/knowledge-owner/README.md +6 -0
  55. package/runtime/agents/knowledge-owner/agent.yaml +37 -0
  56. package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/capability.yaml +28 -0
  57. package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/decision-rules.md +6 -0
  58. package/runtime/agents/knowledge-owner/capabilities/publish-knowledge-snapshot/workflow.md +7 -0
  59. package/runtime/agents/knowledge-owner/infra/.gitkeep +1 -0
  60. package/runtime/agents/knowledge-owner/knowledge/context.md +4 -0
  61. package/runtime/agents/knowledge-owner/knowledge/system.md +4 -0
  62. package/runtime/agents/knowledge-owner/templates/.gitkeep +1 -0
  63. package/runtime/agents/knowledge-reviewer/AGENTS.md +7 -0
  64. package/runtime/agents/knowledge-reviewer/README.md +7 -0
  65. package/runtime/agents/knowledge-reviewer/agent.yaml +36 -0
  66. package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/capability.yaml +26 -0
  67. package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/decision-rules.md +6 -0
  68. package/runtime/agents/knowledge-reviewer/capabilities/review-knowledge-snapshot/workflow.md +7 -0
  69. package/runtime/agents/knowledge-reviewer/infra/.gitkeep +1 -0
  70. package/runtime/agents/knowledge-reviewer/knowledge/context.md +4 -0
  71. package/runtime/agents/knowledge-reviewer/knowledge/system.md +4 -0
  72. package/runtime/agents/knowledge-reviewer/templates/.gitkeep +1 -0
  73. package/runtime/agents/local-memory-manager/AGENTS.md +5 -0
  74. package/runtime/agents/local-memory-manager/README.md +7 -0
  75. package/runtime/agents/local-memory-manager/agent.yaml +38 -0
  76. package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/capability.yaml +19 -0
  77. package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/decision-rules.md +5 -0
  78. package/runtime/agents/local-memory-manager/capabilities/curate-local-memory/workflow.md +6 -0
  79. package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/capability.yaml +19 -0
  80. package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/decision-rules.md +5 -0
  81. package/runtime/agents/local-memory-manager/capabilities/inspect-local-memory/workflow.md +5 -0
  82. package/runtime/agents/local-memory-manager/infra/.gitkeep +1 -0
  83. package/runtime/agents/local-memory-manager/knowledge/context.md +4 -0
  84. package/runtime/agents/local-memory-manager/knowledge/system.md +4 -0
  85. package/runtime/agents/local-memory-manager/templates/.gitkeep +1 -0
  86. package/runtime/agents/memory-sync-manager/AGENTS.md +7 -0
  87. package/runtime/agents/memory-sync-manager/README.md +7 -0
  88. package/runtime/agents/memory-sync-manager/agent.yaml +37 -0
  89. package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/capability.yaml +29 -0
  90. package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/decision-rules.md +6 -0
  91. package/runtime/agents/memory-sync-manager/capabilities/plan-memory-backup/workflow.md +7 -0
  92. package/runtime/agents/memory-sync-manager/infra/.gitkeep +1 -0
  93. package/runtime/agents/memory-sync-manager/knowledge/context.md +4 -0
  94. package/runtime/agents/memory-sync-manager/knowledge/system.md +4 -0
  95. package/runtime/agents/memory-sync-manager/templates/.gitkeep +1 -0
  96. package/runtime/agents/shared-memory-curator/AGENTS.md +5 -0
  97. package/runtime/agents/shared-memory-curator/README.md +6 -0
  98. package/runtime/agents/shared-memory-curator/agent.yaml +38 -0
  99. package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/capability.yaml +19 -0
  100. package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/decision-rules.md +5 -0
  101. package/runtime/agents/shared-memory-curator/capabilities/create-shared-memory/workflow.md +5 -0
  102. package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/capability.yaml +19 -0
  103. package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/decision-rules.md +5 -0
  104. package/runtime/agents/shared-memory-curator/capabilities/publish-shared-submission/workflow.md +5 -0
  105. package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/capability.yaml +19 -0
  106. package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/decision-rules.md +5 -0
  107. package/runtime/agents/shared-memory-curator/capabilities/review-shared-submission/workflow.md +5 -0
  108. package/runtime/agents/shared-memory-curator/infra/.gitkeep +1 -0
  109. package/runtime/agents/shared-memory-curator/knowledge/context.md +5 -0
  110. package/runtime/agents/shared-memory-curator/knowledge/system.md +4 -0
  111. package/runtime/agents/shared-memory-curator/templates/.gitkeep +1 -0
  112. package/runtime/cli/README.md +47 -8
  113. package/runtime/cli/aikit/__init__.py +1 -1
  114. package/runtime/cli/aikit/agent_registry.py +4 -2
  115. package/runtime/cli/aikit/agentic_commands.py +158 -0
  116. package/runtime/cli/aikit/app_home.py +2 -0
  117. package/runtime/cli/aikit/audit.py +16 -6
  118. package/runtime/cli/aikit/catalog.py +278 -8
  119. package/runtime/cli/aikit/cli_dispatch.py +489 -13
  120. package/runtime/cli/aikit/cli_parser.py +146 -8
  121. package/runtime/cli/aikit/contribution.py +132 -2
  122. package/runtime/cli/aikit/doctor_runtime.py +85 -0
  123. package/runtime/cli/aikit/embedded_mini_brain.py +351 -0
  124. package/runtime/cli/aikit/eval.py +356 -10
  125. package/runtime/cli/aikit/human_output.py +310 -4
  126. package/runtime/cli/aikit/interactive_wizard.py +146 -0
  127. package/runtime/cli/aikit/knowledge_base.py +1067 -0
  128. package/runtime/cli/aikit/llm.py +40 -6
  129. package/runtime/cli/aikit/local_artifacts.py +444 -0
  130. package/runtime/cli/aikit/local_llm.py +176 -0
  131. package/runtime/cli/aikit/local_llm_operator.py +15 -5
  132. package/runtime/cli/aikit/main.py +15 -0
  133. package/runtime/cli/aikit/mcp_manifest.py +798 -0
  134. package/runtime/cli/aikit/mcp_tools.py +643 -5
  135. package/runtime/cli/aikit/memory.py +405 -0
  136. package/runtime/cli/aikit/mini_brain.py +56 -25
  137. package/runtime/cli/aikit/model_router.py +42 -9
  138. package/runtime/cli/aikit/natural_prompt_runtime.py +194 -2
  139. package/runtime/cli/aikit/ollama.py +64 -15
  140. package/runtime/cli/aikit/onboarding.py +551 -0
  141. package/runtime/cli/aikit/output.py +67 -0
  142. package/runtime/cli/aikit/prompt_injection.py +12 -1
  143. package/runtime/cli/aikit/review_gate.py +14 -2
  144. package/runtime/cli/aikit/roadmap_cli.py +1 -1
  145. package/runtime/cli/aikit/secrets.py +3 -2
  146. package/runtime/cli/aikit/setup_wizard_payload.py +3 -0
  147. package/runtime/cli/aikit/shared_memory.py +415 -0
  148. package/runtime/cli/aikit/specialist_readiness.py +152 -0
  149. package/runtime/cli/aikit/tasks.py +104 -1
  150. package/runtime/cli/aikit/team.py +380 -0
  151. package/runtime/cli/aikit/toolchain.py +7 -2
  152. package/runtime/cli/aikit/workflows.py +115 -14
  153. package/runtime/models/qwen2.5-0.5b-instruct/manifest.json +30 -0
  154. package/runtime/providers/knowledge-github.yaml +40 -0
  155. package/runtime/providers/knowledge-google-drive.yaml +32 -0
  156. package/runtime/providers/knowledge-local.yaml +26 -0
  157. package/runtime/providers/knowledge-notion.yaml +32 -0
  158. package/runtime/providers/knowledge-obsidian.yaml +24 -0
  159. package/runtime/providers/knowledge-onedrive.yaml +36 -0
  160. package/runtime/providers/knowledge-s3.yaml +45 -0
  161. package/runtime/providers/knowledge-sharepoint.yaml +39 -0
  162. package/runtime/providers/knowledge-supabase.yaml +43 -0
  163. package/runtime/providers/knowledge-vector.yaml +39 -0
  164. package/runtime/requirements.txt +6 -0
  165. package/runtime/scripts/docker-cli-qa.sh +453 -0
  166. package/runtime/scripts/release-catalog-snapshot.json +55 -4
  167. package/runtime/scripts/release-gate.py +54 -13
  168. package/runtime/tooling/toolchain.yaml +92 -0
  169. package/runtime/vendor/skills/napkin/napkin.md +21 -7
  170. package/runtime/workflows/azure-card-analysis/README.md +3 -0
  171. package/runtime/workflows/azure-card-analysis/workflow.yaml +30 -0
  172. package/runtime/workflows/daily-pr-review/README.md +3 -0
  173. package/runtime/workflows/daily-pr-review/workflow.yaml +31 -0
  174. package/runtime/workflows/incident-analysis/README.md +3 -0
  175. package/runtime/workflows/incident-analysis/workflow.yaml +33 -0
  176. package/runtime/workflows/release-prep/README.md +3 -0
  177. 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."""