@invokehq/cli 0.2.3 → 0.2.5
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/agentify.py +128 -0
- package/package.json +1 -1
package/agentify.py
CHANGED
|
@@ -1569,6 +1569,111 @@ def search_command(args: argparse.Namespace) -> int:
|
|
|
1569
1569
|
return 0
|
|
1570
1570
|
|
|
1571
1571
|
|
|
1572
|
+
def action_payload_from_args(args: argparse.Namespace) -> dict[str, Any]:
|
|
1573
|
+
if not args.action:
|
|
1574
|
+
raise CliUsageError(
|
|
1575
|
+
f"Missing action.\n"
|
|
1576
|
+
f"Usage: invoke {args.command} <action> '<json_params>'\n"
|
|
1577
|
+
f"Example: invoke {args.command} stripe.charge_customer '{{\"customer_id\":\"cust_123\",\"amount\":2400}}'"
|
|
1578
|
+
)
|
|
1579
|
+
try:
|
|
1580
|
+
params = json.loads(args.params)
|
|
1581
|
+
except json.JSONDecodeError as exc:
|
|
1582
|
+
raise ValueError(f"params must be valid JSON: {exc}") from exc
|
|
1583
|
+
if not isinstance(params, dict):
|
|
1584
|
+
raise ValueError("params must be a JSON object")
|
|
1585
|
+
|
|
1586
|
+
body: dict[str, Any] = {
|
|
1587
|
+
"action": args.action,
|
|
1588
|
+
"params": params,
|
|
1589
|
+
"agent_id": args.agent_id,
|
|
1590
|
+
}
|
|
1591
|
+
if args.idempotency_key:
|
|
1592
|
+
body["idempotency_key"] = args.idempotency_key
|
|
1593
|
+
if args.apply_safe_fixes:
|
|
1594
|
+
body["apply_safe_fixes"] = True
|
|
1595
|
+
if getattr(args, "preflight_only", False):
|
|
1596
|
+
body["preflight_only"] = True
|
|
1597
|
+
return body
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
def print_preflight_summary(preflight: dict[str, Any]) -> None:
|
|
1601
|
+
print(f"Risk: {preflight.get('risk_score', '-')}" + (
|
|
1602
|
+
f" ({preflight.get('risk_score_numeric')})" if preflight.get("risk_score_numeric") is not None else ""
|
|
1603
|
+
))
|
|
1604
|
+
subject = preflight.get("subject") if isinstance(preflight.get("subject"), dict) else {}
|
|
1605
|
+
if subject.get("tool"):
|
|
1606
|
+
print(f"Subject: {subject.get('tool')} [{subject.get('safety_class') or 'unknown'}]")
|
|
1607
|
+
simulation = preflight.get("simulation") if isinstance(preflight.get("simulation"), dict) else {}
|
|
1608
|
+
if simulation:
|
|
1609
|
+
print(
|
|
1610
|
+
f"Simulation: {simulation.get('similar_traces', 0)} similar traces "
|
|
1611
|
+
f"via {simulation.get('source', 'patterns')}"
|
|
1612
|
+
)
|
|
1613
|
+
|
|
1614
|
+
warnings = preflight.get("warnings") if isinstance(preflight.get("warnings"), list) else []
|
|
1615
|
+
if warnings:
|
|
1616
|
+
print("\nWarnings")
|
|
1617
|
+
for warning in warnings:
|
|
1618
|
+
print(f"- {warning.get('severity', 'warn')}: {warning.get('message')}")
|
|
1619
|
+
|
|
1620
|
+
guardrails = preflight.get("recommended_guardrails") if isinstance(preflight.get("recommended_guardrails"), list) else []
|
|
1621
|
+
if guardrails:
|
|
1622
|
+
print("\nRecommended guardrails")
|
|
1623
|
+
for guardrail in guardrails:
|
|
1624
|
+
applied = "applied" if guardrail.get("applied") else "pending"
|
|
1625
|
+
print(f"- {guardrail.get('type')}: {guardrail.get('action')} [{applied}]")
|
|
1626
|
+
|
|
1627
|
+
safe_fixes = preflight.get("safe_fixes") if isinstance(preflight.get("safe_fixes"), dict) else {}
|
|
1628
|
+
if safe_fixes.get("idempotency_key"):
|
|
1629
|
+
print(f"\nIdempotency key: {safe_fixes.get('idempotency_key')}")
|
|
1630
|
+
print(f"\nDecision: {preflight.get('decision', '-')}")
|
|
1631
|
+
|
|
1632
|
+
|
|
1633
|
+
def preflight_command(args: argparse.Namespace) -> int:
|
|
1634
|
+
credentials = require_credentials(args)
|
|
1635
|
+
response = api_request(
|
|
1636
|
+
"POST",
|
|
1637
|
+
credentials["base_url"],
|
|
1638
|
+
"/v1/preflight",
|
|
1639
|
+
credentials["api_key"],
|
|
1640
|
+
action_payload_from_args(args),
|
|
1641
|
+
)
|
|
1642
|
+
if args.json:
|
|
1643
|
+
print(json.dumps(response, indent=2))
|
|
1644
|
+
return 0
|
|
1645
|
+
print(f"Invoke preflight: {args.action}")
|
|
1646
|
+
print_preflight_summary(response.get("preflight") or {})
|
|
1647
|
+
return 0
|
|
1648
|
+
|
|
1649
|
+
|
|
1650
|
+
def execute_command(args: argparse.Namespace) -> int:
|
|
1651
|
+
credentials = require_credentials(args)
|
|
1652
|
+
response = api_request(
|
|
1653
|
+
"POST",
|
|
1654
|
+
credentials["base_url"],
|
|
1655
|
+
"/v1/executions",
|
|
1656
|
+
credentials["api_key"],
|
|
1657
|
+
action_payload_from_args(args),
|
|
1658
|
+
)
|
|
1659
|
+
if args.json:
|
|
1660
|
+
print(json.dumps(response, indent=2))
|
|
1661
|
+
return 0
|
|
1662
|
+
|
|
1663
|
+
execution = response.get("execution") if isinstance(response.get("execution"), dict) else {}
|
|
1664
|
+
certificate = response.get("certificate") if isinstance(response.get("certificate"), dict) else {}
|
|
1665
|
+
print(f"Invoke execute: {args.action}")
|
|
1666
|
+
preflight = response.get("preflight") if isinstance(response.get("preflight"), dict) else {}
|
|
1667
|
+
if preflight:
|
|
1668
|
+
print_preflight_summary(preflight)
|
|
1669
|
+
print()
|
|
1670
|
+
print(f"Execution ID: {certificate.get('execution_id') or execution.get('execution_id') or '-'}")
|
|
1671
|
+
print(f"Decision: {certificate.get('decision') or execution.get('decision') or execution.get('status') or '-'}")
|
|
1672
|
+
print(f"Final outcome: {certificate.get('final_outcome') or execution.get('final_outcome') or '-'}")
|
|
1673
|
+
print("Certificate returned: yes")
|
|
1674
|
+
return 0
|
|
1675
|
+
|
|
1676
|
+
|
|
1572
1677
|
def workflow_command(args: argparse.Namespace) -> int:
|
|
1573
1678
|
credentials = require_credentials(args)
|
|
1574
1679
|
body: dict[str, Any] = {}
|
|
@@ -1728,6 +1833,29 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
1728
1833
|
search.add_argument("--api-key", help="Override Invoke API key.")
|
|
1729
1834
|
search.set_defaults(func=search_command)
|
|
1730
1835
|
|
|
1836
|
+
preflight = subparsers.add_parser("preflight", help="Simulate an agent action before execution.")
|
|
1837
|
+
preflight.add_argument("action", nargs="?", help="Action name, for example stripe.charge_customer.")
|
|
1838
|
+
preflight.add_argument("params", nargs="?", default="{}", help="JSON params object.")
|
|
1839
|
+
preflight.add_argument("--agent-id", default="cli_agent")
|
|
1840
|
+
preflight.add_argument("--idempotency-key")
|
|
1841
|
+
preflight.add_argument("--apply-safe-fixes", action="store_true", help="Apply recommended guardrails in the returned plan.")
|
|
1842
|
+
preflight.add_argument("--json", action="store_true", help="Print the full JSON response.")
|
|
1843
|
+
preflight.add_argument("--base-url", help="Override Invoke runtime URL.")
|
|
1844
|
+
preflight.add_argument("--api-key", help="Override Invoke API key.")
|
|
1845
|
+
preflight.set_defaults(func=preflight_command)
|
|
1846
|
+
|
|
1847
|
+
execute = subparsers.add_parser("execute", help="Execute an agent action through Invoke's control boundary.")
|
|
1848
|
+
execute.add_argument("action", nargs="?", help="Action name, for example stripe.charge_customer.")
|
|
1849
|
+
execute.add_argument("params", nargs="?", default="{}", help="JSON params object.")
|
|
1850
|
+
execute.add_argument("--agent-id", default="cli_agent")
|
|
1851
|
+
execute.add_argument("--idempotency-key")
|
|
1852
|
+
execute.add_argument("--apply-safe-fixes", action="store_true", help="Apply recommended guardrails before returning the receipt.")
|
|
1853
|
+
execute.add_argument("--preflight-only", action="store_true", help="Only run the pre-execution simulation.")
|
|
1854
|
+
execute.add_argument("--json", action="store_true", help="Print the full JSON response.")
|
|
1855
|
+
execute.add_argument("--base-url", help="Override Invoke runtime URL.")
|
|
1856
|
+
execute.add_argument("--api-key", help="Override Invoke API key.")
|
|
1857
|
+
execute.set_defaults(func=execute_command)
|
|
1858
|
+
|
|
1731
1859
|
workflow = subparsers.add_parser("workflow", help="Run a packaged Invoke workflow.")
|
|
1732
1860
|
workflow.add_argument(
|
|
1733
1861
|
"workflow",
|