feat: add Dictionary support to @Generable macro#45
feat: add Dictionary support to @Generable macro#45kylebrowning wants to merge 1 commit intochristopherkarani:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00e89e55da
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let valueSchema = Value.generationSchema | ||
| return GenerationSchema.primitive( | ||
| [String: Value].self, | ||
| node: .dictionary(GenerationSchema.DictionaryNode(description: nil, values: valueSchema.root)) |
There was a problem hiding this comment.
Carry value defs when building dictionary schema
When Value.generationSchema.root is a $ref (for example, Value is another @Generable type), this code stores that ref in additionalProperties but drops Value.generationSchema.defs by returning GenerationSchema.primitive(...). GenerationSchema.Property.buildNode later only merges schema.defs, so schemas for [String: Value] can emit dangling $refs with missing definitions, which breaks nested dictionary value typing in structured generation/tool schemas.
Useful? React with 👍 / 👎.
| if let desc = dict.description { | ||
| try container.encode(desc, forKey: .description) | ||
| } | ||
| try container.encode(dict.values, forKey: .additionalProperties) |
There was a problem hiding this comment.
Keep Anthropic tool schema compatibility for dictionaries
This new encoding writes additionalProperties as a nested schema object, but Anthropic conversion currently reads additionalProperties only as Bool (convertToInputSchema and convertToPropertySchema in AnthropicProvider+Helpers.swift), so dictionary constraints are silently dropped to an unconstrained object for Anthropic tool calls. As a result, dictionary-typed tool arguments are not validated to the declared value type and can produce downstream conversion failures.
Useful? React with 👍 / 👎.
Summary
@Generablecurrently doesn't supportDictionaryproperty types. Properties like[String: String]cause compilation errors becauseDictionarydoesn't conform toGenerableorConvertibleFromGeneratedContent.This PR adds full Dictionary support across all three layers:
Schema layer (
GenerationSchema.swift).dictionary(DictionaryNode)case toGenerationSchema.NodeDictionaryNodestruct withdescriptionandvaluesfields{"type": "object", "additionalProperties": <value_schema>}properties) from dictionaries (withadditionalProperties)Protocol layer (
Generable.swift)extension Dictionary: Generable where Key == String, Value: Generable.dictionary(values: Value.schema)for the schemaContent conversion layer
Dictionary: ConvertibleFromGeneratedContent— extracts key-value pairs from.structurecontentDictionary: ConvertibleToGeneratedContent— converts entries to.structurecontentMacro layer
No changes needed — the existing macro already had
isDictionaryType()andextractDictionaryTypes()helpers. With Dictionary now conforming toGenerable, the existing code paths work correctly.Example
Test plan
swift buildpasses on the Conduit repo@Generablestructs with[String: String]properties compile and generate correct schemas