agent-json-reliability 0.1.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.
Files changed (36) hide show
  1. agent_json_reliability-0.1.0/LICENSE +5 -0
  2. agent_json_reliability-0.1.0/PKG-INFO +128 -0
  3. agent_json_reliability-0.1.0/README.md +108 -0
  4. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/PKG-INFO +128 -0
  5. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/SOURCES.txt +34 -0
  6. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/dependency_links.txt +1 -0
  7. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/entry_points.txt +3 -0
  8. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/requires.txt +3 -0
  9. agent_json_reliability-0.1.0/agent_json_reliability.egg-info/top_level.txt +2 -0
  10. agent_json_reliability-0.1.0/products/__init__.py +1 -0
  11. agent_json_reliability-0.1.0/products/agent_json_reliability/__init__.py +7 -0
  12. agent_json_reliability-0.1.0/products/agent_json_reliability/inspect.py +62 -0
  13. agent_json_reliability-0.1.0/products/agent_json_reliability/reliable.py +66 -0
  14. agent_json_reliability-0.1.0/products/agent_json_reliability/repair.py +237 -0
  15. agent_json_reliability-0.1.0/products/agent_json_reliability/validate.py +181 -0
  16. agent_json_reliability-0.1.0/products/beta/__init__.py +0 -0
  17. agent_json_reliability-0.1.0/products/beta/app.py +337 -0
  18. agent_json_reliability-0.1.0/products/beta/batch.py +20 -0
  19. agent_json_reliability-0.1.0/products/beta/catalog.py +61 -0
  20. agent_json_reliability-0.1.0/products/beta/identity.py +154 -0
  21. agent_json_reliability-0.1.0/products/beta/landing.py +113 -0
  22. agent_json_reliability-0.1.0/products/beta/security.py +77 -0
  23. agent_json_reliability-0.1.0/products/beta/selfcheck.py +18 -0
  24. agent_json_reliability-0.1.0/products/beta/settings.py +94 -0
  25. agent_json_reliability-0.1.0/products/beta/store.py +137 -0
  26. agent_json_reliability-0.1.0/products/common/__init__.py +7 -0
  27. agent_json_reliability-0.1.0/products/common/timing.py +16 -0
  28. agent_json_reliability-0.1.0/products/gateway/__init__.py +0 -0
  29. agent_json_reliability-0.1.0/products/gateway/manifest.py +138 -0
  30. agent_json_reliability-0.1.0/products/gateway/mcp_server.py +64 -0
  31. agent_json_reliability-0.1.0/products/gateway/mcp_stdio.py +53 -0
  32. agent_json_reliability-0.1.0/products/gateway/rate_limit.py +26 -0
  33. agent_json_reliability-0.1.0/pyproject.toml +37 -0
  34. agent_json_reliability-0.1.0/serve.py +29 -0
  35. agent_json_reliability-0.1.0/setup.cfg +4 -0
  36. agent_json_reliability-0.1.0/tests/test_public_semantics.py +29 -0
@@ -0,0 +1,5 @@
1
+ MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-json-reliability
3
+ Version: 0.1.0
4
+ Summary: Deterministic JSON repair and JSON Schema validation for AI agents and software. No LLM required.
5
+ Author: Agent JSON Reliability contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/toninovo4249-ai/agent-json-reliability
8
+ Keywords: json,json-schema,json-repair,ai-agents,mcp,structured-output
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: fastapi>=0.115.0
17
+ Requires-Dist: uvicorn>=0.30.0
18
+ Requires-Dist: jsonschema>=4.23.0
19
+ Dynamic: license-file
20
+
21
+ # Agent JSON Reliability
22
+
23
+ STATUS=BETA version `0.1.0`
24
+
25
+ AI agents and software frequently emit malformed JSON: markdown fences, trailing commas, single quotes, `True`/`False`/`None`, and extra prose around one object.
26
+
27
+ **Agent JSON Reliability** is a deterministic pipeline for that failure mode:
28
+
29
+ 1. **inspect** — diagnose whether the text is JSON and which failures are present
30
+ 2. **safe repair** — apply only structural, unambiguous fixes
31
+ 3. **validate** — optional JSON Schema check on the result
32
+ 4. **structured diagnostics** — `valid_original`, `repaired`, `valid_final`, `schema_valid`, `unsafe_or_ambiguous`, `changes`, `errors`
33
+
34
+ This is not a generic jsonschema wrapper. The primary value is turning **malformed agent output** into reliable structured data **without an LLM** and **without inventing semantic values**.
35
+
36
+ When repair would require guessing (truncated objects, missing values, competing JSON documents), the service **refuses**. That is correct behavior.
37
+
38
+ Primary HTTP endpoint: `POST /v1/json/reliable`
39
+
40
+ MCP tools (same core functions, no duplicate implementation): `json_reliable` / `reliable_json`, `validate_json`, `repair_json`, `inspect_json`
41
+
42
+ <!-- mcp-name: io.github.toninovo4249-ai/agent-json-reliability -->
43
+
44
+ ## Before / after (safe repair)
45
+
46
+ Malformed agent output:
47
+
48
+ ```json
49
+ {
50
+ "text": "```json\n{\"name\":\"alice\",\"age\":30,}\n```"
51
+ }
52
+ ```
53
+
54
+ Expected result (semantically equivalent valid JSON):
55
+
56
+ - `valid_original=false`
57
+ - `repaired=true`
58
+ - `valid_final=true`
59
+ - `unsafe_or_ambiguous=false`
60
+ - `json` → `{"name":"alice","age":30}`
61
+
62
+ If a schema is supplied and satisfied: `schema_valid=true`.
63
+
64
+ ## Safe refusal (ambiguous)
65
+
66
+ Truncated input such as `{"user":` is JSON-intended but not deterministically repairable without inventing keys or values.
67
+
68
+ Expected:
69
+
70
+ - HTTP `200` (documented safe response)
71
+ - `valid_final=false`
72
+ - `unsafe_or_ambiguous=true` **or** `repaired=false`
73
+
74
+ Do not treat a correct refusal as a product failure.
75
+
76
+ ## Run locally (no Hunter)
77
+
78
+ ```bash
79
+ python -m pip install -r requirements.txt
80
+ python serve.py
81
+ ```
82
+
83
+ Binds `127.0.0.1:8770` by default. Set `PUBLIC_BASE_URL` to an HTTPS origin only when you expose the process yourself. Do not commit a temporary tunnel hostname as the canonical URL.
84
+
85
+ ## HTTP examples
86
+
87
+ See `examples/curl.md`, `examples/python.py`, `examples/javascript.js`.
88
+
89
+ Remote examples use `${PUBLIC_BASE_URL}`. Local default is `http://127.0.0.1:8770`.
90
+
91
+ Share URLs (optional, unverified telemetry tags):
92
+
93
+ - `/?source=github`
94
+ - `/?source=mcp-registry`
95
+ - `/?source=api-directory`
96
+
97
+ ## MCP (stdio — durable)
98
+
99
+ Package transport does not depend on a temporary public URL.
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "agent-json-reliability": {
105
+ "command": "python",
106
+ "args": ["-m", "products.gateway.mcp_stdio"]
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ After you publish to PyPI (free): `uvx agent-json-reliability`.
113
+
114
+ Remote HTTP MCP (`POST /mcp`) is for a running instance. Prefer stdio/package for Official MCP Registry metadata.
115
+
116
+ ## Machine discovery
117
+
118
+ - `GET /.well-known/agent-services.json`
119
+ - `GET /openapi.json`
120
+ - `GET /llms.txt`
121
+ - `GET /AGENTS.md`
122
+ - `POST /mcp` JSON-RPC (`tools/list`, `tools/call`)
123
+
124
+ ## What this package does not include
125
+
126
+ No Hunter market database, no private reports, no Windows user paths, no collectors, no wallets, no x402 payment.
127
+
128
+ Free beta: no auth, no payment.
@@ -0,0 +1,108 @@
1
+ # Agent JSON Reliability
2
+
3
+ STATUS=BETA version `0.1.0`
4
+
5
+ AI agents and software frequently emit malformed JSON: markdown fences, trailing commas, single quotes, `True`/`False`/`None`, and extra prose around one object.
6
+
7
+ **Agent JSON Reliability** is a deterministic pipeline for that failure mode:
8
+
9
+ 1. **inspect** — diagnose whether the text is JSON and which failures are present
10
+ 2. **safe repair** — apply only structural, unambiguous fixes
11
+ 3. **validate** — optional JSON Schema check on the result
12
+ 4. **structured diagnostics** — `valid_original`, `repaired`, `valid_final`, `schema_valid`, `unsafe_or_ambiguous`, `changes`, `errors`
13
+
14
+ This is not a generic jsonschema wrapper. The primary value is turning **malformed agent output** into reliable structured data **without an LLM** and **without inventing semantic values**.
15
+
16
+ When repair would require guessing (truncated objects, missing values, competing JSON documents), the service **refuses**. That is correct behavior.
17
+
18
+ Primary HTTP endpoint: `POST /v1/json/reliable`
19
+
20
+ MCP tools (same core functions, no duplicate implementation): `json_reliable` / `reliable_json`, `validate_json`, `repair_json`, `inspect_json`
21
+
22
+ <!-- mcp-name: io.github.toninovo4249-ai/agent-json-reliability -->
23
+
24
+ ## Before / after (safe repair)
25
+
26
+ Malformed agent output:
27
+
28
+ ```json
29
+ {
30
+ "text": "```json\n{\"name\":\"alice\",\"age\":30,}\n```"
31
+ }
32
+ ```
33
+
34
+ Expected result (semantically equivalent valid JSON):
35
+
36
+ - `valid_original=false`
37
+ - `repaired=true`
38
+ - `valid_final=true`
39
+ - `unsafe_or_ambiguous=false`
40
+ - `json` → `{"name":"alice","age":30}`
41
+
42
+ If a schema is supplied and satisfied: `schema_valid=true`.
43
+
44
+ ## Safe refusal (ambiguous)
45
+
46
+ Truncated input such as `{"user":` is JSON-intended but not deterministically repairable without inventing keys or values.
47
+
48
+ Expected:
49
+
50
+ - HTTP `200` (documented safe response)
51
+ - `valid_final=false`
52
+ - `unsafe_or_ambiguous=true` **or** `repaired=false`
53
+
54
+ Do not treat a correct refusal as a product failure.
55
+
56
+ ## Run locally (no Hunter)
57
+
58
+ ```bash
59
+ python -m pip install -r requirements.txt
60
+ python serve.py
61
+ ```
62
+
63
+ Binds `127.0.0.1:8770` by default. Set `PUBLIC_BASE_URL` to an HTTPS origin only when you expose the process yourself. Do not commit a temporary tunnel hostname as the canonical URL.
64
+
65
+ ## HTTP examples
66
+
67
+ See `examples/curl.md`, `examples/python.py`, `examples/javascript.js`.
68
+
69
+ Remote examples use `${PUBLIC_BASE_URL}`. Local default is `http://127.0.0.1:8770`.
70
+
71
+ Share URLs (optional, unverified telemetry tags):
72
+
73
+ - `/?source=github`
74
+ - `/?source=mcp-registry`
75
+ - `/?source=api-directory`
76
+
77
+ ## MCP (stdio — durable)
78
+
79
+ Package transport does not depend on a temporary public URL.
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "agent-json-reliability": {
85
+ "command": "python",
86
+ "args": ["-m", "products.gateway.mcp_stdio"]
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ After you publish to PyPI (free): `uvx agent-json-reliability`.
93
+
94
+ Remote HTTP MCP (`POST /mcp`) is for a running instance. Prefer stdio/package for Official MCP Registry metadata.
95
+
96
+ ## Machine discovery
97
+
98
+ - `GET /.well-known/agent-services.json`
99
+ - `GET /openapi.json`
100
+ - `GET /llms.txt`
101
+ - `GET /AGENTS.md`
102
+ - `POST /mcp` JSON-RPC (`tools/list`, `tools/call`)
103
+
104
+ ## What this package does not include
105
+
106
+ No Hunter market database, no private reports, no Windows user paths, no collectors, no wallets, no x402 payment.
107
+
108
+ Free beta: no auth, no payment.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-json-reliability
3
+ Version: 0.1.0
4
+ Summary: Deterministic JSON repair and JSON Schema validation for AI agents and software. No LLM required.
5
+ Author: Agent JSON Reliability contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/toninovo4249-ai/agent-json-reliability
8
+ Keywords: json,json-schema,json-repair,ai-agents,mcp,structured-output
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: fastapi>=0.115.0
17
+ Requires-Dist: uvicorn>=0.30.0
18
+ Requires-Dist: jsonschema>=4.23.0
19
+ Dynamic: license-file
20
+
21
+ # Agent JSON Reliability
22
+
23
+ STATUS=BETA version `0.1.0`
24
+
25
+ AI agents and software frequently emit malformed JSON: markdown fences, trailing commas, single quotes, `True`/`False`/`None`, and extra prose around one object.
26
+
27
+ **Agent JSON Reliability** is a deterministic pipeline for that failure mode:
28
+
29
+ 1. **inspect** — diagnose whether the text is JSON and which failures are present
30
+ 2. **safe repair** — apply only structural, unambiguous fixes
31
+ 3. **validate** — optional JSON Schema check on the result
32
+ 4. **structured diagnostics** — `valid_original`, `repaired`, `valid_final`, `schema_valid`, `unsafe_or_ambiguous`, `changes`, `errors`
33
+
34
+ This is not a generic jsonschema wrapper. The primary value is turning **malformed agent output** into reliable structured data **without an LLM** and **without inventing semantic values**.
35
+
36
+ When repair would require guessing (truncated objects, missing values, competing JSON documents), the service **refuses**. That is correct behavior.
37
+
38
+ Primary HTTP endpoint: `POST /v1/json/reliable`
39
+
40
+ MCP tools (same core functions, no duplicate implementation): `json_reliable` / `reliable_json`, `validate_json`, `repair_json`, `inspect_json`
41
+
42
+ <!-- mcp-name: io.github.toninovo4249-ai/agent-json-reliability -->
43
+
44
+ ## Before / after (safe repair)
45
+
46
+ Malformed agent output:
47
+
48
+ ```json
49
+ {
50
+ "text": "```json\n{\"name\":\"alice\",\"age\":30,}\n```"
51
+ }
52
+ ```
53
+
54
+ Expected result (semantically equivalent valid JSON):
55
+
56
+ - `valid_original=false`
57
+ - `repaired=true`
58
+ - `valid_final=true`
59
+ - `unsafe_or_ambiguous=false`
60
+ - `json` → `{"name":"alice","age":30}`
61
+
62
+ If a schema is supplied and satisfied: `schema_valid=true`.
63
+
64
+ ## Safe refusal (ambiguous)
65
+
66
+ Truncated input such as `{"user":` is JSON-intended but not deterministically repairable without inventing keys or values.
67
+
68
+ Expected:
69
+
70
+ - HTTP `200` (documented safe response)
71
+ - `valid_final=false`
72
+ - `unsafe_or_ambiguous=true` **or** `repaired=false`
73
+
74
+ Do not treat a correct refusal as a product failure.
75
+
76
+ ## Run locally (no Hunter)
77
+
78
+ ```bash
79
+ python -m pip install -r requirements.txt
80
+ python serve.py
81
+ ```
82
+
83
+ Binds `127.0.0.1:8770` by default. Set `PUBLIC_BASE_URL` to an HTTPS origin only when you expose the process yourself. Do not commit a temporary tunnel hostname as the canonical URL.
84
+
85
+ ## HTTP examples
86
+
87
+ See `examples/curl.md`, `examples/python.py`, `examples/javascript.js`.
88
+
89
+ Remote examples use `${PUBLIC_BASE_URL}`. Local default is `http://127.0.0.1:8770`.
90
+
91
+ Share URLs (optional, unverified telemetry tags):
92
+
93
+ - `/?source=github`
94
+ - `/?source=mcp-registry`
95
+ - `/?source=api-directory`
96
+
97
+ ## MCP (stdio — durable)
98
+
99
+ Package transport does not depend on a temporary public URL.
100
+
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "agent-json-reliability": {
105
+ "command": "python",
106
+ "args": ["-m", "products.gateway.mcp_stdio"]
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ After you publish to PyPI (free): `uvx agent-json-reliability`.
113
+
114
+ Remote HTTP MCP (`POST /mcp`) is for a running instance. Prefer stdio/package for Official MCP Registry metadata.
115
+
116
+ ## Machine discovery
117
+
118
+ - `GET /.well-known/agent-services.json`
119
+ - `GET /openapi.json`
120
+ - `GET /llms.txt`
121
+ - `GET /AGENTS.md`
122
+ - `POST /mcp` JSON-RPC (`tools/list`, `tools/call`)
123
+
124
+ ## What this package does not include
125
+
126
+ No Hunter market database, no private reports, no Windows user paths, no collectors, no wallets, no x402 payment.
127
+
128
+ Free beta: no auth, no payment.
@@ -0,0 +1,34 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ serve.py
5
+ agent_json_reliability.egg-info/PKG-INFO
6
+ agent_json_reliability.egg-info/SOURCES.txt
7
+ agent_json_reliability.egg-info/dependency_links.txt
8
+ agent_json_reliability.egg-info/entry_points.txt
9
+ agent_json_reliability.egg-info/requires.txt
10
+ agent_json_reliability.egg-info/top_level.txt
11
+ products/__init__.py
12
+ products/agent_json_reliability/__init__.py
13
+ products/agent_json_reliability/inspect.py
14
+ products/agent_json_reliability/reliable.py
15
+ products/agent_json_reliability/repair.py
16
+ products/agent_json_reliability/validate.py
17
+ products/beta/__init__.py
18
+ products/beta/app.py
19
+ products/beta/batch.py
20
+ products/beta/catalog.py
21
+ products/beta/identity.py
22
+ products/beta/landing.py
23
+ products/beta/security.py
24
+ products/beta/selfcheck.py
25
+ products/beta/settings.py
26
+ products/beta/store.py
27
+ products/common/__init__.py
28
+ products/common/timing.py
29
+ products/gateway/__init__.py
30
+ products/gateway/manifest.py
31
+ products/gateway/mcp_server.py
32
+ products/gateway/mcp_stdio.py
33
+ products/gateway/rate_limit.py
34
+ tests/test_public_semantics.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ agent-json-reliability = products.gateway.mcp_stdio:main
3
+ agent-json-reliability-serve = serve:main
@@ -0,0 +1,3 @@
1
+ fastapi>=0.115.0
2
+ uvicorn>=0.30.0
3
+ jsonschema>=4.23.0
@@ -0,0 +1 @@
1
+ """Local zero-cost product prototypes. Independent of collectors."""
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from products.agent_json_reliability.inspect import inspect_json
4
+ from products.agent_json_reliability.repair import repair_json
5
+ from products.agent_json_reliability.validate import validate_json
6
+
7
+ __all__ = ["validate_json", "repair_json", "inspect_json"]
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import re
5
+ from typing import Any
6
+
7
+ from products.agent_json_reliability.repair import repair_json
8
+ from products.common.timing import Clock
9
+
10
+ _FAILURES = [
11
+ ("markdown_fence", re.compile(r"```")),
12
+ ("trailing_comma", re.compile(r",\s*[}\]]")),
13
+ ("single_quotes", re.compile(r"'")),
14
+ ("python_literals", re.compile(r"\b(True|False|None)\b")),
15
+ ("comments", re.compile(r"//|/\*")),
16
+ ("leading_prose", None),
17
+ ("truncated", None),
18
+ ]
19
+
20
+
21
+ def inspect_json(text: str) -> dict[str, Any]:
22
+ with Clock() as sw:
23
+ if not isinstance(text, str):
24
+ text = str(text)
25
+ raw = text.strip()
26
+ valid = False
27
+ err_pos = None
28
+ try:
29
+ json.loads(raw)
30
+ valid = True
31
+ except json.JSONDecodeError as e:
32
+ err_pos = e.pos
33
+ types: list[str] = []
34
+ if re.search(r"```", raw):
35
+ types.append("markdown_fence")
36
+ if re.search(r",\s*[}\]]", raw):
37
+ types.append("trailing_comma")
38
+ if "'" in raw and '"' not in raw:
39
+ types.append("single_quotes")
40
+ if re.search(r"\b(True|False|None)\b", raw):
41
+ types.append("python_literals")
42
+ if "//" in raw or "/*" in raw:
43
+ types.append("comments")
44
+ stripped = raw.lstrip()
45
+ if stripped and stripped[0] not in "{[":
46
+ types.append("leading_prose")
47
+ if raw.count("{") > raw.count("}") or raw.count("[") > raw.count("]"):
48
+ types.append("truncated")
49
+ if re.search(r"\}\s*\{", raw):
50
+ types.append("multiple_objects")
51
+ likely = valid or bool(re.search(r"[\{\[]", raw))
52
+ rep = repair_json(raw)
53
+ complexity = min(100, raw.count("{") + raw.count("[") + raw.count(":") + len(raw) // 200)
54
+ return {
55
+ "valid_json": valid,
56
+ "likely_json": likely,
57
+ "error_position": err_pos,
58
+ "detected_failure_types": types,
59
+ "repair_possible": bool(rep.get("repaired") or valid),
60
+ "estimated_complexity": complexity,
61
+ "processing_ms": sw.ms,
62
+ }
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from products.agent_json_reliability.inspect import inspect_json
6
+ from products.agent_json_reliability.repair import repair_json
7
+ from products.agent_json_reliability.validate import validate_json
8
+ from products.common.timing import Clock
9
+
10
+
11
+ def reliable_json(text: str, schema: dict | None = None, mode: str = "safe") -> dict[str, Any]:
12
+ """inspect → safe repair if needed → optional schema validate. Same primitives as HTTP tools."""
13
+ with Clock() as sw:
14
+ insp = inspect_json(text)
15
+ valid_original = bool(insp.get("valid_json"))
16
+ changes: list[str] = []
17
+ repaired = False
18
+ payload: Any = None
19
+ unsafe = False
20
+ if valid_original:
21
+ import json
22
+
23
+ payload = json.loads(text.strip().lstrip("\ufeff"))
24
+ else:
25
+ rep = repair_json(text, mode)
26
+ repaired = bool(rep.get("repaired"))
27
+ payload = rep.get("json")
28
+ changes = list(rep.get("changes") or [])
29
+ unsafe = bool(rep.get("unsafe_or_ambiguous"))
30
+ valid_final = payload is not None
31
+ schema_valid = None
32
+ errors: list = []
33
+ if valid_final and schema is not None:
34
+ v = validate_json(payload, schema)
35
+ schema_valid = v.get("schema_valid")
36
+ errors = v.get("errors") or []
37
+ valid_final = bool(schema_valid)
38
+ elif not valid_final:
39
+ errors = [{"message": "unrepaired_or_invalid"}]
40
+ return {
41
+ "valid_original": valid_original,
42
+ "repaired": repaired,
43
+ "json": payload,
44
+ "valid_final": valid_final and payload is not None and (schema_valid is not False),
45
+ "schema_valid": schema_valid,
46
+ "unsafe_or_ambiguous": unsafe,
47
+ "changes": changes,
48
+ "errors": errors,
49
+ "inspect": insp,
50
+ "processing_ms": sw.ms,
51
+ "outcome_class": _outcome(valid_original, repaired, payload, schema_valid, errors),
52
+ }
53
+
54
+
55
+ def _outcome(valid_original, repaired, payload, schema_valid, errors) -> str:
56
+ if schema_valid is False:
57
+ return "SCHEMA_INVALID"
58
+ if schema_valid is True:
59
+ return "SCHEMA_VALID"
60
+ if valid_original:
61
+ return "ORIGINAL_VALID"
62
+ if repaired and payload is not None:
63
+ return "SAFE_REPAIR_SUCCESS"
64
+ if any((e.get("message") or "").startswith("schema") for e in errors or []):
65
+ return "INVALID_SCHEMA"
66
+ return "SAFE_REPAIR_REFUSED"