codexloop 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 (104) hide show
  1. codexloop/__init__.py +3 -0
  2. codexloop/application/__init__.py +1 -0
  3. codexloop/application/dto.py +41 -0
  4. codexloop/application/ports.py +158 -0
  5. codexloop/application/runner.py +467 -0
  6. codexloop/application/usecases/__init__.py +1 -0
  7. codexloop/application/usecases/doctor.py +37 -0
  8. codexloop/application/usecases/list_threads.py +14 -0
  9. codexloop/application/usecases/preflight.py +10 -0
  10. codexloop/application/usecases/resume_thread.py +11 -0
  11. codexloop/application/usecases/run_control.py +20 -0
  12. codexloop/application/usecases/run_plan.py +11 -0
  13. codexloop/bootstrap.py +461 -0
  14. codexloop/cli/__init__.py +1 -0
  15. codexloop/cli/app.py +94 -0
  16. codexloop/cli/asyncio.py +80 -0
  17. codexloop/cli/commands/__init__.py +1 -0
  18. codexloop/cli/commands/approval_cmd.py +24 -0
  19. codexloop/cli/commands/capacity.py +33 -0
  20. codexloop/cli/commands/cwd_cmd.py +22 -0
  21. codexloop/cli/commands/doctor.py +27 -0
  22. codexloop/cli/commands/effort_cmd.py +24 -0
  23. codexloop/cli/commands/logs.py +15 -0
  24. codexloop/cli/commands/model_cmd.py +22 -0
  25. codexloop/cli/commands/prompt.py +32 -0
  26. codexloop/cli/commands/reset.py +25 -0
  27. codexloop/cli/commands/resume.py +38 -0
  28. codexloop/cli/commands/run.py +50 -0
  29. codexloop/cli/commands/runs.py +13 -0
  30. codexloop/cli/commands/sandbox_cmd.py +24 -0
  31. codexloop/cli/commands/savepoints.py +25 -0
  32. codexloop/cli/commands/snapshot.py +26 -0
  33. codexloop/cli/commands/status.py +15 -0
  34. codexloop/cli/commands/stop.py +21 -0
  35. codexloop/cli/commands/threads.py +15 -0
  36. codexloop/cli/commands/unwind.py +24 -0
  37. codexloop/cli/commands/watch.py +66 -0
  38. codexloop/cli/render.py +39 -0
  39. codexloop/domain/__init__.py +26 -0
  40. codexloop/domain/approval.py +38 -0
  41. codexloop/domain/backoff.py +34 -0
  42. codexloop/domain/budget.py +56 -0
  43. codexloop/domain/capacity.py +81 -0
  44. codexloop/domain/classify.py +98 -0
  45. codexloop/domain/completion.py +130 -0
  46. codexloop/domain/control.py +167 -0
  47. codexloop/domain/error_codes.py +75 -0
  48. codexloop/domain/errors.py +35 -0
  49. codexloop/domain/loop.py +190 -0
  50. codexloop/domain/model_profile.py +30 -0
  51. codexloop/domain/plan.py +38 -0
  52. codexloop/domain/savepoint.py +32 -0
  53. codexloop/domain/savepoint_message.py +56 -0
  54. codexloop/domain/session.py +32 -0
  55. codexloop/domain/signals.py +25 -0
  56. codexloop/domain/waiting.py +120 -0
  57. codexloop/infrastructure/__init__.py +0 -0
  58. codexloop/infrastructure/agent/__init__.py +0 -0
  59. codexloop/infrastructure/agent/argv.py +102 -0
  60. codexloop/infrastructure/agent/events.py +274 -0
  61. codexloop/infrastructure/agent/gateway.py +189 -0
  62. codexloop/infrastructure/agent/probe.py +74 -0
  63. codexloop/infrastructure/agent/process.py +208 -0
  64. codexloop/infrastructure/agent/schema.py +31 -0
  65. codexloop/infrastructure/agent/scripted.py +201 -0
  66. codexloop/infrastructure/agent/translate.py +120 -0
  67. codexloop/infrastructure/api/__init__.py +26 -0
  68. codexloop/infrastructure/api/api_baseline.json +340 -0
  69. codexloop/infrastructure/api/binder.py +170 -0
  70. codexloop/infrastructure/api/gateway.py +142 -0
  71. codexloop/infrastructure/api/introspect.py +248 -0
  72. codexloop/infrastructure/api/json_io.py +26 -0
  73. codexloop/infrastructure/api/params.py +162 -0
  74. codexloop/infrastructure/api/providers.py +70 -0
  75. codexloop/infrastructure/api/registry.py +13 -0
  76. codexloop/infrastructure/appserver/__init__.py +6 -0
  77. codexloop/infrastructure/appserver/client.py +245 -0
  78. codexloop/infrastructure/appserver/gateway.py +437 -0
  79. codexloop/infrastructure/appserver/ratelimits.py +100 -0
  80. codexloop/infrastructure/audit.py +26 -0
  81. codexloop/infrastructure/capacity_probe.py +57 -0
  82. codexloop/infrastructure/clock.py +26 -0
  83. codexloop/infrastructure/config.py +150 -0
  84. codexloop/infrastructure/control.py +89 -0
  85. codexloop/infrastructure/doctor_env.py +239 -0
  86. codexloop/infrastructure/events.py +23 -0
  87. codexloop/infrastructure/git_savepoints.py +176 -0
  88. codexloop/infrastructure/lock.py +88 -0
  89. codexloop/infrastructure/logging.py +124 -0
  90. codexloop/infrastructure/notify.py +27 -0
  91. codexloop/infrastructure/progress.py +14 -0
  92. codexloop/infrastructure/redact.py +52 -0
  93. codexloop/infrastructure/rollout.py +113 -0
  94. codexloop/infrastructure/rundir.py +57 -0
  95. codexloop/infrastructure/snapshot.py +39 -0
  96. codexloop/infrastructure/state.py +32 -0
  97. codexloop/infrastructure/state_bus.py +27 -0
  98. codexloop/infrastructure/stream_ui.py +44 -0
  99. codexloop/py.typed +0 -0
  100. codexloop-0.1.0.dist-info/METADATA +104 -0
  101. codexloop-0.1.0.dist-info/RECORD +104 -0
  102. codexloop-0.1.0.dist-info/WHEEL +4 -0
  103. codexloop-0.1.0.dist-info/entry_points.txt +2 -0
  104. codexloop-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,39 @@
1
+ """Workspace snapshot helper — copy tree excluding ``.codexloop/``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ from pathlib import Path
7
+
8
+ _SKIP = {".codexloop", ".git"}
9
+
10
+
11
+ def create_snapshot(*, cwd: Path, dest: Path) -> Path:
12
+ """Copy ``cwd`` into ``dest``, skipping control-plane and ``.git`` dirs."""
13
+ dest.mkdir(parents=True, exist_ok=True)
14
+ for child in cwd.iterdir():
15
+ if child.name in _SKIP:
16
+ continue
17
+ target = dest / child.name
18
+ if child.is_dir():
19
+ shutil.copytree(child, target, dirs_exist_ok=True)
20
+ elif child.is_file(): # pragma: no branch
21
+ shutil.copy2(child, target)
22
+ return dest
23
+
24
+
25
+ def restore_snapshot(*, snapshot: Path, cwd: Path) -> None:
26
+ """Restore files from ``snapshot`` into ``cwd`` (does not delete extras)."""
27
+ if not snapshot.is_dir():
28
+ raise FileNotFoundError(f"snapshot not found: {snapshot}")
29
+ for child in snapshot.iterdir():
30
+ target = cwd / child.name
31
+ if child.is_dir():
32
+ if target.exists(): # pragma: no branch
33
+ shutil.rmtree(target)
34
+ shutil.copytree(child, target)
35
+ elif child.is_file(): # pragma: no branch
36
+ shutil.copy2(child, target)
37
+
38
+
39
+ __all__ = ["create_snapshot", "restore_snapshot"]
@@ -0,0 +1,32 @@
1
+ """RunStateStore — persist run state as ``state.json`` under a run directory."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from collections.abc import Mapping
7
+ from pathlib import Path
8
+
9
+ from codexloop.infrastructure.redact import redact
10
+
11
+
12
+ class FileRunStateStore:
13
+ def __init__(self, runs_root: Path) -> None:
14
+ self._runs_root = runs_root
15
+
16
+ def _path(self, run_id: str) -> Path:
17
+ return self._runs_root / run_id / "state.json"
18
+
19
+ def load(self, run_id: str) -> dict[str, object] | None:
20
+ path = self._path(run_id)
21
+ if not path.is_file():
22
+ return None
23
+ data = json.loads(path.read_text(encoding="utf-8"))
24
+ if not isinstance(data, dict):
25
+ return None
26
+ return data
27
+
28
+ def save(self, run_id: str, state: Mapping[str, object]) -> None:
29
+ path = self._path(run_id)
30
+ path.parent.mkdir(parents=True, exist_ok=True)
31
+ safe = redact(dict(state))
32
+ path.write_text(json.dumps(safe, default=str) + "\n", encoding="utf-8")
@@ -0,0 +1,27 @@
1
+ """Minimal run-state bus: read ``state.json`` for ``watch`` / status helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+
9
+ def read_state(path: Path) -> dict[str, object]:
10
+ """Return parsed state.json, or ``{}`` if missing/invalid. Never raises."""
11
+ try:
12
+ if not path.is_file():
13
+ return {}
14
+ data = json.loads(path.read_text(encoding="utf-8"))
15
+ if isinstance(data, dict):
16
+ return data
17
+ except (OSError, json.JSONDecodeError):
18
+ return {}
19
+ return {}
20
+
21
+
22
+ def watch_state(path: Path) -> dict[str, object]:
23
+ """Alias for :func:`read_state` — one-shot snapshot for ``watch``."""
24
+ return read_state(path)
25
+
26
+
27
+ __all__ = ["read_state", "watch_state"]
@@ -0,0 +1,44 @@
1
+ """Optional Textual live token view (``--stream-ui``).
2
+
3
+ !!! note "Roadmap"
4
+ Full token streaming against a live app-server session is still experimental.
5
+ This module ships a minimal Textual shell that tails a JSONL event file so
6
+ ``watch --replay`` and ``--stream-ui`` have a working path today.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from pathlib import Path
12
+
13
+ from textual.app import App, ComposeResult
14
+ from textual.widgets import Footer, Header, RichLog
15
+
16
+
17
+ class StreamUiApp(App[None]):
18
+ """Tail a JSONL event log in a Textual window."""
19
+
20
+ CSS = """
21
+ RichLog { height: 1fr; }
22
+ """
23
+
24
+ def __init__(self, path: Path) -> None:
25
+ super().__init__()
26
+ self._path = path
27
+
28
+ def compose(self) -> ComposeResult:
29
+ yield Header()
30
+ yield RichLog(id="log", highlight=True, markup=False)
31
+ yield Footer()
32
+
33
+ def on_mount(self) -> None:
34
+ log = self.query_one("#log", RichLog)
35
+ if not self._path.is_file():
36
+ log.write(f"(no events yet at {self._path})")
37
+ return
38
+ for line in self._path.read_text(encoding="utf-8").splitlines():
39
+ log.write(line)
40
+
41
+
42
+ def run_stream_ui(path: Path) -> None: # pragma: no cover — interactive TUI entry
43
+ """Blocking entry used by the CLI ``--stream-ui`` flag."""
44
+ StreamUiApp(path).run()
codexloop/py.typed ADDED
File without changes
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.5
2
+ Name: codexloop
3
+ Version: 0.1.0
4
+ Summary: Onion-architected, autonomous OpenAI Codex session runner — never blocks on a human, distinguishes rate limits from exhausted credits, and resumes safely across usage windows.
5
+ Project-URL: Homepage, https://github.com/adammatthewsteinberger/codexloop
6
+ Project-URL: Repository, https://github.com/adammatthewsteinberger/codexloop
7
+ Project-URL: Documentation, https://adammatthewsteinberger.github.io/codexloop/
8
+ Project-URL: Issues, https://github.com/adammatthewsteinberger/codexloop/issues
9
+ Project-URL: Changelog, https://github.com/adammatthewsteinberger/codexloop/blob/main/CHANGELOG.md
10
+ Author-email: Adam Matthew Steinberger <adam@matthewsteinberger.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: agent,automation,cli,codex,gpt,llm,openai
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: MacOS
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Software Development :: Build Tools
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Topic :: Utilities
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.12
29
+ Requires-Dist: anyio>=4.0
30
+ Requires-Dist: openai>=1.40
31
+ Requires-Dist: structlog>=24.1
32
+ Requires-Dist: textual>=1.0
33
+ Requires-Dist: typer>=0.12
34
+ Provides-Extra: dev
35
+ Requires-Dist: bandit>=1.7; extra == 'dev'
36
+ Requires-Dist: build>=1.2; extra == 'dev'
37
+ Requires-Dist: hypothesis>=6.100; extra == 'dev'
38
+ Requires-Dist: import-linter>=2.0; extra == 'dev'
39
+ Requires-Dist: mypy>=1.10; extra == 'dev'
40
+ Requires-Dist: packaging>=24.0; extra == 'dev'
41
+ Requires-Dist: pip-audit>=2.7; extra == 'dev'
42
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
43
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
44
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
45
+ Requires-Dist: pytest>=8.0; extra == 'dev'
46
+ Requires-Dist: ruff>=0.6; extra == 'dev'
47
+ Requires-Dist: twine>=5.0; extra == 'dev'
48
+ Provides-Extra: docs
49
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
50
+ Description-Content-Type: text/markdown
51
+
52
+ # codexloop
53
+
54
+ Autonomous OpenAI Codex / GPT session runner. Same job as
55
+ [claudeloop](https://github.com/adammatthewsteinberger/claudeloop): never block on
56
+ a human, and never treat `insufficient_quota` / billing as a waitable
57
+ `rate_limit_exceeded` window.
58
+
59
+ **Status:** M1–M5 implemented on `feat/m1-pure-core` (onion core, exec gateway,
60
+ capacity probes, control plane, generated REST CLI, optional app-server transport
61
+ with exec fallback). MIT-licensed; author Adam Matthew Steinberger.
62
+
63
+ ## Install
64
+
65
+ ```bash
66
+ pip install -e ".[dev]"
67
+ codexloop --version
68
+ codexloop doctor
69
+ ```
70
+
71
+ ## Quick start
72
+
73
+ ```bash
74
+ codexloop run path/to/plan.md
75
+ codexloop watch --follow
76
+ codexloop stop
77
+ ```
78
+
79
+ ## Plans
80
+
81
+ | Document | Purpose |
82
+ |---|---|
83
+ | [docs/plans/architecture-and-roadmap.md](docs/plans/architecture-and-roadmap.md) | Full design / transplant plan from claudeloop 0.5.4 |
84
+ | [docs/plans/research-notes.md](docs/plans/research-notes.md) | Vendor SDK/CLI capacity + autonomy research |
85
+ | [docs/plans/_shared-transplant-outline.md](docs/plans/_shared-transplant-outline.md) | Cross-product keep/swap + Global Constraints |
86
+ | [docs/superpowers/plans/2026-08-13-codexloop-implementation.md](docs/superpowers/plans/2026-08-13-codexloop-implementation.md) | Bite-sized TDD implementation plan |
87
+
88
+ ## Naming
89
+
90
+ | Item | Value |
91
+ |---|---|
92
+ | PyPI / CLI | `codexloop` |
93
+ | Env prefix | `CODEXLOOP_*` |
94
+ | State dir | `.codexloop/` |
95
+ | Done marker | `CODEXLOOP_TASK_FULLY_COMPLETE` |
96
+
97
+ ## License
98
+
99
+ MIT — see [LICENSE](LICENSE).
100
+
101
+ ## Publishing
102
+
103
+ Releases go **TestPyPI → PyPI** via Trusted Publishing. See
104
+ [docs/publishing.md](docs/publishing.md).
@@ -0,0 +1,104 @@
1
+ codexloop/__init__.py,sha256=4pn6jbs-GOvSd4sYgcwzxYxP3zqNeSkuaevCFQaspJA,102
2
+ codexloop/bootstrap.py,sha256=bmNOlNS0Kd3an2O9Mgbua3Z5bFvc_8YKDN31UEAAmgE,15663
3
+ codexloop/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ codexloop/application/__init__.py,sha256=sA-g5WAYA6X6OjwNO78rPwgBkuevBxvDFTux5iW6kus,70
5
+ codexloop/application/dto.py,sha256=XCh-gBW0fj1iFxtIQZV-NKcNJyZNZ3lWCFOiYdrIRXo,1012
6
+ codexloop/application/ports.py,sha256=8cxdHtiQBKOuuNt_uuOuUe08Gg6nCisLq1luqSbuluY,4440
7
+ codexloop/application/runner.py,sha256=EJT90WlyOFJ6PWi3Tz5CC-PRiTHyXBoW6ssYxu623D0,17539
8
+ codexloop/application/usecases/__init__.py,sha256=h6nxf5zDeva7GLQERfXTFQhX1w8jEVRnC9KRWRa-i8A,77
9
+ codexloop/application/usecases/doctor.py,sha256=Gw-MV7EUpmBp-cQu28tdHfBalgR-7WIu5NoOfWxqegE,912
10
+ codexloop/application/usecases/list_threads.py,sha256=FUOSRq0V6OzxToFLIwZglfjYNkF-Fxxp0LbwfjqHcoc,395
11
+ codexloop/application/usecases/preflight.py,sha256=YXc-a0T62b7vBgxFSRnl4Zuv9ZBnmz_f5ChJYK7NbaU,296
12
+ codexloop/application/usecases/resume_thread.py,sha256=HFM6WFx5DdHrDXALQXb__8rK_Q2X1gvctU5OcnQjq58,424
13
+ codexloop/application/usecases/run_control.py,sha256=Pn4_22bPOriuFq-hH-vvhTU-kTp8tFTZse59Hbd_QaM,516
14
+ codexloop/application/usecases/run_plan.py,sha256=Ok0G9429gPP1oeCF27xjkbbx98paUmrmpi7ky0Dde24,422
15
+ codexloop/cli/__init__.py,sha256=xVwIR3leKTmk01M_WkyTgevbhQjGMovFd1Il7nPm2-I,61
16
+ codexloop/cli/app.py,sha256=WTiIR1fzodFXtFKNwjQo4B51gbHfwskSDOy0iAeimIk,2705
17
+ codexloop/cli/asyncio.py,sha256=vSjlel9dETZ85gBSuqsxf7tFZ-gLRsBFzsR3qk2LGRc,2222
18
+ codexloop/cli/render.py,sha256=XUxb56EQj2uM40BiwcGAdbFtTLYyS9UUf8076g9kqVA,1124
19
+ codexloop/cli/commands/__init__.py,sha256=E-c9v4cvPBJDhbLqd5B8fRpqM6ctCrLmy2FNIlISS7s,71
20
+ codexloop/cli/commands/approval_cmd.py,sha256=t7d5k_Bzw75_EtWLUb_kqJXwAiUodSBlAC8RWomyIAo,852
21
+ codexloop/cli/commands/capacity.py,sha256=ukFEJxNsCAbCwDIHVQvNqd5Kwq0r4ESzF5Na6F-nZkA,1147
22
+ codexloop/cli/commands/cwd_cmd.py,sha256=7coPWV-GQ64JIsGXSdf96K52Ws0nyV4IX_sL1UOoBOE,715
23
+ codexloop/cli/commands/doctor.py,sha256=zA8UVwwDVpxAIO5Tgn1rhHO0WdBZIiqjVUPxJWP3AP0,860
24
+ codexloop/cli/commands/effort_cmd.py,sha256=k9P43OOw4wneAzFmaQ9AQ8bm2TUw5apDZLqdV_LGb7s,819
25
+ codexloop/cli/commands/logs.py,sha256=nA8QwGT5K3gFFgpJNzx7TD-2eUEbYQELzmxBR3fYFBQ,386
26
+ codexloop/cli/commands/model_cmd.py,sha256=FBbLzGv1i9LA9hOEYxfuwdcWM18u2-kaP2nvTTjzZGQ,713
27
+ codexloop/cli/commands/prompt.py,sha256=h2QCjiD6u27lQ8rAPNhvuL1kr5qzXwKrJVllW3XfvEo,1195
28
+ codexloop/cli/commands/reset.py,sha256=uyN04Ql3ow7eQ4_abGHLBcrFZNw3Bji6wMFQ88NKtpM,928
29
+ codexloop/cli/commands/resume.py,sha256=8sOowNgyj5iLhBdGNrcSNKKkz1bjT86pFClOtMGNm3g,1371
30
+ codexloop/cli/commands/run.py,sha256=YvcKtXs_sSHx4TtlvR1CrJDe2cmzw6clWwm_rGceUiQ,1606
31
+ codexloop/cli/commands/runs.py,sha256=5-oG867i9W_KtQVhySwR3PClN-pZ-Bv0neWbVQaBFUo,296
32
+ codexloop/cli/commands/sandbox_cmd.py,sha256=CxkFVeCBWuzF0-eWpBU8BUHQq5VFKAF2Nu4ggT_5tiM,837
33
+ codexloop/cli/commands/savepoints.py,sha256=87DvgvxV_63bSrPb7Y8YK33k6CPLqP3FVO6nP55-IEc,793
34
+ codexloop/cli/commands/snapshot.py,sha256=xUxmoZH-NI1loobBLKJVdpTzGC6yMd6nlxfpzRj7YWY,1013
35
+ codexloop/cli/commands/status.py,sha256=K0NdYGAisqD6T9txuC_ClG4V75l406F3KfqEQjLxauo,396
36
+ codexloop/cli/commands/stop.py,sha256=3fzZF00no5aeMQ7XkJ2WRO11GpZZ7bxR0363hew7tIQ,651
37
+ codexloop/cli/commands/threads.py,sha256=xhkuUuBPpF8-FASKWe7knVHKaIB_KXTQVProWJnSQIY,483
38
+ codexloop/cli/commands/unwind.py,sha256=qIP_mwiwNbndgYjWxFjf3UJ7zguSUSxG9PDlGrOUSiY,925
39
+ codexloop/cli/commands/watch.py,sha256=YudvAnOnXXGB9tVX1wPf6Fo232cRdp7SPs4qnKSUX_I,1802
40
+ codexloop/domain/__init__.py,sha256=iUbe6xHDjX2VHmQ4MvA0so7ia5z_x4Cn2X4f52KAxgc,559
41
+ codexloop/domain/approval.py,sha256=_Ytz0NmlsLtZFzUOJv5S0oJwyDgEPTybS43qlJr9UdA,1024
42
+ codexloop/domain/backoff.py,sha256=Rpgig-85nHUUwzu0Dm90VvP-_M7ovJDwXVasFzTX9-I,1048
43
+ codexloop/domain/budget.py,sha256=UFe5bQM2ewsJCMONcX0GhJAALe_QOwYnQ0LXbpHlojw,1623
44
+ codexloop/domain/capacity.py,sha256=SgqpqTV-RxJohHzmvGxQB0wCy758xZ6BZ3MvYAV1gcQ,1938
45
+ codexloop/domain/classify.py,sha256=sTPS8AaWuP7jqi-zcegKpDCGclpZPcHp0sdwvx8YPU8,3517
46
+ codexloop/domain/completion.py,sha256=e3HuGLrhYdqdRp18oykWAOvikSTNxDyg5bqkQdxBeZw,3546
47
+ codexloop/domain/control.py,sha256=7sLWsCQ6hHsb1Sx_pGj2X2ayZv3usNyO0UfogegkyLk,4455
48
+ codexloop/domain/error_codes.py,sha256=JpzJzYf_P4sw3qIauz09bRmWHjItdxNr55qMlFxEu6I,1936
49
+ codexloop/domain/errors.py,sha256=fJ8c_MxVjHuftq3JTbcfrr2CWgn0fxVSHZHM-TtYC0A,867
50
+ codexloop/domain/loop.py,sha256=bZaDzUsDteG8aOBclNWufZKTRNtFeRjGIxLVteu0AWQ,5862
51
+ codexloop/domain/model_profile.py,sha256=DhEZ89eO19EfkymHjdkgLyDpety8QnWQHxUYoFQpfVg,715
52
+ codexloop/domain/plan.py,sha256=sf-nl5PMpvZK0ra9SatQALtxLER5T_UExulYgvPaOkQ,1101
53
+ codexloop/domain/savepoint.py,sha256=sOA1dg8JFMqwwZsLGZG7nrZxKFTmtknlPz0BJU2Xd-E,818
54
+ codexloop/domain/savepoint_message.py,sha256=lVKDE0l2D77TLKoxiHJeTvUCVAgEluqMTrplB0e7gMs,1711
55
+ codexloop/domain/session.py,sha256=8ns2wP3m79hqnLDNrQOPkgzAYsCjjwJbpICYqdW-P9A,542
56
+ codexloop/domain/signals.py,sha256=oEDyWQxpQ9pM9OX4S7hppE9b8T7Scee8Oeemy7E-TGY,745
57
+ codexloop/domain/waiting.py,sha256=hEJoYYMKZe7IuFZuV3oFXlUGX23jDQw4-JtweqloRPc,4353
58
+ codexloop/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ codexloop/infrastructure/audit.py,sha256=TAYAQO911V8_2k_KazqYZGXiWOQf1MA98-mPi_ejKiY,821
60
+ codexloop/infrastructure/capacity_probe.py,sha256=j2-trejKb91Uy1LYSEf_zMhO8miJNRdbXTXCBiIVqFw,1754
61
+ codexloop/infrastructure/clock.py,sha256=sTpnsw1yJrfOrIl64iSisQFGOv9nMCIZhCAspQpMnzQ,723
62
+ codexloop/infrastructure/config.py,sha256=j2iPx0B3bntU49oc114aDm_V7orMlqB1nsKSKJIIvuI,4777
63
+ codexloop/infrastructure/control.py,sha256=7z2pLfvR2ADE6Zjv1ajm4YMVIee2PJIdBONCoWcaevs,3118
64
+ codexloop/infrastructure/doctor_env.py,sha256=096s30p9He9xo_BRM4ol5_Asjed7nopu8hyhdf4gS4M,8142
65
+ codexloop/infrastructure/events.py,sha256=Ap7JAgYcJmzMrlzjNwyOY0tuQAvee_X4otEggVTyPYE,697
66
+ codexloop/infrastructure/git_savepoints.py,sha256=G7hXjfQLeeyqIJGzauzxvb2w06H9wt9SYdPz1tS-uz0,6481
67
+ codexloop/infrastructure/lock.py,sha256=CqGGDy-MUqe1VfTdbudE2_t8cbTH8-mFSmg2j0K2XJI,2554
68
+ codexloop/infrastructure/logging.py,sha256=hkTYprWGX5CQutAbNV-KoQtNjQCobfU9U9N1UQYjIP0,3852
69
+ codexloop/infrastructure/notify.py,sha256=M-ESKklX8z2yI4jOB4aSESfXT83Qe8mWFmpF7VP2pSI,1009
70
+ codexloop/infrastructure/progress.py,sha256=ASYX88gol3c4FVrxM9cdITQncsLtNsN0uJl4GCe8Zg8,511
71
+ codexloop/infrastructure/redact.py,sha256=N_NJ_rfVLJK_UKIHNlws4ahpPKHCH-Ed7YSvMxkQtto,1444
72
+ codexloop/infrastructure/rollout.py,sha256=4bJcaSKCHMY_brVNvrTWpafGhOIrHgx7C6Q_2gBs3V0,3651
73
+ codexloop/infrastructure/rundir.py,sha256=ECNXaFRQaqAdNdClImCP7dddhJOcOZ2EnhH02uolkGw,1971
74
+ codexloop/infrastructure/snapshot.py,sha256=S36JXFZTV93KnR3CB23dcVcOK4hnruG8J321noWFIsw,1294
75
+ codexloop/infrastructure/state.py,sha256=FsXioTxFxlwKCI7bFNAHRuwu2ptto8mTtrIvCQnmjHA,1024
76
+ codexloop/infrastructure/state_bus.py,sha256=EAdOWTE7jSVOnAEPt6h3B3FKOF3f0hO_YBSrLthI1Q8,741
77
+ codexloop/infrastructure/stream_ui.py,sha256=BPRPEeBv5EelNFq6N-52s-TZWl7XYjPHK8Fh9Vz_3rc,1325
78
+ codexloop/infrastructure/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
+ codexloop/infrastructure/agent/argv.py,sha256=kyMUUp7LanjU5IqE6NQLBI0a_p6iCT1NlfIiNqKRwvE,3228
80
+ codexloop/infrastructure/agent/events.py,sha256=UyzhjTa-fjk7HOkcYmxt8c_IhPxBbt3PZQEgAoMcjDM,7942
81
+ codexloop/infrastructure/agent/gateway.py,sha256=V9kIK7_YLNvnBR137QuyVmqPrbhpHmnVEjw6gj1DKDA,7121
82
+ codexloop/infrastructure/agent/probe.py,sha256=kl6ez8ARpUSZJlP_GCEFnyTAne7GDdRCakh6PwZv3Nc,2902
83
+ codexloop/infrastructure/agent/process.py,sha256=ulVSR2hCybZMEKlm-utC4okEFwr3Vbfn1SuGF2m67i0,6471
84
+ codexloop/infrastructure/agent/schema.py,sha256=NrfVCbKisoEjz4Rr98SYapqprjIxRGhENbfNUa_YQ20,982
85
+ codexloop/infrastructure/agent/scripted.py,sha256=LlYxE7d5a26rpb9sZ2M8Q2lPuCS5CO61fdTywAums_U,7242
86
+ codexloop/infrastructure/agent/translate.py,sha256=GB5RmH5ZB3LifAFglIrmgBHyNOP3R5Ml5mtvCZLjXhE,3828
87
+ codexloop/infrastructure/api/__init__.py,sha256=BLX440wm2CaPwhWDs0zvGQQYYGVF401F4VDxGv5I8c8,633
88
+ codexloop/infrastructure/api/api_baseline.json,sha256=RF4ly4BIwQoOlH-yBJJrFcb9ydIIwgxZ6sxEzWVymec,12569
89
+ codexloop/infrastructure/api/binder.py,sha256=3OkwBgsFZULMAoUx7EjWsrUauCB0wXl0UmlnMsEMeV8,6044
90
+ codexloop/infrastructure/api/gateway.py,sha256=LVbdg_EpI2kykbPSj4T-QECz61P-Efh-g-UuvaEOcIk,4563
91
+ codexloop/infrastructure/api/introspect.py,sha256=6t1B21hH8JQaxybYkrlO8V5Rntur2CmJltxpVsCxk2w,8619
92
+ codexloop/infrastructure/api/json_io.py,sha256=e3wWHJap6KPgD7IQAQgDnc1b7ow-Bx3VHh0nX8CR2CI,875
93
+ codexloop/infrastructure/api/params.py,sha256=wN76IexGnuc5uOvMITtIfS9DAuPjH-jWDu_2CUmJffY,4815
94
+ codexloop/infrastructure/api/providers.py,sha256=m22F2J00ldhsAQb-ichQxuEWjWxCDT2nyXv3B0FvaiA,2880
95
+ codexloop/infrastructure/api/registry.py,sha256=Mq8hIL1Y4E-LTttxGqz8CMMFBvO71C5mO12wwxoFjho,310
96
+ codexloop/infrastructure/appserver/__init__.py,sha256=vlql_zsE4M95mHwepHOyzY5VLRkY8DyTql87OJO1TFQ,312
97
+ codexloop/infrastructure/appserver/client.py,sha256=N8_HcmZj5NSaUOX-g56XM0yLqM4-t1Tz3ZYecc0nw-o,8814
98
+ codexloop/infrastructure/appserver/gateway.py,sha256=rTz40nXycJCsePCym0xvZ1lyizsxqJcmm-pqaZaJi9k,17272
99
+ codexloop/infrastructure/appserver/ratelimits.py,sha256=btP4CCCdK4bK7uHY1_yIkM6tbbkf6LpPqqr7P4gdjEU,3367
100
+ codexloop-0.1.0.dist-info/METADATA,sha256=lYJKWEXPSfonrT9BqQN0myk8oOcxzv9iKyfhSgFuXWA,3976
101
+ codexloop-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
102
+ codexloop-0.1.0.dist-info/entry_points.txt,sha256=5iJcKqQo3HWVfkLLMLFxGLrH58gJBmMZ760Caid0uuc,53
103
+ codexloop-0.1.0.dist-info/licenses/LICENSE,sha256=9ZRUKk2Y2P5Gwro4cQoxhI5sur1Gy7vd5hbgRXcz2Sg,1081
104
+ codexloop-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ codexloop = codexloop.cli.app:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adam Matthew Steinberger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.