@0dai-dev/cli 4.3.5 → 4.3.7

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 (79) hide show
  1. package/README.md +12 -11
  2. package/bin/0dai.js +214 -40
  3. package/lib/ai/manifest/mcp-exposure-contract.json +121 -0
  4. package/lib/ai/meta/manifest/mcp-tool-tiers.json +435 -0
  5. package/lib/ai/registry/mcp-catalog.json +98 -0
  6. package/lib/commands/auth.js +55 -1
  7. package/lib/commands/compliance.js +1 -1
  8. package/lib/commands/detect.js +10 -4
  9. package/lib/commands/doctor.js +545 -26
  10. package/lib/commands/experience.js +40 -5
  11. package/lib/commands/export.js +73 -0
  12. package/lib/commands/feedback.js +157 -15
  13. package/lib/commands/gh.js +26 -0
  14. package/lib/commands/graph.js +9 -4
  15. package/lib/commands/heatmap.js +1 -1
  16. package/lib/commands/init.js +222 -30
  17. package/lib/commands/mcp.js +129 -21
  18. package/lib/commands/models.js +138 -41
  19. package/lib/commands/provider.js +30 -59
  20. package/lib/commands/quota.js +1 -1
  21. package/lib/commands/receipt.js +1 -1
  22. package/lib/commands/run.js +18 -7
  23. package/lib/commands/runner.js +31 -1
  24. package/lib/commands/status.js +44 -11
  25. package/lib/commands/swarm.js +130 -12
  26. package/lib/commands/trust.js +286 -0
  27. package/lib/commands/update.js +184 -38
  28. package/lib/commands/usage.js +1 -1
  29. package/lib/commands/validate.js +32 -3
  30. package/lib/commands/vault.js +46 -9
  31. package/lib/python/__init__.py +0 -0
  32. package/lib/python/agent_quotas.py +525 -0
  33. package/lib/python/anomaly_alert.py +397 -0
  34. package/lib/python/anti_pattern_detector.py +799 -0
  35. package/lib/python/auth.py +443 -0
  36. package/lib/python/capi_profile_guard.py +477 -0
  37. package/lib/python/compliance_report.py +581 -0
  38. package/lib/python/drift_detector.py +388 -0
  39. package/lib/python/experience_pipeline.py +1130 -0
  40. package/lib/python/graph.py +19 -0
  41. package/lib/python/graph_core.py +293 -0
  42. package/lib/python/graph_io.py +179 -0
  43. package/lib/python/graph_legacy.py +2052 -0
  44. package/lib/python/graph_legacy_helpers.py +221 -0
  45. package/lib/python/graph_outcomes_core.py +85 -0
  46. package/lib/python/graph_queries.py +171 -0
  47. package/lib/python/graph_slice.py +198 -0
  48. package/lib/python/graph_slicer.py +576 -0
  49. package/lib/python/graph_slicer_cli.py +60 -0
  50. package/lib/python/graph_validation.py +64 -0
  51. package/lib/python/heatmap.py +934 -0
  52. package/lib/python/json_utils.py +193 -0
  53. package/lib/python/mcp_exposure_check.py +247 -0
  54. package/lib/python/model_router.py +1434 -0
  55. package/lib/python/project_manager.py +621 -0
  56. package/lib/python/provider_profiles.py +1618 -0
  57. package/lib/python/provider_registry.py +1211 -0
  58. package/lib/python/provider_registry_cli.py +125 -0
  59. package/lib/python/receipt_png.py +727 -0
  60. package/lib/python/structural_memory.py +325 -0
  61. package/lib/python/swarm_cost.py +177 -0
  62. package/lib/python/usage_ledger.py +569 -0
  63. package/lib/scripts/mcp_tier_config.py +240 -0
  64. package/lib/shared.js +97 -14
  65. package/lib/tui/index.mjs +35174 -0
  66. package/lib/utils/activation_telemetry.js +230 -11
  67. package/lib/utils/constants.js +7 -1
  68. package/lib/utils/export-bundler.js +285 -0
  69. package/lib/utils/identity.js +198 -1
  70. package/lib/utils/mcp-auth.js +81 -15
  71. package/lib/utils/plan.js +1 -1
  72. package/lib/vault/index.js +19 -3
  73. package/lib/vault/storage.js +21 -2
  74. package/lib/wizard.js +5 -2
  75. package/package.json +9 -3
  76. package/scripts/build-python-bundle.js +106 -0
  77. package/scripts/build-tui.js +14 -1
  78. package/scripts/harvest_experience.py +523 -0
  79. package/scripts/postinstall.js +15 -9
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env python3
2
+ """CLI wrapper for local BYOK provider registry list/switch/clear commands."""
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import pathlib
8
+ import sys
9
+ from typing import Any
10
+
11
+ import provider_registry as pr
12
+
13
+
14
+ def _provider_row(row: dict[str, Any]) -> dict[str, Any]:
15
+ """Return only non-secret provider metadata for CLI output."""
16
+ return {
17
+ "name": str(row.get("name") or ""),
18
+ "endpoint_kind": str(row.get("endpoint_kind") or ""),
19
+ "base_url": str(row.get("base_url") or ""),
20
+ "has_credentials": bool(row.get("has_credentials")),
21
+ "source": str(row.get("source") or ""),
22
+ "active": bool(row.get("active")),
23
+ }
24
+
25
+
26
+ def _profile_payload(profile: dict[str, Any]) -> dict[str, Any]:
27
+ """Return a switch result without raw provider secret material."""
28
+ return {
29
+ "provider_name": str(profile.get("provider_name") or ""),
30
+ "base_url": str(profile.get("base_url") or ""),
31
+ "api_key_ref": str(profile.get("api_key_ref") or ""),
32
+ "model": str(profile.get("model") or ""),
33
+ "updated_at": str(profile.get("updated_at") or ""),
34
+ }
35
+
36
+
37
+ def _print_json(payload: dict[str, Any]) -> None:
38
+ print(json.dumps(payload, sort_keys=True))
39
+
40
+
41
+ def _cmd_list(args: argparse.Namespace) -> int:
42
+ target = pathlib.Path(args.target).resolve()
43
+ providers = [_provider_row(row) for row in pr.list_providers_for_repo(target)]
44
+ if args.json:
45
+ _print_json({"target": str(target), "providers": providers})
46
+ return 0
47
+
48
+ print(f"Provider Status for {target.name}")
49
+ print("=" * 60)
50
+ for row in providers:
51
+ active = "->" if row["active"] else " "
52
+ source = f"[{row['source']}]" if row["source"] else ""
53
+ creds = "yes" if row["has_credentials"] else "no"
54
+ print(f" {active} {row['name']:<12} creds={creds:<3} {source:<10} {row['base_url']}")
55
+ print("")
56
+ return 0
57
+
58
+
59
+ def _cmd_switch(args: argparse.Namespace) -> int:
60
+ target = pathlib.Path(args.target).resolve()
61
+ profile = _profile_payload(pr.switch_provider(target, args.provider))
62
+ if args.json:
63
+ _print_json({"target": str(target), "switched": True, "profile": profile})
64
+ return 0
65
+
66
+ print(f"Switched {target.name} to provider: {profile['provider_name']}")
67
+ print(f" base_url: {profile['base_url']}")
68
+ print(" audit log: ~/.0dai/audit/provider-changes.jsonl")
69
+ return 0
70
+
71
+
72
+ def _cmd_clear(args: argparse.Namespace) -> int:
73
+ target = pathlib.Path(args.target).resolve()
74
+ cleared = pr.clear_repo_profile(target)
75
+ if args.json:
76
+ _print_json({"target": str(target), "cleared": bool(cleared)})
77
+ return 0
78
+
79
+ if cleared:
80
+ print(f"Cleared per-repo profile for {target.name}")
81
+ print("Will fall back to global default or env vars")
82
+ else:
83
+ print(f"No per-repo profile to clear for {target.name}")
84
+ return 0
85
+
86
+
87
+ def build_parser() -> argparse.ArgumentParser:
88
+ common = argparse.ArgumentParser(add_help=False)
89
+ common.add_argument("--target", default=".", help="project directory")
90
+ common.add_argument("--json", action="store_true", help="emit JSON")
91
+
92
+ parser = argparse.ArgumentParser(
93
+ description="Manage local provider registry profiles",
94
+ parents=[common],
95
+ )
96
+ sub = parser.add_subparsers(dest="command", required=True)
97
+
98
+ list_cmd = sub.add_parser("list", parents=[common], help="list configured provider availability")
99
+ list_cmd.set_defaults(func=_cmd_list)
100
+
101
+ switch_cmd = sub.add_parser("switch", parents=[common], help="switch this project to a provider")
102
+ switch_cmd.add_argument("--provider", required=True, help="provider name")
103
+ switch_cmd.set_defaults(func=_cmd_switch)
104
+
105
+ clear_cmd = sub.add_parser("clear", parents=[common], help="clear this project's provider override")
106
+ clear_cmd.set_defaults(func=_cmd_clear)
107
+
108
+ return parser
109
+
110
+
111
+ def main(argv: list[str] | None = None) -> int:
112
+ parser = build_parser()
113
+ args = parser.parse_args(argv)
114
+ try:
115
+ return int(args.func(args) or 0)
116
+ except pr.ProviderRegistryError as exc:
117
+ if getattr(args, "json", False):
118
+ _print_json({"error": str(exc)})
119
+ else:
120
+ print(f"Error: {exc}", file=sys.stderr)
121
+ return 1
122
+
123
+
124
+ if __name__ == "__main__":
125
+ raise SystemExit(main())