agent-first-data 0.12.2__tar.gz → 0.13.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.
- agent_first_data-0.13.1/PKG-INFO +56 -0
- agent_first_data-0.13.1/README.md +47 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data/__init__.py +12 -4
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data/afdata_logging.py +64 -24
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data/cli.py +85 -15
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data/format.py +196 -85
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data/skill.py +157 -40
- agent_first_data-0.13.1/agent_first_data.egg-info/PKG-INFO +56 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/pyproject.toml +1 -1
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/tests/test_afdata_logging.py +82 -7
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/tests/test_cli.py +54 -3
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/tests/test_format.py +10 -9
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/tests/test_skill.py +110 -5
- agent_first_data-0.12.2/PKG-INFO +0 -591
- agent_first_data-0.12.2/README.md +0 -582
- agent_first_data-0.12.2/agent_first_data.egg-info/PKG-INFO +0 -591
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data.egg-info/SOURCES.txt +0 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data.egg-info/dependency_links.txt +0 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/agent_first_data.egg-info/top_level.txt +0 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/setup.cfg +0 -0
- {agent_first_data-0.12.2 → agent_first_data-0.13.1}/tests/test_no_stderr_policy.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-first-data
|
|
3
|
+
Version: 0.13.1
|
|
4
|
+
Summary: A naming convention that lets AI agents understand your data without being told what it means.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Repository, https://github.com/agentfirstkit/agent-first-data
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# Agent-First Data for Python
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install agent-first-data
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from agent_first_data import output_json, output_plain
|
|
18
|
+
|
|
19
|
+
value = {
|
|
20
|
+
"code": "ok",
|
|
21
|
+
"result": {
|
|
22
|
+
"api_key_secret": "sk-123",
|
|
23
|
+
"latency_ms": 1280,
|
|
24
|
+
"db_url": "postgres://user:p@ss@db/app?token_secret=abc",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
print(output_json(value))
|
|
29
|
+
print(output_plain(value))
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Useful names use Python casing: `output_json`, `output_yaml`, `output_plain`, `output_json_with_options`, `redacted_value`, `redact_secrets_in_place`, `redact_url_secrets`, `parse_size`, `normalize_utc_offset`, `cli_parse_output`, `cli_output`, `build_cli_error`, `build_cli_version`, and `cli_handle_version_or_continue`.
|
|
33
|
+
|
|
34
|
+
Logging is available through `init_logging_json`, `init_logging_plain`, `init_logging_yaml`, `span`, and `get_logger`.
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from agent_first_data import init_logging_json
|
|
38
|
+
|
|
39
|
+
init_logging_json("INFO", secret_names=("authorization",))
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Behavior Notes
|
|
43
|
+
|
|
44
|
+
- Default redaction replaces every `_secret` or configured secret-name subtree with `***`, including objects and arrays.
|
|
45
|
+
- `_url` fields scrub userinfo passwords and secret-named query parameters; surrounding whitespace is trimmed and internal whitespace redacts the whole field.
|
|
46
|
+
- YAML/plain quote and escape keys as well as values, sort by UTF-16 code unit order, and render nested objects in arrays as canonical JSON.
|
|
47
|
+
- Logging records use `code: "log"` plus a separate `level` field, so error-level logs are not terminal protocol errors.
|
|
48
|
+
- `build_cli_error(message, hint?)` returns `{code:"error", error: message, hint?}` only.
|
|
49
|
+
- Use `cli_handle_version_or_continue()` before argument parsing so bare `--version` stays conventional and `--version --output json|yaml|plain` stays structured.
|
|
50
|
+
|
|
51
|
+
## Reference
|
|
52
|
+
|
|
53
|
+
- Full convention and API groups: [../docs/overview.md](../docs/overview.md)
|
|
54
|
+
- Formal cross-language contract: [../spec/agent-first-data.md](../spec/agent-first-data.md)
|
|
55
|
+
- Conformance fixtures: [../spec/fixtures](../spec/fixtures)
|
|
56
|
+
- Agent skill: [../skills/agent-first-data.md](../skills/agent-first-data.md)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Agent-First Data for Python
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
pip install agent-first-data
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from agent_first_data import output_json, output_plain
|
|
9
|
+
|
|
10
|
+
value = {
|
|
11
|
+
"code": "ok",
|
|
12
|
+
"result": {
|
|
13
|
+
"api_key_secret": "sk-123",
|
|
14
|
+
"latency_ms": 1280,
|
|
15
|
+
"db_url": "postgres://user:p@ss@db/app?token_secret=abc",
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
print(output_json(value))
|
|
20
|
+
print(output_plain(value))
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Useful names use Python casing: `output_json`, `output_yaml`, `output_plain`, `output_json_with_options`, `redacted_value`, `redact_secrets_in_place`, `redact_url_secrets`, `parse_size`, `normalize_utc_offset`, `cli_parse_output`, `cli_output`, `build_cli_error`, `build_cli_version`, and `cli_handle_version_or_continue`.
|
|
24
|
+
|
|
25
|
+
Logging is available through `init_logging_json`, `init_logging_plain`, `init_logging_yaml`, `span`, and `get_logger`.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from agent_first_data import init_logging_json
|
|
29
|
+
|
|
30
|
+
init_logging_json("INFO", secret_names=("authorization",))
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Behavior Notes
|
|
34
|
+
|
|
35
|
+
- Default redaction replaces every `_secret` or configured secret-name subtree with `***`, including objects and arrays.
|
|
36
|
+
- `_url` fields scrub userinfo passwords and secret-named query parameters; surrounding whitespace is trimmed and internal whitespace redacts the whole field.
|
|
37
|
+
- YAML/plain quote and escape keys as well as values, sort by UTF-16 code unit order, and render nested objects in arrays as canonical JSON.
|
|
38
|
+
- Logging records use `code: "log"` plus a separate `level` field, so error-level logs are not terminal protocol errors.
|
|
39
|
+
- `build_cli_error(message, hint?)` returns `{code:"error", error: message, hint?}` only.
|
|
40
|
+
- Use `cli_handle_version_or_continue()` before argument parsing so bare `--version` stays conventional and `--version --output json|yaml|plain` stays structured.
|
|
41
|
+
|
|
42
|
+
## Reference
|
|
43
|
+
|
|
44
|
+
- Full convention and API groups: [../docs/overview.md](../docs/overview.md)
|
|
45
|
+
- Formal cross-language contract: [../spec/agent-first-data.md](../spec/agent-first-data.md)
|
|
46
|
+
- Conformance fixtures: [../spec/fixtures](../spec/fixtures)
|
|
47
|
+
- Agent skill: [../skills/agent-first-data.md](../skills/agent-first-data.md)
|
|
@@ -15,14 +15,15 @@ from agent_first_data.format import (
|
|
|
15
15
|
output_yaml_with_options,
|
|
16
16
|
output_plain,
|
|
17
17
|
output_plain_with_options,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
redact_secrets_in_place,
|
|
19
|
+
redact_secrets_in_place_with_options,
|
|
20
20
|
redacted_value,
|
|
21
21
|
redacted_value_with,
|
|
22
22
|
redacted_value_with_options,
|
|
23
23
|
redact_url_secrets,
|
|
24
24
|
redact_url_secrets_with_options,
|
|
25
25
|
parse_size,
|
|
26
|
+
normalize_utc_offset,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
from agent_first_data.afdata_logging import (
|
|
@@ -41,6 +42,9 @@ from agent_first_data.cli import (
|
|
|
41
42
|
cli_output,
|
|
42
43
|
cli_output_with_options,
|
|
43
44
|
build_cli_error,
|
|
45
|
+
build_cli_version,
|
|
46
|
+
cli_render_version,
|
|
47
|
+
cli_handle_version_or_continue,
|
|
44
48
|
)
|
|
45
49
|
|
|
46
50
|
from agent_first_data.skill import (
|
|
@@ -74,14 +78,15 @@ __all__ = [
|
|
|
74
78
|
"output_yaml_with_options",
|
|
75
79
|
"output_plain",
|
|
76
80
|
"output_plain_with_options",
|
|
77
|
-
"
|
|
78
|
-
"
|
|
81
|
+
"redact_secrets_in_place",
|
|
82
|
+
"redact_secrets_in_place_with_options",
|
|
79
83
|
"redacted_value",
|
|
80
84
|
"redacted_value_with",
|
|
81
85
|
"redacted_value_with_options",
|
|
82
86
|
"redact_url_secrets",
|
|
83
87
|
"redact_url_secrets_with_options",
|
|
84
88
|
"parse_size",
|
|
89
|
+
"normalize_utc_offset",
|
|
85
90
|
"AfdataHandler",
|
|
86
91
|
"init_logging_json",
|
|
87
92
|
"init_logging_plain",
|
|
@@ -94,6 +99,9 @@ __all__ = [
|
|
|
94
99
|
"cli_output",
|
|
95
100
|
"cli_output_with_options",
|
|
96
101
|
"build_cli_error",
|
|
102
|
+
"build_cli_version",
|
|
103
|
+
"cli_render_version",
|
|
104
|
+
"cli_handle_version_or_continue",
|
|
97
105
|
"SkillSpec",
|
|
98
106
|
"SkillAction",
|
|
99
107
|
"SkillScope",
|
|
@@ -21,13 +21,19 @@ Usage:
|
|
|
21
21
|
import logging
|
|
22
22
|
import sys
|
|
23
23
|
from contextvars import ContextVar, Token
|
|
24
|
-
from typing import Any
|
|
24
|
+
from typing import Any, Sequence
|
|
25
25
|
|
|
26
|
-
from agent_first_data.format import
|
|
26
|
+
from agent_first_data.format import (
|
|
27
|
+
OutputOptions,
|
|
28
|
+
RedactionOptions,
|
|
29
|
+
output_json_with_options,
|
|
30
|
+
output_plain_with_options,
|
|
31
|
+
output_yaml_with_options,
|
|
32
|
+
)
|
|
27
33
|
|
|
28
34
|
_span_fields: ContextVar[dict[str, Any]] = ContextVar("afdata_span", default={})
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
_LEVEL_TO_NAME = {
|
|
31
37
|
"CRITICAL": "error",
|
|
32
38
|
"ERROR": "error",
|
|
33
39
|
"WARNING": "warn",
|
|
@@ -44,17 +50,24 @@ class AfdataHandler(logging.Handler):
|
|
|
44
50
|
Formats output using the library's own output_json/output_plain/output_yaml.
|
|
45
51
|
"""
|
|
46
52
|
|
|
47
|
-
def __init__(
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
format: str = "json",
|
|
56
|
+
redaction: RedactionOptions | None = None,
|
|
57
|
+
secret_names: Sequence[str] | None = None,
|
|
58
|
+
) -> None:
|
|
48
59
|
super().__init__()
|
|
49
60
|
if format not in ("json", "plain", "yaml"):
|
|
50
61
|
raise ValueError(f"Unknown format: {format!r}, expected json/plain/yaml")
|
|
51
62
|
self._format = format
|
|
63
|
+
self._redaction = _redaction_options(redaction, secret_names)
|
|
52
64
|
|
|
53
65
|
def emit(self, record: logging.LogRecord) -> None:
|
|
54
66
|
entry: dict[str, Any] = {
|
|
55
67
|
"timestamp_epoch_ms": int(record.created * 1000),
|
|
56
68
|
"message": record.getMessage(),
|
|
57
|
-
"
|
|
69
|
+
"code": "log",
|
|
70
|
+
"level": _LEVEL_TO_NAME.get(record.levelname, "info"),
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
# Span fields (from contextvars, async-safe)
|
|
@@ -62,26 +75,23 @@ class AfdataHandler(logging.Handler):
|
|
|
62
75
|
if span_data:
|
|
63
76
|
entry.update(span_data)
|
|
64
77
|
|
|
65
|
-
# Event fields (passed via extra= in logging calls)
|
|
66
|
-
|
|
78
|
+
# Event fields (passed via extra= in logging calls). The protocol code
|
|
79
|
+
# is always "log"; use event for business categorization.
|
|
67
80
|
extra = getattr(record, "_afdata_fields", None)
|
|
68
81
|
if extra:
|
|
69
82
|
for k, v in extra.items():
|
|
70
83
|
if k == "code":
|
|
71
|
-
|
|
84
|
+
continue
|
|
72
85
|
entry[k] = v
|
|
73
86
|
|
|
74
|
-
#
|
|
75
|
-
|
|
76
|
-
entry["code"] = _LEVEL_TO_CODE.get(record.levelname, "info")
|
|
77
|
-
|
|
78
|
-
# Format using the library's own output functions
|
|
87
|
+
# Format using the library's own output functions.
|
|
88
|
+
options = OutputOptions(redaction=self._redaction)
|
|
79
89
|
if self._format == "plain":
|
|
80
|
-
line =
|
|
90
|
+
line = output_plain_with_options(entry, options)
|
|
81
91
|
elif self._format == "yaml":
|
|
82
|
-
line =
|
|
92
|
+
line = output_yaml_with_options(entry, options)
|
|
83
93
|
else:
|
|
84
|
-
line =
|
|
94
|
+
line = output_json_with_options(entry, options)
|
|
85
95
|
|
|
86
96
|
sys.stdout.write(line + "\n")
|
|
87
97
|
sys.stdout.flush()
|
|
@@ -100,26 +110,56 @@ class _AfdataLoggerAdapter(logging.LoggerAdapter):
|
|
|
100
110
|
return msg, kwargs
|
|
101
111
|
|
|
102
112
|
|
|
103
|
-
def
|
|
104
|
-
|
|
113
|
+
def _redaction_options(
|
|
114
|
+
redaction: RedactionOptions | None,
|
|
115
|
+
secret_names: Sequence[str] | None,
|
|
116
|
+
) -> RedactionOptions:
|
|
117
|
+
if redaction is not None and secret_names is not None:
|
|
118
|
+
raise ValueError("Pass either redaction or secret_names, not both")
|
|
119
|
+
if redaction is not None:
|
|
120
|
+
return redaction
|
|
121
|
+
if secret_names is not None:
|
|
122
|
+
return RedactionOptions(secret_names=tuple(secret_names))
|
|
123
|
+
return RedactionOptions()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _init_with_format(
|
|
127
|
+
format: str,
|
|
128
|
+
level: str = "INFO",
|
|
129
|
+
redaction: RedactionOptions | None = None,
|
|
130
|
+
secret_names: Sequence[str] | None = None,
|
|
131
|
+
) -> None:
|
|
132
|
+
handler = AfdataHandler(format=format, redaction=redaction, secret_names=secret_names)
|
|
105
133
|
root = logging.getLogger()
|
|
106
134
|
root.handlers = [handler]
|
|
107
135
|
root.setLevel(getattr(logging, level.upper(), logging.INFO))
|
|
108
136
|
|
|
109
137
|
|
|
110
|
-
def init_json(
|
|
138
|
+
def init_json(
|
|
139
|
+
level: str = "INFO",
|
|
140
|
+
redaction: RedactionOptions | None = None,
|
|
141
|
+
secret_names: Sequence[str] | None = None,
|
|
142
|
+
) -> None:
|
|
111
143
|
"""Initialize the root logger with AFDATA JSON output to stdout."""
|
|
112
|
-
_init_with_format("json", level)
|
|
144
|
+
_init_with_format("json", level, redaction=redaction, secret_names=secret_names)
|
|
113
145
|
|
|
114
146
|
|
|
115
|
-
def init_plain(
|
|
147
|
+
def init_plain(
|
|
148
|
+
level: str = "INFO",
|
|
149
|
+
redaction: RedactionOptions | None = None,
|
|
150
|
+
secret_names: Sequence[str] | None = None,
|
|
151
|
+
) -> None:
|
|
116
152
|
"""Initialize the root logger with AFDATA plain/logfmt output to stdout."""
|
|
117
|
-
_init_with_format("plain", level)
|
|
153
|
+
_init_with_format("plain", level, redaction=redaction, secret_names=secret_names)
|
|
118
154
|
|
|
119
155
|
|
|
120
|
-
def init_yaml(
|
|
156
|
+
def init_yaml(
|
|
157
|
+
level: str = "INFO",
|
|
158
|
+
redaction: RedactionOptions | None = None,
|
|
159
|
+
secret_names: Sequence[str] | None = None,
|
|
160
|
+
) -> None:
|
|
121
161
|
"""Initialize the root logger with AFDATA YAML output to stdout."""
|
|
122
|
-
_init_with_format("yaml", level)
|
|
162
|
+
_init_with_format("yaml", level, redaction=redaction, secret_names=secret_names)
|
|
123
163
|
|
|
124
164
|
|
|
125
165
|
def get_logger(name: str, **fields: Any) -> logging.LoggerAdapter:
|
|
@@ -7,6 +7,7 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from agent_first_data.format import (
|
|
9
9
|
OutputOptions,
|
|
10
|
+
build_json,
|
|
10
11
|
output_json,
|
|
11
12
|
output_json_with_options,
|
|
12
13
|
output_yaml,
|
|
@@ -93,27 +94,96 @@ def cli_output_with_options(
|
|
|
93
94
|
return output_json_with_options(value, output_options)
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
def build_cli_version(version: str) -> dict:
|
|
98
|
+
"""Build a standard CLI version value."""
|
|
99
|
+
return build_json("version", {"version": version})
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def cli_render_version(
|
|
103
|
+
name: str,
|
|
104
|
+
version: str,
|
|
105
|
+
format: OutputFormat | None = None,
|
|
106
|
+
) -> str:
|
|
107
|
+
"""Render CLI version output.
|
|
108
|
+
|
|
109
|
+
Pass an OutputFormat for AFDATA JSON/YAML/plain. Pass None to preserve
|
|
110
|
+
conventional "<name> <version>" text.
|
|
111
|
+
"""
|
|
112
|
+
rendered = (
|
|
113
|
+
f"{name} {version}" if format is None else cli_output(build_cli_version(version), format)
|
|
114
|
+
)
|
|
115
|
+
return rendered.rstrip("\n") + "\n"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def cli_handle_version_or_continue(
|
|
119
|
+
raw_args: list[str],
|
|
120
|
+
name: str,
|
|
121
|
+
version: str,
|
|
122
|
+
default_output: OutputFormat | None = None,
|
|
123
|
+
output_flag: str = "--output",
|
|
124
|
+
allow_output_format: bool = True,
|
|
125
|
+
) -> str | None:
|
|
126
|
+
"""Render version output if --version/-V is present; otherwise return None.
|
|
127
|
+
|
|
128
|
+
Raises ValueError for malformed version requests, for example
|
|
129
|
+
``--version --output xml``. The caller should convert that to a CLI error
|
|
130
|
+
with ``build_cli_error``.
|
|
131
|
+
"""
|
|
132
|
+
version_requested = False
|
|
133
|
+
output_format: OutputFormat | None = None
|
|
134
|
+
output_error: ValueError | None = None
|
|
135
|
+
|
|
136
|
+
i = 0
|
|
137
|
+
while i < len(raw_args):
|
|
138
|
+
arg = raw_args[i]
|
|
139
|
+
if arg == "--":
|
|
140
|
+
break
|
|
141
|
+
if arg in ("--version", "-V"):
|
|
142
|
+
version_requested = True
|
|
143
|
+
i += 1
|
|
144
|
+
continue
|
|
145
|
+
if allow_output_format and (arg == output_flag or arg.startswith(f"{output_flag}=")):
|
|
146
|
+
value: str | None
|
|
147
|
+
if arg.startswith(f"{output_flag}="):
|
|
148
|
+
value = arg.split("=", 1)[1]
|
|
149
|
+
step = 1
|
|
150
|
+
elif i + 1 < len(raw_args) and not raw_args[i + 1].startswith("-"):
|
|
151
|
+
value = raw_args[i + 1]
|
|
152
|
+
step = 2
|
|
153
|
+
else:
|
|
154
|
+
value = None
|
|
155
|
+
step = 1
|
|
156
|
+
if value is None:
|
|
157
|
+
output_error = ValueError(
|
|
158
|
+
f"missing value for {output_flag}: expected json, yaml, or plain"
|
|
159
|
+
)
|
|
160
|
+
else:
|
|
161
|
+
try:
|
|
162
|
+
output_format = cli_parse_output(value)
|
|
163
|
+
except ValueError as e:
|
|
164
|
+
output_error = e
|
|
165
|
+
i += step
|
|
166
|
+
continue
|
|
167
|
+
i += 1
|
|
168
|
+
|
|
169
|
+
if not version_requested:
|
|
170
|
+
return None
|
|
171
|
+
if output_error is not None:
|
|
172
|
+
raise output_error
|
|
173
|
+
return cli_render_version(
|
|
174
|
+
name,
|
|
175
|
+
version,
|
|
176
|
+
output_format if allow_output_format and output_format is not None else default_output,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
96
180
|
def build_cli_error(message: str, hint: str | None = None) -> dict:
|
|
97
181
|
"""Build a standard CLI parse error value.
|
|
98
182
|
|
|
99
183
|
Use when argument parsing fails or a flag value is invalid.
|
|
100
184
|
Print with output_json and exit with code 2.
|
|
101
|
-
|
|
102
|
-
>>> v = build_cli_error("--output: invalid value 'xml'")
|
|
103
|
-
>>> v["code"]
|
|
104
|
-
'error'
|
|
105
|
-
>>> v["error_code"]
|
|
106
|
-
'invalid_request'
|
|
107
|
-
>>> v["retryable"]
|
|
108
|
-
False
|
|
109
185
|
"""
|
|
110
|
-
m: dict = {
|
|
111
|
-
"code": "error",
|
|
112
|
-
"error_code": "invalid_request",
|
|
113
|
-
"error": message,
|
|
114
|
-
"retryable": False,
|
|
115
|
-
"trace": {"duration_ms": 0},
|
|
116
|
-
}
|
|
186
|
+
m: dict = {"code": "error", "error": message}
|
|
117
187
|
if hint is not None:
|
|
118
188
|
m["hint"] = hint
|
|
119
189
|
return m
|