agyloop 0.1.0__py3-none-any.whl

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 (97) hide show
  1. agyloop/__init__.py +3 -0
  2. agyloop/application/__init__.py +1 -0
  3. agyloop/application/dto.py +42 -0
  4. agyloop/application/ports.py +167 -0
  5. agyloop/application/runner.py +1575 -0
  6. agyloop/application/usecases/__init__.py +1 -0
  7. agyloop/application/usecases/doctor.py +121 -0
  8. agyloop/application/usecases/list_sessions.py +10 -0
  9. agyloop/application/usecases/resume_session.py +30 -0
  10. agyloop/application/usecases/run_control.py +122 -0
  11. agyloop/application/usecases/run_plan.py +45 -0
  12. agyloop/bootstrap.py +630 -0
  13. agyloop/cli/__init__.py +1 -0
  14. agyloop/cli/app.py +98 -0
  15. agyloop/cli/asyncio.py +23 -0
  16. agyloop/cli/commands/__init__.py +1 -0
  17. agyloop/cli/commands/attach_cmd.py +51 -0
  18. agyloop/cli/commands/config_cmd.py +18 -0
  19. agyloop/cli/commands/doctor.py +75 -0
  20. agyloop/cli/commands/logs.py +28 -0
  21. agyloop/cli/commands/model_cmd.py +23 -0
  22. agyloop/cli/commands/preset_cmd.py +23 -0
  23. agyloop/cli/commands/prompt.py +45 -0
  24. agyloop/cli/commands/reset.py +30 -0
  25. agyloop/cli/commands/resume.py +135 -0
  26. agyloop/cli/commands/run.py +189 -0
  27. agyloop/cli/commands/runs.py +26 -0
  28. agyloop/cli/commands/savepoints.py +33 -0
  29. agyloop/cli/commands/sessions.py +33 -0
  30. agyloop/cli/commands/snapshot_cmd.py +40 -0
  31. agyloop/cli/commands/status.py +23 -0
  32. agyloop/cli/commands/stop.py +34 -0
  33. agyloop/cli/commands/unwind.py +32 -0
  34. agyloop/cli/commands/watch.py +48 -0
  35. agyloop/cli/render.py +43 -0
  36. agyloop/domain/__init__.py +1 -0
  37. agyloop/domain/budget.py +77 -0
  38. agyloop/domain/capacity.py +74 -0
  39. agyloop/domain/chatter.py +54 -0
  40. agyloop/domain/classify.py +283 -0
  41. agyloop/domain/completion.py +122 -0
  42. agyloop/domain/control.py +210 -0
  43. agyloop/domain/errors.py +43 -0
  44. agyloop/domain/loop.py +229 -0
  45. agyloop/domain/model_policy.py +69 -0
  46. agyloop/domain/model_profile.py +172 -0
  47. agyloop/domain/permission.py +42 -0
  48. agyloop/domain/plan.py +73 -0
  49. agyloop/domain/pricing.py +67 -0
  50. agyloop/domain/quota.py +21 -0
  51. agyloop/domain/savepoint.py +33 -0
  52. agyloop/domain/savepoint_message.py +57 -0
  53. agyloop/domain/session.py +64 -0
  54. agyloop/domain/slash.py +55 -0
  55. agyloop/domain/snapshot.py +62 -0
  56. agyloop/domain/stop_summary.py +54 -0
  57. agyloop/domain/waiting.py +246 -0
  58. agyloop/infrastructure/__init__.py +1 -0
  59. agyloop/infrastructure/agent/__init__.py +1 -0
  60. agyloop/infrastructure/agent/autonomy.py +156 -0
  61. agyloop/infrastructure/agent/catalog.py +49 -0
  62. agyloop/infrastructure/agent/cli_argv.py +141 -0
  63. agyloop/infrastructure/agent/gateway.py +233 -0
  64. agyloop/infrastructure/agent/gateway_cli.py +125 -0
  65. agyloop/infrastructure/agent/gemini_rewrite.py +197 -0
  66. agyloop/infrastructure/agent/harness_logs.py +58 -0
  67. agyloop/infrastructure/agent/harness_retarget.py +376 -0
  68. agyloop/infrastructure/agent/options.py +114 -0
  69. agyloop/infrastructure/agent/policies.py +45 -0
  70. agyloop/infrastructure/agent/probe.py +111 -0
  71. agyloop/infrastructure/agent/translate.py +143 -0
  72. agyloop/infrastructure/api/__init__.py +1 -0
  73. agyloop/infrastructure/api/binder.py +145 -0
  74. agyloop/infrastructure/api/discover.py +71 -0
  75. agyloop/infrastructure/api/gateway.py +172 -0
  76. agyloop/infrastructure/api/registry.py +20 -0
  77. agyloop/infrastructure/api/surface_baseline.json +599 -0
  78. agyloop/infrastructure/api/vertex_baseline.json +243 -0
  79. agyloop/infrastructure/config.py +123 -0
  80. agyloop/infrastructure/control.py +138 -0
  81. agyloop/infrastructure/doctor_env.py +151 -0
  82. agyloop/infrastructure/events.py +71 -0
  83. agyloop/infrastructure/git_savepoints.py +209 -0
  84. agyloop/infrastructure/logging.py +142 -0
  85. agyloop/infrastructure/notify.py +24 -0
  86. agyloop/infrastructure/redact.py +37 -0
  87. agyloop/infrastructure/resources.py +152 -0
  88. agyloop/infrastructure/rundir.py +197 -0
  89. agyloop/infrastructure/snapshot.py +180 -0
  90. agyloop/infrastructure/state_bus.py +49 -0
  91. agyloop/infrastructure/stream_ui.py +208 -0
  92. agyloop/py.typed +1 -0
  93. agyloop-0.1.0.dist-info/METADATA +164 -0
  94. agyloop-0.1.0.dist-info/RECORD +97 -0
  95. agyloop-0.1.0.dist-info/WHEEL +4 -0
  96. agyloop-0.1.0.dist-info/entry_points.txt +2 -0
  97. agyloop-0.1.0.dist-info/licenses/LICENSE +21 -0
agyloop/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Autonomous Google Antigravity and Gemini session runner."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """Application layer for agyloop use cases."""
@@ -0,0 +1,42 @@
1
+ """Data transfer objects passed between application/ and infrastructure/ adapters.
2
+ Not domain value objects — these carry the raw shape of one SDK interaction
3
+ before domain.classify.classify() and domain.completion.evaluate() reduce them
4
+ to CapacityState / CompletionVerdict."""
5
+
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass
9
+ from datetime import datetime
10
+
11
+ from agyloop.domain.classify import TurnSignals
12
+ from agyloop.domain.completion import StructuredVerdict
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class TurnOutcome:
17
+ """What one real or probe turn produced, translated from raw SDK messages
18
+ by infrastructure/agent/translate.py."""
19
+
20
+ signals: TurnSignals
21
+ verdict: StructuredVerdict | None
22
+ output_text: str
23
+ session_id: str | None
24
+ cost_usd: float = 0.0
25
+ prompt_tokens: int = 0
26
+ completion_tokens: int = 0
27
+ raw_events: tuple[dict[str, object], ...] = ()
28
+
29
+
30
+ @dataclass(frozen=True, slots=True)
31
+ class ProbeResult:
32
+ signals: TurnSignals
33
+ at: datetime
34
+
35
+
36
+ @dataclass(frozen=True, slots=True)
37
+ class RunResult:
38
+ success: bool
39
+ reason: str
40
+ session_id: str | None
41
+ turns_spent: int
42
+ dollars_spent: float
@@ -0,0 +1,167 @@
1
+ """Application ports — Protocols implemented by infrastructure/, never imported
2
+ from it. See docs/plans/architecture-and-roadmap.md §11: application/ knows the
3
+ SHAPE of a collaborator, never its concrete type."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from datetime import datetime
8
+ from typing import Any, Protocol
9
+
10
+ from agyloop.application.dto import TurnOutcome
11
+ from agyloop.domain.control import ControlCommand
12
+ from agyloop.domain.model_profile import ModelEffortProfile
13
+ from agyloop.domain.savepoint import SavePointRef, UnwindResult
14
+ from agyloop.domain.session import SessionRef
15
+ from agyloop.domain.snapshot import SnapshotReason, SnapshotRef
16
+
17
+
18
+ class Clock(Protocol):
19
+ def now(self) -> datetime: ...
20
+
21
+
22
+ class Sleeper(Protocol):
23
+ async def sleep_until(self, instant: datetime) -> None: ...
24
+
25
+
26
+ class AgentGateway(Protocol):
27
+ """Wraps a live google.antigravity Agent session. The port must not leak
28
+ google.antigravity types: ``set_permission_mode`` takes an agyloop enum
29
+ (autonomous | scoped | safe | yolo) that a later adapter compiles into a
30
+ policy list. Deliberately not a one-shot query — the session survives a
31
+ capacity rejection so the run can probe and resume.
32
+ """
33
+
34
+ async def send_turn(self, prompt_text: str) -> TurnOutcome: ...
35
+ async def close(self) -> None: ...
36
+ async def set_profile(self, profile: ModelEffortProfile) -> None: ...
37
+ async def set_permission_mode(self, mode: str) -> None: ...
38
+ async def set_cwd(self, cwd: str) -> None: ...
39
+ async def set_session_resources(self, **kwargs: Any) -> None: ...
40
+ def resolve_tool_approval(self, request_id: str, *, allow: bool, reason: str = "") -> bool: ...
41
+
42
+
43
+ class RunResources(Protocol):
44
+ """Run-scoped attachments / skills / folders / memories applied mid-run."""
45
+
46
+ def apply_mutate(
47
+ self, *, action: str, kind: str, value: str, name: str | None = None
48
+ ) -> dict[str, Any]: ...
49
+ def gateway_payload(self) -> dict[str, Any]: ...
50
+ def set_permission_mode(self, mode: str) -> None: ...
51
+ def set_cwd(self, path: str) -> None: ...
52
+
53
+
54
+ class CapacityProbe(Protocol):
55
+ async def probe(self) -> TurnOutcome: ...
56
+
57
+
58
+ class SessionCatalog(Protocol):
59
+ """Enumerates agyloop's run registry, not vendor conversations."""
60
+
61
+ def most_recent(self, cwd: str) -> SessionRef | None: ...
62
+ def list_all(self, cwd: str | None = None) -> list[SessionRef]: ...
63
+
64
+
65
+ class ProgressReporter(Protocol):
66
+ def turn_sent(self, *, attempt: int) -> None: ...
67
+ def waiting(self, *, reason: str, until: datetime) -> None: ...
68
+ def finished(self, *, success: bool, reason: str) -> None: ...
69
+
70
+
71
+ class AuditLog(Protocol):
72
+ def record(self, event_type: str, payload: dict[str, Any]) -> None: ...
73
+
74
+
75
+ class Notifier(Protocol):
76
+ def notify(self, message: str) -> None: ...
77
+
78
+
79
+ class Logger(Protocol):
80
+ """Structured application logging — implemented by infrastructure/logging."""
81
+
82
+ def bind(self, **kwargs: Any) -> Logger: ...
83
+ def debug(self, event: str, **kwargs: Any) -> None: ...
84
+ def info(self, event: str, **kwargs: Any) -> None: ...
85
+ def warning(self, event: str, **kwargs: Any) -> None: ...
86
+ def error(self, event: str, **kwargs: Any) -> None: ...
87
+
88
+
89
+ class RunStateStore(Protocol):
90
+ def save(self, run_id: str, state: dict[str, Any]) -> None: ...
91
+ def load(self, run_id: str) -> dict[str, Any] | None: ...
92
+
93
+
94
+ class SessionLock(Protocol):
95
+ def acquire(self, session_id: str) -> bool: ...
96
+ def release(self, session_id: str) -> None: ...
97
+
98
+
99
+ class ApiGateway(Protocol):
100
+ """Generated Gemini REST surface (ADR 0015). ``agyloop api`` is bound from
101
+ the committed Developer discovery baseline and guarded by a drift gate."""
102
+
103
+ def invoke(self, method_path: str, **kwargs: Any) -> Any: ...
104
+
105
+
106
+ class RunControl(Protocol):
107
+ def poll(self) -> list[ControlCommand]: ...
108
+
109
+
110
+ class RunEventSink(Protocol):
111
+ def emit(self, event_type: str, payload: dict[str, Any] | None = None) -> None: ...
112
+ def bind(
113
+ self,
114
+ *,
115
+ session_id: str | None = None,
116
+ attempt: int | None = None,
117
+ phase: str | None = None,
118
+ trace_id: str | None = None,
119
+ turn_id: str | None = None,
120
+ ) -> None: ...
121
+
122
+
123
+ class StreamUi(Protocol):
124
+ """Optional full-screen stream UI — fed deltas; Textual lives in infrastructure."""
125
+
126
+ def on_delta(self, text: str, *, turn_id: str, seq: int) -> None: ...
127
+ def on_turn_boundary(self, *, turn_id: str, attempt: int) -> None: ...
128
+ def on_prompt(self, text: str) -> None: ...
129
+ def on_assistant(self, text: str) -> None: ...
130
+ def on_tool(self, name: str, summary: str) -> None: ...
131
+ def on_status(self, state: dict[str, Any]) -> None: ...
132
+ def close(self) -> None: ...
133
+
134
+
135
+ class SavePointStore(Protocol):
136
+ def create(
137
+ self,
138
+ *,
139
+ run_id: str,
140
+ label: str,
141
+ message: str = "",
142
+ attempt: int | None = None,
143
+ verdict_name: str = "Continue",
144
+ summary: str = "",
145
+ remaining_work: tuple[str, ...] = (),
146
+ ) -> SavePointRef | None: ...
147
+ def list_points(self, run_id: str) -> list[SavePointRef]: ...
148
+ def unwind(self, *, run_id: str, to: str, backup: bool) -> UnwindResult: ...
149
+ def changes_since(self, since_sha: str | None) -> str: ...
150
+
151
+
152
+ class StateBus(Protocol):
153
+ """Publish run state changes for external pollers / subscribers."""
154
+
155
+ def publish(self, event_type: str, state: dict[str, Any]) -> None: ...
156
+
157
+
158
+ class RunSnapshotSink(Protocol):
159
+ """Write handoff snapshots and publish path+digest on the state bus."""
160
+
161
+ def emit(
162
+ self,
163
+ reason: SnapshotReason,
164
+ *,
165
+ context: dict[str, Any] | None = None,
166
+ bundle: bool | None = None,
167
+ ) -> SnapshotRef | None: ...