easy_talk 3.2.0 → 3.3.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -43
- data/CHANGELOG.md +105 -0
- data/README.md +510 -2018
- data/docs/json_schema_compliance.md +140 -26
- data/docs/primitive-schema-rfc.md +894 -0
- data/examples/ruby_llm/Gemfile +12 -0
- data/examples/ruby_llm/structured_output.rb +47 -0
- data/examples/ruby_llm/tools_integration.rb +49 -0
- data/lib/easy_talk/builders/base_builder.rb +2 -1
- data/lib/easy_talk/builders/boolean_builder.rb +2 -1
- data/lib/easy_talk/builders/collection_helpers.rb +4 -0
- data/lib/easy_talk/builders/composition_builder.rb +7 -2
- data/lib/easy_talk/builders/integer_builder.rb +2 -1
- data/lib/easy_talk/builders/null_builder.rb +4 -1
- data/lib/easy_talk/builders/number_builder.rb +4 -1
- data/lib/easy_talk/builders/object_builder.rb +64 -3
- data/lib/easy_talk/builders/registry.rb +15 -1
- data/lib/easy_talk/builders/string_builder.rb +3 -1
- data/lib/easy_talk/builders/temporal_builder.rb +7 -0
- data/lib/easy_talk/builders/tuple_builder.rb +89 -0
- data/lib/easy_talk/builders/typed_array_builder.rb +4 -2
- data/lib/easy_talk/builders/union_builder.rb +5 -1
- data/lib/easy_talk/configuration.rb +17 -2
- data/lib/easy_talk/errors.rb +1 -0
- data/lib/easy_talk/errors_helper.rb +3 -0
- data/lib/easy_talk/extensions/ruby_llm_compatibility.rb +58 -0
- data/lib/easy_talk/json_schema_equality.rb +46 -0
- data/lib/easy_talk/keywords.rb +0 -1
- data/lib/easy_talk/model.rb +42 -1
- data/lib/easy_talk/model_helper.rb +4 -0
- data/lib/easy_talk/naming_strategies.rb +4 -0
- data/lib/easy_talk/property.rb +7 -0
- data/lib/easy_talk/ref_helper.rb +6 -0
- data/lib/easy_talk/schema.rb +1 -0
- data/lib/easy_talk/schema_definition.rb +52 -6
- data/lib/easy_talk/schema_methods.rb +36 -5
- data/lib/easy_talk/sorbet_extension.rb +1 -0
- data/lib/easy_talk/type_introspection.rb +45 -1
- data/lib/easy_talk/types/tuple.rb +77 -0
- data/lib/easy_talk/validation_adapters/active_model_adapter.rb +350 -62
- data/lib/easy_talk/validation_adapters/active_model_schema_validation.rb +106 -0
- data/lib/easy_talk/validation_adapters/base.rb +12 -0
- data/lib/easy_talk/validation_adapters/none_adapter.rb +9 -0
- data/lib/easy_talk/validation_builder.rb +1 -0
- data/lib/easy_talk/version.rb +1 -1
- data/lib/easy_talk.rb +1 -0
- metadata +17 -4
|
@@ -8,9 +8,9 @@ This document defines the strategy for testing and improving `EasyTalk`'s compli
|
|
|
8
8
|
|
|
9
9
|
### Infrastructure
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- **Submodule**: Located at `spec/fixtures/json_schema_test_suite`.
|
|
12
|
+
- **Converter**: `spec/support/json_schema_converter.rb` dynamically converts raw JSON Schema definitions into `EasyTalk::Model` classes at runtime.
|
|
13
|
+
- **Runner**: `spec/integration/json_schema_compliance_spec.rb` iterates over the test suite files, generates models, and asserts valid/invalid behavior.
|
|
14
14
|
|
|
15
15
|
## Running the Tests
|
|
16
16
|
|
|
@@ -22,34 +22,148 @@ To run the compliance suite:
|
|
|
22
22
|
bundle exec rspec --tag json_schema_compliance spec/integration/json_schema_compliance_spec.rb
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Schema Wrapping Strategy
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Since `EasyTalk` models are always objects, the JSON Schema test suite's root-level primitive tests (e.g., `{"type": "integer"}` with data `5`) require adaptation.
|
|
28
28
|
|
|
29
|
-
###
|
|
30
|
-
The current test runner skips many tests (marked as `pending` or explicit `skip`).
|
|
31
|
-
* **Root Primitives**: `EasyTalk` models are Objects. Tests for root integers/strings are skipped.
|
|
32
|
-
* **Strict Naming**: Tests with property names that are invalid Ruby identifiers (e.g., `foo-bar`, `123`, `constructor`) are currently skipped.
|
|
33
|
-
* **Missing Keywords**: Keywords like `patternProperties`, `const`, and `oneOf` (in specific contexts) may fail.
|
|
29
|
+
### How It Works
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
1. **Select a Feature**: Pick a specific file (e.g., `properties.json`, `required.json`) or a skipped section.
|
|
37
|
-
2. **Un-skip Tests**: Remove the `skip` logic in `spec/integration/json_schema_compliance_spec.rb` for that feature.
|
|
38
|
-
3. **Run & Analyze**: Run the specific test file.
|
|
39
|
-
```bash
|
|
40
|
-
bundle exec rspec --tag json_schema_compliance
|
|
41
|
-
```
|
|
42
|
-
4. **Implement Fix**: Modify `EasyTalk` internals (e.g., `keywords.rb`, `schema_definition.rb`) to support the feature.
|
|
43
|
-
5. **Sanitize Inputs**: Update `JsonSchemaConverter` if the test case requires adaptation (e.g., mapping a JSON key to a safe Ruby method name via `as:`) without changing the underlying validation logic.
|
|
31
|
+
The `JsonSchemaConverter` uses a **wrapper property strategy**:
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
1. **Detection**: `needs_wrapping?` checks if the schema is non-object (no `type: object` or `properties` key)
|
|
34
|
+
2. **Wrapping**: Non-object schemas become a `value` property on a wrapper object
|
|
35
|
+
3. **Data transformation**: Primitive test data is wrapped as `{"value": data}`
|
|
36
|
+
|
|
37
|
+
**Example transformation:**
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Original JSON Schema test:
|
|
41
|
+
Schema: {"type": "integer", "minimum": 1}
|
|
42
|
+
Data: 5
|
|
43
|
+
Valid: true
|
|
44
|
+
|
|
45
|
+
Transformed for EasyTalk:
|
|
46
|
+
Schema: {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": { "value": {"type": "integer", "minimum": 1} },
|
|
49
|
+
"required": ["value"]
|
|
50
|
+
}
|
|
51
|
+
Data: {"value": 5}
|
|
52
|
+
Valid: true
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This preserves validation semantics while fitting EasyTalk's object-based model.
|
|
56
|
+
|
|
57
|
+
## Current Test Results
|
|
58
|
+
|
|
59
|
+
As of the latest run:
|
|
60
|
+
|
|
61
|
+
| Metric | Count |
|
|
62
|
+
|--------|-------|
|
|
63
|
+
| Total examples | 916 |
|
|
64
|
+
| Passing | ~193 |
|
|
65
|
+
| Failing | 165 |
|
|
66
|
+
| Pending (known unsupported) | 558 |
|
|
67
|
+
|
|
68
|
+
### Known Unsupported Features
|
|
69
|
+
|
|
70
|
+
The following test files are skipped entirely via `KNOWN_FAILURES`:
|
|
71
|
+
|
|
72
|
+
| File | Reason |
|
|
73
|
+
|------|--------|
|
|
74
|
+
| `not.json` | `not` keyword not supported |
|
|
75
|
+
| `anyOf.json` | `anyOf` validation not supported |
|
|
76
|
+
| `allOf.json` | `allOf` validation not supported |
|
|
77
|
+
| `oneOf.json` | `oneOf` validation not supported |
|
|
78
|
+
| `refRemote.json` | Remote `$ref` not supported |
|
|
79
|
+
| `dependencies.json` | Dependencies not supported |
|
|
80
|
+
| `definitions.json` | `$defs`/definitions not supported |
|
|
81
|
+
| `if-then-else.json` | Conditional logic not supported |
|
|
82
|
+
| `patternProperties.json` | Pattern properties not supported |
|
|
83
|
+
| `properties.json` | Complex property interactions not supported |
|
|
84
|
+
| `propertyNames.json` | Property names validation not supported |
|
|
85
|
+
| `ref.json` | Complex `$ref` not supported |
|
|
86
|
+
| `required.json` | Complex required checks not supported |
|
|
87
|
+
| `additionalItems.json` | Additional items not supported |
|
|
88
|
+
| `additionalProperties.json` | Additional properties validation not supported |
|
|
89
|
+
| `boolean_schema.json` | Boolean schemas (`true`/`false` as schema) not supported |
|
|
90
|
+
| `const.json` | `const` keyword not supported |
|
|
91
|
+
| `default.json` | Default keyword behavior not supported |
|
|
92
|
+
| `enum.json` | Enum validation not fully supported |
|
|
93
|
+
| `infinite-loop-detection.json` | Infinite loop detection not supported |
|
|
94
|
+
| `maxProperties.json` | Max properties not supported |
|
|
95
|
+
| `minProperties.json` | Min properties not supported |
|
|
96
|
+
|
|
97
|
+
## Compliance Gaps
|
|
98
|
+
|
|
99
|
+
The 165 failing tests reveal real validation gaps in EasyTalk:
|
|
100
|
+
|
|
101
|
+
### 1. Type Coercion (Intentional Behavior)
|
|
102
|
+
|
|
103
|
+
EasyTalk uses ActiveModel's numericality validation which coerces strings to numbers:
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
user = User.new(age: "30") # String
|
|
107
|
+
user.valid? # => true (coerced to integer 30)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Per JSON Schema, `"30"` should be invalid for `type: integer`. This is documented as **intentional behavior** for Rails compatibility. A `strict_types` configuration option is planned (see [#137](https://github.com/sergiobayona/easy_talk/issues/137)).
|
|
111
|
+
|
|
112
|
+
### 2. Format Validation Scope
|
|
113
|
+
|
|
114
|
+
JSON Schema specifies that format validations should only apply to strings and ignore other types. EasyTalk currently validates format on the assigned value regardless of type.
|
|
115
|
+
|
|
116
|
+
### 3. Empty String Presence
|
|
117
|
+
|
|
118
|
+
EasyTalk uses ActiveModel's presence validation for required fields, which rejects empty strings. JSON Schema considers `""` a valid string.
|
|
119
|
+
|
|
120
|
+
### 4. Array Type Validation
|
|
121
|
+
|
|
122
|
+
Array element types are not strictly validated at runtime.
|
|
123
|
+
|
|
124
|
+
### 5. Null Type
|
|
125
|
+
|
|
126
|
+
The `null` type is not fully implemented as a standalone type.
|
|
127
|
+
|
|
128
|
+
### 6. uniqueItems
|
|
129
|
+
|
|
130
|
+
Array uniqueness constraint is not enforced during validation.
|
|
131
|
+
|
|
132
|
+
## Workflow for Improvements
|
|
133
|
+
|
|
134
|
+
1. **Select a Feature**: Pick a specific file from `KNOWN_FAILURES` or analyze failing tests.
|
|
135
|
+
2. **Enable Tests**: Remove the file from `KNOWN_FAILURES` in the spec.
|
|
136
|
+
3. **Run & Analyze**:
|
|
137
|
+
```bash
|
|
138
|
+
bundle exec rspec --tag json_schema_compliance spec/integration/json_schema_compliance_spec.rb
|
|
139
|
+
```
|
|
140
|
+
4. **Implement Fix**: Modify EasyTalk internals to support the feature.
|
|
141
|
+
5. **Update Converter**: If needed, update `JsonSchemaConverter` for test adaptation.
|
|
142
|
+
|
|
143
|
+
## Critical Implementation Notes
|
|
144
|
+
|
|
145
|
+
### Reserved Words
|
|
146
|
+
|
|
147
|
+
Properties like `method`, `class`, `constructor` conflict with Ruby. The converter sanitizes these via `sanitize_property_name` and uses the `as:` option to preserve the original JSON key.
|
|
148
|
+
|
|
149
|
+
### Boolean Schemas
|
|
150
|
+
|
|
151
|
+
`properties: { foo: false }` is valid JSON Schema (property forbidden) but not currently supported.
|
|
152
|
+
|
|
153
|
+
### Strict Property Validation
|
|
154
|
+
|
|
155
|
+
EasyTalk raises `InvalidPropertyNameError` for invalid property names at definition time. Full compliance would require allowing arbitrary property keys.
|
|
49
156
|
|
|
50
157
|
## Contributing
|
|
51
158
|
|
|
52
159
|
When adding support for a new JSON Schema keyword:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
160
|
+
|
|
161
|
+
1. Check if a test file exists in `spec/fixtures/json_schema_test_suite/tests/draft7/`.
|
|
162
|
+
2. Remove the filename from `KNOWN_FAILURES` in `spec/integration/json_schema_compliance_spec.rb`.
|
|
163
|
+
3. Run the tests and analyze failures.
|
|
164
|
+
4. Implement the feature in EasyTalk.
|
|
165
|
+
5. Update this document with any new findings.
|
|
166
|
+
|
|
167
|
+
## Related Issues
|
|
168
|
+
|
|
169
|
+
- [#137](https://github.com/sergiobayona/easy_talk/issues/137) - Add `strict_types` configuration option
|