Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions .agents/skills/a2ui-dart-development/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
name: a2ui-dart-development
description: >-
Language version, analysis, formatting and verification rules for Dart code

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description field opens with the noun phrase Language version, analysis, formatting and verification rules, which triggers a lint_skill.py warning. Opening with a third-person verb keeps the skill frontmatter consistent with a2ui-dart-versioning and passes lint_skill.py without warnings.

Suggested change
Language version, analysis, formatting and verification rules for Dart code
Defines language version, analysis, formatting, and verification rules for Dart code

馃 Agent-generated

in the A2UI repository (the packages under dart/ and the Flutter samples
under samples/client/flutter/). Use when writing, refactoring or reviewing
Dart code, and before claiming that a line of Dart does not compile.
---

# Dart development

This skill is for anyone who writes or reviews Dart code in this repository:
the packages under `dart/`, such as `a2ui_core` and `a2ui_agent`, and the
Flutter samples under `samples/client/flutter/`. To record a change in a
package's `CHANGELOG.md`, see
[a2ui-dart-versioning](../a2ui-dart-versioning/SKILL.md).

## Language version

The lower bound of `environment: sdk:` in a package's `pubspec.yaml` is the
Dart language version of that package. Every language feature released up to
that version is valid in the package. Every later feature is a compile error,
whatever SDK is installed. The packages do not all require the same version,
so read the `pubspec.yaml` of the package you are changing. For example,
`dart/a2ui_core` requires `>=3.5.0` and `dart/a2ui_agent` requires
`>=3.8.0`, so `{'catalogId': ?catalogId}` is valid in `a2ui_agent` and a
compile error in `a2ui_core`.

Features that assistants often misjudge, with the version that added each:

- 3.0: records, patterns (`if (json case {'id': final String id})`, switch
expressions, destructuring), and the class modifiers `sealed`, `final`,
`base`, `interface` and `mixin class`.
- 3.3: extension types.
- 3.6: digit separators, such as `1_000_000`.
- 3.7: wildcard variables. A parameter or local named `_` declares nothing,
so several parameters of one function can each be named `_`.
- 3.8: null-aware elements. `{'key': ?value}` and `[?item]` leave the entry
out when the value is null.
- 3.10: dot shorthands. Where the context type is known, `.center` stands for
`Alignment.center` and `.new(...)` for a constructor call.
- 3.12: private named parameters, such as `A({required this._x})`.
- 3.13: primary constructors, such as `class Point(final int x, final int y);`.

The full list is in Dart's
[language evolution](https://dart.dev/resources/language/evolution) page.

When you write code:

- Use the features the package's language version allows, as the code around
yours does. Do not rewrite valid code into an older form. Some lints ask for
the newer form: with `package:lints/recommended.yaml`, which the root
`analysis_options.yaml` includes, `use_null_aware_elements` flags
`if (value != null) 'key': value` in a package where `'key': ?value` works.
- Do not use a feature newer than the package's language version, even when
your SDK supports it. Raising the lower bound of `environment: sdk:` drops
users of older SDKs, so it is a change of its own, with a reason and an
entry in `CHANGELOG.md`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scripts/fix_format.sh passes explicit --language-version=3.10 and --language-version=3.5 flags to dart format, and presubmit-lint.yml runs ./scripts/fix_format.sh --check on every pull request. The guidance for raising environment: sdk: mentions CHANGELOG.md but omits updating the pinned version in scripts/fix_format.sh.

Suggested change
entry in `CHANGELOG.md`.
entry in `CHANGELOG.md`, and an update to the pinned `--language-version` in
`scripts/fix_format.sh`.

馃 Agent-generated


When you review code, or before you say that a line does not compile:

1. Find the language version that the feature needs. Your training data may
predate the feature, so check the
[language evolution](https://dart.dev/resources/language/evolution) page
rather than relying on memory.
2. Compare it with the lower bound of `environment: sdk:` in the
`pubspec.yaml` of the package that holds the file.
3. If you can run commands, run `flutter analyze` in the package. When the
feature is newer than the package allows, the error names the version
that the feature needs.

Report a syntax error only when the feature is newer than the package's
language version or the analyzer reports one.

## Analysis

The root [`analysis_options.yaml`](../../../analysis_options.yaml) applies to
every package. A package's own `analysis_options.yaml`, where there is one,
includes it and adds exclusions. The settings that most often fail a change:

- `strict-casts`, `strict-inference` and `strict-raw-types`: a value read from
JSON is `Object?` or `dynamic`, so cast it or match it with a pattern before
using it as a narrower type.
- `lines_longer_than_80_chars`, which `dart/a2ui_cli` turns off.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The package 'dart/a2ui_cli' is not listed in the repository structure in 'AGENTS.md'. If this package does not exist or was renamed, please update this reference to the correct package name (e.g., 'a2ui_agent' or 'a2ui_flutter').

Suggested change
- `lines_longer_than_80_chars`, which `dart/a2ui_cli` turns off.
- 'lines_longer_than_80_chars', which 'dart/a2ui_agent' turns off.

- `specify_nonobvious_local_variable_types` and
`omit_obvious_local_variable_types`: write the type of a local variable when
its initializer does not make the type obvious, and leave it off when it
does. A literal, such as `3` or `<int>[]`, a constructor call with type
arguments, such as `List<int>.of(xs)`, and a local variable or parameter
make the type obvious. A getter or method call, such as `map.entries` or
`xs.first`, does not, and neither does `List.of(xs)`. The variable of a
`for (... in ...)` loop follows the same rule, with the iterable in place of
the initializer.
- `prefer_relative_imports` for imports within a package's `lib/`.
- `comment_references`: a name in `[brackets]` in a doc comment must resolve.
- `unawaited_futures`: await a future, or pass it to `unawaited`.

Comment on lines +96 to +97

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider adding a 'Common Pitfalls & Best Practices' subsection to document repository-specific Dart guidelines (such as map validation, safe element retrieval with 'firstOrNull', and raw string handling). This will make the skill file much more valuable for developers and automated agents.

Suggested change
- `unawaited_futures`: await a future, or pass it to `unawaited`.
- 'unawaited_futures': await a future, or pass it to 'unawaited'.
### Common Pitfalls & Best Practices
- Map Validation: When validating map inputs that can be either 'Map<dynamic, dynamic>' (e.g., from YAML parsers) or 'Map<String, Object?>', do not check 'is Map<String, Object?>' directly. Instead, check 'is Map' and use '.cast<String, Object?>()'. Defensive validation of map keys before calling '.cast' is unnecessary if the casted map is only accessed via direct key lookups (e.g., '[]') and never iterated.
- Safe Element Retrieval: Use 'firstOrNull' instead of 'first' on 'Iterable' to defensively avoid a 'StateError' if the collection is empty.
- Raw Strings: Backslashes have no special meaning inside raw string literals (prefixed with 'r') and do not escape the closing quote delimiter. Raw string literals can safely end with a backslash.
References
  1. In Dart, use .cast<String, Object?>() on Map instead of checking 'is Map<String, Object?>' directly, use firstOrNull instead of first to avoid StateError, and handle raw string literals correctly with trailing backslashes.

## Formatting

`dart format` picks its style from the language version. From 3.7 it uses
the tall style, which places arguments and trailing commas differently, so
the same code formats differently in `a2ui_core` and in `a2ui_agent`. Run
`dart format` in the package rather than copying the layout of another
package.

## Verification

Run these in the directory of each package you changed, as the
[Flutter packages workflow](../../../.github/workflows/flutter_packages_test.yml)
does:

```bash
dart pub get
dart format --output=none --set-exit-if-changed .
flutter analyze --fatal-infos
flutter test --test-randomize-ordering-seed=random
```

`--fatal-infos` fails on lints too, so a change that leaves any analyzer info
fails CI. In `dart/a2ui_agent`, CI also runs
`dart run tool/generate_express_parser.dart --check`, which fails when the
generated Express parser is out of date with the grammar. After editing the
grammar, run the tool without `--check` and commit its output.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flutter_packages_test.yml excludes dart/a2ui_agent/e2e_test and samples/client/flutter/restaurant_finder/e2e_test from flutter test, running only dart pub get, dart format, and flutter analyze --fatal-infos on them. Those e2e_test suites call live Gemini models via ./scripts/e2e_test.sh and require GEMINI_API_KEY to be set. Contributors or agents editing an e2e_test package will hit immediate GEMINI_API_KEY is not configured test failures during local verification.

Suggested change
grammar, run the tool without `--check` and commit its output.
grammar, run the tool without `--check` and commit its output. In `e2e_test`
packages (`dart/a2ui_agent/e2e_test` and
`samples/client/flutter/restaurant_finder/e2e_test`), `flutter_packages_test.yml`
runs only `dart pub get`, `dart format`, and `flutter analyze --fatal-infos`
because their tests require `GEMINI_API_KEY` (see `./scripts/e2e_test.sh`).

馃 Agent-generated

6 changes: 6 additions & 0 deletions .gemini/styleguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ auto-formatter, for each language, as described in
- Code should follow the guidance and principles described in
[the A2UI contribution guidelines](../CONTRIBUTING.md).
- If there are code changes, code should have tests.
- Dart code may use every language feature up to the lower bound of
`environment: sdk:` in its package's `pubspec.yaml`, such as null-aware
elements (`{'key': ?value}`) from Dart 3.8. Before calling Dart syntax
invalid, check that version, as
[the Dart development skill](../.agents/skills/a2ui-dart-development/SKILL.md)
describes.
- PR descriptions should include the Pre-Review Checklist from
[the PR template](https://github.com/flutter/genui/blob/main/.github/PULL_REQUEST_TEMPLATE.md),
with all of the steps completed.
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This document is the authoritative guide for AI agents working within the A2UI r
- **For implementing new SDKs in a client language:** Read [.agents/skills/a2ui-implement-new-sdks-for-client-language/SKILL.md](.agents/skills/a2ui-implement-new-sdks-for-client-language/SKILL.md)
- **For developing Python code anywhere in the repository (libraries, agents, tools, scripts, best practices):** Read [.agents/skills/a2ui-python-development/SKILL.md](.agents/skills/a2ui-python-development/SKILL.md)
- **For developing in the Swift codebase (core, SwiftUI, sample):** Read [.agents/skills/a2ui-swift-development/SKILL.md](.agents/skills/a2ui-swift-development/SKILL.md)
- **For writing or reviewing Dart code (`dart/`, Flutter samples):** Read [.agents/skills/a2ui-dart-development/SKILL.md](.agents/skills/a2ui-dart-development/SKILL.md)
- **For recording a change in the CHANGELOG of a Dart package under `dart/`, or releasing one:** Read [.agents/skills/a2ui-dart-versioning/SKILL.md](.agents/skills/a2ui-dart-versioning/SKILL.md)

---
Expand Down Expand Up @@ -63,7 +64,7 @@ For a detailed explanation of the methodology, lifecycle, and workflows, read th
- **`specification/`**: Versioned subdirectories (`v0_8/`, `v0_9/`, `v0_9_1/`, `v1_0/`) containing JSON schemas and human-readable guides (older versions also bundle their basic catalog). The `specification/<version>/docs/a2ui_protocol.md` file is the most important source of truth for each protocol version, and the `specification/<version>/json` directory contains the associated schemas for the protocol.
- **`python/`**: Core state SDK (`a2ui_core/`), framework-agnostic agent SDK (`a2ui_agent/`), agent framework integrations for A2A (`a2ui_a2a/`) and ADK (`a2ui_adk/`), and catalog packages (`catalogs/`) for Python.
- **`conformance/`**: Language-agnostic test suites (`core/`, `agent/`, `extensions/`) and test data (`test_data/`) for verifying behavioral parity across all SDK implementations.
- **`dart/`**: Dart implementations including core state model (`a2ui_core/`), agent SDK (`a2ui_agent/`), and Flutter framework adapter (`a2ui_flutter/`).
- **`dart/`**: Dart implementations including core state model (`a2ui_core/`), agent SDK (`a2ui_agent/`), Flutter framework adapter (`a2ui_flutter/`), and developer CLI (`a2ui_cli/`).
- **`kotlin/`**: Legacy Kotlin agent SDK (`agent_sdk_legacy/`).
- **`typescript/`**: Framework-agnostic Web Core state and protocol logic (`core/web_core/`), web framework renderers (`renderers/lit/`, `renderers/angular/`, `renderers/react/`), Markdown renderer (`renderers/markdown-it/`), TypeScript agent SDK (`agents/a2ui_agent/`), TypeScript catalog packages (`catalogs/`), and release scripts (`scripts/`).
- **`samples/`**: Ready-to-run demo agents utilizing Python ADK (`agent/adk/`), MCP server (`agent/mcp/`), and sample clients (`client/lit/`, `client/angular/`, `client/react/`, `client/flutter/`).
Expand Down
4 changes: 4 additions & 0 deletions dart/a2ui_agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

- Lower the SDK constraint to `>=3.8.0 <4.0.0`, the oldest version the
package's code compiles with. On Dart 3.8 and 3.9 the package resolves
once `json_schema_builder`, which `a2ui_core` depends on, publishes a
version that allows them; 0.1.7 requires Dart 3.10.
- Support cross-catalog `$ref` references across peer catalogs in
`resolveCatalogs`, `validatePayloads`, `DirectJsonPromptGenerator` (preserving
unbundled external `$ref`s in `Catalog.toJson()` while retaining transitive
Expand Down
6 changes: 5 additions & 1 deletion dart/a2ui_agent/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ repository: https://github.com/a2ui-project/a2ui/tree/main/dart/a2ui_agent
resolution: workspace

environment:
sdk: ">=3.10.0 <4.0.0"
# Lower than the bound of a2ui_flutter on purpose. a2ui_agent is plain Dart,
# used by agents on servers that do not run Flutter, so it allows every SDK
# its own code compiles with. 3.8 is the lowest one, because the code uses
# null-aware elements (`{'key': ?value}`).
sdk: ">=3.8.0 <4.0.0"

dependencies:
a2ui_core: ^0.3.0
Expand Down
4 changes: 4 additions & 0 deletions dart/a2ui_core/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ version: 0.3.0
resolution: workspace

environment:
# Lower than the bound of a2ui_flutter on purpose. a2ui_core is plain Dart,
# used outside Flutter too, such as by agents and servers, and by Flutter
# apps on older SDKs, so it allows every SDK its own code compiles with. 3.5
# is the lowest version that `resolution: workspace` allows.
sdk: ">=3.5.0 <4.0.0"

dependencies:
Expand Down
Loading