agent-devkit 0.3.0 → 0.3.2

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 CHANGED
@@ -30,7 +30,7 @@ agent doctor
30
30
  Expected version for this release:
31
31
 
32
32
  ```text
33
- agent 0.3.0
33
+ agent 0.3.2
34
34
  ```
35
35
 
36
36
  ## Quick Start
@@ -45,8 +45,15 @@ agent llm list
45
45
  agent commands list
46
46
  ```
47
47
 
48
- Agent DevKit `v0.3.0` also includes deterministic runtime discovery and
49
- integration commands:
48
+ Agent DevKit `v0.3.2` includes the embedded Qwen2.5-0.5B mini-brain
49
+ contract for local bootstrap conversations without Ollama, Claude, Codex or API
50
+ keys. The npm package stays small; `agent setup mini-brain --yes` downloads the
51
+ GGUF into `.agent-devkit/models` after explicit opt-in.
52
+ When you rename the local agent, Agent DevKit now creates a matching command
53
+ alias under `.agent-devkit/bin` and can add that directory to PATH with
54
+ `agent alias path --yes`.
55
+ The `v0.3.0` deterministic runtime discovery and integration commands remain
56
+ available:
50
57
 
51
58
  ```bash
52
59
  agent roadmap
@@ -73,14 +80,15 @@ Run a natural-language task:
73
80
  agent "analise o problema relatado no card 9900"
74
81
  ```
75
82
 
76
- Natural-language mode requires an LLM backend. Deterministic commands such as
77
- `agent agents list`, `agent capabilities list`, `agent doctor`, `agent provider`
78
- and `agent run` do not require an LLM.
83
+ Natural-language mode can start with the embedded mini-brain. Stronger
84
+ coordinator/reviewer backends remain optional for higher-level work.
85
+ Deterministic commands such as `agent agents list`, `agent capabilities list`,
86
+ `agent doctor`, `agent provider` and `agent run` do not require an external LLM.
79
87
 
80
88
  Running `agent` without arguments starts the local onboarding status and wizard:
81
89
  memory, personality, LLM backends, Ollama, toolchain, sources and next actions.
82
- Use `agent onboard minimal` for identity, coordinator LLM, Qwen3-0.6B via
83
- Ollama and local memory. Use `agent onboard complete` to include toolchain,
90
+ Use `agent onboard minimal` for identity, optional coordinator LLM, installable
91
+ mini-brain and local memory. Use `agent onboard complete` to include toolchain,
84
92
  providers/sources, specialist catalog, local automations, tasks, notifications,
85
93
  knowledge and shared memory. Both commands return plans; external installs
86
94
  still require explicit opt-in.
@@ -97,6 +105,7 @@ Useful operational commands:
97
105
  agent plan "analyze Azure card 7914"
98
106
  agent execute --dry-run "summarize these logs"
99
107
  agent workflow install daily-pr-review --dry-run
108
+ agent setup mini-brain --yes
100
109
  agent local-llm doctor
101
110
  agent local-llm install qwen3:0.6b --dry-run
102
111
  agent skill create my-skill --description "Local skill"
@@ -224,9 +233,11 @@ agent llm configure openrouter --api-key-env OPENROUTER_API_KEY --model openai/g
224
233
  agent llm doctor openrouter
225
234
  ```
226
235
 
227
- ### Option F: Ollama local backend
236
+ ### Embedded mini-brain and Ollama local backend
228
237
 
229
238
  ```bash
239
+ agent setup mini-brain --yes
240
+ agent local-llm doctor
230
241
  agent ollama status
231
242
  agent ollama models
232
243
  agent ollama pull qwen3:0.6b --dry-run
@@ -236,8 +247,11 @@ agent llm configure ollama --base-url http://localhost:11434/v1 --model qwen3:0.
236
247
  agent llm doctor ollama
237
248
  ```
238
249
 
239
- Ollama is treated as an operational worker for repetitive local tasks. Codex and
240
- Claude remain the preferred coordinators and reviewers for high-level planning,
250
+ Agent DevKit includes an installable embedded mini-brain for initial
251
+ conversation, onboarding and setup without external authentication. The GGUF is
252
+ downloaded to `.agent-devkit/models` only after opt-in. Ollama is still treated
253
+ as an optional operational worker for repetitive local tasks. Codex and Claude
254
+ remain the preferred coordinators and reviewers for high-level planning,
241
255
  software changes, documents, automation decisions and final review.
242
256
 
243
257
  ### Switch or override the backend
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-devkit",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Agent DevKit CLI runtime for specialist AI agents, capabilities and provider-aware automations.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/runtime/README.md CHANGED
@@ -65,8 +65,8 @@ agent secrets doctor
65
65
  agent mcp tools
66
66
  ```
67
67
 
68
- `agent onboard minimal` planeja o setup essencial: identidade, coordenador LLM,
69
- mini-cerebro Qwen3-0.6B via Ollama e memoria local. `agent onboard complete`
68
+ `agent onboard minimal` planeja o setup essencial: identidade, coordenador LLM
69
+ opcional, mini-cerebro local instalavel sob demanda e memoria local. `agent onboard complete`
70
70
  inclui tambem toolchain, providers/sources, catalogo de agentes, automacoes
71
71
  locais, tarefas, notificacoes, knowledge e memoria compartilhada. Ambos
72
72
  retornam plano deterministico; instalacoes externas continuam exigindo opt-in.
@@ -247,14 +247,23 @@ Uso:
247
247
  agent "roteie este pedido para o agente especialista adequado"
248
248
  ```
249
249
 
250
- ### Opcao F: usar Ollama local
250
+ ### Mini cerebro embarcado e Ollama local
251
251
 
252
- O Agent DevKit consegue diagnosticar Ollama, listar modelos, planejar pull e
253
- usar o backend local como trabalhador operacional. Claude/Codex continuam sendo
254
- os coordenadores e revisores preferenciais para decisao, especificacao e entrega
255
- final.
252
+ O Agent DevKit vem com um mini cerebro local baseado no contrato
253
+ `Qwen/Qwen2.5-0.5B-Instruct` para conversa inicial, onboarding, setup e tarefas
254
+ simples sem depender de Claude, Codex, API externa ou Ollama. O pacote npm
255
+ inclui o manifest do modelo; o GGUF e baixado para `.agent-devkit/models` sob
256
+ demanda com `agent setup mini-brain --yes`.
257
+
258
+ Ollama continua suportado como pool opcional de workers locais. O Agent DevKit
259
+ consegue diagnosticar Ollama, listar modelos, planejar pull e usar o backend
260
+ local como trabalhador operacional quando ele estiver configurado ou tiver
261
+ modelos instalados. Claude/Codex continuam sendo os coordenadores e revisores
262
+ preferenciais para decisao, especificacao e entrega final.
256
263
 
257
264
  ```bash
265
+ agent setup mini-brain --yes
266
+ agent local-llm doctor
258
267
  agent ollama status
259
268
  agent ollama models
260
269
  agent ollama pull qwen3:0.6b --dry-run
@@ -325,9 +334,10 @@ executa a task primaria pelo runner existente e revisa a conclusao pelo
325
334
  `review_gate`.
326
335
 
327
336
  Para tarefas operacionais como resumo, classificacao, extracao e normalizacao,
328
- o runtime pode delegar uma subtarefa limitada ao `local-llm-operator` usando
329
- Ollama. O resultado local aparece em `local_llm_execution` e e usado apenas como
330
- contexto de apoio pelo coordenador principal.
337
+ o runtime pode usar o mini cerebro embarcado para bootstrap/conversa simples ou
338
+ delegar uma subtarefa limitada ao `local-llm-operator` usando Ollama quando
339
+ disponivel. O resultado local aparece em `local_llm_execution` e e usado apenas
340
+ como contexto de apoio pelo coordenador principal.
331
341
 
332
342
  Quando `review_gate.required = true`, o Agent DevKit exige uma segunda revisao
333
343
  concreta pelo `execution-reviewer`, preferindo `claude-code` ou `codex-cli`.
@@ -209,8 +209,8 @@ agent onboard minimal
209
209
  agent onboard complete
210
210
  ```
211
211
 
212
- `minimal` cobre identidade, coordenador LLM, mini-cerebro Qwen3-0.6B via
213
- Ollama e memoria local. `complete` inclui tambem toolchain, providers/sources,
212
+ `minimal` cobre identidade, coordenador LLM opcional, mini-cerebro local
213
+ instalavel sob demanda e memoria local. `complete` inclui tambem toolchain, providers/sources,
214
214
  catalogo de agentes, automacoes locais, tarefas, notificacoes, knowledge e
215
215
  memoria compartilhada. Instalacoes externas continuam exigindo opt-in.
216
216
 
@@ -232,9 +232,12 @@ remoto continua exigindo provider, criptografia e opt-in explicito.
232
232
 
233
233
  ## Backends LLM
234
234
 
235
- O modo `agent "<prompt>"` exige um backend LLM. O Agent DevKit suporta tres
235
+ O modo `agent "<prompt>"` consegue conversar e orientar setup com o mini cerebro
236
+ local depois que ele for instalado com opt-in. Para coordenacao/revisao mais forte, o Agent DevKit suporta estas
236
237
  familias de backend:
237
238
 
239
+ - Mini cerebro local instalavel (`embedded-mini-brain`) para onboarding, setup e
240
+ conversa simples sem autenticacao externa.
238
241
  - CLIs oficiais autenticadas fora do Agent DevKit (`codex-cli` e
239
242
  `claude-code`).
240
243
  - APIs configuradas por referencia a variavel de ambiente (`openai`,
@@ -321,6 +324,8 @@ agent llm doctor openrouter
321
324
  ### Ollama local
322
325
 
323
326
  ```bash
327
+ agent setup mini-brain --yes
328
+ agent local-llm doctor
324
329
  agent ollama status
325
330
  agent ollama models
326
331
  agent ollama pull qwen3:0.6b --dry-run
@@ -330,12 +335,15 @@ agent llm configure ollama --base-url http://localhost:11434/v1 --model qwen3:0.
330
335
  agent llm doctor ollama
331
336
  ```
332
337
 
333
- Ollama e tratado como executor operacional local. Codex e Claude continuam como
334
- coordenadores/revisores preferenciais para decisao, especificacao, codigo,
335
- documentos, automacoes e fechamento de entrega.
338
+ O mini cerebro embarcado e a base inicial para conversa/setup sem dependencia
339
+ externa. Ollama e tratado como executor operacional local opcional. Codex e
340
+ Claude continuam como coordenadores/revisores preferenciais para decisao,
341
+ especificacao, codigo, documentos, automacoes e fechamento de entrega.
336
342
 
337
343
  Backends suportados no MVP:
338
344
 
345
+ - `embedded-mini-brain`: mini cerebro local embarcado para bootstrap e tarefas
346
+ simples.
339
347
  - `openai`: API OpenAI ou endpoint OpenAI-compatible.
340
348
  - `anthropic`: API Anthropic.
341
349
  - `openrouter`: API OpenRouter.
@@ -1,3 +1,3 @@
1
1
  """Public CLI implementation for AI DevKit."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.2"
@@ -3,9 +3,11 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json
6
+ import os
6
7
  import re
7
8
  import shutil
8
9
  import sys
10
+ import unicodedata
9
11
  from pathlib import Path
10
12
  from typing import Any
11
13
 
@@ -14,6 +16,8 @@ from cli.aikit.app_home import app_home, ensure_app_home
14
16
 
15
17
  ALIAS_PATTERN = re.compile(r"^[A-Za-z][A-Za-z0-9_-]{1,63}$")
16
18
  RESERVED_ALIASES = {"agent", "aikit", "ai-devkit", "python", "python3"}
19
+ SHELL_BLOCK_BEGIN = "# >>> agent-devkit aliases >>>"
20
+ SHELL_BLOCK_END = "# <<< agent-devkit aliases <<<"
17
21
 
18
22
 
19
23
  def aliases_config_path() -> Path:
@@ -84,6 +88,38 @@ def add_alias(name: str, *, force: bool = False) -> dict[str, Any]:
84
88
  return payload
85
89
 
86
90
 
91
+ def ensure_alias_for_agent_name(agent_name: str, *, force: bool = False) -> dict[str, Any]:
92
+ suggested = suggest_alias_name(agent_name)
93
+ payload: dict[str, Any] = {
94
+ "kind": "alias",
95
+ "requested_name": agent_name,
96
+ "suggested_name": suggested,
97
+ "created": False,
98
+ }
99
+ if not suggested:
100
+ return {
101
+ **payload,
102
+ "status": "invalid",
103
+ "message": "Agent name cannot be converted to a safe command alias.",
104
+ "path_status": alias_path_status(),
105
+ }
106
+ try:
107
+ added = add_alias(suggested, force=force)
108
+ except ValueError as exc:
109
+ return {
110
+ **payload,
111
+ "name": suggested,
112
+ "status": "blocked",
113
+ "message": str(exc),
114
+ "path_status": alias_path_status(suggested),
115
+ }
116
+ added["created"] = True
117
+ added["requested_name"] = agent_name
118
+ added["suggested_name"] = suggested
119
+ added["path_status"] = alias_path_status(suggested)
120
+ return added
121
+
122
+
87
123
  def remove_alias(name: str) -> dict[str, Any]:
88
124
  alias = validate_alias_name(name)
89
125
  config = load_aliases()
@@ -138,6 +174,7 @@ def alias_payload(alias: str, item: dict[str, Any]) -> dict[str, Any]:
138
174
  "cmd_path": str(aliases_bin_dir() / f"{alias}.cmd"),
139
175
  "ps1_path": str(aliases_bin_dir() / f"{alias}.ps1"),
140
176
  "created_by": item.get("created_by"),
177
+ "path_status": alias_path_status(alias),
141
178
  }
142
179
 
143
180
 
@@ -194,3 +231,147 @@ def alias_executable_path(alias: str) -> Path:
194
231
 
195
232
  def alias_paths(alias: str) -> list[Path]:
196
233
  return [alias_executable_path(alias), aliases_bin_dir() / f"{alias}.cmd", aliases_bin_dir() / f"{alias}.ps1"]
234
+
235
+
236
+ def suggest_alias_name(agent_name: str) -> str | None:
237
+ cleaned = " ".join(str(agent_name or "").split()).strip()
238
+ if not cleaned:
239
+ return None
240
+ try:
241
+ return validate_alias_name(cleaned)
242
+ except ValueError:
243
+ pass
244
+ ascii_name = unicodedata.normalize("NFKD", cleaned).encode("ascii", "ignore").decode("ascii")
245
+ alias = re.sub(r"[^A-Za-z0-9_-]+", "-", ascii_name).strip("-_")
246
+ if alias and not alias[0].isalpha():
247
+ alias = f"agent-{alias}"
248
+ if len(alias) == 1:
249
+ alias = f"{alias}-agent"
250
+ alias = alias[:64].strip("-_")
251
+ if not alias:
252
+ return None
253
+ try:
254
+ return validate_alias_name(alias)
255
+ except ValueError:
256
+ return None
257
+
258
+
259
+ def alias_path_status(alias: str | None = None) -> dict[str, Any]:
260
+ bin_dir = aliases_bin_dir()
261
+ path_entries = os.environ.get("PATH", "").split(os.pathsep) if os.environ.get("PATH") else []
262
+ bin_dir_in_path = any(paths_equal(Path(entry), bin_dir) for entry in path_entries if entry)
263
+ found = shutil.which(alias) if alias else None
264
+ available = False
265
+ if alias and found:
266
+ try:
267
+ available = Path(found).resolve() in {path.resolve() for path in alias_paths(alias)}
268
+ except OSError:
269
+ available = False
270
+ plan = alias_path_setup_plan()
271
+ return {
272
+ "bin_dir": str(bin_dir),
273
+ "bin_dir_in_path": bin_dir_in_path,
274
+ "alias_available": available,
275
+ "found": found,
276
+ "setup_required": not bin_dir_in_path,
277
+ "setup": plan,
278
+ }
279
+
280
+
281
+ def paths_equal(left: Path, right: Path) -> bool:
282
+ try:
283
+ return left.expanduser().resolve() == right.expanduser().resolve()
284
+ except OSError:
285
+ return left.expanduser() == right.expanduser()
286
+
287
+
288
+ def alias_path_setup_plan() -> dict[str, Any]:
289
+ bin_dir = aliases_bin_dir()
290
+ if os.name == "nt":
291
+ return {
292
+ "platform": "windows",
293
+ "target": "user PATH",
294
+ "command": f'agent alias path --yes',
295
+ "description": f"Add {bin_dir} to the current user's PATH.",
296
+ }
297
+ profile = detect_shell_profile()
298
+ return {
299
+ "platform": "posix",
300
+ "target": str(profile),
301
+ "command": "agent alias path --yes",
302
+ "description": f"Add {bin_dir} to PATH for future shell sessions.",
303
+ }
304
+
305
+
306
+ def setup_alias_path(*, yes: bool = False) -> dict[str, Any]:
307
+ status = alias_path_status()
308
+ payload: dict[str, Any] = {
309
+ "kind": "alias-path",
310
+ "bin_dir": status["bin_dir"],
311
+ "path_status": status,
312
+ "executed": False,
313
+ }
314
+ if not status["setup_required"]:
315
+ return {**payload, "status": "ok", "message": "Agent DevKit alias bin directory is already on PATH."}
316
+ if not yes:
317
+ return {
318
+ **payload,
319
+ "status": "needs-confirmation",
320
+ "message": "Run `agent alias path --yes` to make configured aliases available as shell commands.",
321
+ }
322
+ if os.name == "nt":
323
+ return install_windows_user_path(payload)
324
+ return install_posix_shell_path(payload)
325
+
326
+
327
+ def install_posix_shell_path(payload: dict[str, Any]) -> dict[str, Any]:
328
+ profile = detect_shell_profile()
329
+ bin_dir = aliases_bin_dir()
330
+ profile.parent.mkdir(parents=True, exist_ok=True)
331
+ current = profile.read_text(encoding="utf-8") if profile.exists() else ""
332
+ export_line = f'export PATH="{bin_dir}:$PATH"'
333
+ block = f"\n{SHELL_BLOCK_BEGIN}\n{export_line}\n{SHELL_BLOCK_END}\n"
334
+ if str(bin_dir) not in current:
335
+ profile.write_text(current.rstrip() + block, encoding="utf-8")
336
+ return {
337
+ **payload,
338
+ "status": "updated",
339
+ "executed": True,
340
+ "profile": str(profile),
341
+ "message": "Alias PATH configured for future shell sessions. Restart the terminal or source the profile.",
342
+ }
343
+
344
+
345
+ def install_windows_user_path(payload: dict[str, Any]) -> dict[str, Any]:
346
+ bin_dir = str(aliases_bin_dir())
347
+ try:
348
+ import winreg
349
+
350
+ with winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | winreg.KEY_WRITE) as key:
351
+ try:
352
+ current, value_type = winreg.QueryValueEx(key, "Path")
353
+ except FileNotFoundError:
354
+ current, value_type = "", winreg.REG_EXPAND_SZ
355
+ entries = [entry for entry in str(current).split(os.pathsep) if entry]
356
+ if not any(paths_equal(Path(entry), aliases_bin_dir()) for entry in entries):
357
+ new_value = os.pathsep.join([bin_dir, *entries])
358
+ winreg.SetValueEx(key, "Path", 0, value_type, new_value)
359
+ except OSError as exc:
360
+ return {**payload, "status": "failed", "executed": False, "message": str(exc)}
361
+ return {
362
+ **payload,
363
+ "status": "updated",
364
+ "executed": True,
365
+ "profile": "HKCU\\Environment\\Path",
366
+ "message": "Alias PATH configured for future Windows terminal sessions.",
367
+ }
368
+
369
+
370
+ def detect_shell_profile() -> Path:
371
+ shell = Path(os.environ.get("SHELL", "")).name
372
+ home = Path.home()
373
+ if shell == "zsh":
374
+ return home / ".zshrc"
375
+ if shell == "bash":
376
+ return home / ".bashrc"
377
+ return home / ".profile"
@@ -20,6 +20,7 @@ APP_DIRS = (
20
20
  "memory",
21
21
  "sessions",
22
22
  "tasks",
23
+ "models",
23
24
  "backups",
24
25
  "policies",
25
26
  "audit",
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  from typing import Any
8
8
 
9
9
  from cli.aikit import __version__
10
- from cli.aikit.aliases import add_alias, list_aliases, remove_alias, sync_aliases
10
+ from cli.aikit.aliases import add_alias, list_aliases, remove_alias, setup_alias_path, sync_aliases
11
11
  from cli.aikit.agentic_commands import agentic_execute, agentic_plan
12
12
  from cli.aikit.app_home import app_home_status, migrate_default_home
13
13
  from cli.aikit.architecture import architecture_contract
@@ -1530,6 +1530,10 @@ def dispatch_alias(args: argparse.Namespace) -> dict[str, Any]:
1530
1530
  if args.name:
1531
1531
  raise DevKitError("alias sync does not accept a name")
1532
1532
  return sync_aliases()
1533
+ if args.action == "path":
1534
+ if args.name:
1535
+ raise DevKitError("alias path does not accept a name")
1536
+ return setup_alias_path(yes=args.yes)
1533
1537
  except ValueError as exc:
1534
1538
  raise DevKitError(str(exc)) from exc
1535
1539
  raise DevKitError(f"unsupported alias action: {args.action}")
@@ -246,14 +246,15 @@ def build_parser(prog: str | None = None) -> argparse.ArgumentParser:
246
246
  setup_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
247
247
  setup_parser.add_argument("--dry-run", action="store_true", help="show setup plan without installing external tools")
248
248
  setup_parser.add_argument("--yes", action="store_true", help="confirm setup actions")
249
- setup_parser.add_argument("--set-default", action="store_true", help="make the mini-brain Ollama backend the default LLM")
249
+ setup_parser.add_argument("--set-default", action="store_true", help="make the embedded mini-brain the default LLM")
250
250
  setup_parser.add_argument("action", nargs="?", default="plan", choices=["plan", "personality", "mini-brain"])
251
251
 
252
252
  alias_parser = subparsers.add_parser("alias", help="manage local command aliases for agent")
253
253
  alias_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)
254
- alias_parser.add_argument("action", nargs="?", default="list", choices=["add", "list", "remove", "sync"])
254
+ alias_parser.add_argument("action", nargs="?", default="list", choices=["add", "list", "remove", "sync", "path"])
255
255
  alias_parser.add_argument("name", nargs="?")
256
256
  alias_parser.add_argument("--force", action="store_true", help="allow replacing an existing local alias file")
257
+ alias_parser.add_argument("--yes", action="store_true", help="confirm alias PATH setup")
257
258
 
258
259
  session_parser = subparsers.add_parser("session", help="manage local conversation sessions")
259
260
  session_parser.add_argument("--json", action="store_true", default=argparse.SUPPRESS, help=argparse.SUPPRESS)