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,551 @@
|
|
|
1
|
+
"""First-run and no-argument onboarding for Agent DevKit."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from cli.aikit.agent_registry import load_agent_registry
|
|
9
|
+
from cli.aikit.app_home import app_home_status
|
|
10
|
+
from cli.aikit.llm import doctor_backends, list_backends
|
|
11
|
+
from cli.aikit.memory import ensure_memory
|
|
12
|
+
from cli.aikit.ollama import ollama_status
|
|
13
|
+
from cli.aikit.personality import load_personality
|
|
14
|
+
from cli.aikit.sessions import list_sessions, show_session
|
|
15
|
+
from cli.aikit.setup_wizard import setup_wizard
|
|
16
|
+
from cli.aikit.sources import list_sources, source_status
|
|
17
|
+
from cli.aikit.specialist_readiness import specialist_readiness
|
|
18
|
+
from cli.aikit.tasks import load_tasks, public_task, task_is_due, list_tasks
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
ONBOARDING_MODE_SCHEMA_VERSION = "agent-devkit.onboarding-plan/v1"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def onboarding_status(root: Path) -> dict[str, Any]:
|
|
25
|
+
"""Return a local, deterministic startup snapshot for `agent` without args."""
|
|
26
|
+
|
|
27
|
+
home = app_home_status()
|
|
28
|
+
memory = ensure_memory()
|
|
29
|
+
personality = load_personality()
|
|
30
|
+
sessions = summarize_sessions()
|
|
31
|
+
setup = setup_wizard(root, dry_run=True, yes=False)
|
|
32
|
+
llms = summarize_llms()
|
|
33
|
+
ollama = ollama_status()
|
|
34
|
+
sources = summarize_sources()
|
|
35
|
+
tasks = summarize_tasks()
|
|
36
|
+
specialists = specialist_readiness(root)
|
|
37
|
+
|
|
38
|
+
blockers = startup_blockers(setup=setup, llms=llms)
|
|
39
|
+
suggestions = suggested_actions(
|
|
40
|
+
memory=memory,
|
|
41
|
+
personality=personality,
|
|
42
|
+
sessions=sessions,
|
|
43
|
+
setup=setup,
|
|
44
|
+
llms=llms,
|
|
45
|
+
ollama=ollama,
|
|
46
|
+
sources=sources,
|
|
47
|
+
tasks=tasks,
|
|
48
|
+
specialists=specialists,
|
|
49
|
+
)
|
|
50
|
+
status = "ready"
|
|
51
|
+
if blockers:
|
|
52
|
+
status = "needs-setup"
|
|
53
|
+
elif suggestions:
|
|
54
|
+
status = "needs-attention"
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
"kind": "onboarding",
|
|
58
|
+
"schema_version": "agent-devkit.onboarding/v1",
|
|
59
|
+
"status": status,
|
|
60
|
+
"agent": {
|
|
61
|
+
"name": personality.get("agent_name") or "Agent DevKit",
|
|
62
|
+
"tone": personality.get("tone"),
|
|
63
|
+
"detail_level": personality.get("detail_level"),
|
|
64
|
+
"language": personality.get("language"),
|
|
65
|
+
"user_name": personality.get("user_name"),
|
|
66
|
+
},
|
|
67
|
+
"home": home,
|
|
68
|
+
"memory": {
|
|
69
|
+
"status": memory.get("status"),
|
|
70
|
+
"home": memory.get("home"),
|
|
71
|
+
"created": memory.get("created") or [],
|
|
72
|
+
"file_count": len(memory.get("files") or []),
|
|
73
|
+
},
|
|
74
|
+
"sessions": {
|
|
75
|
+
"status": sessions.get("status"),
|
|
76
|
+
"home": sessions.get("home"),
|
|
77
|
+
"active_session_id": sessions.get("active_session_id"),
|
|
78
|
+
"count": len(sessions.get("items") or []),
|
|
79
|
+
"active": sessions.get("active"),
|
|
80
|
+
"recent": sessions.get("recent") or [],
|
|
81
|
+
},
|
|
82
|
+
"llm": llms,
|
|
83
|
+
"ollama": summarize_ollama(ollama),
|
|
84
|
+
"toolchain": summarize_toolchain(setup.get("toolchain") or {}),
|
|
85
|
+
"sources": sources,
|
|
86
|
+
"tasks": tasks,
|
|
87
|
+
"specialists": summarize_specialists(specialists),
|
|
88
|
+
"blockers": blockers,
|
|
89
|
+
"suggested_actions": suggestions,
|
|
90
|
+
"onboarding_modes": onboarding_modes(),
|
|
91
|
+
"startup_flow": startup_flow(status=status, sessions=sessions, tasks=tasks, blockers=blockers),
|
|
92
|
+
"assistant_prompt": assistant_prompt(status=status, sessions=sessions, tasks=tasks, blockers=blockers, actions=suggestions),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def onboarding_plan(root: Path, mode: str) -> dict[str, Any]:
|
|
97
|
+
selected_mode = normalize_onboarding_mode(mode)
|
|
98
|
+
status = onboarding_status(root)
|
|
99
|
+
registry = load_agent_registry(root)
|
|
100
|
+
minimal_steps = [
|
|
101
|
+
plan_step(
|
|
102
|
+
"personality",
|
|
103
|
+
"Configurar nome publico, usuario, idioma, tom e nivel de detalhe.",
|
|
104
|
+
"agent setup personality",
|
|
105
|
+
write_policy="local_config_write",
|
|
106
|
+
),
|
|
107
|
+
plan_step(
|
|
108
|
+
"coordinator-llm",
|
|
109
|
+
"Registrar Claude Code, Codex CLI ou API como coordenador/planejador/revisor opcional para tarefas de alto nivel.",
|
|
110
|
+
"agent llm list",
|
|
111
|
+
write_policy="local_config_write",
|
|
112
|
+
),
|
|
113
|
+
plan_step(
|
|
114
|
+
"mini-brain",
|
|
115
|
+
"Validar o mini cerebro embarcado Qwen2.5-0.5B para conversa simples, setup e tarefas operacionais leves.",
|
|
116
|
+
"agent setup mini-brain --dry-run",
|
|
117
|
+
write_policy="local_config_write",
|
|
118
|
+
model="Qwen/Qwen2.5-0.5B-Instruct",
|
|
119
|
+
),
|
|
120
|
+
plan_step(
|
|
121
|
+
"sessions-and-memory",
|
|
122
|
+
"Inicializar memoria local, sessoes, preferencias e identidade em .agent-devkit.",
|
|
123
|
+
"agent memory show",
|
|
124
|
+
write_policy="local_config_write",
|
|
125
|
+
),
|
|
126
|
+
]
|
|
127
|
+
complete_steps = minimal_steps + [
|
|
128
|
+
plan_step(
|
|
129
|
+
"toolchain",
|
|
130
|
+
"Revisar CLIs locais e planejar instalacao com opt-in por ferramenta.",
|
|
131
|
+
"agent toolchain doctor",
|
|
132
|
+
write_policy="confirm",
|
|
133
|
+
),
|
|
134
|
+
plan_step(
|
|
135
|
+
"providers-and-sources",
|
|
136
|
+
"Preparar configuracao sob demanda para providers, sources e credenciais por referencia segura.",
|
|
137
|
+
"agent source list",
|
|
138
|
+
write_policy="local_config_write",
|
|
139
|
+
),
|
|
140
|
+
plan_step(
|
|
141
|
+
"specialist-catalog",
|
|
142
|
+
"Validar catalogo completo e readiness de agentes especialistas por provider/source.",
|
|
143
|
+
"agent doctor",
|
|
144
|
+
write_policy="read_only",
|
|
145
|
+
),
|
|
146
|
+
plan_step(
|
|
147
|
+
"local-automation-factory",
|
|
148
|
+
"Preparar criacao local de scripts, skills, knowledge e agentes personalizados em .agent-devkit.",
|
|
149
|
+
"agent local list",
|
|
150
|
+
write_policy="local_config_write",
|
|
151
|
+
),
|
|
152
|
+
plan_step(
|
|
153
|
+
"tasks-and-notifications",
|
|
154
|
+
"Configurar tarefas agendadas e notificacoes locais com eventos de conclusao/bloqueio.",
|
|
155
|
+
"agent notifications doctor",
|
|
156
|
+
write_policy="local_config_write",
|
|
157
|
+
),
|
|
158
|
+
plan_step(
|
|
159
|
+
"knowledge-and-shared-memory",
|
|
160
|
+
"Inicializar knowledge local e memoria compartilhada com curadoria pelo dono.",
|
|
161
|
+
"agent knowledge doctor",
|
|
162
|
+
write_policy="local_config_write",
|
|
163
|
+
),
|
|
164
|
+
]
|
|
165
|
+
steps = minimal_steps if selected_mode == "minimal" else complete_steps
|
|
166
|
+
return {
|
|
167
|
+
"kind": "onboarding-plan",
|
|
168
|
+
"schema_version": ONBOARDING_MODE_SCHEMA_VERSION,
|
|
169
|
+
"status": "planned",
|
|
170
|
+
"mode": selected_mode,
|
|
171
|
+
"external_actions_executed": False,
|
|
172
|
+
"agent": status.get("agent"),
|
|
173
|
+
"home": status.get("home"),
|
|
174
|
+
"agent_catalog": {
|
|
175
|
+
"agents": len(registry.get("agents") or {}),
|
|
176
|
+
"capabilities": len(registry.get("capabilities") or {}),
|
|
177
|
+
},
|
|
178
|
+
"steps": steps,
|
|
179
|
+
"next_steps": [step["command"] for step in steps],
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def normalize_onboarding_mode(mode: str) -> str:
|
|
184
|
+
if mode in {"minimal", "complete"}:
|
|
185
|
+
return mode
|
|
186
|
+
raise ValueError(f"unsupported onboarding mode: {mode}")
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def onboarding_modes() -> list[dict[str, Any]]:
|
|
190
|
+
return [
|
|
191
|
+
{
|
|
192
|
+
"id": "minimal",
|
|
193
|
+
"label": "Onboarding minimo",
|
|
194
|
+
"command": "agent onboard minimal",
|
|
195
|
+
"purpose": "Deixar o agente conversavel e utilizavel com identidade, coordenador LLM, mini-brain e memoria local.",
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"id": "complete",
|
|
199
|
+
"label": "Onboarding completo",
|
|
200
|
+
"command": "agent onboard complete",
|
|
201
|
+
"purpose": "Revisar tambem toolchain, providers, fontes, catalogo, automacoes locais, tarefas, notificacoes e memorias compartilhadas.",
|
|
202
|
+
},
|
|
203
|
+
]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def plan_step(
|
|
207
|
+
step_id: str,
|
|
208
|
+
purpose: str,
|
|
209
|
+
command: str,
|
|
210
|
+
*,
|
|
211
|
+
write_policy: str,
|
|
212
|
+
model: str | None = None,
|
|
213
|
+
) -> dict[str, Any]:
|
|
214
|
+
payload = {
|
|
215
|
+
"id": step_id,
|
|
216
|
+
"status": "planned",
|
|
217
|
+
"purpose": purpose,
|
|
218
|
+
"command": command,
|
|
219
|
+
"write_policy": write_policy,
|
|
220
|
+
"external_write": False,
|
|
221
|
+
}
|
|
222
|
+
if model:
|
|
223
|
+
payload["model"] = model
|
|
224
|
+
return payload
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def summarize_llms() -> dict[str, Any]:
|
|
228
|
+
backends = list_backends()
|
|
229
|
+
doctor = doctor_backends()
|
|
230
|
+
items = doctor.get("items") or []
|
|
231
|
+
usable = [item for item in items if item.get("status") == "ok" and item.get("id") != "ollama"]
|
|
232
|
+
ollama_item = next((item for item in items if item.get("id") == "ollama"), None)
|
|
233
|
+
preference = backends.get("preference") or {}
|
|
234
|
+
return {
|
|
235
|
+
"status": "ok" if usable else "missing",
|
|
236
|
+
"default": backends.get("default"),
|
|
237
|
+
"primary": preference.get("primary"),
|
|
238
|
+
"fallback_enabled": preference.get("fallback_enabled"),
|
|
239
|
+
"configured_count": len([item for item in backends.get("items") or [] if item.get("configured")]),
|
|
240
|
+
"usable_count": len(usable),
|
|
241
|
+
"backends": [
|
|
242
|
+
{
|
|
243
|
+
"id": item.get("id"),
|
|
244
|
+
"status": item.get("status"),
|
|
245
|
+
"configured": item.get("configured"),
|
|
246
|
+
"kind": item.get("kind"),
|
|
247
|
+
}
|
|
248
|
+
for item in items
|
|
249
|
+
],
|
|
250
|
+
"ollama_backend": {
|
|
251
|
+
"status": ollama_item.get("status") if isinstance(ollama_item, dict) else None,
|
|
252
|
+
"configured": ollama_item.get("configured") if isinstance(ollama_item, dict) else None,
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def summarize_ollama(payload: dict[str, Any]) -> dict[str, Any]:
|
|
258
|
+
return {
|
|
259
|
+
"status": payload.get("status"),
|
|
260
|
+
"binary": payload.get("binary"),
|
|
261
|
+
"version": payload.get("version"),
|
|
262
|
+
"daemon": payload.get("daemon"),
|
|
263
|
+
"model_count": payload.get("model_count", 0),
|
|
264
|
+
"install_plan": payload.get("install_plan"),
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def summarize_toolchain(payload: dict[str, Any]) -> dict[str, Any]:
|
|
269
|
+
items = payload.get("items") or []
|
|
270
|
+
return {
|
|
271
|
+
"status": payload.get("status"),
|
|
272
|
+
"platform": payload.get("platform"),
|
|
273
|
+
"required_missing": payload.get("required_missing") or [],
|
|
274
|
+
"optional_missing": payload.get("optional_missing") or [],
|
|
275
|
+
"ok_count": len([item for item in items if item.get("status") == "ok"]),
|
|
276
|
+
"missing_count": len([item for item in items if item.get("status") == "missing"]),
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def summarize_sources() -> dict[str, Any]:
|
|
281
|
+
sources = list_sources()
|
|
282
|
+
try:
|
|
283
|
+
status = source_status()
|
|
284
|
+
except ValueError:
|
|
285
|
+
status = {"status": "missing", "items": []}
|
|
286
|
+
return {
|
|
287
|
+
"status": status.get("status"),
|
|
288
|
+
"count": len(sources.get("items") or []),
|
|
289
|
+
"defaults": sources.get("defaults") or {},
|
|
290
|
+
"stored_secret": bool(sources.get("stored_secret")),
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def summarize_tasks() -> dict[str, Any]:
|
|
295
|
+
tasks = list_tasks()
|
|
296
|
+
raw = load_tasks()
|
|
297
|
+
raw_items = [item for item in raw.get("tasks") or [] if isinstance(item, dict)]
|
|
298
|
+
items = tasks.get("items") or []
|
|
299
|
+
enabled = [item for item in items if item.get("status") == "enabled"]
|
|
300
|
+
due = [public_task(item) for item in raw_items if item.get("status") == "enabled" and task_is_due(item)]
|
|
301
|
+
pending = [item for item in enabled if item.get("run_count", 0) == 0]
|
|
302
|
+
return {
|
|
303
|
+
"status": tasks.get("status"),
|
|
304
|
+
"count": len(items),
|
|
305
|
+
"enabled_count": len(enabled),
|
|
306
|
+
"pending_count": len(pending),
|
|
307
|
+
"due_count": len(due),
|
|
308
|
+
"due": due[:5],
|
|
309
|
+
"pending": pending[:5],
|
|
310
|
+
"path": tasks.get("path"),
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def summarize_specialists(payload: dict[str, Any]) -> dict[str, Any]:
|
|
315
|
+
return {
|
|
316
|
+
"status": payload.get("status"),
|
|
317
|
+
"agents_total": payload.get("agents_total"),
|
|
318
|
+
"capabilities_total": payload.get("capabilities_total"),
|
|
319
|
+
"agents_with_provider_requirements": payload.get("agents_with_provider_requirements"),
|
|
320
|
+
"ready_agents": payload.get("ready_agents"),
|
|
321
|
+
"partial_agents": payload.get("partial_agents"),
|
|
322
|
+
"needs_setup_agents": payload.get("needs_setup_agents"),
|
|
323
|
+
"configured_providers": payload.get("configured_providers") or [],
|
|
324
|
+
"missing_providers": payload.get("missing_providers") or [],
|
|
325
|
+
"next_steps": payload.get("next_steps") or [],
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def startup_flow(
|
|
330
|
+
*,
|
|
331
|
+
status: str,
|
|
332
|
+
sessions: dict[str, Any],
|
|
333
|
+
tasks: dict[str, Any],
|
|
334
|
+
blockers: list[dict[str, str]],
|
|
335
|
+
) -> list[dict[str, str]]:
|
|
336
|
+
steps = [
|
|
337
|
+
{"id": "validate-home", "status": "done", "label": "Validar home local e memoria"},
|
|
338
|
+
{"id": "validate-setup", "status": "attention" if blockers else "done", "label": "Validar setup minimo"},
|
|
339
|
+
{
|
|
340
|
+
"id": "check-session",
|
|
341
|
+
"status": "active" if sessions.get("active") else "empty",
|
|
342
|
+
"label": "Verificar conversa ou analise em andamento",
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"id": "check-tasks",
|
|
346
|
+
"status": "due" if tasks.get("due_count") else ("pending" if tasks.get("pending_count") else "empty"),
|
|
347
|
+
"label": "Verificar tarefas pendentes e dados a retornar",
|
|
348
|
+
},
|
|
349
|
+
{"id": "ask-next-action", "status": status, "label": "Responder ou perguntar o proximo objetivo"},
|
|
350
|
+
]
|
|
351
|
+
return steps
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def assistant_prompt(
|
|
355
|
+
*,
|
|
356
|
+
status: str,
|
|
357
|
+
sessions: dict[str, Any],
|
|
358
|
+
tasks: dict[str, Any],
|
|
359
|
+
blockers: list[dict[str, str]],
|
|
360
|
+
actions: list[dict[str, str]],
|
|
361
|
+
) -> str:
|
|
362
|
+
if blockers:
|
|
363
|
+
return "Preciso concluir o setup minimo antes de executar tarefas. Posso iniciar o onboarding minimo ou completo."
|
|
364
|
+
if tasks.get("due_count"):
|
|
365
|
+
return "Encontrei tarefas agendadas prontas para revisao. Posso listar, executar em dry-run ou aguardar sua instrucao."
|
|
366
|
+
if tasks.get("pending_count"):
|
|
367
|
+
pending = tasks.get("pending") if isinstance(tasks.get("pending"), list) else []
|
|
368
|
+
first = pending[0] if pending and isinstance(pending[0], dict) else {}
|
|
369
|
+
title = first.get("title") or first.get("id") or "tarefa pendente"
|
|
370
|
+
active = sessions.get("active") if isinstance(sessions.get("active"), dict) else None
|
|
371
|
+
if active:
|
|
372
|
+
session_title = active.get("title") or active.get("id")
|
|
373
|
+
return f"Existe uma sessao ativa: {session_title}. Tambem encontrei tarefa pendente: {title}. Posso continuar a conversa, listar tarefas ou executar a pendencia em dry-run."
|
|
374
|
+
return f"Encontrei tarefa pendente: {title}. Posso listar, executar em dry-run ou receber uma nova tarefa."
|
|
375
|
+
active = sessions.get("active") if isinstance(sessions.get("active"), dict) else None
|
|
376
|
+
if active:
|
|
377
|
+
title = active.get("title") or active.get("id")
|
|
378
|
+
return f"Existe uma sessao ativa: {title}. Posso continuar essa conversa, mostrar status ou iniciar uma nova tarefa."
|
|
379
|
+
if actions:
|
|
380
|
+
return "Estou pronto. Posso continuar o onboarding, configurar ferramentas sob demanda ou receber uma tarefa em linguagem natural."
|
|
381
|
+
return "Estou pronto. O que voce quer fazer agora?"
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def startup_blockers(*, setup: dict[str, Any], llms: dict[str, Any]) -> list[dict[str, str]]:
|
|
385
|
+
blockers: list[dict[str, str]] = []
|
|
386
|
+
toolchain = setup.get("toolchain") or {}
|
|
387
|
+
for item in toolchain.get("required_missing") or []:
|
|
388
|
+
blockers.append(
|
|
389
|
+
{
|
|
390
|
+
"id": f"toolchain.{item}",
|
|
391
|
+
"message": f"Required toolchain item is missing: {item}.",
|
|
392
|
+
"command": f"agent toolchain install {item} --dry-run",
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
if llms.get("usable_count", 0) < 1:
|
|
396
|
+
blockers.append(
|
|
397
|
+
{
|
|
398
|
+
"id": "llm.unavailable",
|
|
399
|
+
"message": "No usable coordinator LLM backend was detected.",
|
|
400
|
+
"command": "agent llm doctor",
|
|
401
|
+
}
|
|
402
|
+
)
|
|
403
|
+
return blockers
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def suggested_actions(
|
|
407
|
+
*,
|
|
408
|
+
memory: dict[str, Any],
|
|
409
|
+
personality: dict[str, Any],
|
|
410
|
+
sessions: dict[str, Any],
|
|
411
|
+
setup: dict[str, Any],
|
|
412
|
+
llms: dict[str, Any],
|
|
413
|
+
ollama: dict[str, Any],
|
|
414
|
+
sources: dict[str, Any],
|
|
415
|
+
tasks: dict[str, Any],
|
|
416
|
+
specialists: dict[str, Any],
|
|
417
|
+
) -> list[dict[str, str]]:
|
|
418
|
+
actions: list[dict[str, str]] = []
|
|
419
|
+
due_tasks = tasks.get("due") if isinstance(tasks.get("due"), list) else []
|
|
420
|
+
pending_tasks = tasks.get("pending") if isinstance(tasks.get("pending"), list) else []
|
|
421
|
+
first_due = due_tasks[0] if due_tasks and isinstance(due_tasks[0], dict) else None
|
|
422
|
+
first_pending = pending_tasks[0] if pending_tasks and isinstance(pending_tasks[0], dict) else None
|
|
423
|
+
if first_due and first_due.get("id"):
|
|
424
|
+
actions.append(
|
|
425
|
+
{
|
|
426
|
+
"id": "tasks.run-due",
|
|
427
|
+
"label": f"Run due task: {first_due.get('title') or first_due.get('id')}",
|
|
428
|
+
"command": f"agent task run {first_due['id']} --dry-run",
|
|
429
|
+
}
|
|
430
|
+
)
|
|
431
|
+
if first_pending and first_pending.get("id"):
|
|
432
|
+
actions.append(
|
|
433
|
+
{
|
|
434
|
+
"id": "tasks.run-pending",
|
|
435
|
+
"label": f"Run pending task: {first_pending.get('title') or first_pending.get('id')}",
|
|
436
|
+
"command": f"agent task run {first_pending['id']} --dry-run",
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
actions.append(
|
|
440
|
+
{
|
|
441
|
+
"id": "tasks.review",
|
|
442
|
+
"label": "Review local scheduled and manual tasks",
|
|
443
|
+
"command": "agent task list",
|
|
444
|
+
}
|
|
445
|
+
)
|
|
446
|
+
if memory.get("created"):
|
|
447
|
+
actions.append(
|
|
448
|
+
{
|
|
449
|
+
"id": "memory.review",
|
|
450
|
+
"label": "Review local memory files",
|
|
451
|
+
"command": "agent memory show",
|
|
452
|
+
}
|
|
453
|
+
)
|
|
454
|
+
if not personality.get("user_name"):
|
|
455
|
+
actions.append(
|
|
456
|
+
{
|
|
457
|
+
"id": "personality.setup",
|
|
458
|
+
"label": "Configure agent name, user name and response style",
|
|
459
|
+
"command": "agent setup personality",
|
|
460
|
+
}
|
|
461
|
+
)
|
|
462
|
+
if llms.get("usable_count", 0) < 1:
|
|
463
|
+
actions.append(
|
|
464
|
+
{
|
|
465
|
+
"id": "llm.configure",
|
|
466
|
+
"label": "Configure a coordinator LLM backend",
|
|
467
|
+
"command": "agent llm doctor",
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
if ollama.get("status") == "missing":
|
|
471
|
+
actions.append(
|
|
472
|
+
{
|
|
473
|
+
"id": "ollama.install",
|
|
474
|
+
"label": "Inspect local Ollama mini-brain setup",
|
|
475
|
+
"command": "agent ollama status",
|
|
476
|
+
}
|
|
477
|
+
)
|
|
478
|
+
if (setup.get("toolchain") or {}).get("optional_missing"):
|
|
479
|
+
actions.append(
|
|
480
|
+
{
|
|
481
|
+
"id": "toolchain.optional",
|
|
482
|
+
"label": "Review optional local tools",
|
|
483
|
+
"command": "agent toolchain doctor",
|
|
484
|
+
}
|
|
485
|
+
)
|
|
486
|
+
if sources.get("count", 0) < 1:
|
|
487
|
+
actions.append(
|
|
488
|
+
{
|
|
489
|
+
"id": "sources.configure",
|
|
490
|
+
"label": "Add reusable project/provider sources when needed",
|
|
491
|
+
"command": "agent source list",
|
|
492
|
+
}
|
|
493
|
+
)
|
|
494
|
+
if specialists.get("status") in {"needs-setup", "partial"}:
|
|
495
|
+
next_steps = specialists.get("next_steps") if isinstance(specialists.get("next_steps"), list) else []
|
|
496
|
+
actions.append(
|
|
497
|
+
{
|
|
498
|
+
"id": "specialists.readiness",
|
|
499
|
+
"label": "Review specialist agent provider readiness",
|
|
500
|
+
"command": str(next_steps[0] if next_steps else "agent doctor"),
|
|
501
|
+
}
|
|
502
|
+
)
|
|
503
|
+
if tasks.get("count", 0) < 1:
|
|
504
|
+
actions.append(
|
|
505
|
+
{
|
|
506
|
+
"id": "tasks.create",
|
|
507
|
+
"label": "Create scheduled or recurring tasks when useful",
|
|
508
|
+
"command": "agent task list",
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
if not sessions.get("active_session_id"):
|
|
512
|
+
actions.append(
|
|
513
|
+
{
|
|
514
|
+
"id": "session.start",
|
|
515
|
+
"label": "Start by sending a natural-language task",
|
|
516
|
+
"command": "agent \"o que voce consegue fazer aqui?\"",
|
|
517
|
+
}
|
|
518
|
+
)
|
|
519
|
+
return dedupe_actions(actions)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def dedupe_actions(actions: list[dict[str, str]]) -> list[dict[str, str]]:
|
|
523
|
+
seen: set[str] = set()
|
|
524
|
+
deduped: list[dict[str, str]] = []
|
|
525
|
+
for action in actions:
|
|
526
|
+
action_id = action.get("id")
|
|
527
|
+
if not action_id or action_id in seen:
|
|
528
|
+
continue
|
|
529
|
+
seen.add(action_id)
|
|
530
|
+
deduped.append(action)
|
|
531
|
+
return deduped
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def summarize_sessions() -> dict[str, Any]:
|
|
535
|
+
sessions = list_sessions()
|
|
536
|
+
active_id = sessions.get("active_session_id")
|
|
537
|
+
active = None
|
|
538
|
+
if active_id:
|
|
539
|
+
try:
|
|
540
|
+
payload = show_session(str(active_id))
|
|
541
|
+
active = payload.get("session")
|
|
542
|
+
if isinstance(active, dict):
|
|
543
|
+
active["summary"] = payload.get("summary")
|
|
544
|
+
active["recent_messages"] = payload.get("recent_messages") or []
|
|
545
|
+
except ValueError:
|
|
546
|
+
active = None
|
|
547
|
+
return {
|
|
548
|
+
**sessions,
|
|
549
|
+
"active": active,
|
|
550
|
+
"recent": (sessions.get("items") or [])[:5],
|
|
551
|
+
}
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
+
from cli.aikit.prompt_injection import external_content_block
|
|
7
8
|
from cli.aikit.write_policy import coerce_write_policy_metadata, write_policy_public_fields
|
|
8
9
|
|
|
9
10
|
|
|
@@ -66,6 +67,16 @@ def run_payload(
|
|
|
66
67
|
"next_steps": next_steps or [],
|
|
67
68
|
"artifacts": normalize_artifacts(artifacts),
|
|
68
69
|
}
|
|
70
|
+
external_content = runtime_external_content(
|
|
71
|
+
agent_id=str(agent.get("id") or ""),
|
|
72
|
+
capability_id=capability,
|
|
73
|
+
stdout=stdout,
|
|
74
|
+
stderr=stderr,
|
|
75
|
+
evidence=evidence or [],
|
|
76
|
+
)
|
|
77
|
+
if external_content:
|
|
78
|
+
payload["external_content"] = external_content
|
|
79
|
+
payload["prompt_injection"] = prompt_injection_summary(external_content)
|
|
69
80
|
if guardrail is not None:
|
|
70
81
|
payload["guardrail"] = guardrail
|
|
71
82
|
if error:
|
|
@@ -77,6 +88,62 @@ def run_payload(
|
|
|
77
88
|
return payload
|
|
78
89
|
|
|
79
90
|
|
|
91
|
+
def runtime_external_content(
|
|
92
|
+
*,
|
|
93
|
+
agent_id: str,
|
|
94
|
+
capability_id: str,
|
|
95
|
+
stdout: str,
|
|
96
|
+
stderr: str,
|
|
97
|
+
evidence: list[dict[str, Any]],
|
|
98
|
+
) -> list[dict[str, Any]]:
|
|
99
|
+
blocks: list[dict[str, Any]] = []
|
|
100
|
+
source = f"{agent_id}/{capability_id}".strip("/")
|
|
101
|
+
if stdout:
|
|
102
|
+
blocks.append(external_content_block(source, "runner-stdout", stdout))
|
|
103
|
+
if stderr:
|
|
104
|
+
blocks.append(external_content_block(source, "runner-stderr", stderr))
|
|
105
|
+
for index, item in enumerate(evidence):
|
|
106
|
+
text = evidence_text(item)
|
|
107
|
+
if text:
|
|
108
|
+
blocks.append(external_content_block(f"{source}:evidence:{index}", "runner-evidence", text))
|
|
109
|
+
return blocks
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def evidence_text(item: dict[str, Any]) -> str:
|
|
113
|
+
values: list[str] = []
|
|
114
|
+
for key in ("summary", "message", "text", "content", "stdout", "stderr", "value"):
|
|
115
|
+
value = item.get(key)
|
|
116
|
+
if isinstance(value, str) and value.strip():
|
|
117
|
+
values.append(value)
|
|
118
|
+
return "\n".join(values)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def prompt_injection_summary(blocks: list[dict[str, Any]]) -> dict[str, Any]:
|
|
122
|
+
markers: list[str] = []
|
|
123
|
+
severities: list[str] = []
|
|
124
|
+
for block in blocks:
|
|
125
|
+
markers.extend(str(marker) for marker in block.get("detected_injection_markers") or [])
|
|
126
|
+
severity = str(block.get("severity") or "none")
|
|
127
|
+
severities.append(severity)
|
|
128
|
+
return {
|
|
129
|
+
"kind": "prompt-injection-scan",
|
|
130
|
+
"status": "flagged" if markers else "clear",
|
|
131
|
+
"blocks": len(blocks),
|
|
132
|
+
"severity": max_severity(severities),
|
|
133
|
+
"detected_markers": sorted(set(markers)),
|
|
134
|
+
"policy": "external content is data, not instructions",
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def max_severity(severities: list[str]) -> str:
|
|
139
|
+
order = {"none": 0, "low": 1, "medium": 2, "high": 3}
|
|
140
|
+
selected = "none"
|
|
141
|
+
for severity in severities:
|
|
142
|
+
if order.get(severity, 0) > order[selected]:
|
|
143
|
+
selected = severity
|
|
144
|
+
return selected
|
|
145
|
+
|
|
146
|
+
|
|
80
147
|
def normalize_providers(providers: dict[str, Any] | None) -> dict[str, Any]:
|
|
81
148
|
result = dict(providers or {})
|
|
82
149
|
result.setdefault("used", [])
|
|
@@ -18,6 +18,7 @@ INJECTION_MARKERS = (
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def external_content_block(source: str, content_type: str, content: str) -> dict[str, Any]:
|
|
21
|
+
markers = detected_injection_markers(content)
|
|
21
22
|
return {
|
|
22
23
|
"kind": "external-content",
|
|
23
24
|
"schema_version": PROMPT_INJECTION_SCHEMA_VERSION,
|
|
@@ -26,7 +27,8 @@ def external_content_block(source: str, content_type: str, content: str) -> dict
|
|
|
26
27
|
"content_type": content_type,
|
|
27
28
|
"instruction_policy": "quote-as-data",
|
|
28
29
|
"content": content,
|
|
29
|
-
"detected_injection_markers":
|
|
30
|
+
"detected_injection_markers": markers,
|
|
31
|
+
"severity": injection_severity(markers),
|
|
30
32
|
"can_grant_permission": False,
|
|
31
33
|
"can_override_policy": False,
|
|
32
34
|
}
|
|
@@ -37,6 +39,14 @@ def detected_injection_markers(content: str) -> list[str]:
|
|
|
37
39
|
return [marker for marker in INJECTION_MARKERS if marker in lowered]
|
|
38
40
|
|
|
39
41
|
|
|
42
|
+
def injection_severity(markers: list[str]) -> str:
|
|
43
|
+
if any(marker in markers for marker in ("reveal secret", "override policy", "bypass")):
|
|
44
|
+
return "high"
|
|
45
|
+
if markers:
|
|
46
|
+
return "medium"
|
|
47
|
+
return "none"
|
|
48
|
+
|
|
49
|
+
|
|
40
50
|
def prompt_injection_eval_fixture() -> dict[str, Any]:
|
|
41
51
|
block = external_content_block(
|
|
42
52
|
"eval-fixture",
|
|
@@ -48,6 +58,7 @@ def prompt_injection_eval_fixture() -> dict[str, Any]:
|
|
|
48
58
|
and block["instruction_policy"] == "quote-as-data"
|
|
49
59
|
and block["can_grant_permission"] is False
|
|
50
60
|
and block["can_override_policy"] is False
|
|
61
|
+
and block["severity"] in {"medium", "high"}
|
|
51
62
|
and bool(block["detected_injection_markers"])
|
|
52
63
|
)
|
|
53
64
|
return {
|