bonito-cli 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/PKG-INFO +1 -1
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/deploy.py +5 -8
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/init.py +123 -1
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/providers.py +73 -1
- bonito_cli-0.7.0/bonito_cli/examples/enterprise.yaml +67 -0
- bonito_cli-0.7.0/bonito_cli/examples/multi-provider-failover.yaml +35 -0
- bonito_cli-0.7.0/bonito_cli/examples/quickstart.yaml +7 -0
- bonito_cli-0.7.0/bonito_cli/examples/support-agent.yaml +22 -0
- bonito_cli-0.7.0/bonito_cli/utils/__init__.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/pyproject.toml +2 -1
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/.gitignore +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/CHANGELOG.md +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/CLI_SPEC.md +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/README.md +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/__init__.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/__main__.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/api.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/app.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/__init__.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/admin.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/agents.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/analytics.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/approval.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/audit.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/auth.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/chat.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/compliance.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/deployments.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/gateway.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/groups.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/kb.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/mcp.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/memory.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/models.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/plan.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/policies.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/projects.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/rbac.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/routing.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/scheduler.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/secrets.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/commands/sso.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/config.py +0 -0
- {bonito_cli-0.6.0/bonito_cli/utils → bonito_cli-0.7.0/bonito_cli/examples}/__init__.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/utils/auth.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/utils/display.py +0 -0
- {bonito_cli-0.6.0 → bonito_cli-0.7.0}/bonito_cli/utils/feature_gate.py +0 -0
|
@@ -100,8 +100,8 @@ def _validate(cfg: Dict[str, Any]) -> List[str]:
|
|
|
100
100
|
continue
|
|
101
101
|
if "system_prompt" not in agent_cfg:
|
|
102
102
|
errors.append(f"agents.{agent_name}: missing 'system_prompt'")
|
|
103
|
-
if "model" not in agent_cfg:
|
|
104
|
-
errors.append(f"agents.{agent_name}: missing 'model'")
|
|
103
|
+
if "model" not in agent_cfg and "model_id" not in agent_cfg:
|
|
104
|
+
errors.append(f"agents.{agent_name}: missing 'model' (or 'model_id')")
|
|
105
105
|
|
|
106
106
|
return errors
|
|
107
107
|
|
|
@@ -490,10 +490,10 @@ def _deploy_agents(
|
|
|
490
490
|
agent_mcp_refs = cfg.get("mcp_servers", [])
|
|
491
491
|
agent_delegates = cfg.get("delegates", [])
|
|
492
492
|
if agent_mcp_refs or agent_delegates:
|
|
493
|
-
payload["tool_policy"] = {"mode": "
|
|
493
|
+
payload["tool_policy"] = {"mode": "allowed", "allowed": [], "denied": [], "http_allowlist": []}
|
|
494
494
|
elif cfg.get("rag"):
|
|
495
495
|
# RAG agents get search_knowledge_base tool
|
|
496
|
-
payload["tool_policy"] = {"mode": "
|
|
496
|
+
payload["tool_policy"] = {"mode": "allowed", "allowed": ["kb_search"], "denied": [], "http_allowlist": []}
|
|
497
497
|
|
|
498
498
|
# Attach knowledge base if configured via RAG section
|
|
499
499
|
rag = cfg.get("rag", {})
|
|
@@ -505,10 +505,7 @@ def _deploy_agents(
|
|
|
505
505
|
elif verbose:
|
|
506
506
|
console.print(f" [dim yellow]! KB '{kb_name}' not found - skipping[/dim yellow]")
|
|
507
507
|
|
|
508
|
-
#
|
|
509
|
-
agent_secrets = cfg.get("secrets", [])
|
|
510
|
-
if agent_secrets:
|
|
511
|
-
payload["secrets"] = agent_secrets
|
|
508
|
+
# Note: agent secrets are managed via /api/secrets, not in the agent payload
|
|
512
509
|
|
|
513
510
|
# Check if agent already exists — update instead of creating a duplicate
|
|
514
511
|
existing = existing_agents.get(display_name.lower())
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
|
+
import shutil
|
|
7
8
|
import subprocess
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Dict, List, Optional, Any
|
|
@@ -417,4 +418,125 @@ def init_wizard(
|
|
|
417
418
|
console.print("• Store your API key: [cyan]export BONITO_API_KEY={api_key}[/cyan]")
|
|
418
419
|
console.print("• Start chatting: [cyan]bonito chat[/cyan]")
|
|
419
420
|
console.print("• View usage: [cyan]bonito analytics usage[/cyan]")
|
|
420
|
-
console.print("• Manage models: [cyan]bonito models list[/cyan]")
|
|
421
|
+
console.print("• Manage models: [cyan]bonito models list[/cyan]")
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
# ── Template scaffolding ──────────────────────────────────────
|
|
425
|
+
|
|
426
|
+
_EXAMPLES_DIR = Path(__file__).resolve().parent.parent / "examples"
|
|
427
|
+
|
|
428
|
+
_TEMPLATES = {
|
|
429
|
+
"1": {
|
|
430
|
+
"name": "Quickstart",
|
|
431
|
+
"file": "quickstart.yaml",
|
|
432
|
+
"description": "Single provider (OpenAI) — simplest possible setup",
|
|
433
|
+
},
|
|
434
|
+
"2": {
|
|
435
|
+
"name": "Multi-Provider Failover",
|
|
436
|
+
"file": "multi-provider-failover.yaml",
|
|
437
|
+
"description": "3 providers with failover and cost-optimized routing",
|
|
438
|
+
},
|
|
439
|
+
"3": {
|
|
440
|
+
"name": "Support Agent",
|
|
441
|
+
"file": "support-agent.yaml",
|
|
442
|
+
"description": "Customer support agent with governed tools and KB search",
|
|
443
|
+
},
|
|
444
|
+
"4": {
|
|
445
|
+
"name": "Enterprise",
|
|
446
|
+
"file": "enterprise.yaml",
|
|
447
|
+
"description": "Multi-cloud (AWS/Azure/GCP), failover routing, governed agents",
|
|
448
|
+
},
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
@app.command("template")
|
|
453
|
+
def init_template(
|
|
454
|
+
output: Optional[Path] = typer.Option(
|
|
455
|
+
None,
|
|
456
|
+
"--output", "-o",
|
|
457
|
+
help="Output file path (default: ./bonito.yaml)",
|
|
458
|
+
),
|
|
459
|
+
template: Optional[str] = typer.Option(
|
|
460
|
+
None,
|
|
461
|
+
"--template", "-t",
|
|
462
|
+
help="Template number (1-4) for non-interactive use",
|
|
463
|
+
),
|
|
464
|
+
):
|
|
465
|
+
"""
|
|
466
|
+
Scaffold a bonito.yaml from a starter template.
|
|
467
|
+
|
|
468
|
+
Shows a menu of available templates, copies your pick to the
|
|
469
|
+
current directory, and prints next steps.
|
|
470
|
+
|
|
471
|
+
\b
|
|
472
|
+
Examples:
|
|
473
|
+
bonito init template
|
|
474
|
+
bonito init template -t 1
|
|
475
|
+
bonito init template -t 4 -o infra/bonito.yaml
|
|
476
|
+
"""
|
|
477
|
+
dest = output or Path.cwd() / "bonito.yaml"
|
|
478
|
+
|
|
479
|
+
# ── Show menu ─────────────────────────────────────────────
|
|
480
|
+
console.print(Panel(
|
|
481
|
+
"[bold cyan]Bonito Template Scaffolding[/bold cyan]\n\n"
|
|
482
|
+
"Pick a starter template to generate a [bold]bonito.yaml[/bold] file.",
|
|
483
|
+
border_style="cyan",
|
|
484
|
+
))
|
|
485
|
+
|
|
486
|
+
table = Table(show_header=True, header_style="bold cyan", border_style="dim")
|
|
487
|
+
table.add_column("#", style="bold", width=3)
|
|
488
|
+
table.add_column("Template", style="bold white")
|
|
489
|
+
table.add_column("Description", style="dim")
|
|
490
|
+
|
|
491
|
+
for key, tmpl in _TEMPLATES.items():
|
|
492
|
+
table.add_row(key, tmpl["name"], tmpl["description"])
|
|
493
|
+
|
|
494
|
+
console.print(table)
|
|
495
|
+
console.print()
|
|
496
|
+
|
|
497
|
+
# ── Pick template ─────────────────────────────────────────
|
|
498
|
+
if template is not None:
|
|
499
|
+
choice = template.strip()
|
|
500
|
+
else:
|
|
501
|
+
choice = Prompt.ask(
|
|
502
|
+
"[cyan]Select a template[/cyan]",
|
|
503
|
+
choices=list(_TEMPLATES.keys()),
|
|
504
|
+
default="1",
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
if choice not in _TEMPLATES:
|
|
508
|
+
print_error(f"Invalid template: {choice}. Choose 1-{len(_TEMPLATES)}.")
|
|
509
|
+
raise typer.Exit(1)
|
|
510
|
+
|
|
511
|
+
selected = _TEMPLATES[choice]
|
|
512
|
+
src = _EXAMPLES_DIR / selected["file"]
|
|
513
|
+
|
|
514
|
+
if not src.exists():
|
|
515
|
+
print_error(f"Template file not found: {src}")
|
|
516
|
+
raise typer.Exit(1)
|
|
517
|
+
|
|
518
|
+
# ── Check for existing file ───────────────────────────────
|
|
519
|
+
if dest.exists():
|
|
520
|
+
overwrite = Confirm.ask(
|
|
521
|
+
f"[yellow]{dest} already exists. Overwrite?[/yellow]",
|
|
522
|
+
default=False,
|
|
523
|
+
)
|
|
524
|
+
if not overwrite:
|
|
525
|
+
console.print("[dim]Aborted.[/dim]")
|
|
526
|
+
raise typer.Exit(0)
|
|
527
|
+
|
|
528
|
+
# ── Copy template ─────────────────────────────────────────
|
|
529
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
530
|
+
shutil.copy2(src, dest)
|
|
531
|
+
|
|
532
|
+
print_success(f"Created {dest} from template [bold]{selected['name']}[/bold]")
|
|
533
|
+
|
|
534
|
+
# ── Next steps ────────────────────────────────────────────
|
|
535
|
+
console.print(Panel(
|
|
536
|
+
f"[bold]Next steps:[/bold]\n\n"
|
|
537
|
+
f" 1. Edit [cyan]{dest}[/cyan] to add credentials or customise\n"
|
|
538
|
+
f" 2. Deploy: [cyan]bonito deploy -f {dest}[/cyan]\n"
|
|
539
|
+
f" 3. Or validate first: [cyan]bonito deploy -f {dest} --dry-run[/cyan]",
|
|
540
|
+
title="[bold green]Ready[/bold green]",
|
|
541
|
+
border_style="green",
|
|
542
|
+
))
|
|
@@ -23,7 +23,11 @@ from ..utils.display import (
|
|
|
23
23
|
console = Console()
|
|
24
24
|
app = typer.Typer(help="☁️ Cloud provider management")
|
|
25
25
|
|
|
26
|
-
_EMOJI = {
|
|
26
|
+
_EMOJI = {
|
|
27
|
+
"aws": "☁️ ", "azure": "🔷", "gcp": "🔺",
|
|
28
|
+
"aws_bedrock": "☁️ ", "azure_openai": "🔷", "gcp_vertex": "🔺",
|
|
29
|
+
"openai": "🤖", "anthropic": "🧠", "groq": "⚡", "openrouter": "🔀",
|
|
30
|
+
}
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
# ── list ────────────────────────────────────────────────────────
|
|
@@ -215,6 +219,74 @@ def add_gcp(
|
|
|
215
219
|
)
|
|
216
220
|
|
|
217
221
|
|
|
222
|
+
@add_app.command("openai")
|
|
223
|
+
def add_openai(
|
|
224
|
+
api_key: Optional[str] = typer.Option(None, "--api-key", help="OpenAI API key"),
|
|
225
|
+
name: Optional[str] = typer.Option(None, "--name"),
|
|
226
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
227
|
+
):
|
|
228
|
+
"""Connect an OpenAI provider."""
|
|
229
|
+
ensure_authenticated()
|
|
230
|
+
if not api_key:
|
|
231
|
+
api_key = Prompt.ask("OpenAI API Key", password=True)
|
|
232
|
+
_connect_provider(
|
|
233
|
+
{"provider_type": "openai", "name": name or "OpenAI", "credentials": {"api_key": api_key}},
|
|
234
|
+
get_output_format(json_output),
|
|
235
|
+
"OpenAI",
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@add_app.command("anthropic")
|
|
240
|
+
def add_anthropic(
|
|
241
|
+
api_key: Optional[str] = typer.Option(None, "--api-key", help="Anthropic API key"),
|
|
242
|
+
name: Optional[str] = typer.Option(None, "--name"),
|
|
243
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
244
|
+
):
|
|
245
|
+
"""Connect an Anthropic provider."""
|
|
246
|
+
ensure_authenticated()
|
|
247
|
+
if not api_key:
|
|
248
|
+
api_key = Prompt.ask("Anthropic API Key", password=True)
|
|
249
|
+
_connect_provider(
|
|
250
|
+
{"provider_type": "anthropic", "name": name or "Anthropic", "credentials": {"api_key": api_key}},
|
|
251
|
+
get_output_format(json_output),
|
|
252
|
+
"Anthropic",
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@add_app.command("groq")
|
|
257
|
+
def add_groq(
|
|
258
|
+
api_key: Optional[str] = typer.Option(None, "--api-key", help="Groq API key"),
|
|
259
|
+
name: Optional[str] = typer.Option(None, "--name"),
|
|
260
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
261
|
+
):
|
|
262
|
+
"""Connect a Groq provider."""
|
|
263
|
+
ensure_authenticated()
|
|
264
|
+
if not api_key:
|
|
265
|
+
api_key = Prompt.ask("Groq API Key", password=True)
|
|
266
|
+
_connect_provider(
|
|
267
|
+
{"provider_type": "groq", "name": name or "Groq", "credentials": {"api_key": api_key}},
|
|
268
|
+
get_output_format(json_output),
|
|
269
|
+
"Groq",
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@add_app.command("openrouter")
|
|
274
|
+
def add_openrouter(
|
|
275
|
+
api_key: Optional[str] = typer.Option(None, "--api-key", help="OpenRouter API key"),
|
|
276
|
+
name: Optional[str] = typer.Option(None, "--name"),
|
|
277
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
278
|
+
):
|
|
279
|
+
"""Connect an OpenRouter provider."""
|
|
280
|
+
ensure_authenticated()
|
|
281
|
+
if not api_key:
|
|
282
|
+
api_key = Prompt.ask("OpenRouter API Key", password=True)
|
|
283
|
+
_connect_provider(
|
|
284
|
+
{"provider_type": "openrouter", "name": name or "OpenRouter", "credentials": {"api_key": api_key}},
|
|
285
|
+
get_output_format(json_output),
|
|
286
|
+
"OpenRouter",
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
218
290
|
app.add_typer(add_app, name="add")
|
|
219
291
|
|
|
220
292
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
name: enterprise-ai-ops
|
|
3
|
+
description: "Enterprise AI operations — multi-cloud, failover, governed agents"
|
|
4
|
+
|
|
5
|
+
providers:
|
|
6
|
+
- name: aws-bedrock
|
|
7
|
+
type: aws
|
|
8
|
+
- name: azure-openai
|
|
9
|
+
type: azure
|
|
10
|
+
- name: gcp-vertex
|
|
11
|
+
type: gcp
|
|
12
|
+
- name: anthropic-direct
|
|
13
|
+
type: anthropic
|
|
14
|
+
|
|
15
|
+
routing:
|
|
16
|
+
- name: production-failover
|
|
17
|
+
strategy: failover
|
|
18
|
+
targets:
|
|
19
|
+
- provider: aws-bedrock
|
|
20
|
+
model: us.anthropic.claude-sonnet-4-20250514-v1:0
|
|
21
|
+
priority: 1
|
|
22
|
+
- provider: azure-openai
|
|
23
|
+
model: gpt-4o
|
|
24
|
+
priority: 2
|
|
25
|
+
- provider: gcp-vertex
|
|
26
|
+
model: gemini-2.0-flash
|
|
27
|
+
priority: 3
|
|
28
|
+
|
|
29
|
+
- name: internal-cost-optimized
|
|
30
|
+
strategy: cost
|
|
31
|
+
targets:
|
|
32
|
+
- provider: gcp-vertex
|
|
33
|
+
model: gemini-2.0-flash
|
|
34
|
+
priority: 1
|
|
35
|
+
- provider: aws-bedrock
|
|
36
|
+
model: us.amazon.nova-lite-v1:0
|
|
37
|
+
priority: 2
|
|
38
|
+
|
|
39
|
+
agents:
|
|
40
|
+
- name: Tier 1 Support
|
|
41
|
+
model_id: us.anthropic.claude-sonnet-4-20250514-v1:0
|
|
42
|
+
system_prompt: |
|
|
43
|
+
Enterprise support agent. Investigate alerts, follow internal playbooks,
|
|
44
|
+
and remediate issues. Escalate to Tier 2 if unresolved after 2 attempts.
|
|
45
|
+
model_config:
|
|
46
|
+
temperature: 0.2
|
|
47
|
+
max_tokens: 2048
|
|
48
|
+
tools:
|
|
49
|
+
mode: allowlist
|
|
50
|
+
allowed:
|
|
51
|
+
- kb_search
|
|
52
|
+
- http
|
|
53
|
+
http_allowlist:
|
|
54
|
+
- "https://internal-api.company.com/*"
|
|
55
|
+
|
|
56
|
+
- name: Knowledge Assistant
|
|
57
|
+
model_id: gpt-4o
|
|
58
|
+
system_prompt: |
|
|
59
|
+
Internal knowledge assistant. Answer questions about company policies,
|
|
60
|
+
processes, and documentation using the knowledge base.
|
|
61
|
+
model_config:
|
|
62
|
+
temperature: 0.3
|
|
63
|
+
max_tokens: 1024
|
|
64
|
+
tools:
|
|
65
|
+
mode: allowlist
|
|
66
|
+
allowed:
|
|
67
|
+
- kb_search
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
name: multi-provider
|
|
3
|
+
description: "Multi-provider setup with automatic failover routing"
|
|
4
|
+
|
|
5
|
+
providers:
|
|
6
|
+
- name: openai-primary
|
|
7
|
+
type: openai
|
|
8
|
+
- name: anthropic-backup
|
|
9
|
+
type: anthropic
|
|
10
|
+
- name: groq-fast
|
|
11
|
+
type: groq
|
|
12
|
+
|
|
13
|
+
routing:
|
|
14
|
+
- name: smart-failover
|
|
15
|
+
strategy: failover
|
|
16
|
+
targets:
|
|
17
|
+
- provider: anthropic-backup
|
|
18
|
+
model: anthropic/claude-sonnet-4-20250514
|
|
19
|
+
priority: 1
|
|
20
|
+
- provider: openai-primary
|
|
21
|
+
model: gpt-4o
|
|
22
|
+
priority: 2
|
|
23
|
+
- provider: groq-fast
|
|
24
|
+
model: llama-3.3-70b-versatile
|
|
25
|
+
priority: 3
|
|
26
|
+
|
|
27
|
+
- name: cost-optimized
|
|
28
|
+
strategy: cost
|
|
29
|
+
targets:
|
|
30
|
+
- provider: groq-fast
|
|
31
|
+
model: llama-3.3-70b-versatile
|
|
32
|
+
priority: 1
|
|
33
|
+
- provider: openai-primary
|
|
34
|
+
model: gpt-4o-mini
|
|
35
|
+
priority: 2
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: "1"
|
|
2
|
+
name: support-bot
|
|
3
|
+
description: "Customer support agent with governed tools and knowledge base"
|
|
4
|
+
|
|
5
|
+
providers:
|
|
6
|
+
- name: openai
|
|
7
|
+
type: openai
|
|
8
|
+
|
|
9
|
+
agents:
|
|
10
|
+
- name: Customer Support
|
|
11
|
+
model_id: gpt-4o
|
|
12
|
+
system_prompt: |
|
|
13
|
+
You are a helpful customer support agent. Answer questions accurately
|
|
14
|
+
using the knowledge base. If you don't know the answer, escalate to
|
|
15
|
+
a human. Always be polite and concise.
|
|
16
|
+
model_config:
|
|
17
|
+
temperature: 0.3
|
|
18
|
+
max_tokens: 1024
|
|
19
|
+
tools:
|
|
20
|
+
mode: allowlist
|
|
21
|
+
allowed:
|
|
22
|
+
- kb_search
|
|
File without changes
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bonito-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "Bonito CLI — Unified multi-cloud AI management from your terminal"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -25,3 +25,4 @@ bonito = "bonito_cli.app:app"
|
|
|
25
25
|
|
|
26
26
|
[tool.hatch.build.targets.wheel]
|
|
27
27
|
packages = ["bonito_cli"]
|
|
28
|
+
artifacts = ["bonito_cli/examples/*.yaml"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|