agent-first-data 0.7.3__tar.gz → 0.8.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.
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/PKG-INFO +15 -5
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/README.md +13 -3
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data/__init__.py +4 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data/format.py +53 -13
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data.egg-info/PKG-INFO +15 -5
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/pyproject.toml +2 -2
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/tests/test_format.py +19 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data/afdata_logging.py +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data/cli.py +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data.egg-info/SOURCES.txt +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data.egg-info/dependency_links.txt +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data.egg-info/top_level.txt +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/setup.cfg +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/tests/test_afdata_logging.py +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/tests/test_cli.py +0 -0
- {agent_first_data-0.7.3 → agent_first_data-0.8.0}/tests/test_no_stderr_policy.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
6
|
+
Project-URL: Repository, https://github.com/agentfirstkit/agent-first-data
|
|
7
7
|
Requires-Python: >=3.9
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
|
|
@@ -74,7 +74,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
74
74
|
|
|
75
75
|
## API Reference
|
|
76
76
|
|
|
77
|
-
Total: **
|
|
77
|
+
Total: **15 public APIs and 2 types** + **AFDATA logging** (3 protocol builders + 2 redacted value helpers + 4 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat` + `RedactionPolicy`)
|
|
78
78
|
|
|
79
79
|
### Protocol Builders (returns dict)
|
|
80
80
|
|
|
@@ -91,6 +91,15 @@ build_json_error(message: str, hint: str = None, trace: Any = None) -> dict
|
|
|
91
91
|
build_json(code: str, fields: Any, trace: Any = None) -> dict
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
### Redacted Values (returns Any)
|
|
95
|
+
|
|
96
|
+
Use these before raw HTTP/MCP/SSE serializers that do not call `output_json`.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
redacted_value(value: Any) -> Any
|
|
100
|
+
redacted_value_with(value: Any, redaction_policy: RedactionPolicy) -> Any
|
|
101
|
+
```
|
|
102
|
+
|
|
94
103
|
**Use case:** structured protocol payloads (frameworks automatically serialize)
|
|
95
104
|
|
|
96
105
|
**Example:**
|
|
@@ -144,6 +153,7 @@ output_plain(value: Any) -> str # Single-line logfmt, keys stripped, values for
|
|
|
144
153
|
class RedactionPolicy(enum.Enum):
|
|
145
154
|
RedactionTraceOnly = "RedactionTraceOnly"
|
|
146
155
|
RedactionNone = "RedactionNone"
|
|
156
|
+
RedactionStrict = "RedactionStrict"
|
|
147
157
|
```
|
|
148
158
|
|
|
149
159
|
**Example:**
|
|
@@ -513,7 +523,7 @@ All formats automatically redact `_secret` fields.
|
|
|
513
523
|
|
|
514
524
|
## Repository
|
|
515
525
|
|
|
516
|
-
This package is part of the [agent-first-data](https://github.com/
|
|
526
|
+
This package is part of the [agent-first-data](https://github.com/agentfirstkit/agent-first-data) repository, which also contains:
|
|
517
527
|
|
|
518
528
|
- **`spec/`** — Full AFDATA specification with suffix definitions, protocol format rules, and cross-language test fixtures
|
|
519
529
|
- **`skills/`** — AI coding agent skill for working with AFDATA conventions
|
|
@@ -521,7 +531,7 @@ This package is part of the [agent-first-data](https://github.com/cmnspore/agent
|
|
|
521
531
|
To run tests, clone the full repository (tests use shared cross-language fixtures from `spec/fixtures/`):
|
|
522
532
|
|
|
523
533
|
```bash
|
|
524
|
-
git clone https://github.com/
|
|
534
|
+
git clone https://github.com/agentfirstkit/agent-first-data
|
|
525
535
|
cd agent-first-data/python
|
|
526
536
|
python -m pytest
|
|
527
537
|
```
|
|
@@ -65,7 +65,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
65
65
|
|
|
66
66
|
## API Reference
|
|
67
67
|
|
|
68
|
-
Total: **
|
|
68
|
+
Total: **15 public APIs and 2 types** + **AFDATA logging** (3 protocol builders + 2 redacted value helpers + 4 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat` + `RedactionPolicy`)
|
|
69
69
|
|
|
70
70
|
### Protocol Builders (returns dict)
|
|
71
71
|
|
|
@@ -82,6 +82,15 @@ build_json_error(message: str, hint: str = None, trace: Any = None) -> dict
|
|
|
82
82
|
build_json(code: str, fields: Any, trace: Any = None) -> dict
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
### Redacted Values (returns Any)
|
|
86
|
+
|
|
87
|
+
Use these before raw HTTP/MCP/SSE serializers that do not call `output_json`.
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
redacted_value(value: Any) -> Any
|
|
91
|
+
redacted_value_with(value: Any, redaction_policy: RedactionPolicy) -> Any
|
|
92
|
+
```
|
|
93
|
+
|
|
85
94
|
**Use case:** structured protocol payloads (frameworks automatically serialize)
|
|
86
95
|
|
|
87
96
|
**Example:**
|
|
@@ -135,6 +144,7 @@ output_plain(value: Any) -> str # Single-line logfmt, keys stripped, values for
|
|
|
135
144
|
class RedactionPolicy(enum.Enum):
|
|
136
145
|
RedactionTraceOnly = "RedactionTraceOnly"
|
|
137
146
|
RedactionNone = "RedactionNone"
|
|
147
|
+
RedactionStrict = "RedactionStrict"
|
|
138
148
|
```
|
|
139
149
|
|
|
140
150
|
**Example:**
|
|
@@ -504,7 +514,7 @@ All formats automatically redact `_secret` fields.
|
|
|
504
514
|
|
|
505
515
|
## Repository
|
|
506
516
|
|
|
507
|
-
This package is part of the [agent-first-data](https://github.com/
|
|
517
|
+
This package is part of the [agent-first-data](https://github.com/agentfirstkit/agent-first-data) repository, which also contains:
|
|
508
518
|
|
|
509
519
|
- **`spec/`** — Full AFDATA specification with suffix definitions, protocol format rules, and cross-language test fixtures
|
|
510
520
|
- **`skills/`** — AI coding agent skill for working with AFDATA conventions
|
|
@@ -512,7 +522,7 @@ This package is part of the [agent-first-data](https://github.com/cmnspore/agent
|
|
|
512
522
|
To run tests, clone the full repository (tests use shared cross-language fixtures from `spec/fixtures/`):
|
|
513
523
|
|
|
514
524
|
```bash
|
|
515
|
-
git clone https://github.com/
|
|
525
|
+
git clone https://github.com/agentfirstkit/agent-first-data
|
|
516
526
|
cd agent-first-data/python
|
|
517
527
|
python -m pytest
|
|
518
528
|
```
|
|
@@ -10,6 +10,8 @@ from agent_first_data.format import (
|
|
|
10
10
|
output_yaml,
|
|
11
11
|
output_plain,
|
|
12
12
|
internal_redact_secrets,
|
|
13
|
+
redacted_value,
|
|
14
|
+
redacted_value_with,
|
|
13
15
|
parse_size,
|
|
14
16
|
)
|
|
15
17
|
|
|
@@ -41,6 +43,8 @@ __all__ = [
|
|
|
41
43
|
"output_yaml",
|
|
42
44
|
"output_plain",
|
|
43
45
|
"internal_redact_secrets",
|
|
46
|
+
"redacted_value",
|
|
47
|
+
"redacted_value_with",
|
|
44
48
|
"parse_size",
|
|
45
49
|
"AfdataHandler",
|
|
46
50
|
"AfdataJsonHandler",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""AFDATA output formatting and protocol templates.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
11 public APIs and 1 type: protocol builders, redacted value helpers,
|
|
4
|
+
output formatters, redaction, parse_size, and RedactionPolicy.
|
|
4
5
|
"""
|
|
5
6
|
|
|
6
7
|
from __future__ import annotations
|
|
@@ -51,25 +52,22 @@ def build_json(code: str, fields: Any, trace: Any = None) -> dict:
|
|
|
51
52
|
class RedactionPolicy(str, Enum):
|
|
52
53
|
RedactionTraceOnly = "RedactionTraceOnly"
|
|
53
54
|
RedactionNone = "RedactionNone"
|
|
55
|
+
RedactionStrict = "RedactionStrict"
|
|
54
56
|
|
|
55
57
|
|
|
56
58
|
def output_json(value: Any) -> str:
|
|
57
59
|
"""Format as single-line JSON. Secrets redacted, original keys, raw values."""
|
|
58
|
-
|
|
59
|
-
_redact_secrets(v)
|
|
60
|
-
return json.dumps(v, ensure_ascii=False, separators=(",", ":"))
|
|
60
|
+
return json.dumps(redacted_value(value), ensure_ascii=False, separators=(",", ":"))
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def output_json_with(value: Any, redaction_policy: RedactionPolicy) -> str:
|
|
64
64
|
"""Format as single-line JSON with explicit redaction policy."""
|
|
65
|
-
|
|
66
|
-
_apply_redaction_policy(v, redaction_policy)
|
|
67
|
-
return json.dumps(v, ensure_ascii=False, separators=(",", ":"))
|
|
65
|
+
return json.dumps(redacted_value_with(value, redaction_policy), ensure_ascii=False, separators=(",", ":"))
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
def output_yaml(value: Any) -> str:
|
|
71
69
|
"""Format as multi-line YAML. Keys stripped, values formatted, secrets redacted."""
|
|
72
|
-
value =
|
|
70
|
+
value = redacted_value(value)
|
|
73
71
|
lines = ["---"]
|
|
74
72
|
_render_yaml_processed(value, 0, lines)
|
|
75
73
|
return "\n".join(lines)
|
|
@@ -77,16 +75,13 @@ def output_yaml(value: Any) -> str:
|
|
|
77
75
|
|
|
78
76
|
def output_plain(value: Any) -> str:
|
|
79
77
|
"""Format as single-line logfmt. Keys stripped, values formatted, secrets redacted."""
|
|
80
|
-
value =
|
|
78
|
+
value = redacted_value(value)
|
|
81
79
|
pairs: list[tuple[str, str]] = []
|
|
82
80
|
_collect_plain_pairs(value, "", pairs)
|
|
83
81
|
pairs.sort(key=lambda p: p[0].encode("utf-16-be"))
|
|
84
82
|
parts = []
|
|
85
83
|
for k, v in pairs:
|
|
86
|
-
|
|
87
|
-
parts.append(f'{k}="{v}"')
|
|
88
|
-
else:
|
|
89
|
-
parts.append(f"{k}={v}")
|
|
84
|
+
parts.append(f"{k}={_quote_logfmt_value(v)}")
|
|
90
85
|
return " ".join(parts)
|
|
91
86
|
|
|
92
87
|
|
|
@@ -100,6 +95,20 @@ def internal_redact_secrets(value: Any) -> None:
|
|
|
100
95
|
_redact_secrets(value)
|
|
101
96
|
|
|
102
97
|
|
|
98
|
+
def redacted_value(value: Any) -> Any:
|
|
99
|
+
"""Return a JSON-safe copy with default _secret redaction applied."""
|
|
100
|
+
v = _sanitize_for_json(value)
|
|
101
|
+
_redact_secrets(v)
|
|
102
|
+
return v
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def redacted_value_with(value: Any, redaction_policy: RedactionPolicy) -> Any:
|
|
106
|
+
"""Return a JSON-safe copy with an explicit redaction policy applied."""
|
|
107
|
+
v = _sanitize_for_json(value)
|
|
108
|
+
_apply_redaction_policy(v, redaction_policy)
|
|
109
|
+
return v
|
|
110
|
+
|
|
111
|
+
|
|
103
112
|
def _apply_redaction_policy(value: Any, redaction_policy: RedactionPolicy) -> None:
|
|
104
113
|
if redaction_policy == RedactionPolicy.RedactionTraceOnly:
|
|
105
114
|
if isinstance(value, dict) and "trace" in value:
|
|
@@ -107,6 +116,9 @@ def _apply_redaction_policy(value: Any, redaction_policy: RedactionPolicy) -> No
|
|
|
107
116
|
return
|
|
108
117
|
if redaction_policy == RedactionPolicy.RedactionNone:
|
|
109
118
|
return
|
|
119
|
+
if redaction_policy == RedactionPolicy.RedactionStrict:
|
|
120
|
+
_redact_secrets_strict(value)
|
|
121
|
+
return
|
|
110
122
|
# Safety fallback for unknown values.
|
|
111
123
|
_redact_secrets(value)
|
|
112
124
|
|
|
@@ -211,6 +223,18 @@ def _redact_secrets(value: Any) -> None:
|
|
|
211
223
|
_redact_secrets(item)
|
|
212
224
|
|
|
213
225
|
|
|
226
|
+
def _redact_secrets_strict(value: Any) -> None:
|
|
227
|
+
if isinstance(value, dict):
|
|
228
|
+
for k in list(value.keys()):
|
|
229
|
+
if k.endswith("_secret") or k.endswith("_SECRET"):
|
|
230
|
+
value[k] = "***"
|
|
231
|
+
else:
|
|
232
|
+
_redact_secrets_strict(value[k])
|
|
233
|
+
elif isinstance(value, list):
|
|
234
|
+
for item in value:
|
|
235
|
+
_redact_secrets_strict(item)
|
|
236
|
+
|
|
237
|
+
|
|
214
238
|
# ═══════════════════════════════════════════
|
|
215
239
|
# Suffix Processing
|
|
216
240
|
# ═══════════════════════════════════════════
|
|
@@ -572,3 +596,19 @@ def _plain_scalar(value: Any) -> str:
|
|
|
572
596
|
if isinstance(value, (int, float)):
|
|
573
597
|
return str(value)
|
|
574
598
|
return str(value)
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def _quote_logfmt_value(value: str) -> str:
|
|
602
|
+
if value == "":
|
|
603
|
+
return ""
|
|
604
|
+
needs_quote = any(c.isspace() or c in '="\\"' for c in value)
|
|
605
|
+
if not needs_quote:
|
|
606
|
+
return value
|
|
607
|
+
escaped = (
|
|
608
|
+
value.replace("\\", "\\\\")
|
|
609
|
+
.replace('"', '\\"')
|
|
610
|
+
.replace("\n", "\\n")
|
|
611
|
+
.replace("\r", "\\r")
|
|
612
|
+
.replace("\t", "\\t")
|
|
613
|
+
)
|
|
614
|
+
return f'"{escaped}"'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-first-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents
|
|
5
5
|
License-Expression: MIT
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
6
|
+
Project-URL: Repository, https://github.com/agentfirstkit/agent-first-data
|
|
7
7
|
Requires-Python: >=3.9
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
|
|
@@ -74,7 +74,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
|
|
|
74
74
|
|
|
75
75
|
## API Reference
|
|
76
76
|
|
|
77
|
-
Total: **
|
|
77
|
+
Total: **15 public APIs and 2 types** + **AFDATA logging** (3 protocol builders + 2 redacted value helpers + 4 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat` + `RedactionPolicy`)
|
|
78
78
|
|
|
79
79
|
### Protocol Builders (returns dict)
|
|
80
80
|
|
|
@@ -91,6 +91,15 @@ build_json_error(message: str, hint: str = None, trace: Any = None) -> dict
|
|
|
91
91
|
build_json(code: str, fields: Any, trace: Any = None) -> dict
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
### Redacted Values (returns Any)
|
|
95
|
+
|
|
96
|
+
Use these before raw HTTP/MCP/SSE serializers that do not call `output_json`.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
redacted_value(value: Any) -> Any
|
|
100
|
+
redacted_value_with(value: Any, redaction_policy: RedactionPolicy) -> Any
|
|
101
|
+
```
|
|
102
|
+
|
|
94
103
|
**Use case:** structured protocol payloads (frameworks automatically serialize)
|
|
95
104
|
|
|
96
105
|
**Example:**
|
|
@@ -144,6 +153,7 @@ output_plain(value: Any) -> str # Single-line logfmt, keys stripped, values for
|
|
|
144
153
|
class RedactionPolicy(enum.Enum):
|
|
145
154
|
RedactionTraceOnly = "RedactionTraceOnly"
|
|
146
155
|
RedactionNone = "RedactionNone"
|
|
156
|
+
RedactionStrict = "RedactionStrict"
|
|
147
157
|
```
|
|
148
158
|
|
|
149
159
|
**Example:**
|
|
@@ -513,7 +523,7 @@ All formats automatically redact `_secret` fields.
|
|
|
513
523
|
|
|
514
524
|
## Repository
|
|
515
525
|
|
|
516
|
-
This package is part of the [agent-first-data](https://github.com/
|
|
526
|
+
This package is part of the [agent-first-data](https://github.com/agentfirstkit/agent-first-data) repository, which also contains:
|
|
517
527
|
|
|
518
528
|
- **`spec/`** — Full AFDATA specification with suffix definitions, protocol format rules, and cross-language test fixtures
|
|
519
529
|
- **`skills/`** — AI coding agent skill for working with AFDATA conventions
|
|
@@ -521,7 +531,7 @@ This package is part of the [agent-first-data](https://github.com/cmnspore/agent
|
|
|
521
531
|
To run tests, clone the full repository (tests use shared cross-language fixtures from `spec/fixtures/`):
|
|
522
532
|
|
|
523
533
|
```bash
|
|
524
|
-
git clone https://github.com/
|
|
534
|
+
git clone https://github.com/agentfirstkit/agent-first-data
|
|
525
535
|
cd agent-first-data/python
|
|
526
536
|
python -m pytest
|
|
527
537
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agent-first-data"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.8.0"
|
|
4
4
|
description = "Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
readme = "README.md"
|
|
@@ -8,7 +8,7 @@ requires-python = ">=3.9"
|
|
|
8
8
|
dependencies = []
|
|
9
9
|
|
|
10
10
|
[project.urls]
|
|
11
|
-
Repository = "https://github.com/
|
|
11
|
+
Repository = "https://github.com/agentfirstkit/agent-first-data"
|
|
12
12
|
|
|
13
13
|
[build-system]
|
|
14
14
|
requires = ["setuptools>=68"]
|
|
@@ -9,6 +9,8 @@ from agent_first_data import (
|
|
|
9
9
|
build_json,
|
|
10
10
|
RedactionPolicy,
|
|
11
11
|
internal_redact_secrets,
|
|
12
|
+
redacted_value,
|
|
13
|
+
redacted_value_with,
|
|
12
14
|
output_json,
|
|
13
15
|
output_json_with,
|
|
14
16
|
output_yaml,
|
|
@@ -156,3 +158,20 @@ def test_output_json_with_none_keeps_secrets():
|
|
|
156
158
|
)
|
|
157
159
|
parsed = json.loads(out)
|
|
158
160
|
assert parsed["api_key_secret"] == "sk-live-123"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_redacted_value_returns_safe_copy():
|
|
164
|
+
inp = {"api_key_secret": "sk-live-123", "nested": {"token_secret": "tok"}}
|
|
165
|
+
got = redacted_value(inp)
|
|
166
|
+
assert got["api_key_secret"] == "***"
|
|
167
|
+
assert got["nested"]["token_secret"] == "***"
|
|
168
|
+
assert inp["api_key_secret"] == "sk-live-123"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_redacted_value_with_strict_redacts_secret_subtree():
|
|
172
|
+
inp = {"db_secret": {"password_secret": "real", "host": "localhost"}}
|
|
173
|
+
default = redacted_value(inp)
|
|
174
|
+
strict = redacted_value_with(inp, RedactionPolicy.RedactionStrict)
|
|
175
|
+
assert default["db_secret"]["password_secret"] == "***"
|
|
176
|
+
assert default["db_secret"]["host"] == "localhost"
|
|
177
|
+
assert strict["db_secret"] == "***"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_first_data-0.7.3 → agent_first_data-0.8.0}/agent_first_data.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|