Compare commits

...

56 Commits

Author SHA1 Message Date
Zamil Majdy
553e224caf Merge remote-tracking branch 'origin/dev' into feat/file-ref-structured-parsing-v2 2026-03-17 06:16:49 +07:00
Zamil Majdy
46acc2cfc1 fix(backend/copilot): update test mock targets after get_manager rename
Tests were mocking the removed `get_manager` function. Updated mock
targets to reference `get_workspace_manager` which replaced it.
2026-03-17 04:47:15 +07:00
Zamil Majdy
1c55c134ac refactor(backend/copilot): reorder functions top-down and remove get_manager wrapper
Address PR review comments from Pwuts:
- Reorder file_ref.py: public API functions first, private helpers after
- Reorder file_content_parser.py: public API first, parsers/helpers after
- Remove get_manager() wrapper in workspace_files.py; callers now import
  get_workspace_manager directly from backend.copilot.context
2026-03-17 02:50:28 +07:00
Zamil Majdy
4f7bab3375 fix(backend/copilot): narrow sandbox exception handling, add missing tests, improve docs
- Replace bare `except Exception` in sandbox file read with specific
  exception types (FileNotFoundError, OSError, UnicodeDecodeError) plus
  E2B SandboxException, re-raising unexpected exceptions as real bugs.
- Expand __init__.py docstring explaining why lazy imports (PEP 562) are
  needed: tool_adapter uses TOOL_REGISTRY at module level, making the
  circular import cycle non-trivial to restructure.
- Add docstring to _is_tabular explaining why isinstance checks are
  appropriate (structural type guard on opaque Any, not duck typing).
- Add integration tests: bare ref binary format with line range (ignored),
  bare ref TOML parsing.
- Add pyarrow skipif markers to file_ref_test.py binary format tests.
2026-03-17 00:30:38 +07:00
Zamil Majdy
981891aebe fix(backend/copilot): address PR review comments
- Narrow `except Exception` to specific types in `read_file_bytes`
- Use `itertools.zip_longest` in `_tabular_to_list_of_dicts`
- Add NaN handling test for parquet bare refs
2026-03-16 17:27:53 +07:00
Zamil Majdy
c44d8d7a98 fix(backend): address all remaining PR review items
Blockers:
- TOCTOU in local file read: replace os.path.getsize + open with a
  single read(_MAX_BARE_REF_BYTES + 1) to detect oversized files
  atomically
- PARSE_EXCEPTIONS: replace filter(None,...) + type: ignore with
  _optional_exc() loader helpers that raise ImportError at parse time;
  removes all type: ignore suppressors
- _check_content_size: raise ValueError instead of FileRefExpansionError
  so _expand_bare_ref can unify all resolution errors in one handler

Should-fix:
- _adapt_to_schema: non-tabular list to object-typed field now raises
  FileRefExpansionError instead of passing through silently; update test
- _parse_delimited: extract _row_has_content predicate to module-level
  and use consistently in both the initial read and sniffer-fallback pass
- _parse_xlsx: add engine="openpyxl" explicitly to pd.read_excel

Nice-to-have:
- sdk/__init__.py: convert sequential if branches to dispatch dict
- _adapt_to_schema: extract _adapt_dict_to_array and _adapt_list_to_object
  helpers to stay under the 40-line limit
- _parse_jsonl: cache keys_tuple = tuple(keys) to avoid O(n*k) allocations
- _parse_yaml: add runtime warning when multi-document YAML (---) detected
- is_media_file_ref (file.py): document URL-in-source-code false-positive risk
2026-03-16 06:19:54 +07:00
Zamil Majdy
1b7a446e97 test(backend): add 2 missing test cases from coderabbitai review
- test_unknown_mime_falls_through_to_extension: verifies that when an
  unrecognized MIME is present, infer_format_from_uri falls through to
  extension-based detection (e.g. text/plain + .csv → csv)
- test_bare_ref_binary_format_ignores_line_range: documents that binary
  bare refs (parquet/xlsx) silently drop the [start-end] range and parse
  full file content (line slicing is meaningless on binary bytes)
2026-03-15 22:58:01 +07:00
Zamil Majdy
d10ae1f392 fix(backend/copilot): narrow exception handling in _infer_format_from_workspace
Replace bare `except Exception` catch-all with specific exceptions
(ValueError, FileNotFoundError, OSError, PermissionError, AttributeError,
TypeError) so unexpected programming errors (e.g. KeyError, RuntimeError)
propagate instead of being silently swallowed as a None return.

Addresses autogpt-reviewer comments #2930931556 and #2930341488.
2026-03-15 22:43:29 +07:00
Zamil Majdy
72b40f03bd fix(backend): address remaining review comments — ArrowException, binary line range warning, CSV blank-line filter, _is_tabular refactor
- Add pyarrow.ArrowException to PARSE_EXCEPTIONS so ArrowIOError and
  ArrowCapacityError (which don't inherit from ValueError/TypeError) are
  caught by the fallback contract in parse_file_content and _expand_bare_ref
- Log a warning when a line range is specified for a binary format bare ref
  (parquet/xlsx) instead of silently ignoring it
- Fix _parse_delimited blank-line filter: csv.reader never yields [] so
  'if row' was a no-op; now uses 'if any(cell for cell in row)' to
  properly skip rows where every cell is empty
- Refactor _is_tabular to early-return pattern, avoiding a double iteration
  over parsed[0] (once for isinstance(row, list) check, once for str check)
2026-03-15 22:24:43 +07:00
Zamil Majdy
575a956df2 fix(copilot): broaden exception handling in read_file_bytes for GCS errors
The workspace branch of read_file_bytes only caught PermissionError and
OSError, missing network/API exceptions from the gcloud.aio library
(e.g. aiohttp.ClientError, asyncio.TimeoutError). Add a catch-all
Exception handler that logs a warning and wraps the error in ValueError,
consistent with the sandbox branch and _infer_format_from_workspace.
2026-03-15 14:05:18 +07:00
Zamil Majdy
6001f9dde0 fix(backend/copilot): optimize size guard with fast lower-bound check
Add a fast lower-bound check in _check_content_size: if the character
count already exceeds the byte limit, reject immediately without
allocating an encoded copy. This avoids a ~10MB temporary allocation
for strings near the size limit. The existing upper-bound fast path
(char_len * 4 <= limit) is preserved for the common under-limit case.

Addresses autogpt-reviewer should-fix item #3 from PR #12392.
2026-03-15 13:35:29 +07:00
Zamil Majdy
90d986973e fix(backend): address autogpt-reviewer should-fix items for file parsing
- Rename infer_format → infer_format_from_uri for clarity (all callers updated)
- Add .xls format detection and helpful error message suggesting .xlsx conversion
- Strengthen test_invalid_yaml_fallback to assert exact return value
- Add tests: NaN in Parquet, header-only CSV, binary format + line range, .xls UX
- Add docstring to _expand inner function in file_ref.py
2026-03-15 04:11:26 +07:00
Zamil Majdy
3638384f08 fix(backend): address PR review — integration tests and cleaner ragged row handling
Add 6 integration tests for bare ref structured parsing in
expand_file_refs_in_args (JSON, CSV, YAML, unknown extension, invalid
JSON fallback, embedded ref stays string).

Simplify _tabular_to_list_of_dicts to use zip + pad instead of
index-based iteration, per reviewer suggestion.
2026-03-14 23:45:37 +07:00
Zamil Majdy
447a6f10fb fix(backend): harden file parsing, add lazy imports, and improve file_ref safety checks 2026-03-14 23:00:46 +07:00
Zamil Majdy
c39e1a2701 fix: add workspace/sandbox size limits, deduplicate parse exceptions, case-insensitive MIME
- Enforce 10MB size limit on workspace and sandbox file reads
- Extract shared PARSE_EXCEPTIONS constant to eliminate duplication
- Consolidate _create_blob/_create_binary_blob into single function
- Add globals() caching for lazy PEP 562 imports
- Fix case-insensitive MIME fragment matching per RFC 2045
2026-03-14 22:27:15 +07:00
Zamil Majdy
f037e02bd6 Merge remote-tracking branch 'origin/dev' into feat/file-ref-structured-parsing-v2 2026-03-14 22:11:09 +07:00
Zamil Majdy
4934f7a766 fix(backend/copilot): harden file-ref parsing — size guards, edge cases, sniffer fallback
- Add pre-read size check in read_file_bytes for local files
- Add OpenpyxlInvalidFile to parse_file_content exception list
- Add csv.Sniffer fallback for misidentified delimiters
- Add application/yaml MIME mapping
- Fix _is_tabular to reject empty header rows
- Fix _adapt_to_schema dict→List[str] not wrapping incorrectly
- Fix _apply_line_range to note when range exceeds file
- Remove inconsistent ChatSession string quoting
- Add clarifying comments for budget/size check ordering
- Add tests for all new behaviors
2026-03-14 21:54:52 +07:00
Zamil Majdy
eafac037c2 Merge remote-tracking branch 'origin/dev' into feat/file-ref-structured-parsing-v2 2026-03-14 10:21:00 +07:00
Zamil Majdy
5873dc81fe fix(backend/copilot): catch openpyxl.InvalidFileException in bare ref parsing
InvalidFileException extends Exception directly (not ValueError/OSError),
so it wasn't caught by the existing exception tuple. Corrupt .xlsx files
would crash instead of raising FileRefExpansionError.
2026-03-14 06:56:26 +07:00
Zamil Majdy
81c51f91f3 fix(backend): fix 2 CI test failures from media resolution changes
- test_multi_file_commit_error_path: provide execution_context kwarg
  now required by GithubMultiFileCommitBlock.run()
- test_non_media_string_field_still_reads_content: mock
  _infer_format_from_workspace to avoid event loop binding issue in CI
2026-03-14 06:44:23 +07:00
Zamil Majdy
1e03a56f28 fix(backend/blocks): address code review — type consistency, tests, docs
- Use FileOperation enum instead of raw string in commits.py run()
- Remove unused _MediaFileBlock test helper class
- Add tests for resolve_media_content with data URI and HTTPS inputs
- Clarify prompting docs: pass workspace:// directly, not via @@agptfile
2026-03-14 06:27:37 +07:00
Zamil Majdy
50b2dffc2e fix(backend/blocks): preserve binary files in MediaFileType fields
- Add `_is_media_file_field` check in file_ref.py `_expand` to pass
  through workspace:// URIs for `format: "file"` schema fields,
  skipping file reading and format inference that would corrupt binary
  content (images, videos, etc.) via UTF-8 decoding
- Add `resolve_media_content` helper in file.py to encapsulate the
  is_media_file_ref + store_media_file pattern for blocks
- Add `parse_data_uri` and `is_media_file_ref` utilities in file.py,
  consolidating regex from store_media_file and get_mime_type
- Update GithubMultiFileCommitBlock to use resolve_media_content and
  parse_data_uri for proper binary blob encoding via GitHub API
- Add LLM education in prompting.py about `format: "file"` fields
  and workspace:// references for media content
- Add tests for all new functionality
2026-03-14 06:23:28 +07:00
Zamil Majdy
7b866a9f22 fix(backend): catch binary parser exceptions (BadZipFile, KeyError, TypeError)
openpyxl.InvalidFileException and zipfile.BadZipFile extend Exception
directly (not ValueError/OSError), so corrupt xlsx files would escape
the narrowed exception handlers in both parse_file_content and
_expand_bare_ref. Add KeyError (covers ArrowKeyError, OptionError),
TypeError (covers ArrowTypeError), and zipfile.BadZipFile to both
catch clauses.
2026-03-13 22:42:29 +07:00
Zamil Majdy
d48eb12d50 refactor(copilot): inline MIME format lookup in _infer_format_from_workspace
Collapse 3-line MIME lookup (get → if → return fallback) into a single
`return ... or ...` expression, as noted in self-review.
2026-03-13 22:05:20 +07:00
Zamil Majdy
ecbab7f3a0 refactor(backend): address PR review - extract helpers, DRY parsers, defer pandas
- Extract `_to_str()` helper to deduplicate `content.decode("utf-8", errors="replace")` (3 call sites)
- Extract `_check_content_size()` to consolidate duplicated size guard logic
- Extract `_expand_bare_ref()` from `_expand` inner function (~90 lines -> ~30 lines each)
- Move `expect_string` computation inside bare-ref branch (lazy evaluation)
- Narrow `except Exception` in parse block to specific exception types
- DRY `_parse_json`/`_parse_yaml` with `_parse_container` helper
- Defer `import pandas` to binary parser functions to avoid ~200ms cold start
- Tighten parser return type annotations
2026-03-13 19:54:11 +07:00
Zamil Majdy
b7551a1d18 fix(backend): use actual byte size for string size guard, narrow exception handling
- Size guard in _expand now computes len(content.encode("utf-8")) for
  strings instead of len(content) which returns character count. This
  fixes a security issue where multi-byte UTF-8 strings (e.g. emoji)
  could pass up to 40MB through a 10MB byte limit.
- Narrow except Exception in _infer_format_from_workspace to only catch
  expected IO/lookup failures (ValueError, FileNotFoundError, OSError,
  PermissionError).
- Narrow except Exception in parse_file_content to only catch expected
  parse failures, letting programming bugs surface.
2026-03-13 19:40:20 +07:00
Zamil Majdy
f1366ea139 Merge remote-tracking branch 'origin/dev' into feat/file-ref-structured-parsing-v2 2026-03-13 19:27:04 +07:00
Zamil Majdy
68f430f792 fix(backend): restore PyYAML cp38 wheel hashes in poetry.lock
Local poetry lock on Python 3.13 strips cp38 hashes that CI (Python
3.11) needs for the lock file consistency check.
2026-03-13 18:18:09 +07:00
Zamil Majdy
cb50c48eda fix(backend): restore PyYAML cp38 hashes in poetry.lock and guard row truncation
- Re-add PyYAML cp38 wheel hashes dropped by local poetry lock on
  Python 3.13 (CI needs them for Python 3.11)
- Truncate rows to header length before dict conversion to prevent
  None keys when data rows exceed header column count
2026-03-13 18:17:22 +07:00
Zamil Majdy
b3af75a71e Merge remote-tracking branch 'origin/dev' into feat/file-ref-structured-parsing-v2
# Conflicts:
#	autogpt_platform/backend/poetry.lock
2026-03-13 18:08:19 +07:00
Zamil Majdy
e0abb66ffc refactor(backend): address reviewer comments on file ref PR
- Narrow bare `except Exception` to `(PermissionError, OSError)` /
  `OSError` in read_file_bytes
- Use itertools.zip_longest in _tabular_to_list_of_dicts for cleaner
  ragged-row handling
- Tighten pyarrow version constraint from >=14.0.0 to ^23.0.0
2026-03-13 17:52:03 +07:00
Zamil Majdy
13985feb3d fix(backend): extract list values from dict for List[List[Any]] block inputs
When a dict (YAML/TOML) is passed to a List[List[Any]]-typed input
(e.g. ConcatenateListsBlock), instead of wrapping the whole dict as
[dict] (which causes pydantic to coerce dict → list of tuples),
extract all list-typed values from the dict as inner lists.

Example: YAML {"fruits": [{...},{...}]} → [[{...},{...}]] instead of
[{"fruits": [...]}] which pydantic would coerce to [(key, val), ...].

Falls back to [dict] wrapping when no list values exist in the dict.
2026-03-13 16:40:41 +07:00
Zamil Majdy
bce0214a6a fix(backend): pad ragged rows with None in tabular conversion helpers
_tabular_to_column_dict and _tabular_to_list_of_dicts now use None for
missing values in shorter rows instead of silently dropping them. This
ensures all columns have equal length in column-dict output.
2026-03-13 16:26:54 +07:00
Zamil Majdy
a937433d8e fix(backend): add isinstance(parsed, list) guards for pyright narrowing
After isinstance(parsed, dict) on line 339, pyright narrows the type to
Any | dict and _is_tabular() alone doesn't narrow it back. Adding
explicit isinstance(parsed, list) checks satisfies pyright's type
narrowing.
2026-03-13 16:15:20 +07:00
Zamil Majdy
04bb0bef69 fix(backend): fix pyright type errors in tabular helper signatures
Widen parameter type from list[list] to list so pyright doesn't complain
about Any not being assignable to list[list] after _is_tabular() guard.
2026-03-13 16:04:06 +07:00
Zamil Majdy
e47ab6a295 fix(backend): convert tabular data to list-of-dicts for Any-typed block inputs
FindInDictionaryBlock has `input: Any` which produces a JSON schema with
no "type" key. _adapt_to_schema was only checking for explicit type matches
("object", "array"), so tabular data [[header],[rows]] passed through
unchanged — causing FindInDict to return silent empty [] on key lookup.

Fix: when prop_schema has no type (Any field), convert tabular data to
list-of-dicts [{col: val, ...}, ...] which FindInDict's list-of-dicts
branch (line 195-199) handles correctly.

Refactored _adapt_to_schema to extract _is_tabular(), _tabular_to_list_of_dicts(),
and _tabular_to_column_dict() helpers for clarity.

Added 7 E2E tests covering CSV/TSV/JSONL/Parquet/YAML/JSON × Any-typed block.
2026-03-13 15:47:25 +07:00
Zamil Majdy
ad542db7fd feat(backend): add schema-aware type adaptation for file ref expansion
When parsed file content doesn't match the block's expected schema type,
_adapt_to_schema() converts it to a more useful representation:
- Dict → array schema: wraps dict in [dict] instead of pydantic flattening
  keys/values (fixes YAML/TOML dict → list block quirky coercion)
- Tabular list → object schema: converts [[header], [rows]...] to column-dict
  {"col1": [vals], ...} (fixes CSV/JSONL/Excel → dict block empty results)

Adds E2E tests for YAML→list, TOML→list, CSV→dict, JSONL→dict, and
Parquet→dict adaptations.
2026-03-13 15:23:27 +07:00
Zamil Majdy
78cc963633 fix(backend): require ≥2 dicts for JSONL tabular detection
Single-line JSONL with one dict was incorrectly converted to a table
due to vacuously true all() on empty lines[1:]. Now requires ≥2
uniform dicts before applying table format conversion.
2026-03-13 15:03:47 +07:00
Zamil Majdy
d7b0e16112 feat(backend): JSONL tabular detection — uniform dicts → table format
When all JSONL lines are dicts with identical keys (tabular data),
_parse_jsonl now returns [header_row, data_row1, ...] instead of
[{dict1}, {dict2}, ...]. This makes JSONL output consistent with
CSV/TSV/Parquet/Excel and avoids awkward pydantic coercion when
list[list] blocks receive a list of dicts.

Heterogeneous JSONL (different keys or mixed types) keeps the
existing behavior of returning a plain list of parsed values.

Also adds comprehensive E2E tests for:
- JSONL × block type matrix (list, string, dict)
- Parquet × block type matrix (now that pyarrow is available)
2026-03-13 14:57:50 +07:00
Zamil Majdy
83e4a8a00d poetry lock 2026-03-13 14:53:11 +07:00
Zamil Majdy
9fedd98a19 fix(backend): add pyarrow dependency for parquet file parsing
pyarrow is required by pandas.read_parquet() but was never declared
in pyproject.toml, causing parquet file parsing to fail at runtime.
2026-03-13 14:51:58 +07:00
Zamil Majdy
edc138fbec fix(backend): reject binary formats (parquet/xlsx) passed to string-typed block inputs
Binary formats decoded to UTF-8 produce garbled output. Instead of
silently passing raw bytes as text, raise FileRefExpansionError with a
clear message directing users to use structured (list/object) blocks.
2026-03-13 14:31:22 +07:00
Zamil Majdy
59278ba3de fix(copilot): update integration test patches for get_manager → get_workspace_manager rename 2026-03-13 14:16:01 +07:00
Zamil Majdy
1fcd38ae6a test(copilot): add e2e tests proving CSV→string block gets raw text after coercion
Adds 3 end-to-end tests that exercise the full pipeline:
  expand_file_refs_in_args → coerce_inputs_to_schema

- test_e2e_csv_to_string_block_no_json_dumps: proves the old bug
  (CSV parsed to list → json.dumps'd) is fixed — block gets raw CSV
- test_e2e_csv_to_list_block_parses: proves non-string blocks still
  get structured parsed data
- test_e2e_json_to_string_block_returns_raw_json: proves JSON file
  ref to string-typed block returns raw JSON text, not parsed dict
2026-03-13 14:03:38 +07:00
Zamil Majdy
c342ccc42c fix(copilot): resolve circular imports and add full format×schema matrix tests
- Move get_workspace_manager to copilot/context.py to break the
  tools → sdk → tools circular import chain
- Make sdk/__init__.py use PEP 562 lazy loading to avoid eagerly
  importing service.py (which chains to tools/)
- Replace local import in run_block.py with top-level import
- Add parametrized matrix tests covering JSON/CSV/TSV/JSONL/YAML/TOML
  × string-typed/non-string/opaque-object schema combinations
- Add two-phase expansion integration test (tool-level skip + block-level expand)
2026-03-13 13:56:03 +07:00
Zamil Majdy
79b881393e fix(backend): surface actual parse errors for binary formats and skip parsing for string-typed inputs
- Add strict mode to parse_file_content that propagates exceptions instead
  of silently falling back, used for binary formats (parquet/xlsx) so the
  actual error (missing library, corrupt file) is shown instead of a
  blanket message
- Make expand_file_refs_in_args schema-aware: when the tool input schema
  declares a parameter as type "string", structured parsing is skipped and
  raw file content is returned as-is (e.g., CSV text stays as CSV text,
  not json.dumps of parsed rows)
- Pass input_schema from tool_adapter through to file ref expansion
2026-03-13 13:28:30 +07:00
Zamil Majdy
9300b3223f fix(backend): resolve workspace file format from metadata when URI has no extension
Workspace URIs by ID (workspace://abc123) have no file extension and
may lack a MIME fragment. When infer_format returns None, fall back to
querying the workspace file manager for the file's stored MIME type and
original filename to determine the correct parser.

Also rename _MIME_TO_FORMAT → MIME_TO_FORMAT (public) for reuse.
2026-03-13 12:45:18 +07:00
Zamil Majdy
d5136891bf fix(backend): raise clear error when binary format parsing fails
When parse_file_content falls back for binary formats (parquet/xlsx),
detect the fallback and raise FileRefExpansionError with a clear message
about missing dependencies instead of silently returning garbled UTF-8
decoded bytes.
2026-03-13 05:41:29 +07:00
Zamil Majdy
3b4586bbe6 fix(backend): guard pd.isna() against non-scalar cells in _df_to_rows
pd.isna() on a list/dict returns a boolean array which raises ValueError
in a boolean context. Add _is_nan() helper that checks is_scalar first.
2026-03-13 04:19:55 +07:00
Zamil Majdy
bc1d68310c fix(backend): fix pyright errors in file_content_parser_test
- Add pyright: ignore[reportMissingImports] for optional pyarrow import
- Add type: ignore[arg-type] for BytesIO passed to to_excel
2026-03-13 04:18:26 +07:00
Zamil Majdy
abd59d4d1d fix(backend): fix NaN→None normalization in _df_to_rows for float64 columns
df.where(df.notna(), None) silently converts None back to NaN in float64
columns. Use explicit pd.isna() cell-level checking instead. Add test to
verify no NaN leaks into serialized output.
2026-03-13 03:56:17 +07:00
Zamil Majdy
d87d522706 feat(backend): add bare-ref integration tests and fix size guard allocation
- Add 6 integration tests for bare-ref structured parsing in file_ref_test.py
  (JSON, CSV, unknown ext, invalid JSON, embedded ref, oversized)
- Remove unnecessary .encode("utf-8") allocation in size guard — use len()
  as a lower-bound proxy for character count
- Add per-ref truncation for unknown-format bare refs to _MAX_EXPAND_CHARS
- Normalize bytes fallback to string for binary format parse failures
2026-03-13 03:54:07 +07:00
Zamil Majdy
262c1811b5 fix(backend): address Sentry review — truncate unknown-format bare refs and normalize bytes fallback
- Apply _MAX_EXPAND_CHARS (200k) truncation to bare refs with unknown
  format, matching the inline expansion behavior
- Normalize bytes→str when parse_file_content falls back to raw bytes
  for binary formats, ensuring tools never receive raw bytes
2026-03-13 03:49:43 +07:00
Zamil Majdy
48d4f3716b fix(backend): skip parquet tests when pyarrow is not installed
pyarrow is not bundled as a direct dependency — the fallback contract
handles the missing engine at runtime.  Skip the fixture-based test
that needs pyarrow to generate test data.
2026-03-13 03:45:03 +07:00
Zamil Majdy
340b18d40b fix(backend): address PR review comments for file content parser
- Move local imports (yaml, pandas) to top-level
- Add size limit guard (_MAX_BARE_REF_BYTES=10MB) for bare ref expansion
- Ignore line ranges for binary formats (parquet/xlsx) instead of garbling
- Strip query strings in infer_format URI parsing
- Fix type annotations for parser dicts (Callable instead of Any)
- Replace NaN with None in parquet/xlsx output for JSON serializability
- Fix TOML empty dict fallback (always return parsed dict)
- Remove .xls/.vnd.ms-excel mappings (openpyxl doesn't support legacy .xls)
- Add posixpath.splitext usage comment
- Update prompt to mention first-sheet-only and .xls limitation
- Restore pyyaml cp38 entries in poetry.lock
2026-03-13 03:28:31 +07:00
Zamil Majdy
35f54549b5 feat(backend/copilot): parse @@agptfile bare refs by file extension
When the entire tool argument is a bare @@agptfile: reference, the
resolved content is now parsed based on the file's extension or MIME
type instead of content-sniffing.

Supported formats: JSON, JSONL, CSV, TSV, YAML, TOML, Parquet, Excel.
Unrecognised formats or parse failures fall back to plain string.
2026-03-13 02:58:00 +07:00

Diff Content Not Available