Capability-set targeting + Claude Code headless provider + resilience fixes
Capability targeting (new feature): - loop --capability <SET|ALL> scopes which capability library the loop reasons against. data/capability_sets/<name>.json (same schema as capabilities.json) holds one-off targeted products; drop a file in and pass its name, no code changes. First set: agentminder (Broadcom AgentMinder, agentic-AI identity). - capabilities.set_active_set() swaps the active library; keyword pre-filter is bypassed for small targeted sets so every signal is evaluated. New 'capability-sets' command lists them; run banner shows the active set. LLM provider — the '429' was a disguised policy block: - Anthropic rejects Claude Code OAuth tokens on /v1/messages for non-Claude-Code traffic with a fake rate_limit_error (no anthropic-ratelimit-* headers). New 'claude-cli' provider runs inference through the sanctioned headless path (claude -p --append-system-prompt --model), now the default provider. - OAuth keychain token auto-refresh via headless claude when expired. Resilience: - STATE_DIR is overridable (macOS endpoint-security locked output/state via com.apple.macl); load_memory tolerates PermissionError; exa usage counter tolerates malformed files; run.py handles Ctrl-C cleanly (no traceback). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,8 @@ from src.memory import store, feedback
|
||||
|
||||
|
||||
def cmd_loop(args):
|
||||
from src import capabilities
|
||||
capabilities.set_active_set(args.capability)
|
||||
if args.no_domain_filter:
|
||||
config.EXA_DOMAIN_FILTER = False # per-run override
|
||||
if args.domain_filter:
|
||||
@@ -95,6 +97,19 @@ def cmd_recalibrate(args):
|
||||
print(f" {k}: weight={v['weight']} (n={v['samples']})")
|
||||
|
||||
|
||||
def cmd_capability_sets(args):
|
||||
from src import capabilities
|
||||
import json as _json
|
||||
for name in capabilities.available_sets():
|
||||
if name == "ALL":
|
||||
n = len(_json.loads((config.DATA_DIR / "capabilities.json").read_text())["capabilities"])
|
||||
print(f" ALL {n} capabilities (full portfolio, default)")
|
||||
else:
|
||||
doc = _json.loads((config.DATA_DIR / "capability_sets" / f"{name}.json").read_text())
|
||||
caps = ", ".join(c["name"].split(" — ")[0] for c in doc["capabilities"])
|
||||
print(f" {name:12} {len(doc['capabilities'])} capability(ies): {caps}")
|
||||
|
||||
|
||||
def cmd_accounts(args):
|
||||
for a in crm.load_accounts():
|
||||
prods = a.get("currentProducts") or []
|
||||
@@ -137,6 +152,9 @@ def main(argv=None):
|
||||
p_loop.add_argument("--limit", type=int,
|
||||
help="process at most N accounts (strategic + least-recently-run first); "
|
||||
"successive runs resume where the last left off")
|
||||
p_loop.add_argument("--capability", default="ALL", metavar="SET",
|
||||
help="capability set to reason against: ALL (full portfolio, default) "
|
||||
"or a name from data/capability_sets/ (e.g. agentminder)")
|
||||
p_loop.add_argument("--no-domain-filter", action="store_true",
|
||||
help="broad-web news about the account (default behavior)")
|
||||
p_loop.add_argument("--domain-filter", action="store_true",
|
||||
@@ -168,13 +186,20 @@ def main(argv=None):
|
||||
p_re = sub.add_parser("recalibrate", help="Recompute feedback weights (weekly job)")
|
||||
p_re.set_defaults(func=cmd_recalibrate)
|
||||
|
||||
sub.add_parser("capability-sets", help="List available capability sets"
|
||||
).set_defaults(func=cmd_capability_sets)
|
||||
sub.add_parser("accounts", help="List target accounts").set_defaults(func=cmd_accounts)
|
||||
sub.add_parser("briefs", help="List all generated briefs").set_defaults(func=cmd_briefs)
|
||||
sub.add_parser("exa-usage", help="Show Exa.ai request budget").set_defaults(func=cmd_exa_usage)
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
config.ensure_dirs()
|
||||
args.func(args)
|
||||
try:
|
||||
args.func(args)
|
||||
except KeyboardInterrupt:
|
||||
print("\nInterrupted — no partial briefs were written; unprocessed "
|
||||
"signals will be retried on the next run.")
|
||||
return 130
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user