opencac 0.2.0__tar.gz

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.
opencac-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lpoee976
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.
opencac-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: opencac
3
+ Version: 0.2.0
4
+ Summary: OpenCAC: Claude Code, Antigravity, and Codex working together across cloud APIs and local models.
5
+ Author: Codex
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/lpoee/opencac
8
+ Project-URL: Repository, https://github.com/lpoee/opencac
9
+ Project-URL: Issues, https://github.com/lpoee/opencac/issues
10
+ Keywords: opencac,claude-code,codex,antigravity,multi-agent-orchestration,ai-coding-agent-pipeline,claude-code-codex-together,ai-coding-workflow-automation,orchestrate-ai-coding-tools,developer-cli-tools,ai-agent-chaining,reduce-ai-api-cost,local-llm-code-quality,air-gapped-ai-coding,private-ai-code-generation,local-llm,hybrid-ai,jsonl,audit-log,speculative-decoding,llama-cpp,validated-handoff,session-resume
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Dynamic: license-file
23
+
24
+ # OpenCAC
25
+
26
+ **OpenCAC is multi-agent orchestration CLI for AI coding tools. Wires Claude Code, Antigravity, and Codex into one pipeline with validated handoffs, audit logging, and speculative decoding for local LLMs.**
27
+
28
+ ```bash
29
+ pip install .
30
+ opencac run "refactor the auth module" --mode private
31
+ ```
32
+
33
+ ## Why
34
+
35
+ For developers who already use multiple AI coding agents and want one CLI to orchestrate them — with cloud models, local LLMs, or both.
36
+
37
+ ```
38
+ - Claude Code, Codex, Antigravity powerful alone, but each runs in its own world
39
+ - Cloud api burns money — every hosted model call costs real tokens.
40
+ - Local LLMs lack quality — small models are cheap but can't reliably produce production-grade code.
41
+
42
+ OpenCAC solves this by chaining agents into a four-role pipeline where each agent does what it's best at, with structured validation at every hop.
43
+ ```
44
+
45
+ ## Features
46
+
47
+ ```
48
+ 1. FOUR-ROLE PIPELINE
49
+ dispatcher → antigravity (research) → claude-code (plan) → codex (execute)
50
+ - Structured envelopes at every hop; downstream critiques upstream before acting
51
+ - Codex runs assess_plan — dangerous commands rejected, not blindly run
52
+
53
+ 2. ROUTING MODES
54
+ private Loopback only. Private guard required. For sensitive / air-gapped work.
55
+ cloud Cloud API tokens. No local infra needed.
56
+ hybrid Cloud first, falls back to local LLM when tokens are missing.
57
+
58
+ 3. LOCAL LLM SUPPORT
59
+ - Each role points to its own llama.cpp server endpoint
60
+ - Built-in spec decoding config (n-gram / draft-model) → generates llama-server commands
61
+ - Probe: constrained-grammar check verifies each endpoint before pipeline starts
62
+
63
+ 4. SIDECAR VALIDATION
64
+ - Schema check on every hop — agent whitelist, message-type whitelist, payload fields
65
+ - Blocked commands: rm -rf /, shutdown, mkfs, fork bomb
66
+ - Private mode: loopback-only on all URLs including callbacks
67
+
68
+ 5. JSONL AUDIT LOG
69
+ - One JSON line per action — timestamp, session_id, kind
70
+ - Filter by session, query last N entries
71
+ - Session resume: rebuild plan from log, skip completed steps
72
+
73
+ 6. CLI + HTTP
74
+ CLI opencac run, opencac audit, opencac resume, interactive REPL
75
+ HTTP POST /run, GET /tasks/<id>, per-agent endpoints, /.well-known/agent.json
76
+ Distributed CLI routes through HTTP service, sync and async
77
+
78
+ 7. SMART QUESTION ROUTING
79
+ - Ends with ? or starts with who/what/how/why → QA path, skips pipeline
80
+ - Task input → full pipeline, outputs artifacts
81
+ - Mentions docs/code/error/test → research step first
82
+ ```
83
+
84
+ ## Quick Start
85
+
86
+ ```bash
87
+ git clone https://github.com/lpoee/opencac.git && cd opencac
88
+ python3 -m venv .venv && . .venv/bin/activate && pip install .
89
+ ```
90
+
91
+ ```bash
92
+ # Private (local llama.cpp shards)
93
+ export A2A_ANTIGRAVITY_URL=http://127.0.0.1:18101
94
+ export A2A_CLAUDE_CODE_URL=http://127.0.0.1:18102
95
+ export A2A_CODEX_URL=http://127.0.0.1:18103
96
+ opencac run "task" --mode private
97
+
98
+ # Cloud
99
+ export A2A_ANTIGRAVITY_TOKEN=...
100
+ export A2A_CLAUDE_CODE_TOKEN=...
101
+ export A2A_CODEX_TOKEN=...
102
+ opencac run "task" --mode cloud
103
+
104
+ # Hybrid
105
+ export A2A_CLOUD_FALLBACK_LOCAL=1
106
+ opencac run "task" --mode cloud
107
+ ```
108
+
109
+ ## Agent Integration
110
+
111
+ Connect real AI agents for production-quality research, planning, and code generation.
112
+ When set, the pipeline calls real agents first and falls back to local heuristics on failure.
113
+
114
+ ```bash
115
+ # Antigravity — Gemini research via JSON-RPC (A2A protocol)
116
+ export OPENCAC_RESEARCH_URL=http://127.0.0.1:18791
117
+
118
+ # Claude Code — planning via Claude Bridge (Anthropic messages API)
119
+ export OPENCAC_PLANNER_URL=http://127.0.0.1:9300
120
+
121
+ # Codex — AI code generation via CLI
122
+ export OPENCAC_CODEX_BINARY=/usr/local/bin/codex
123
+
124
+ opencac run "refactor the auth module" --mode private
125
+ ```
126
+
127
+ | Variable | Agent | Protocol | Purpose |
128
+ | ---------------------- | ------------- | --------------------------- | -------------------------- |
129
+ | `OPENCAC_RESEARCH_URL` | Antigravity | JSON-RPC 2.0 `message/send` | Web research via Gemini |
130
+ | `OPENCAC_PLANNER_URL` | Claude Bridge | `POST /v1/messages` | Plan generation via Claude |
131
+ | `OPENCAC_CODEX_BINARY` | Codex CLI | JSONL subprocess | AI code generation |
132
+
133
+ The `generate` plan action dispatches work to Codex CLI for AI-assisted code generation.
134
+ Without these variables, the pipeline uses deterministic local heuristics (file search, template plans, subprocess execution).
135
+
136
+ Docker:
137
+
138
+ ```bash
139
+ docker build -t opencac .
140
+ docker run --rm -p 8000:8000 -v "$(pwd)/data:/data" opencac
141
+ ```
142
+
143
+ ## Speculative Decoding
144
+
145
+ ```bash
146
+ opencac run "task" --mode private \
147
+ --spec-type ngram-simple \
148
+ --draft-max 64 --draft-min 16
149
+ ```
150
+
151
+ | Strategy | Description | VRAM |
152
+ | -------------------------- | ------------------------------------ | ----------- |
153
+ | Self-speculative (default) | n-gram cache on main model | Zero extra |
154
+ | Draft-model | Smaller model generates draft tokens | Extra model |
155
+
156
+ ## HTTP API
157
+
158
+ | Method | Path | Description |
159
+ | ------ | -------------------------------- | ----------------- |
160
+ | `GET` | `/.well-known/agent.json` | Agent card |
161
+ | `GET` | `/tasks/<id>` | Status + steps |
162
+ | `GET` | `/audit?session_id=<id>&last=20` | Audit log |
163
+ | `POST` | `/run` | Run task |
164
+ | `POST` | `/run?distributed=1&async=1` | Async distributed |
165
+ | `POST` | `/agents/<agent>/message/send` | Message an agent |
166
+
167
+ ## Output
168
+
169
+ - `artifacts/<session-id>/plan.json` — execution plan
170
+ - `artifacts/<session-id>/result.md` — routing, strategy, step results
171
+ - `.opencac/audit.jsonl` — full event log
172
+
173
+ ## Testing
174
+
175
+ ```bash
176
+ PYTHONPATH=src pytest -q # 32 tests
177
+ ```
178
+
179
+ ## Security
180
+
181
+ See [SECURITY.md](SECURITY.md).
182
+
183
+ ## Contributing
184
+
185
+ [CONTRIBUTING.md](CONTRIBUTING.md).
186
+
187
+ ## License
188
+
189
+ MIT
@@ -0,0 +1,166 @@
1
+ # OpenCAC
2
+
3
+ **OpenCAC is multi-agent orchestration CLI for AI coding tools. Wires Claude Code, Antigravity, and Codex into one pipeline with validated handoffs, audit logging, and speculative decoding for local LLMs.**
4
+
5
+ ```bash
6
+ pip install .
7
+ opencac run "refactor the auth module" --mode private
8
+ ```
9
+
10
+ ## Why
11
+
12
+ For developers who already use multiple AI coding agents and want one CLI to orchestrate them — with cloud models, local LLMs, or both.
13
+
14
+ ```
15
+ - Claude Code, Codex, Antigravity powerful alone, but each runs in its own world
16
+ - Cloud api burns money — every hosted model call costs real tokens.
17
+ - Local LLMs lack quality — small models are cheap but can't reliably produce production-grade code.
18
+
19
+ OpenCAC solves this by chaining agents into a four-role pipeline where each agent does what it's best at, with structured validation at every hop.
20
+ ```
21
+
22
+ ## Features
23
+
24
+ ```
25
+ 1. FOUR-ROLE PIPELINE
26
+ dispatcher → antigravity (research) → claude-code (plan) → codex (execute)
27
+ - Structured envelopes at every hop; downstream critiques upstream before acting
28
+ - Codex runs assess_plan — dangerous commands rejected, not blindly run
29
+
30
+ 2. ROUTING MODES
31
+ private Loopback only. Private guard required. For sensitive / air-gapped work.
32
+ cloud Cloud API tokens. No local infra needed.
33
+ hybrid Cloud first, falls back to local LLM when tokens are missing.
34
+
35
+ 3. LOCAL LLM SUPPORT
36
+ - Each role points to its own llama.cpp server endpoint
37
+ - Built-in spec decoding config (n-gram / draft-model) → generates llama-server commands
38
+ - Probe: constrained-grammar check verifies each endpoint before pipeline starts
39
+
40
+ 4. SIDECAR VALIDATION
41
+ - Schema check on every hop — agent whitelist, message-type whitelist, payload fields
42
+ - Blocked commands: rm -rf /, shutdown, mkfs, fork bomb
43
+ - Private mode: loopback-only on all URLs including callbacks
44
+
45
+ 5. JSONL AUDIT LOG
46
+ - One JSON line per action — timestamp, session_id, kind
47
+ - Filter by session, query last N entries
48
+ - Session resume: rebuild plan from log, skip completed steps
49
+
50
+ 6. CLI + HTTP
51
+ CLI opencac run, opencac audit, opencac resume, interactive REPL
52
+ HTTP POST /run, GET /tasks/<id>, per-agent endpoints, /.well-known/agent.json
53
+ Distributed CLI routes through HTTP service, sync and async
54
+
55
+ 7. SMART QUESTION ROUTING
56
+ - Ends with ? or starts with who/what/how/why → QA path, skips pipeline
57
+ - Task input → full pipeline, outputs artifacts
58
+ - Mentions docs/code/error/test → research step first
59
+ ```
60
+
61
+ ## Quick Start
62
+
63
+ ```bash
64
+ git clone https://github.com/lpoee/opencac.git && cd opencac
65
+ python3 -m venv .venv && . .venv/bin/activate && pip install .
66
+ ```
67
+
68
+ ```bash
69
+ # Private (local llama.cpp shards)
70
+ export A2A_ANTIGRAVITY_URL=http://127.0.0.1:18101
71
+ export A2A_CLAUDE_CODE_URL=http://127.0.0.1:18102
72
+ export A2A_CODEX_URL=http://127.0.0.1:18103
73
+ opencac run "task" --mode private
74
+
75
+ # Cloud
76
+ export A2A_ANTIGRAVITY_TOKEN=...
77
+ export A2A_CLAUDE_CODE_TOKEN=...
78
+ export A2A_CODEX_TOKEN=...
79
+ opencac run "task" --mode cloud
80
+
81
+ # Hybrid
82
+ export A2A_CLOUD_FALLBACK_LOCAL=1
83
+ opencac run "task" --mode cloud
84
+ ```
85
+
86
+ ## Agent Integration
87
+
88
+ Connect real AI agents for production-quality research, planning, and code generation.
89
+ When set, the pipeline calls real agents first and falls back to local heuristics on failure.
90
+
91
+ ```bash
92
+ # Antigravity — Gemini research via JSON-RPC (A2A protocol)
93
+ export OPENCAC_RESEARCH_URL=http://127.0.0.1:18791
94
+
95
+ # Claude Code — planning via Claude Bridge (Anthropic messages API)
96
+ export OPENCAC_PLANNER_URL=http://127.0.0.1:9300
97
+
98
+ # Codex — AI code generation via CLI
99
+ export OPENCAC_CODEX_BINARY=/usr/local/bin/codex
100
+
101
+ opencac run "refactor the auth module" --mode private
102
+ ```
103
+
104
+ | Variable | Agent | Protocol | Purpose |
105
+ | ---------------------- | ------------- | --------------------------- | -------------------------- |
106
+ | `OPENCAC_RESEARCH_URL` | Antigravity | JSON-RPC 2.0 `message/send` | Web research via Gemini |
107
+ | `OPENCAC_PLANNER_URL` | Claude Bridge | `POST /v1/messages` | Plan generation via Claude |
108
+ | `OPENCAC_CODEX_BINARY` | Codex CLI | JSONL subprocess | AI code generation |
109
+
110
+ The `generate` plan action dispatches work to Codex CLI for AI-assisted code generation.
111
+ Without these variables, the pipeline uses deterministic local heuristics (file search, template plans, subprocess execution).
112
+
113
+ Docker:
114
+
115
+ ```bash
116
+ docker build -t opencac .
117
+ docker run --rm -p 8000:8000 -v "$(pwd)/data:/data" opencac
118
+ ```
119
+
120
+ ## Speculative Decoding
121
+
122
+ ```bash
123
+ opencac run "task" --mode private \
124
+ --spec-type ngram-simple \
125
+ --draft-max 64 --draft-min 16
126
+ ```
127
+
128
+ | Strategy | Description | VRAM |
129
+ | -------------------------- | ------------------------------------ | ----------- |
130
+ | Self-speculative (default) | n-gram cache on main model | Zero extra |
131
+ | Draft-model | Smaller model generates draft tokens | Extra model |
132
+
133
+ ## HTTP API
134
+
135
+ | Method | Path | Description |
136
+ | ------ | -------------------------------- | ----------------- |
137
+ | `GET` | `/.well-known/agent.json` | Agent card |
138
+ | `GET` | `/tasks/<id>` | Status + steps |
139
+ | `GET` | `/audit?session_id=<id>&last=20` | Audit log |
140
+ | `POST` | `/run` | Run task |
141
+ | `POST` | `/run?distributed=1&async=1` | Async distributed |
142
+ | `POST` | `/agents/<agent>/message/send` | Message an agent |
143
+
144
+ ## Output
145
+
146
+ - `artifacts/<session-id>/plan.json` — execution plan
147
+ - `artifacts/<session-id>/result.md` — routing, strategy, step results
148
+ - `.opencac/audit.jsonl` — full event log
149
+
150
+ ## Testing
151
+
152
+ ```bash
153
+ PYTHONPATH=src pytest -q # 32 tests
154
+ ```
155
+
156
+ ## Security
157
+
158
+ See [SECURITY.md](SECURITY.md).
159
+
160
+ ## Contributing
161
+
162
+ [CONTRIBUTING.md](CONTRIBUTING.md).
163
+
164
+ ## License
165
+
166
+ MIT
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "opencac"
7
+ version = "0.2.0"
8
+ description = "OpenCAC: Claude Code, Antigravity, and Codex working together across cloud APIs and local models."
9
+ requires-python = ">=3.9"
10
+ authors = [{ name = "Codex" }]
11
+ readme = "README.md"
12
+ license = "MIT"
13
+ keywords = [
14
+ "opencac",
15
+ "claude-code",
16
+ "codex",
17
+ "antigravity",
18
+ "multi-agent-orchestration",
19
+ "ai-coding-agent-pipeline",
20
+ "claude-code-codex-together",
21
+ "ai-coding-workflow-automation",
22
+ "orchestrate-ai-coding-tools",
23
+ "developer-cli-tools",
24
+ "ai-agent-chaining",
25
+ "reduce-ai-api-cost",
26
+ "local-llm-code-quality",
27
+ "air-gapped-ai-coding",
28
+ "private-ai-code-generation",
29
+ "local-llm",
30
+ "hybrid-ai",
31
+ "jsonl",
32
+ "audit-log",
33
+ "speculative-decoding",
34
+ "llama-cpp",
35
+ "validated-handoff",
36
+ "session-resume",
37
+ ]
38
+ classifiers = [
39
+ "Development Status :: 3 - Alpha",
40
+ "Intended Audience :: Developers",
41
+ "Operating System :: OS Independent",
42
+ "Programming Language :: Python :: 3",
43
+ "Programming Language :: Python :: 3.9",
44
+ "Programming Language :: Python :: 3.10",
45
+ "Programming Language :: Python :: 3.11",
46
+ "Programming Language :: Python :: 3.12",
47
+ ]
48
+
49
+ [project.scripts]
50
+ opencac = "opencac.cli:main"
51
+
52
+ [project.urls]
53
+ Homepage = "https://github.com/lpoee/opencac"
54
+ Repository = "https://github.com/lpoee/opencac"
55
+ Issues = "https://github.com/lpoee/opencac/issues"
56
+
57
+ [tool.setuptools]
58
+ package-dir = {"" = "src"}
59
+
60
+ [tool.setuptools.packages.find]
61
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ __all__ = [
2
+ "agents",
3
+ "audit",
4
+ "cli",
5
+ "cli_runtime",
6
+ "pipeline",
7
+ "roles",
8
+ "runtime",
9
+ "schemas",
10
+ "service",
11
+ "sidecar",
12
+ ]
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from .pipeline import resume_pipeline, run_pipeline
4
+ from .roles import Antigravity, ClaudeCodePlanner, CodexExecutor
5
+ from .runtime import InferenceConfig, RoutingConfig, Sidecar, ensure_private_runtime, make_envelope
6
+
7
+ __all__ = [
8
+ "Antigravity",
9
+ "ClaudeCodePlanner",
10
+ "CodexExecutor",
11
+ "InferenceConfig",
12
+ "RoutingConfig",
13
+ "Sidecar",
14
+ "ensure_private_runtime",
15
+ "make_envelope",
16
+ "run_pipeline",
17
+ "resume_pipeline",
18
+ ]
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import threading
5
+ from dataclasses import dataclass
6
+ from datetime import datetime, timezone
7
+ from pathlib import Path
8
+ from typing import Any, Dict, List, Optional
9
+
10
+
11
+ def utc_now() -> str:
12
+ return datetime.now(timezone.utc).isoformat()
13
+
14
+
15
+ @dataclass
16
+ class AuditLog:
17
+ path: Path
18
+
19
+ def __post_init__(self) -> None:
20
+ self.path.parent.mkdir(parents=True, exist_ok=True)
21
+ self._io_lock = threading.Lock()
22
+ self._session_offsets: Dict[str, List[int]] = {}
23
+ self._all_offsets: List[int] = []
24
+ self._indexed_size = 0
25
+
26
+ def append(self, event: Dict[str, Any]) -> Dict[str, Any]:
27
+ enriched = {"ts": utc_now(), **event}
28
+ encoded = (json.dumps(enriched, ensure_ascii=False) + "\n").encode("utf-8")
29
+ with self._io_lock:
30
+ offset = self.path.stat().st_size if self.path.exists() else 0
31
+ with self.path.open("ab") as handle:
32
+ handle.write(encoded)
33
+ self._all_offsets.append(offset)
34
+ session_id = enriched.get("session_id")
35
+ if isinstance(session_id, str):
36
+ self._session_offsets.setdefault(session_id, []).append(offset)
37
+ self._indexed_size = offset + len(encoded)
38
+ return enriched
39
+
40
+ def read(self, session_id: Optional[str] = None, last: int = 20) -> List[Dict[str, Any]]:
41
+ if not self.path.exists():
42
+ return []
43
+ with self._io_lock:
44
+ self._ensure_index_locked()
45
+ if session_id is None:
46
+ offsets = self._all_offsets[-last:]
47
+ else:
48
+ offsets = self._session_offsets.get(session_id, [])[-last:]
49
+ return self._read_offsets_locked(offsets)
50
+
51
+ def _ensure_index_locked(self) -> None:
52
+ if not self.path.exists():
53
+ self._session_offsets = {}
54
+ self._all_offsets = []
55
+ self._indexed_size = 0
56
+ return
57
+ current_size = self.path.stat().st_size
58
+ if current_size < self._indexed_size:
59
+ self._session_offsets = {}
60
+ self._all_offsets = []
61
+ self._indexed_size = 0
62
+ if current_size == self._indexed_size:
63
+ return
64
+ with self.path.open("rb") as handle:
65
+ handle.seek(self._indexed_size)
66
+ while True:
67
+ offset = handle.tell()
68
+ line = handle.readline()
69
+ if not line:
70
+ break
71
+ try:
72
+ item = json.loads(line.decode("utf-8"))
73
+ except json.JSONDecodeError:
74
+ continue
75
+ self._all_offsets.append(offset)
76
+ session_id = item.get("session_id")
77
+ if isinstance(session_id, str):
78
+ self._session_offsets.setdefault(session_id, []).append(offset)
79
+ self._indexed_size = handle.tell()
80
+
81
+ def _read_offsets_locked(self, offsets: List[int]) -> List[Dict[str, Any]]:
82
+ entries: List[Dict[str, Any]] = []
83
+ with self.path.open("rb") as handle:
84
+ for offset in offsets:
85
+ handle.seek(offset)
86
+ line = handle.readline()
87
+ if not line:
88
+ continue
89
+ entries.append(json.loads(line.decode("utf-8")))
90
+ return entries