a2ui-project / a2ui-project/a2ui

[BUG]: non-ASCII data model keys are unreachable from templates in Dart, web_core and Python

Đang mở Phù hợp với người mới
#2,500 1 bình luận 0 reaction 1 người được giao Được @Varun-S10 nhận Xem trên GitHub
P2 status: first-line-handled status: needs review type: bug
Ngôn ngữ chính
TypeScript
Star
16.4k
Fork
1.3k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
134

Mô tả

- [x] I have searched the existing issues to make sure this bug has not already been reported.

## Describe the Bug

A data model key containing any non-ASCII character cannot be referenced from a template. `${señor}`, `${café/precio}` and `${日本}` are parse errors in Dart, TypeScript and Python, and parse correctly in Swift.

| template | Dart | TypeScript | Python | Swift |
| --- | --- | --- | --- | --- |
| `${señor}` | error | error | error | `{path: "señor"}` |
| `${café/precio}` | error | error | error | `{path: "café/precio"}` |
| `${日本}` | error | error | error | `{path: "日本"}` |
| `hola ${señor} qué tal` | error | error | error | parses, literals intact |
| `${a_b-c.d}` | ok | ok | ok | ok |

So an agent that names its data with anything but English ASCII produces a surface that renders on iOS and fails everywhere else.

The data model itself has no such limit, which makes the state reachable but undisplayable:

```dart
final m = DataModel({});
m.set('/señor', 'Diego'); // fine
m.get('/señor'); // 'Diego'
ExpressionParser().parse(r'${señor}'); // A2uiExpressionError
```

An agent can write the key, and read it back through `getClientDataModel`, but cannot put it on screen.

## Root cause

The identifier scanners disagree, and the pattern is worth noting: the three that fail carry a hand-written ASCII range, while the one that works uses its language's own Unicode-aware predicate.

- `dart/a2ui_core/lib/src/processing/expressions.dart` — `_isAlnum` tests code units `0x30–0x39`, `0x41–0x5A`, `0x61–0x7A`.
- `renderers/web_core/.../expression_parser.ts` — `isAlnum` tests `c >= 'a' && c <= 'z'` and friends.
- `agent_sdks/python/a2ui_core/.../expression_parser.py` — `is_alnum` tests `"a" <= c <= "z"` and friends.
- `swift/core/Sources/BasicCatalog/Functions/ExpressionParser.swift` — `scanPathOrIdentifier` tests `c.isLetter || c.isNumber`, which is Unicode-aware in Swift.

The ASCII range looks like a literal port of the same three lines between the first three implementations; Swift's reads like the idiomatic translation, and is the one that comes out right.

## Expected Behavior

I would suggest aligning the other three with Swift rather than the reverse:

- The data model is JSON, and JSON object keys are Unicode strings.
- Paths are JSON Pointer (RFC 6901), which places no restriction on the characters in a key.
- Nothing in the v0.9 specification or in `basic_catalog_implementation_guide.md` says an identifier inside `${...}` must be ASCII.
- Restricting it makes part of a legal data model unreachable from the UI, which is the asymmetry shown above.

Each fix is a couple of lines: Dart has `RegExp(r'\p{L}|\p{N}', unicode: true)` or `String.fromCharCode` category checks, TypeScript has `/[\p{L}\p{N}]/u`, Python has `str.isalnum()`.

If instead the intent is that identifiers are ASCII-only, then that belongs in the guide, and Swift should be tightened — but then agents need a documented way to reach a key that ASCII cannot spell.

## Steps to Reproduce

```
${señor}
```

through each implementation's `ExpressionParser.parse`. Full table above.

## Environment Details

- **OS**: macOS
- **Browser/Platform**: Dart 3.12.2, Node.js 25.2.1, Python 3.13, Swift 6.2.1
- **SDK/Package Name & Version**: all four at main (676a899)
- **Protocol Version**: v0.9

## Additional Context

Found by running all four parser implementations over the same corpus, the method used for #2496 and #2498, now extended from two implementations to four. Two other results from the same run:

- On the `null` keyword left open in #2496, Dart is alone: TypeScript, Python and Swift all produce `''`. That is worth weighing in that discussion, though the guide's wording still points the other way.
- The Python parser raises bare `ValueError` for every parse failure, rather than the `A2uiParseError` its own SDK defines in `a2ui/core/exceptions.py`. Since the conformance schema's error categories map onto that hierarchy, a Python harness for a parser suite cannot currently distinguish a protocol error from any other `ValueError`. Filing separately if useful.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

The issue points to the identifier scanner in each language's expression parser: dart/a2ui_core/lib/src/processing/expressions.dart, renderers/web_core/.../expression_parser.ts, agent_sdks/python/a2ui_core/.../expression_parser.py, and swift/core/Sources/BasicCatalog/Functions/ExpressionParser.swift. Start by locating the _isAlnum/isAlnum/is_alnum function in each file and replace the ASCII range check with a Unicode-aware one (e.g., str.isalnum() in Python, /[\p{L}\p{N}]/u in TypeScript). Verify the fix by parsing a template like '${señor}' and ensuring it no longer throws an error.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
dart, python, swift, typescript
Lĩnh vực
backend-api-design, internationalization
Loại issue
Lỗi
Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
75/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.