token-runtime 0.1.0a2__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.
@@ -0,0 +1,351 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable, Mapping
4
+ from copy import deepcopy
5
+ from dataclasses import dataclass, replace
6
+
7
+ from .capabilities import (
8
+ CapabilityDetector,
9
+ CapabilityKey,
10
+ CapabilityProfile,
11
+ CapabilityRegistry,
12
+ )
13
+ from .compatibility import (
14
+ CompatibilityRecord,
15
+ CompatibilityRegistry,
16
+ CompatibilityState,
17
+ )
18
+ from .conformance import ConformanceResult, require_conformance, run_conformance
19
+ from .gemini_adapter import GeminiGenerateContentAdapter
20
+
21
+
22
+ GEMINI_GENERATE_CONTENT_KEY = CapabilityKey(
23
+ "generic-google",
24
+ "gemini_generate_content",
25
+ "google",
26
+ )
27
+ EVIDENCE_ID = "token-gemini-adapter-1:offline-request-boundary-v1"
28
+
29
+
30
+ @dataclass(frozen=True, slots=True)
31
+ class GeminiConformanceBundle:
32
+ profile: CapabilityProfile
33
+ record: CompatibilityRecord
34
+ detector: CapabilityDetector
35
+
36
+
37
+ def build_gemini_conformance() -> GeminiConformanceBundle:
38
+ profile = CapabilityProfile(
39
+ key=GEMINI_GENERATE_CONTENT_KEY,
40
+ server_cache="cached-content-reference-preserved",
41
+ tool_calls=True,
42
+ reasoning_state="exact-replay-required",
43
+ exact_byte_preservation=True,
44
+ evidence_id=EVIDENCE_ID,
45
+ )
46
+ record = CompatibilityRecord(
47
+ key=GEMINI_GENERATE_CONTENT_KEY,
48
+ state=CompatibilityState.PASSTHROUGH_ONLY,
49
+ evidence_id=EVIDENCE_ID,
50
+ reason="offline_conformance_only",
51
+ )
52
+ capabilities = CapabilityRegistry()
53
+ capabilities.register(profile)
54
+ compatibility = CompatibilityRegistry()
55
+ compatibility.register(record)
56
+ return GeminiConformanceBundle(
57
+ profile=profile,
58
+ record=record,
59
+ detector=CapabilityDetector(capabilities, compatibility),
60
+ )
61
+
62
+
63
+ def _supported_fixture() -> dict[str, object]:
64
+ return {
65
+ "contents": [
66
+ {"role": "user", "parts": [{"text": "current task"}]},
67
+ {
68
+ "role": "model",
69
+ "parts": [
70
+ {
71
+ "functionCall": {
72
+ "id": "call_1",
73
+ "name": "lookup",
74
+ "args": {"q": "status"},
75
+ }
76
+ }
77
+ ],
78
+ },
79
+ ],
80
+ "systemInstruction": {"parts": [{"text": "stable policy"}]},
81
+ "tools": [
82
+ {
83
+ "functionDeclarations": [
84
+ {
85
+ "name": "lookup",
86
+ "description": "fixture",
87
+ "parameters": {"type": "OBJECT"},
88
+ }
89
+ ]
90
+ }
91
+ ],
92
+ "toolConfig": {"functionCallingConfig": {"mode": "AUTO"}},
93
+ "cachedContent": "cachedContents/cache-1",
94
+ "generationConfig": {"temperature": 0.2, "thinkingLevel": "LOW"},
95
+ "futureField": {"preserve": True},
96
+ }
97
+
98
+
99
+ def _supported_roundtrip() -> bool:
100
+ payload = _supported_fixture()
101
+ adapter = GeminiGenerateContentAdapter()
102
+ envelope = adapter.parse(payload)
103
+ return envelope.wire_safe and adapter.serialize(envelope) == payload
104
+
105
+
106
+ def _roleless_text_roundtrip() -> bool:
107
+ payload = {"contents": [{"parts": [{"text": "hello"}]}]}
108
+ adapter = GeminiGenerateContentAdapter()
109
+ envelope = adapter.parse(payload)
110
+ user = next((block for block in envelope.blocks if block.text == "hello"), None)
111
+ return (
112
+ envelope.wire_safe
113
+ and user is not None
114
+ and user.kind == "user"
115
+ and user.role == "user"
116
+ and user.metadata.get("path") == ("contents", 0, "parts", 0, "text")
117
+ and adapter.serialize(envelope) == payload
118
+ )
119
+
120
+
121
+ def _cached_content_reference_preserved() -> bool:
122
+ payload = _supported_fixture()
123
+ adapter = GeminiGenerateContentAdapter()
124
+ envelope = adapter.parse(payload)
125
+ serialized = adapter.serialize(envelope)
126
+ return (
127
+ envelope.wire_safe
128
+ and serialized == payload
129
+ and serialized["cachedContent"] == "cachedContents/cache-1"
130
+ )
131
+
132
+
133
+ def _text_path_mutation_preserves_protocol() -> bool:
134
+ payload = _supported_fixture()
135
+ adapter = GeminiGenerateContentAdapter()
136
+ envelope = adapter.parse(payload)
137
+ target = next(block for block in envelope.blocks if block.text == "current task")
138
+ changed = replace(
139
+ envelope,
140
+ blocks=tuple(
141
+ replace(block, text="updated task") if block is target else block
142
+ for block in envelope.blocks
143
+ ),
144
+ )
145
+ actual = adapter.serialize(changed)
146
+ expected = deepcopy(payload)
147
+ expected["contents"][0]["parts"][0]["text"] = "updated task"
148
+ return actual == expected
149
+
150
+
151
+ def _system_instruction_text_mutation() -> bool:
152
+ payload = _supported_fixture()
153
+ adapter = GeminiGenerateContentAdapter()
154
+ envelope = adapter.parse(payload)
155
+ target = next(block for block in envelope.blocks if block.kind == "system")
156
+ changed = replace(
157
+ envelope,
158
+ blocks=tuple(
159
+ replace(block, text="updated policy") if block is target else block
160
+ for block in envelope.blocks
161
+ ),
162
+ )
163
+ actual = adapter.serialize(changed)
164
+ expected = deepcopy(payload)
165
+ expected["systemInstruction"]["parts"][0]["text"] = "updated policy"
166
+ return actual == expected
167
+
168
+
169
+ def _tool_classification() -> bool:
170
+ call_payload = _supported_fixture()
171
+ call_envelope = GeminiGenerateContentAdapter().parse(call_payload)
172
+ call_by_kind = {block.kind: block for block in call_envelope.blocks}
173
+ call_required = {"tool_schema", "tool_call"}
174
+
175
+ response_payload = {
176
+ "contents": [
177
+ {
178
+ "role": "user",
179
+ "parts": [
180
+ {
181
+ "functionResponse": {
182
+ "id": "call_1",
183
+ "name": "lookup",
184
+ "response": {"status": "green"},
185
+ }
186
+ }
187
+ ],
188
+ }
189
+ ]
190
+ }
191
+ response_envelope = GeminiGenerateContentAdapter().parse(response_payload)
192
+ output = next(
193
+ block for block in response_envelope.blocks if block.kind == "tool_output"
194
+ )
195
+ return (
196
+ call_envelope.wire_safe
197
+ and call_required <= set(call_by_kind)
198
+ and all("path" not in call_by_kind[kind].metadata for kind in call_required)
199
+ and not response_envelope.wire_safe
200
+ and "path" not in output.metadata
201
+ and GeminiGenerateContentAdapter().serialize(response_envelope) == response_payload
202
+ )
203
+
204
+
205
+ def _function_response_exact_passthrough() -> bool:
206
+ payload = {
207
+ "contents": [
208
+ {
209
+ "role": "user",
210
+ "parts": [
211
+ {
212
+ "functionResponse": {
213
+ "name": "lookup",
214
+ "response": {"status": "green"},
215
+ }
216
+ }
217
+ ],
218
+ }
219
+ ]
220
+ }
221
+ adapter = GeminiGenerateContentAdapter()
222
+ envelope = adapter.parse(payload)
223
+ return (
224
+ not envelope.wire_safe
225
+ and any(block.kind == "tool_output" for block in envelope.blocks)
226
+ and adapter.serialize(envelope) == payload
227
+ )
228
+
229
+
230
+ def _thought_signature_exact_passthrough() -> bool:
231
+ payload = {
232
+ "contents": [
233
+ {
234
+ "role": "model",
235
+ "parts": [
236
+ {
237
+ "functionCall": {"name": "lookup", "args": {"q": "x"}},
238
+ "thoughtSignature": "opaque-signature",
239
+ }
240
+ ],
241
+ }
242
+ ]
243
+ }
244
+ adapter = GeminiGenerateContentAdapter()
245
+ envelope = adapter.parse(payload)
246
+ return (
247
+ not envelope.wire_safe
248
+ and adapter.serialize(envelope) == payload
249
+ and any(block.kind == "protocol_state" for block in envelope.blocks)
250
+ )
251
+
252
+
253
+ def _unknown_multimodal_passthrough() -> bool:
254
+ payload = {
255
+ "contents": [
256
+ {
257
+ "role": "user",
258
+ "parts": [
259
+ {"text": "describe"},
260
+ {"inlineData": {"mimeType": "image/png", "data": "opaque"}},
261
+ ],
262
+ }
263
+ ]
264
+ }
265
+ adapter = GeminiGenerateContentAdapter()
266
+ envelope = adapter.parse(payload)
267
+ return not envelope.wire_safe and adapter.serialize(envelope) == payload
268
+
269
+
270
+ def _unsupported_tool_passthrough() -> bool:
271
+ payload = {
272
+ "contents": [{"role": "user", "parts": [{"text": "search"}]}],
273
+ "tools": [{"googleSearch": {}}],
274
+ }
275
+ adapter = GeminiGenerateContentAdapter()
276
+ envelope = adapter.parse(payload)
277
+ return not envelope.wire_safe and adapter.serialize(envelope) == payload
278
+
279
+
280
+ def _malformed_function_passthrough() -> bool:
281
+ payload = {
282
+ "contents": [
283
+ {"role": "model", "parts": [{"functionCall": {"args": {"q": "x"}}}]}
284
+ ]
285
+ }
286
+ adapter = GeminiGenerateContentAdapter()
287
+ envelope = adapter.parse(payload)
288
+ return not envelope.wire_safe and adapter.serialize(envelope) == payload
289
+
290
+
291
+ def _streaming_unclaimed() -> bool:
292
+ bundle = build_gemini_conformance()
293
+ return (
294
+ bundle.profile.streaming == "unknown"
295
+ and GeminiGenerateContentAdapter.protocol_id == "gemini_generate_content"
296
+ )
297
+
298
+
299
+ def _certification_state_passthrough_only() -> bool:
300
+ bundle = build_gemini_conformance()
301
+ return (
302
+ bundle.record.state is CompatibilityState.PASSTHROUGH_ONLY
303
+ and bundle.record.reason == "offline_conformance_only"
304
+ and bundle.profile.evidence_id == bundle.record.evidence_id
305
+ )
306
+
307
+
308
+ def _near_match_non_inheritance() -> bool:
309
+ bundle = build_gemini_conformance()
310
+ keys = (
311
+ CapabilityKey(
312
+ "generic-google",
313
+ "gemini_generate_content",
314
+ "google",
315
+ model_family="gemini-future",
316
+ ),
317
+ CapabilityKey("generic-google", "gemini_generate_content", "google-v2"),
318
+ CapabilityKey("gemini-cli", "gemini_generate_content", "google"),
319
+ )
320
+ return all(
321
+ bundle.detector.detect(key).profile is None
322
+ and bundle.detector.detect(key).compatibility.state
323
+ is CompatibilityState.PASSTHROUGH_ONLY
324
+ and bundle.detector.detect(key).compatibility.reason == "unknown_capability"
325
+ for key in keys
326
+ )
327
+
328
+
329
+ def gemini_conformance_cases() -> Mapping[str, Callable[[], bool]]:
330
+ return {
331
+ "cached_content_reference_preserved": _cached_content_reference_preserved,
332
+ "certification_state_passthrough_only": _certification_state_passthrough_only,
333
+ "function_response_exact_passthrough": _function_response_exact_passthrough,
334
+ "malformed_function_passthrough": _malformed_function_passthrough,
335
+ "near_match_non_inheritance": _near_match_non_inheritance,
336
+ "roleless_text_roundtrip": _roleless_text_roundtrip,
337
+ "streaming_unclaimed": _streaming_unclaimed,
338
+ "supported_roundtrip": _supported_roundtrip,
339
+ "system_instruction_text_mutation": _system_instruction_text_mutation,
340
+ "text_path_mutation_preserves_protocol": _text_path_mutation_preserves_protocol,
341
+ "thought_signature_exact_passthrough": _thought_signature_exact_passthrough,
342
+ "tool_classification": _tool_classification,
343
+ "unknown_multimodal_passthrough": _unknown_multimodal_passthrough,
344
+ "unsupported_tool_passthrough": _unsupported_tool_passthrough,
345
+ }
346
+
347
+
348
+ def run_gemini_conformance() -> tuple[ConformanceResult, ...]:
349
+ results = run_conformance(gemini_conformance_cases())
350
+ require_conformance(results)
351
+ return results
@@ -0,0 +1,272 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ import hashlib
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ import re
9
+ from typing import Literal
10
+
11
+
12
+ _BEGIN = b"# >>> TOKEN MANAGED >>>"
13
+ _END = b"# <<< TOKEN MANAGED <<<"
14
+ _BASE_RE = re.compile(br"(?m)^OPENAI_BASE_URL\s*=.*$")
15
+ _MANAGED_RE = re.compile(
16
+ re.escape(_BEGIN) + br"\r?\n.*?\r?\n" + re.escape(_END) + br"(?:\r?\n)?",
17
+ re.DOTALL,
18
+ )
19
+
20
+
21
+ @dataclass(frozen=True, slots=True)
22
+ class Integration:
23
+ kind: Literal["codex", "openai_env"]
24
+ path: Path
25
+ root: Path
26
+
27
+
28
+ @dataclass(frozen=True, slots=True)
29
+ class InstallPlan:
30
+ integration: Integration
31
+ mode: Literal["sidecar", "managed_block", "managed_toml"]
32
+ target_path: Path
33
+ gateway_url: str
34
+ original_bytes: bytes | None
35
+ desired_bytes: bytes
36
+ safe_to_apply: bool = True
37
+ reason: str = "ready"
38
+ metadata_path: Path | None = None
39
+ metadata_bytes: bytes | None = None
40
+
41
+
42
+ @dataclass(frozen=True, slots=True)
43
+ class ApplyResult:
44
+ changed: bool
45
+ reason: str
46
+ target_path: Path
47
+
48
+
49
+ def detect_integrations(root: str | Path) -> list[Integration]:
50
+ base = Path(root)
51
+ found: list[Integration] = []
52
+ codex = base / ".codex" / "config.toml"
53
+ if codex.is_file():
54
+ found.append(Integration("codex", codex, base))
55
+ env = base / ".env"
56
+ if env.is_file():
57
+ content = env.read_bytes()
58
+ if b"OPENAI_" in content or _BEGIN in content:
59
+ found.append(Integration("openai_env", env, base))
60
+ return found
61
+
62
+
63
+ def _managed_block(gateway_url: str) -> bytes:
64
+ return (
65
+ _BEGIN + b"\n" +
66
+ f"OPENAI_BASE_URL={gateway_url}\n".encode("utf-8") +
67
+ _END + b"\n"
68
+ )
69
+
70
+
71
+ def _replace_or_append_block(original: bytes, gateway_url: str) -> bytes:
72
+ block = _managed_block(gateway_url)
73
+ if _MANAGED_RE.search(original):
74
+ return _MANAGED_RE.sub(block, original, count=1)
75
+ separator = b"" if not original or original.endswith((b"\n", b"\r")) else b"\n"
76
+ return original + separator + block
77
+
78
+
79
+ def _codex_provider_sections(content: bytes):
80
+ return list(re.finditer(br"(?m)^\[model_providers\.([A-Za-z0-9_-]+)\][ \t]*(?:\r?\n|$)", content))
81
+
82
+
83
+ def _replace_codex_base_url(content: bytes, provider_id: str, new_url: str):
84
+ sections = _codex_provider_sections(content)
85
+ match = next((m for m in sections if m.group(1).decode() == provider_id), None)
86
+ if match is None:
87
+ return None
88
+ next_headers = [m.start() for m in re.finditer(br"(?m)^\[[^\r\n]+\][ \t]*(?:\r?\n|$)", content) if m.start() > match.start()]
89
+ end = min(next_headers) if next_headers else len(content)
90
+ section = content[match.end():end]
91
+ base = re.search(br'(?m)^[ \t]*base_url[ \t]*=[ \t]*"([^"\r\n]+)"', section)
92
+ if base is None:
93
+ return None
94
+ start = match.end() + base.start(1)
95
+ stop = match.end() + base.end(1)
96
+ old = content[start:stop].decode("utf-8")
97
+ desired = content[:start] + new_url.encode("utf-8") + content[stop:]
98
+ return old, desired
99
+
100
+
101
+ def _plan_codex(integration: Integration, gateway_url: str) -> InstallPlan:
102
+ original = integration.path.read_bytes()
103
+ target = integration.path
104
+ metadata_path = integration.root / ".token" / "integrations" / "codex.json"
105
+ if metadata_path.exists():
106
+ try:
107
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
108
+ except (OSError, ValueError, TypeError):
109
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, original, False, "invalid_codex_metadata", metadata_path)
110
+ current_hash = hashlib.sha256(original).hexdigest()
111
+ if metadata.get("strategy") == "managed_provider_base_url" and current_hash == metadata.get("desired_sha256"):
112
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, original, True, "already_managed", metadata_path, metadata_path.read_bytes())
113
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, original, False, "target_drift", metadata_path)
114
+ sections = _codex_provider_sections(original)
115
+ if len(sections) != 1:
116
+ reason = "ambiguous_codex_provider" if len(sections) > 1 else "missing_codex_provider"
117
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, original, False, reason, metadata_path)
118
+ provider_id = sections[0].group(1).decode("utf-8")
119
+ replaced = _replace_codex_base_url(original, provider_id, gateway_url)
120
+ if replaced is None:
121
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, original, False, "missing_codex_base_url", metadata_path)
122
+ old_url, desired = replaced
123
+ metadata = {
124
+ "kind": "codex", "strategy": "managed_provider_base_url",
125
+ "provider_id": provider_id, "gateway_url": gateway_url,
126
+ "original_base_url": old_url,
127
+ "original_sha256": hashlib.sha256(original).hexdigest(),
128
+ "desired_sha256": hashlib.sha256(desired).hexdigest(),
129
+ }
130
+ metadata_bytes = (json.dumps(metadata, indent=2, sort_keys=True) + "\n").encode("utf-8")
131
+ return InstallPlan(integration, "managed_toml", target, gateway_url, original, desired, True, "ready", metadata_path, metadata_bytes)
132
+
133
+
134
+ def plan_install(integration: Integration, *, gateway_url: str) -> InstallPlan:
135
+ if integration.kind == "codex":
136
+ return _plan_codex(integration, gateway_url)
137
+
138
+ original = integration.path.read_bytes()
139
+ unmanaged = _BASE_RE.search(_MANAGED_RE.sub(b"", original))
140
+ safe = unmanaged is None
141
+ desired = _replace_or_append_block(original, gateway_url) if safe else original
142
+ metadata_path = integration.root / ".token" / "integrations" / "openai_env.json"
143
+ if metadata_path.exists():
144
+ metadata_bytes = metadata_path.read_bytes()
145
+ else:
146
+ separator_added = bool(original and not original.endswith((b"\n", b"\r")))
147
+ metadata_bytes = (json.dumps({
148
+ "kind": "openai_env",
149
+ "original_sha256": hashlib.sha256(original).hexdigest(),
150
+ "separator_added": separator_added,
151
+ }, indent=2, sort_keys=True) + "\n").encode("utf-8")
152
+ return InstallPlan(
153
+ integration, "managed_block", integration.path, gateway_url,
154
+ original, desired, safe_to_apply=safe,
155
+ reason="ready" if safe else "existing_openai_base_url_unmanaged",
156
+ metadata_path=metadata_path, metadata_bytes=metadata_bytes,
157
+ )
158
+
159
+
160
+ def _atomic_write(path: Path, content: bytes) -> None:
161
+ path.parent.mkdir(parents=True, exist_ok=True)
162
+ tmp = path.with_name(path.name + ".token-tmp")
163
+ tmp.write_bytes(content)
164
+ os.chmod(tmp, 0o600)
165
+ os.replace(tmp, path)
166
+
167
+
168
+ def apply_plan(plan: InstallPlan, *, apply: bool = False) -> ApplyResult:
169
+ current = plan.target_path.read_bytes() if plan.target_path.exists() else None
170
+ changed = current != plan.desired_bytes
171
+ if not plan.safe_to_apply:
172
+ return ApplyResult(False, plan.reason, plan.target_path)
173
+ if not apply or not changed:
174
+ return ApplyResult(changed, "dry_run" if not apply else "unchanged", plan.target_path)
175
+ if current not in (plan.original_bytes, plan.desired_bytes):
176
+ return ApplyResult(False, "target_drift", plan.target_path)
177
+ try:
178
+ _atomic_write(plan.target_path, plan.desired_bytes)
179
+ if plan.metadata_path is not None and plan.metadata_bytes is not None:
180
+ _atomic_write(plan.metadata_path, plan.metadata_bytes)
181
+ except Exception:
182
+ if plan.original_bytes is None:
183
+ plan.target_path.unlink(missing_ok=True)
184
+ else:
185
+ _atomic_write(plan.target_path, plan.original_bytes)
186
+ if plan.metadata_path is not None:
187
+ plan.metadata_path.unlink(missing_ok=True)
188
+ raise
189
+ return ApplyResult(True, "applied", plan.target_path)
190
+
191
+
192
+ def restore_plan(plan: InstallPlan, *, apply: bool = False) -> ApplyResult:
193
+ current = plan.target_path.read_bytes() if plan.target_path.exists() else None
194
+ desired = plan.original_bytes
195
+ metadata_exists = bool(plan.metadata_path and plan.metadata_path.exists())
196
+ changed = current != desired or metadata_exists
197
+ if not apply or not changed:
198
+ return ApplyResult(changed, "dry_run" if not apply else "unchanged", plan.target_path)
199
+ if current not in (plan.original_bytes, plan.desired_bytes):
200
+ return ApplyResult(False, "target_drift", plan.target_path)
201
+ if current != desired:
202
+ if desired is None:
203
+ plan.target_path.unlink(missing_ok=True)
204
+ else:
205
+ _atomic_write(plan.target_path, desired)
206
+ if plan.metadata_path is not None:
207
+ plan.metadata_path.unlink(missing_ok=True)
208
+ return ApplyResult(True, "restored", plan.target_path)
209
+
210
+
211
+ def uninstall_integration(integration: Integration, *, apply: bool = False) -> ApplyResult:
212
+ if integration.kind == "codex":
213
+ metadata_path = integration.root / ".token" / "integrations" / "codex.json"
214
+ if not metadata_path.exists():
215
+ return ApplyResult(False, "unchanged" if apply else "dry_run", integration.path)
216
+ if not apply:
217
+ return ApplyResult(True, "dry_run", integration.path)
218
+ try:
219
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
220
+ except (OSError, ValueError, TypeError):
221
+ return ApplyResult(False, "invalid_codex_metadata", integration.path)
222
+ if metadata.get("strategy") == "sidecar":
223
+ metadata_path.unlink()
224
+ return ApplyResult(True, "uninstalled", integration.path)
225
+ if metadata.get("strategy") != "managed_provider_base_url":
226
+ return ApplyResult(False, "invalid_codex_metadata", integration.path)
227
+ current = integration.path.read_bytes()
228
+ current_hash = hashlib.sha256(current).hexdigest()
229
+ if current_hash == metadata.get("original_sha256"):
230
+ metadata_path.unlink()
231
+ return ApplyResult(True, "metadata_removed", integration.path)
232
+ if current_hash != metadata.get("desired_sha256"):
233
+ return ApplyResult(False, "target_drift", integration.path)
234
+ restored = _replace_codex_base_url(current, str(metadata.get("provider_id")), str(metadata.get("original_base_url")))
235
+ if restored is None:
236
+ return ApplyResult(False, "restore_failed", integration.path)
237
+ _, desired = restored
238
+ if hashlib.sha256(desired).hexdigest() != metadata.get("original_sha256"):
239
+ return ApplyResult(False, "restore_hash_mismatch", integration.path)
240
+ _atomic_write(integration.path, desired)
241
+ metadata_path.unlink()
242
+ return ApplyResult(True, "uninstalled", integration.path)
243
+
244
+ target = integration.path
245
+ current = target.read_bytes()
246
+ match = _MANAGED_RE.search(current)
247
+ metadata_path = integration.root / ".token" / "integrations" / "openai_env.json"
248
+ metadata_exists = metadata_path.exists()
249
+ if match is None:
250
+ if apply and metadata_exists:
251
+ metadata_path.unlink()
252
+ changed = metadata_exists
253
+ return ApplyResult(changed, "metadata_removed" if apply and changed else ("dry_run" if not apply else "unchanged"), target)
254
+
255
+ separator_added = False
256
+ if metadata_exists:
257
+ try:
258
+ metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
259
+ separator_added = bool(metadata.get("separator_added", False))
260
+ except (OSError, ValueError, TypeError):
261
+ separator_added = False
262
+ start = match.start()
263
+ end = match.end()
264
+ desired = current[:start] + current[end:]
265
+ if separator_added and start > 0 and current[start - 1:start] == b"\n":
266
+ desired = current[:start - 1] + current[end:]
267
+
268
+ if not apply:
269
+ return ApplyResult(True, "dry_run", target)
270
+ _atomic_write(target, desired)
271
+ metadata_path.unlink(missing_ok=True)
272
+ return ApplyResult(True, "uninstalled", target)