gcf-python 2.7.0__tar.gz → 2.7.1__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.
- {gcf_python-2.7.0 → gcf_python-2.7.1}/CHANGELOG.md +4 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/PKG-INFO +2 -2
- {gcf_python-2.7.0 → gcf_python-2.7.1}/README.md +1 -1
- {gcf_python-2.7.0 → gcf_python-2.7.1}/pyproject.toml +1 -1
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/__init__.py +1 -1
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/fastmcp.py +13 -2
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_fastmcp.py +16 -1
- {gcf_python-2.7.0 → gcf_python-2.7.1}/.github/FUNDING.yml +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/.github/workflows/ci.yml +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/.github/workflows/publish.yml +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/.gitignore +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/LICENSE +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/assets/divider-wave-2.png +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/assets/divider.png +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/assets/gcf-hero-wire-delta.png +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/assets/gcf-python-diagram.png +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/__main__.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/cli.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/constants.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/decode.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/decode_generic.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/delta.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/encode.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/generic.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/generic_delta.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/keyed_map.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/packroot.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/scalar.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/session.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/stream.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/stream_generic.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/src/gcf/types.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/__init__.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_conformance_v2.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_decode.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_delta.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_encode.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_generic.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_generic_delta.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_generic_delta_fuzz.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_generic_delta_session.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_keyed_map_fuzz.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_roundtrip.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_roundtrip_v2.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_session.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_stream.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_stream_fielddecl.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/tests/test_stream_generic.py +0 -0
- {gcf_python-2.7.0 → gcf_python-2.7.1}/uv.lock +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v2.7.1 (2026-08-16)
|
|
4
|
+
|
|
5
|
+
- gcf.fastmcp: the response middleware now uses GCF only when the wire is smaller than the JSON it replaces (never-grow), so a small tool result is never enlarged.
|
|
6
|
+
|
|
3
7
|
## v2.7.0 (2026-08-15)
|
|
4
8
|
|
|
5
9
|
- Decode: quoted-key/array-value round-trip (SPEC 4.2).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gcf-python
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.1
|
|
4
4
|
Summary: The AI-native wire format for structured data. 50-92% fewer tokens than JSON, with multi-turn delta encoding for agent loops. 100% comprehension on every frontier model. Zero dependencies.
|
|
5
5
|
Project-URL: Homepage, https://github.com/blackwell-systems/gcf-python
|
|
6
6
|
Project-URL: Documentation, https://gcformat.com/
|
|
@@ -322,7 +322,7 @@ GCF wins 15/16 datasets on the expanded [token efficiency benchmark](https://git
|
|
|
322
322
|
|
|
323
323
|
**Zero runtime dependencies. Permanently.** All six implementations depend only on their language's standard library. No transitive dependencies. No supply chain risk. This is a permanent commitment: GCF will never take on external runtime dependencies. MIT licensed. All implementations support both generic profile (`encodeGeneric`) and graph profile (`encode`). CLI included in all 6 languages.
|
|
324
324
|
|
|
325
|
-
**Specification:** [SPEC v3.5.3 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with
|
|
325
|
+
**Specification:** [SPEC v3.5.3 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with 281 conformance fixtures, 43,000,000,000+ lossless round-trips verified across 5 formats and 6 languages. Current versions: Go v1.7.1, TypeScript v2.6.1, Python v2.7.0, Rust v3.0.1, Swift v2.7.1, Kotlin v2.6.1, .NET v0.2.1. Cross-language conformance verified across all seven SDKs.
|
|
326
326
|
|
|
327
327
|
## Adopted by
|
|
328
328
|
|
|
@@ -295,7 +295,7 @@ GCF wins 15/16 datasets on the expanded [token efficiency benchmark](https://git
|
|
|
295
295
|
|
|
296
296
|
**Zero runtime dependencies. Permanently.** All six implementations depend only on their language's standard library. No transitive dependencies. No supply chain risk. This is a permanent commitment: GCF will never take on external runtime dependencies. MIT licensed. All implementations support both generic profile (`encodeGeneric`) and graph profile (`encode`). CLI included in all 6 languages.
|
|
297
297
|
|
|
298
|
-
**Specification:** [SPEC v3.5.3 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with
|
|
298
|
+
**Specification:** [SPEC v3.5.3 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with 281 conformance fixtures, 43,000,000,000+ lossless round-trips verified across 5 formats and 6 languages. Current versions: Go v1.7.1, TypeScript v2.6.1, Python v2.7.0, Rust v3.0.1, Swift v2.7.1, Kotlin v2.6.1, .NET v0.2.1. Cross-language conformance verified across all seven SDKs.
|
|
299
299
|
|
|
300
300
|
## Adopted by
|
|
301
301
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gcf-python"
|
|
7
|
-
version = "2.7.
|
|
7
|
+
version = "2.7.1"
|
|
8
8
|
description = "The AI-native wire format for structured data. 50-92% fewer tokens than JSON, with multi-turn delta encoding for agent loops. 100% comprehension on every frontier model. Zero dependencies."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -18,8 +18,11 @@ wire, so the response uses fewer tokens when it crosses the LLM boundary. It is:
|
|
|
18
18
|
|
|
19
19
|
- **Opt-in** — nothing changes unless ``RESPONSE_FORMAT=gcf`` is set (or
|
|
20
20
|
``enabled=True`` is passed).
|
|
21
|
-
- **
|
|
22
|
-
|
|
21
|
+
- **Never-grow** — GCF is used only when the wire is actually smaller than the
|
|
22
|
+
JSON it would replace; a small result is never enlarged.
|
|
23
|
+
- **Lossless and fail-safe** — the wire must decode back to the same value, and
|
|
24
|
+
on any encoding error the original result is returned, so a tool call is never
|
|
25
|
+
grown, dropped, or garbled over formatting.
|
|
23
26
|
- **Non-destructive** — only a lone JSON text block is re-encoded; a result
|
|
24
27
|
carrying an image or any second block is left untouched, and the tool's
|
|
25
28
|
``structuredContent`` (if any) is preserved so output-schema validation and
|
|
@@ -94,8 +97,16 @@ class GcfResponseMiddleware(Middleware):
|
|
|
94
97
|
if payload is None:
|
|
95
98
|
return result
|
|
96
99
|
|
|
100
|
+
# _json_payload guarantees exactly one text block, so this is the JSON text
|
|
101
|
+
# the client would otherwise receive.
|
|
102
|
+
original = result.content[0].text
|
|
103
|
+
|
|
97
104
|
try:
|
|
98
105
|
wire = encode_generic(payload)
|
|
106
|
+
# Never-grow: only replace the JSON when GCF is actually smaller, so a
|
|
107
|
+
# small result is never enlarged.
|
|
108
|
+
if len(wire) >= len(original):
|
|
109
|
+
return result
|
|
99
110
|
# Verify the wire decodes back to the same value before shipping it, so a
|
|
100
111
|
# result is never replaced with an unparseable or lossy encoding.
|
|
101
112
|
if decode_generic(wire) != payload:
|
|
@@ -120,6 +120,19 @@ def test_encode_error_falls_back_to_json():
|
|
|
120
120
|
assert _text(out) == text
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
def test_never_grow_keeps_json_when_gcf_larger():
|
|
124
|
+
# A tiny single-field object: GCF's header overhead exceeds the JSON, so the
|
|
125
|
+
# never-grow guard keeps the JSON rather than emit a larger wire.
|
|
126
|
+
data = {"ok": True}
|
|
127
|
+
text = json.dumps(data)
|
|
128
|
+
result = _result(TextContent(type="text", text=text), structured_content=data)
|
|
129
|
+
|
|
130
|
+
out = _run(GcfResponseMiddleware(enabled=True), result)
|
|
131
|
+
|
|
132
|
+
assert _text(out) == text
|
|
133
|
+
assert not _text(out).startswith("GCF ")
|
|
134
|
+
|
|
135
|
+
|
|
123
136
|
# --- fuzz: the safety invariant on arbitrary JSON ---
|
|
124
137
|
|
|
125
138
|
# Characters that stress GCF's delimiter/quoting rules and unicode handling.
|
|
@@ -176,6 +189,8 @@ def test_fuzz_middleware_never_grows_corrupts_or_crashes():
|
|
|
176
189
|
if got == text:
|
|
177
190
|
continue # declined -> original JSON kept (always safe)
|
|
178
191
|
|
|
179
|
-
# Otherwise it MUST be a GCF wire that
|
|
192
|
+
# Otherwise it MUST be a GCF wire that is smaller than the JSON (never-grow)
|
|
193
|
+
# and round-trips to the exact payload.
|
|
180
194
|
assert got.startswith("GCF profile=generic")
|
|
195
|
+
assert len(got) < len(text)
|
|
181
196
|
assert decode_generic(got) == payload
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|