-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasciinema_sync_demo.py
More file actions
116 lines (93 loc) · 3.33 KB
/
asciinema_sync_demo.py
File metadata and controls
116 lines (93 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""Asciinema-friendly sync demo for agent-control-plane.
Run:
uv run python examples/asciinema_sync_demo.py
uv run python examples/asciinema_sync_demo.py --db ./custom.db
"""
from __future__ import annotations
from datetime import UTC, datetime, timedelta
from decimal import Decimal
from pathlib import Path
from agent_control_plane.sync import ControlPlaneFacade, DictEventMapper
from agent_control_plane.types.enums import ApprovalDecisionType, EventKind
from agent_control_plane.types.proposals import ActionProposal
DEFAULT_DB = Path("./control_plane_asciinema_demo.db")
def run_demo(db_path: Path) -> None:
db_path.unlink(missing_ok=True)
mapper = DictEventMapper(
{
"job_started": EventKind.CYCLE_STARTED,
"job_completed": EventKind.CYCLE_COMPLETED,
}
)
facade = ControlPlaneFacade.from_database_url(f"sqlite:///{db_path}", mapper=mapper)
facade.setup()
session = facade.open_session(
"asciinema-sync-demo",
max_cost=Decimal("25.00"),
max_action_count=5,
command_id="demo-open-session",
)
print(f"session_id={session}")
proposal = ActionProposal(
session_id=session,
resource_id="ticket-42",
resource_type="support_ticket",
decision="status",
reasoning="Demo status check",
metadata={"source": "asciinema"},
weight=Decimal("1.25"),
score=Decimal("0.91"),
)
created = facade.create_proposal(proposal, command_id="demo-create-proposal")
print(f"proposal_id={created.id}")
ticket = facade.create_ticket(
session,
created.id,
timeout_at=datetime.now(UTC) + timedelta(minutes=10),
command_id="demo-create-ticket",
)
print(f"ticket_id={ticket.id}")
approved = facade.approve_ticket(
ticket.id,
decided_by="ops-demo",
reason="Approved in terminal demo",
decision_type=ApprovalDecisionType.ALLOW_ONCE,
command_id="demo-approve-ticket",
)
print(f"ticket_status={approved.status}")
budget_ok = facade.check_budget(session, cost=Decimal("1.25"), action_count=1)
print(f"budget_check={budget_ok}")
facade.increment_budget(session, cost=Decimal("1.25"), action_count=1)
app_seq = facade.emit_app(
session,
"job_started",
{"job_id": "demo-1", "note": "mapped app event"},
state_bearing=True,
)
print(f"app_event_seq={app_seq}")
emit_seq = facade.emit(
session,
EventKind.EXECUTION_COMPLETED,
{"proposal_id": str(created.id), "result": "ok"},
state_bearing=True,
agent_id="asciinema-agent",
command_id="demo-emit-execution",
)
print(f"execution_event_seq={emit_seq}")
closed = facade.close_session(
session,
payload={"result": "ok"},
command_id="demo-close-session",
)
print(f"final_status={closed.session.status}")
events = facade.replay(session)
print(f"event_count={len(events)}")
facade.close()
def main() -> None:
import argparse
parser = argparse.ArgumentParser(description="Run sync ACP demo for terminal/asciinema recording.")
parser.add_argument("--db", default=str(DEFAULT_DB), help="SQLite database path for the demo run")
args = parser.parse_args()
run_demo(Path(args.db))
if __name__ == "__main__":
main()