-
Notifications
You must be signed in to change notification settings - Fork 0
chore: sync workflow templates #552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,8 +14,6 @@ | |
| from pathlib import Path | ||
| from typing import Any | ||
|
|
||
| from src.ndjson_parser import read_ndjson_file | ||
|
|
||
| _DEFAULT_METRICS_DIR = "agent-metrics" | ||
| _DEFAULT_OUTPUT = "agent-metrics-summary.md" | ||
| _DEFAULT_JSON_OUTPUT = "agent-metrics-summary.json" | ||
|
|
@@ -305,6 +303,66 @@ def _canonical_parse_error_detail(path: Path, error: str) -> ParseErrorDetail: | |
| return _parse_error_detail(path, line, reason) | ||
|
|
||
|
|
||
| def read_ndjson_file(path: Path) -> tuple[list[dict[str, Any]], list[str]]: | ||
| """Read an NDJSON file without depending on Workflows-only modules.""" | ||
| try: | ||
| handle = path.open("r", encoding="utf-8") | ||
| except OSError as exc: | ||
| return [], [f"{path}: {exc}"] | ||
|
|
||
| entries: list[dict[str, Any]] = [] | ||
| errors: list[str] = [] | ||
| raw_lines_for_fallback: list[str] = [] | ||
| raw_fallback_bytes = 0 | ||
| raw_fallback_truncated = False | ||
| with handle: | ||
| for line_number, line in enumerate(handle, start=1): | ||
| raw = line.strip() | ||
| if not raw: | ||
| continue | ||
| if not entries and not raw_fallback_truncated: | ||
| raw_bytes = len(raw.encode("utf-8")) + 1 | ||
| fallback_within_limit = ( | ||
| len(raw_lines_for_fallback) < _MAX_LEGACY_JSON_FALLBACK_LINES | ||
| and raw_fallback_bytes + raw_bytes <= _MAX_LEGACY_JSON_FALLBACK_BYTES | ||
| ) | ||
| if fallback_within_limit: | ||
| raw_fallback_bytes += raw_bytes | ||
| raw_lines_for_fallback.append(raw) | ||
| else: | ||
| raw_fallback_truncated = True | ||
| raw_lines_for_fallback = [] | ||
| try: | ||
| parsed = json.loads(raw) | ||
| except json.JSONDecodeError as exc: | ||
| errors.append(f"{path}:{line_number}: invalid JSON ({exc.msg})") | ||
| continue | ||
| if isinstance(parsed, dict): | ||
| entries.append(parsed) | ||
| raw_lines_for_fallback = [] | ||
| else: | ||
| errors.append(f"{path}:{line_number}: expected object, got {type(parsed).__name__}") | ||
|
|
||
| if entries or not errors: | ||
| return entries, errors | ||
|
|
||
| raw_text = "\n".join(raw_lines_for_fallback) | ||
| if raw_fallback_truncated: | ||
| errors.append(f"{path}: legacy-json-fallback-buffer-limit") | ||
| return entries, errors | ||
|
|
||
| try: | ||
| parsed_file = json.loads(raw_text) | ||
| except json.JSONDecodeError: | ||
| return entries, errors | ||
|
|
||
| if isinstance(parsed_file, dict): | ||
| return [parsed_file], [] | ||
| if isinstance(parsed_file, list) and all(isinstance(item, dict) for item in parsed_file): | ||
| return list(parsed_file), [] | ||
| return entries, errors | ||
|
Comment on lines
+323
to
+363
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t let an interior object disable the legacy JSON fallback. A valid pretty-printed legacy JSON array can contain a line that is itself a JSON object, especially the last element. That makes 🐛 Proposed fix- if not entries and not raw_fallback_truncated:
+ if not raw_fallback_truncated:
raw_bytes = len(raw.encode("utf-8")) + 1
fallback_within_limit = (
len(raw_lines_for_fallback) < _MAX_LEGACY_JSON_FALLBACK_LINES
and raw_fallback_bytes + raw_bytes <= _MAX_LEGACY_JSON_FALLBACK_BYTES
)
@@
if isinstance(parsed, dict):
entries.append(parsed)
- raw_lines_for_fallback = []
else:
errors.append(f"{path}:{line_number}: expected object, got {type(parsed).__name__}")
- if entries or not errors:
+ if not errors:
return entries, errors
- raw_text = "\n".join(raw_lines_for_fallback)
if raw_fallback_truncated:
- errors.append(f"{path}: legacy-json-fallback-buffer-limit")
+ if not entries:
+ errors.append(f"{path}: legacy-json-fallback-buffer-limit")
return entries, errors
+ raw_text = "\n".join(raw_lines_for_fallback)
try:
parsed_file = json.loads(raw_text)
except json.JSONDecodeError:
return entries, errors🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| def read_metric_ndjson_files( | ||
| files: Iterable[Path], | ||
| ) -> tuple[list[dict[str, Any]], list[ParseErrorDetail]]: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Catch read/decode failures during iteration.
path.open()can succeed while the laterfor line in handleraisesUnicodeDecodeErrororOSError. In the weekly metrics workflow, one malformed artifact would crash aggregation instead of being reported through parse-error details.🛡️ Proposed fix
🤖 Prompt for AI Agents