a2ui-core 0.2.0__tar.gz → 0.3.0__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.
Files changed (133) hide show
  1. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/.gitignore +3 -0
  2. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/CHANGELOG.md +74 -0
  3. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/PKG-INFO +2 -1
  4. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/pyproject.toml +2 -1
  5. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/__init__.py +20 -1
  6. a2ui_core-0.3.0/src/a2ui/core/basic_catalog/__init__.py +67 -0
  7. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_8/__init__.py +2 -0
  8. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_8/components.py +50 -45
  9. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_8/styles.py +2 -2
  10. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_9/__init__.py +2 -0
  11. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_9/components.py +110 -80
  12. a2ui_core-0.3.0/src/a2ui/core/basic_catalog/v0_9/function_apis.py +361 -0
  13. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_9/function_impls.py +68 -21
  14. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v0_9/styles.py +4 -3
  15. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v1_0/__init__.py +51 -4
  16. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v1_0/components.py +130 -100
  17. a2ui_core-0.3.0/src/a2ui/core/basic_catalog/v1_0/function_apis.py +372 -0
  18. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v1_0/function_impls.py +101 -59
  19. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/v1_0/functions.py +0 -6
  20. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/catalog/__init__.py +40 -9
  21. a2ui_core-0.3.0/src/a2ui/core/catalog/_spec_shape.py +269 -0
  22. a2ui_core-0.3.0/src/a2ui/core/catalog/catalog.py +919 -0
  23. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/catalog/functions.py +40 -7
  24. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/catalog/reference_map.py +19 -1
  25. a2ui_core-0.3.0/src/a2ui/core/catalog/system_functions.py +147 -0
  26. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/common/__init__.py +2 -0
  27. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/common/semver.py +31 -0
  28. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/expressions/expression_parser.py +64 -21
  29. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/v0_8.py +36 -9
  30. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/message_processor.py +107 -19
  31. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/resolution/component_context.py +6 -6
  32. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/resolution/data_context.py +183 -83
  33. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/resolution/generic_binder.py +132 -33
  34. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/rpc/rpc_handler.py +10 -13
  35. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/__init__.py +9 -0
  36. a2ui_core-0.3.0/src/a2ui/core/schema/_dynamic_types.py +372 -0
  37. a2ui_core-0.3.0/src/a2ui/core/schema/_json_schema.py +409 -0
  38. a2ui_core-0.3.0/src/a2ui/core/schema/agent_to_renderer_schema.py +229 -0
  39. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/common_types.py +85 -7
  40. a2ui_core-0.3.0/src/a2ui/core/schema/common_types_schema.py +421 -0
  41. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/__init__.py +8 -0
  42. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/client_capabilities.py +2 -2
  43. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/client_to_server.py +2 -2
  44. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/server_to_client.py +81 -10
  45. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/__init__.py +6 -0
  46. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/client_capabilities.py +7 -6
  47. a2ui_core-0.3.0/src/a2ui/core/schema/v0_9/common_types.py +354 -0
  48. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/server_capabilities.py +3 -3
  49. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/server_to_client.py +65 -18
  50. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/__init__.py +12 -2
  51. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/agent_capabilities.py +3 -3
  52. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/agent_to_renderer.py +111 -18
  53. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/catalog_definition.py +30 -21
  54. a2ui_core-0.3.0/src/a2ui/core/schema/v1_0/common_types.py +549 -0
  55. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/renderer_capabilities.py +2 -2
  56. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/renderer_to_agent.py +4 -4
  57. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/component_model.py +5 -7
  58. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/data_model.py +1 -6
  59. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/surface_components_model.py +9 -5
  60. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/surface_group_model.py +5 -9
  61. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/surface_model.py +15 -14
  62. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/validation_helpers.py +8 -7
  63. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/validation/__init__.py +16 -12
  64. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/validation/payload_validator.py +53 -26
  65. a2ui_core-0.3.0/src/a2ui/core/validation/schema_validator.py +138 -0
  66. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_accessibility.py +15 -3
  67. a2ui_core-0.3.0/tests/test_agent_to_renderer_schema.py +293 -0
  68. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_catalog.py +300 -622
  69. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_codegen_pydantic.py +535 -35
  70. a2ui_core-0.3.0/tests/test_common_types_schema.py +300 -0
  71. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_components.py +7 -29
  72. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_conformance.py +529 -99
  73. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_dynamic_types_strictness.py +10 -3
  74. a2ui_core-0.3.0/tests/test_expression_parser.py +115 -0
  75. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_functions.py +53 -2
  76. a2ui_core-0.3.0/tests/test_processing.py +601 -0
  77. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_resolution.py +384 -32
  78. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_rpc.py +0 -125
  79. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_schema.py +73 -0
  80. a2ui_core-0.3.0/tests/test_schema_patterns.py +141 -0
  81. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_state.py +43 -136
  82. a2ui_core-0.2.0/src/a2ui/core/basic_catalog/__init__.py +0 -20
  83. a2ui_core-0.2.0/src/a2ui/core/basic_catalog/v0_9/function_apis.py +0 -253
  84. a2ui_core-0.2.0/src/a2ui/core/basic_catalog/v1_0/function_apis.py +0 -254
  85. a2ui_core-0.2.0/src/a2ui/core/basic_catalog/v1_0/operator_apis.py +0 -31
  86. a2ui_core-0.2.0/src/a2ui/core/catalog/catalog.py +0 -1096
  87. a2ui_core-0.2.0/src/a2ui/core/schema/v0_9/common_types.py +0 -241
  88. a2ui_core-0.2.0/src/a2ui/core/schema/v1_0/common_types.py +0 -331
  89. a2ui_core-0.2.0/tests/test_expression_parser.py +0 -187
  90. a2ui_core-0.2.0/tests/test_processing.py +0 -1679
  91. a2ui_core-0.2.0/tests/test_specification_drift.py +0 -386
  92. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/README.md +0 -0
  93. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/_compat.py +0 -0
  94. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/components.py +0 -0
  95. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/expression_parser.py +0 -0
  96. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/function_apis.py +0 -0
  97. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/function_impls.py +0 -0
  98. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/locale_formatting.py +0 -0
  99. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/basic_catalog/styles.py +0 -0
  100. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/catalog/components.py +0 -0
  101. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/common/events.py +0 -0
  102. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/common/uax31.py +0 -0
  103. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/exceptions.py +0 -0
  104. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/expressions/__init__.py +0 -0
  105. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/__init__.py +0 -0
  106. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/__init__.py +0 -0
  107. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/base.py +0 -0
  108. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/factory.py +0 -0
  109. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/v0_9.py +0 -0
  110. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/adapters/v1_0.py +0 -0
  111. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/execution_context.py +0 -0
  112. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/format_pydantic_error.py +0 -0
  113. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/processing/operations.py +0 -0
  114. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/py.typed +0 -0
  115. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/resolution/__init__.py +0 -0
  116. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/resolution/resolved_binding.py +0 -0
  117. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/rpc/__init__.py +0 -0
  118. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/client_capabilities.py +0 -0
  119. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/client_to_server.py +0 -0
  120. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/constants.py +0 -0
  121. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/server_to_client.py +0 -0
  122. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/catalog_definition.py +0 -0
  123. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_8/constants.py +0 -0
  124. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/client_to_server.py +0 -0
  125. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v0_9/constants.py +0 -0
  126. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/schema/v1_0/constants.py +0 -0
  127. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/state/__init__.py +0 -0
  128. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/src/a2ui/core/version.py +0 -0
  129. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_adapters.py +0 -0
  130. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_compat_shims.py +0 -0
  131. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_format_pydantic_error.py +0 -0
  132. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_reference_map.py +0 -0
  133. {a2ui_core-0.2.0 → a2ui_core-0.3.0}/tests/test_semver.py +0 -0
@@ -15,6 +15,9 @@ site/
15
15
  .venv/
16
16
  coverage/
17
17
 
18
+ # Older a2ui-agent-sdk builds copied specification JSON into these directories.
19
+ # Nothing writes there anymore, but older checkouts can still have the files;
20
+ # these rules keep them out of commits and locally built wheels.
18
21
  ## old agent SDK path
19
22
  a2a_agents/python/a2ui_agent/src/a2ui/assets/**/*.json
20
23
  agent_sdks/python/src/a2ui/assets/**/*.json
@@ -1,5 +1,75 @@
1
1
  ## Unreleased
2
2
 
3
+ - `inline_local_refs` is exported from `a2ui.core`. It writes a schema's local
4
+ `#/` references inline, keeping references to common types, as
5
+ `Catalog.from_json` does
6
+ ([#2966](https://github.com/a2ui-project/a2ui/pull/2966)).
7
+ - (v1_0) The basic catalog's `and`, `or` and `not` read a ValidationResult
8
+ operand by its `valid` member instead of treating every non-empty dict as
9
+ truthy, so the v1.0 specification's nested
10
+ `and(required, or(required, required))` check is false when a field is
11
+ empty. The v0.9 catalog keeps plain truthiness, since its validators return
12
+ booleans.
13
+ - **BREAKING**: `DataContext` validates a function call's arguments as
14
+ written, before resolving the bindings and nested calls in them, and passes
15
+ the resolved values to the function body without validating them again.
16
+ The catalog's argument schema describes the written shape (a
17
+ `DynamicBoolean` admits a `{"@call": ...}`), so validating the resolved
18
+ values rejected, for example, the ValidationResult a v1.0 validator returns
19
+ to `and`, `or` or `not`. This matches web_core. Accordingly,
20
+ `FunctionImplementation.execute` no longer validates its arguments; callers
21
+ that invoke it directly validate the written arguments first, with
22
+ `PayloadValidator.validate_function` or the function's schema model.
23
+ - **BREAKING**: `ComponentModel.component_tree` names the component under
24
+ `component`, as an `updateComponents` message does, instead of `type`. A
25
+ property named `type` no longer replaces the component type in the tree,
26
+ and is kept. `ComponentModel.validate` validates that same dict, so a
27
+ property named `component` or `id` no longer replaces the model's own
28
+ during validation ([#2930](https://github.com/a2ui-project/a2ui/pull/2930)).
29
+ - The path syntax and function call depth checks in
30
+ `validate_recursion_and_paths` also read v1.0's `@path` and `@call`. A v1.0
31
+ payload with a malformed `@path`, or with `@call` expressions nested deeper
32
+ than the limit, used to pass validation
33
+ ([#3013](https://github.com/a2ui-project/a2ui/pull/3013)).
34
+ - JSON Schema patterns are validated with `regex` (`SchemaValidator` in
35
+ `a2ui.core.validation`), supporting Unicode property escapes such as
36
+ `\p{XID_Start}` and `\p{XID_Continue}` natively and anchoring `$` to the end
37
+ of the string per ECMA-262. `clean_schema_node` leaves `const`, `enum`,
38
+ `default`, and `examples` values untouched.
39
+ - `PayloadValidator` reports invalid `Extensions` keys even with
40
+ `allow_unknown_elements`.
41
+ - Catalog schemas reference `DynamicStringList` for string list values, as the
42
+ basic catalog does, instead of `DynamicValue`.
43
+ - Patch and pre-release protocol versions use the common types of their release
44
+ line (`1.0.0-rc.1` uses v1.0). Unparsable versions raise `A2uiCatalogError`
45
+ when a catalog schema is built.
46
+ - `GenericBinder` binds `$ref`s to catalog-defined dynamic defs (for example
47
+ `DynamicDate`).
48
+ - Add `CatalogApi`, the name for a schema-only `Catalog[ComponentApi, FunctionApi]`, exported from `a2ui.core`. `Catalog.from_json` returns it.
49
+ - Execute `functionCall` and `call` component actions locally in `GenericBinder` and prevent `SurfaceModel.dispatch_action` from emitting them as agent-facing `on_action` events.
50
+ - `ExpressionParser` accepts number literals with a leading decimal point
51
+ (`.5`, `-.5`, `+.5`, `.5e2`), including as function-call arguments. `.foo`
52
+ and `./x` are still paths.
53
+ - `ExpressionParser` raises `A2uiExpressionError` for a number literal outside
54
+ the double range, such as `1e999` or a 400-digit integer. It used to return
55
+ `inf` for float literals and an exact `int` for integer literals. Integer
56
+ literals longer than 4,300 digits no longer raise a bare `ValueError`.
57
+ - **BREAKING**: Optional JSON Schema `default` annotations in generated v0.9
58
+ and v1.0 Pydantic models are kept in field descriptions instead of becoming
59
+ field values. `const` values remain fixed.
60
+ - **BREAKING**: `BasicCatalog` from `a2ui.core.basic_catalog` is a factory that
61
+ returns the basic catalog of a protocol version, for example
62
+ `BasicCatalog("0.9")`. The package no longer re-exports the v0.9 basic
63
+ catalog's symbols; import them from `a2ui.core.basic_catalog.v0_9`.
64
+ - The v0.8 basic catalog's `catalog_id` is the v0.8 standard catalog ID,
65
+ `https://a2ui.org/specification/v0_8/standard_catalog_definition.json`.
66
+ - **BREAKING**: `PayloadValidator`, `SurfaceModel`, `SurfaceGroupModel`,
67
+ `DataContext`, and `RpcHandler` are no longer generic. They take `CatalogApi`
68
+ catalogs, so remove type arguments such as
69
+ `SurfaceModel[MyComponent, MyFunction]`.
70
+
71
+ ## 0.2.0 (2026-09-28)
72
+
3
73
  - **BREAKING**: Module paths and validation interfaces moved or changed in v0.2.0. Deprecation shims are provided for renamed public module paths; importing them emits a `DeprecationWarning` naming the new path. These shims will be removed in `v0.3.0`.
4
74
 
5
75
  **Shimmed Modules (Deprecated; removal in v0.3.0):**
@@ -144,6 +214,10 @@
144
214
  suite cannot be parsed, when a case has no `name` or `action`, or when an
145
215
  action has no handler. Suites the core library cannot run are named in
146
216
  `UNRUNNABLE_SUITES` with a reason.
217
+ - Move `@index` (`IndexApi`, `IndexArgs`, `IndexImplementation`) from
218
+ `a2ui.core.basic_catalog.v1_0` (`v1_0/operator_apis.py` removed) to
219
+ `a2ui.core.catalog`, where `system_functions_for` supplies it to v1.0 and
220
+ later catalogs.
147
221
 
148
222
  ## 0.1.1
149
223
 
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: a2ui-core
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: A2UI Python SDK - Core Library
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: babel>=2.14.0
7
7
  Requires-Dist: jsonschema>=4.26.0
8
8
  Requires-Dist: pydantic>=2.10.0
9
9
  Requires-Dist: referencing>=0.37.0
10
+ Requires-Dist: regex>=2024.11.6
10
11
  Description-Content-Type: text/markdown
11
12
 
12
13
  # A2UI Core Library (`a2ui_core`)
@@ -19,10 +19,11 @@ description = "A2UI Python SDK - Core Library"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.10"
21
21
  dependencies = [
22
+ "babel>=2.14.0",
22
23
  "jsonschema>=4.26.0",
23
24
  "pydantic>=2.10.0",
24
25
  "referencing>=0.37.0",
25
- "babel>=2.14.0",
26
+ "regex>=2024.11.6",
26
27
  ]
27
28
 
28
29
  [dependency-groups]
@@ -14,6 +14,12 @@
14
14
 
15
15
  from a2ui.core.catalog import (
16
16
  Catalog as Catalog,
17
+ CatalogApi as CatalogApi,
18
+ get_agent_to_renderer_schema_json as get_agent_to_renderer_schema_json,
19
+ get_agent_to_renderer_schema_map as get_agent_to_renderer_schema_map,
20
+ get_common_types_schema_json as get_common_types_schema_json,
21
+ get_common_types_schema_map as get_common_types_schema_map,
22
+ inline_local_refs as inline_local_refs,
17
23
  is_valid_uax31_identifier as is_valid_uax31_identifier,
18
24
  )
19
25
  from a2ui.core.exceptions import (
@@ -36,8 +42,13 @@ from a2ui.core.processing import (
36
42
  MessageProcessor as MessageProcessor,
37
43
  MessageProcessorOptions as MessageProcessorOptions,
38
44
  )
45
+ from a2ui.core.resolution import DataContext as DataContext
39
46
  from a2ui.core.rpc import CallOptions as CallOptions, RpcHandler as RpcHandler
40
- from a2ui.core.state import DataModel as DataModel, SurfaceModel as SurfaceModel
47
+ from a2ui.core.state import (
48
+ ComponentModel as ComponentModel,
49
+ DataModel as DataModel,
50
+ SurfaceModel as SurfaceModel,
51
+ )
41
52
  from a2ui.core.validation import (
42
53
  PayloadValidator as PayloadValidator,
43
54
  RELAXED_VALIDATION as RELAXED_VALIDATION,
@@ -61,6 +72,9 @@ __all__ = [
61
72
  "CallOptions",
62
73
  "CapabilitiesOptions",
63
74
  "Catalog",
75
+ "CatalogApi",
76
+ "ComponentModel",
77
+ "DataContext",
64
78
  "DataModel",
65
79
  "ExecutionContext",
66
80
  "MessageProcessor",
@@ -73,5 +87,10 @@ __all__ = [
73
87
  "SurfaceModel",
74
88
  "ValidationConfig",
75
89
  "__version__",
90
+ "get_agent_to_renderer_schema_json",
91
+ "get_agent_to_renderer_schema_map",
92
+ "get_common_types_schema_json",
93
+ "get_common_types_schema_map",
94
+ "inline_local_refs",
76
95
  "is_valid_uax31_identifier",
77
96
  ]
@@ -0,0 +1,67 @@
1
+ # Copyright 2024 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """A2UI Basic Catalog Module."""
16
+
17
+ from __future__ import annotations
18
+
19
+ from a2ui.core.catalog import CatalogApi
20
+ from a2ui.core.common import to_protocol_version
21
+ from a2ui.core.exceptions import A2uiError
22
+ from a2ui.core.schema import ProtocolVersion
23
+
24
+ from . import v0_8, v0_9, v1_0
25
+
26
+
27
+ def BasicCatalog(
28
+ protocol_version: ProtocolVersion | str,
29
+ locale: str | None = None,
30
+ ) -> CatalogApi:
31
+ """Returns the basic catalog instance for the specified protocol version.
32
+
33
+ Args:
34
+ protocol_version: The protocol version (e.g. ProtocolVersion.V0_9,
35
+ ProtocolVersion.V1_0, 'v0.9', '0.9', '1.0').
36
+ locale: Optional locale string for function implementations.
37
+
38
+ Returns:
39
+ The versioned BasicCatalog instance.
40
+
41
+ Raises:
42
+ A2uiError: If the protocol version is not supported.
43
+ """
44
+ try:
45
+ p_ver = to_protocol_version(protocol_version)
46
+ except (ValueError, A2uiError) as e:
47
+ raise A2uiError(
48
+ f"Unsupported protocol version for BasicCatalog: '{protocol_version}'."
49
+ ) from e
50
+
51
+ if p_ver == ProtocolVersion.V0_8:
52
+ return v0_8.BasicCatalog(locale=locale)
53
+ if p_ver in (ProtocolVersion.V0_9, ProtocolVersion.V0_9_1):
54
+ return v0_9.BasicCatalog(locale=locale)
55
+ if p_ver == ProtocolVersion.V1_0:
56
+ return v1_0.BasicCatalog(locale=locale)
57
+ raise A2uiError(
58
+ f"Unsupported protocol version for BasicCatalog: '{protocol_version}'."
59
+ )
60
+
61
+
62
+ __all__ = [
63
+ "BasicCatalog",
64
+ "v0_8",
65
+ "v0_9",
66
+ "v1_0",
67
+ ]
@@ -76,6 +76,8 @@ from ...catalog import Catalog, ModelComponentApi, FunctionImplementation
76
76
 
77
77
 
78
78
  def _basic_catalog_id(protocol_version: str) -> str:
79
+ if protocol_version == "v0.8":
80
+ return f"{PROTOCOL_BASE_URL}/v0_8/standard_catalog_definition.json"
79
81
  return (
80
82
  f"{PROTOCOL_BASE_URL}/{protocol_version.replace('.', '_')}/catalogs/basic/catalog.json"
81
83
  )
@@ -30,6 +30,7 @@ from ...schema.common_types import (
30
30
  FunctionCall,
31
31
  ListReference,
32
32
  SingleReference,
33
+ SpecBaseModel,
33
34
  StrictBaseModel,
34
35
  TemplateChildList,
35
36
  )
@@ -40,24 +41,24 @@ class TextItem(StrictBaseModel):
40
41
  """The value of the text field. This can be a literal string or a reference to a value in the data model ('path', e.g. '/user/name')."""
41
42
 
42
43
  model_config = ConfigDict(populate_by_name=True)
43
- literal_string: str | None = Field(None, alias="literalString")
44
- path: str | None = Field(None)
44
+ literal_string: str | None = Field(default=None, alias="literalString")
45
+ path: str | None = Field(default=None)
45
46
 
46
47
 
47
48
  class UrlItem(StrictBaseModel):
48
49
  """The URL of the audio to be played. This can be a literal string ('literal') or a reference to a value in the data model ('path', e.g. '/song/url')."""
49
50
 
50
51
  model_config = ConfigDict(populate_by_name=True)
51
- literal_string: str | None = Field(None, alias="literalString")
52
- path: str | None = Field(None)
52
+ literal_string: str | None = Field(default=None, alias="literalString")
53
+ path: str | None = Field(default=None)
53
54
 
54
55
 
55
56
  class AltTextItem(StrictBaseModel):
56
57
  """The alt text for the image. This can be a literal string ('literal') or a reference to a value in the data model ('path', e.g. '/thumbnail/altText')."""
57
58
 
58
59
  model_config = ConfigDict(populate_by_name=True)
59
- literal_string: str | None = Field(None, alias="literalString")
60
- path: str | None = Field(None)
60
+ literal_string: str | None = Field(default=None, alias="literalString")
61
+ path: str | None = Field(default=None)
61
62
 
62
63
 
63
64
  class NameItem(StrictBaseModel):
@@ -116,25 +117,25 @@ class NameItem(StrictBaseModel):
116
117
  "warning",
117
118
  ]
118
119
  | None
119
- ) = Field(None, alias="literalString")
120
- path: str | None = Field(None)
120
+ ) = Field(default=None, alias="literalString")
121
+ path: str | None = Field(default=None)
121
122
 
122
123
 
123
124
  class DescriptionItem(StrictBaseModel):
124
125
  """A description of the audio, such as a title or summary. This can be a literal string or a reference to a value in the data model ('path', e.g. '/song/title')."""
125
126
 
126
127
  model_config = ConfigDict(populate_by_name=True)
127
- literal_string: str | None = Field(None, alias="literalString")
128
- path: str | None = Field(None)
128
+ literal_string: str | None = Field(default=None, alias="literalString")
129
+ path: str | None = Field(default=None)
129
130
 
130
131
 
131
132
  class ChildrenItem(StrictBaseModel):
132
133
  """Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list."""
133
134
 
134
135
  model_config = ConfigDict(populate_by_name=True)
135
- explicit_list: list[str] | None = Field(None, alias="explicitList")
136
+ explicit_list: list[str] | None = Field(default=None, alias="explicitList")
136
137
  template: TemplateItem | None = Field(
137
- None,
138
+ default=None,
138
139
  description=(
139
140
  "A template for generating a dynamic list of children from a data model"
140
141
  " list. `componentId` is the component to use as a template, and"
@@ -161,31 +162,31 @@ class ActionItem(StrictBaseModel):
161
162
 
162
163
  model_config = ConfigDict(populate_by_name=True)
163
164
  name: str = Field(...)
164
- context: list[ContextItem] | None = Field(None)
165
+ context: list[ContextItem] | None = Field(default=None)
165
166
 
166
167
 
167
168
  class LabelItem(StrictBaseModel):
168
169
  """The label for the slider. This can be a literal string or a reference to a value in the data model ('path')."""
169
170
 
170
171
  model_config = ConfigDict(populate_by_name=True)
171
- literal_string: str | None = Field(None, alias="literalString")
172
- path: str | None = Field(None)
172
+ literal_string: str | None = Field(default=None, alias="literalString")
173
+ path: str | None = Field(default=None)
173
174
 
174
175
 
175
176
  class ValueItem(StrictBaseModel):
176
177
  """The current value of the slider. This can be a literal number ('literalNumber') or a reference to a value in the data model ('path', e.g. '/restaurant/cost')."""
177
178
 
178
179
  model_config = ConfigDict(populate_by_name=True)
179
- literal_number: float | None = Field(None, alias="literalNumber")
180
- path: str | None = Field(None)
180
+ literal_number: float | None = Field(default=None, alias="literalNumber")
181
+ path: str | None = Field(default=None)
181
182
 
182
183
 
183
184
  class SelectionItem(StrictBaseModel):
184
185
  """The currently selected values for the component. This can be a literal array of strings or a path to an array in the data model('path', e.g. '/hotel/options')."""
185
186
 
186
187
  model_config = ConfigDict(populate_by_name=True)
187
- literal_array: list[str] | None = Field(None, alias="literalArray")
188
- path: str | None = Field(None)
188
+ literal_array: list[str] | None = Field(default=None, alias="literalArray")
189
+ path: str | None = Field(default=None)
189
190
 
190
191
 
191
192
  class OptionItem(StrictBaseModel):
@@ -214,8 +215,8 @@ class TitleItem(StrictBaseModel):
214
215
  """The tab title. Defines the value as either a literal value or a path to data model value (e.g. '/options/title')."""
215
216
 
216
217
  model_config = ConfigDict(populate_by_name=True)
217
- literal_string: str | None = Field(None, alias="literalString")
218
- path: str | None = Field(None)
218
+ literal_string: str | None = Field(default=None, alias="literalString")
219
+ path: str | None = Field(default=None)
219
220
 
220
221
 
221
222
  class ContextItem(StrictBaseModel):
@@ -243,7 +244,7 @@ class TextComponent(ComponentCommon):
243
244
  ),
244
245
  )
245
246
  usage_hint: Literal["h1", "h2", "h3", "h4", "h5", "caption", "body"] | None = Field(
246
- None,
247
+ default=None,
247
248
  alias="usageHint",
248
249
  description=(
249
250
  "A hint for the base text style. One of: - `h1`: Largest heading. - `h2`:"
@@ -265,7 +266,7 @@ class ImageComponent(ComponentCommon):
265
266
  ),
266
267
  )
267
268
  alt_text: AltTextItem | None = Field(
268
- None,
269
+ default=None,
269
270
  alias="altText",
270
271
  description=(
271
272
  "The alt text for the image. This can be a literal string ('literal') or a"
@@ -274,7 +275,7 @@ class ImageComponent(ComponentCommon):
274
275
  ),
275
276
  )
276
277
  fit: Literal["contain", "cover", "fill", "none", "scale-down"] | None = Field(
277
- None,
278
+ default=None,
278
279
  description=(
279
280
  "Specifies how the image should be resized to fit its container. This"
280
281
  " corresponds to the CSS 'object-fit' property."
@@ -286,7 +287,7 @@ class ImageComponent(ComponentCommon):
286
287
  ]
287
288
  | None
288
289
  ) = Field(
289
- None,
290
+ default=None,
290
291
  alias="usageHint",
291
292
  description=(
292
293
  "A hint for the image size and style. One of: - `icon`: Small square icon."
@@ -330,7 +331,7 @@ class AudioPlayerComponent(ComponentCommon):
330
331
  ),
331
332
  )
332
333
  description: DescriptionItem | None = Field(
333
- None,
334
+ default=None,
334
335
  description=(
335
336
  "A description of the audio, such as a title or summary. This can be a"
336
337
  " literal string or a reference to a value in the data model ('path', e.g."
@@ -352,14 +353,14 @@ class RowComponent(ComponentCommon):
352
353
  Literal["center", "end", "spaceAround", "spaceBetween", "spaceEvenly", "start"]
353
354
  | None
354
355
  ) = Field(
355
- None,
356
+ default=None,
356
357
  description=(
357
358
  "Defines the arrangement of children along the main axis (horizontally)."
358
359
  " This corresponds to the CSS 'justify-content' property."
359
360
  ),
360
361
  )
361
362
  alignment: Literal["start", "center", "end", "stretch"] | None = Field(
362
- None,
363
+ default=None,
363
364
  description=(
364
365
  "Defines the alignment of children along the cross axis (vertically). This"
365
366
  " corresponds to the CSS 'align-items' property."
@@ -380,14 +381,14 @@ class ColumnComponent(ComponentCommon):
380
381
  Literal["start", "center", "end", "spaceBetween", "spaceAround", "spaceEvenly"]
381
382
  | None
382
383
  ) = Field(
383
- None,
384
+ default=None,
384
385
  description=(
385
386
  "Defines the arrangement of children along the main axis (vertically). This"
386
387
  " corresponds to the CSS 'justify-content' property."
387
388
  ),
388
389
  )
389
390
  alignment: Literal["center", "end", "start", "stretch"] | None = Field(
390
- None,
391
+ default=None,
391
392
  description=(
392
393
  "Defines the alignment of children along the cross axis (horizontally)."
393
394
  " This corresponds to the CSS 'align-items' property."
@@ -405,10 +406,11 @@ class ListComponent(ComponentCommon):
405
406
  ),
406
407
  )
407
408
  direction: Literal["vertical", "horizontal"] | None = Field(
408
- None, description="The direction in which the list items are laid out."
409
+ default=None, description="The direction in which the list items are laid out."
409
410
  )
410
411
  alignment: Literal["start", "center", "end", "stretch"] | None = Field(
411
- None, description="Defines the alignment of children along the cross axis."
412
+ default=None,
413
+ description="Defines the alignment of children along the cross axis.",
412
414
  )
413
415
 
414
416
 
@@ -434,7 +436,7 @@ class TabsComponent(ComponentCommon):
434
436
  class DividerComponent(ComponentCommon):
435
437
  component: Literal["Divider"] = "Divider"
436
438
  axis: Literal["horizontal", "vertical"] | None = Field(
437
- None, description="The orientation of the divider."
439
+ default=None, description="The orientation of the divider."
438
440
  )
439
441
 
440
442
 
@@ -465,7 +467,7 @@ class ButtonComponent(ComponentCommon):
465
467
  ),
466
468
  )
467
469
  primary: bool | None = Field(
468
- None,
470
+ default=None,
469
471
  description="Indicates if this button should be styled as the primary action.",
470
472
  )
471
473
  action: ActionItem = Field(
@@ -506,7 +508,7 @@ class TextFieldComponent(ComponentCommon):
506
508
  ),
507
509
  )
508
510
  text: TextItem | None = Field(
509
- None,
511
+ default=None,
510
512
  description=(
511
513
  "The value of the text field. This can be a literal string or a reference"
512
514
  " to a value in the data model ('path', e.g. '/user/name')."
@@ -515,10 +517,12 @@ class TextFieldComponent(ComponentCommon):
515
517
  text_field_type: (
516
518
  Literal["date", "longText", "number", "shortText", "obscured"] | None
517
519
  ) = Field(
518
- None, alias="textFieldType", description="The type of input field to display."
520
+ default=None,
521
+ alias="textFieldType",
522
+ description="The type of input field to display.",
519
523
  )
520
524
  validation_regexp: str | None = Field(
521
- None,
525
+ default=None,
522
526
  alias="validationRegexp",
523
527
  description=(
524
528
  "A regular expression used for client-side validation of the input."
@@ -537,12 +541,12 @@ class DateTimeInputComponent(ComponentCommon):
537
541
  ),
538
542
  )
539
543
  enable_date: bool | None = Field(
540
- None,
544
+ default=None,
541
545
  alias="enableDate",
542
546
  description="If true, allows the user to select a date.",
543
547
  )
544
548
  enable_time: bool | None = Field(
545
- None,
549
+ default=None,
546
550
  alias="enableTime",
547
551
  description="If true, allows the user to select a time.",
548
552
  )
@@ -562,22 +566,23 @@ class MultipleChoiceComponent(ComponentCommon):
562
566
  ..., description="An array of available options for the user to choose from."
563
567
  )
564
568
  max_allowed_selections: int | None = Field(
565
- None,
569
+ default=None,
566
570
  alias="maxAllowedSelections",
567
571
  description="The maximum number of options that the user is allowed to select.",
568
572
  )
569
573
  variant: Literal["checkbox", "chips"] | None = Field(
570
- None, description="The display style of the component."
574
+ default=None, description="The display style of the component."
571
575
  )
572
576
  filterable: bool | None = Field(
573
- None, description="If true, displays a search input to filter the options."
577
+ default=None,
578
+ description="If true, displays a search input to filter the options.",
574
579
  )
575
580
 
576
581
 
577
582
  class SliderComponent(ComponentCommon):
578
583
  component: Literal["Slider"] = "Slider"
579
584
  label: LabelItem | None = Field(
580
- None,
585
+ default=None,
581
586
  description=(
582
587
  "The label for the slider. This can be a literal string or a reference to a"
583
588
  " value in the data model ('path')."
@@ -592,10 +597,10 @@ class SliderComponent(ComponentCommon):
592
597
  ),
593
598
  )
594
599
  min_value: float | None = Field(
595
- None, alias="minValue", description="The minimum value of the slider."
600
+ default=None, alias="minValue", description="The minimum value of the slider."
596
601
  )
597
602
  max_value: float | None = Field(
598
- None, alias="maxValue", description="The maximum value of the slider."
603
+ default=None, alias="maxValue", description="The maximum value of the slider."
599
604
  )
600
605
 
601
606
 
@@ -21,9 +21,9 @@ from ...schema.common_types import StrictBaseModel
21
21
 
22
22
  class Styles(BaseModel):
23
23
  model_config = ConfigDict(populate_by_name=True)
24
- font: str | None = Field(None, description="The primary font for the UI.")
24
+ font: str | None = Field(default=None, description="The primary font for the UI.")
25
25
  primary_color: str | None = Field(
26
- None,
26
+ default=None,
27
27
  alias="primaryColor",
28
28
  description="The primary UI color as a hexadecimal code (e.g., '#00BFFF').",
29
29
  pattern=r"^#[0-9a-fA-F]{6}$",
@@ -84,6 +84,8 @@ from ...catalog import Catalog, ModelComponentApi, FunctionImplementation
84
84
 
85
85
 
86
86
  def _basic_catalog_id(protocol_version: str) -> str:
87
+ if protocol_version == "v0.8":
88
+ return f"{PROTOCOL_BASE_URL}/v0_8/standard_catalog_definition.json"
87
89
  return (
88
90
  f"{PROTOCOL_BASE_URL}/{protocol_version.replace('.', '_')}/catalogs/basic/catalog.json"
89
91
  )