From 1e80ae508ef84088a43ae7c556efcde50f3593a8 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Thu, 1 Feb 2024 12:41:08 +0100 Subject: [PATCH] Implement derive macro to convert structs to GBNF rules. This is the initial implementation of a derive macro implementation that converts structs into GBNF grammars. This simplies the code by allowing us to get rid of all the hardcoded GBNF strings, prevents errors from manually editing or copying said strings, and other benefits. The main purpose of this implementation is to lay the foundation for generating hyper-specific GBNF rules that will allow us to limit LLM output to specific UUIDs. LLM can't generate a weird response for an exit or entity ID if it is only allowed to generate a specific list of UUIDs in its response. --- .gitignore | 2 +- Cargo.lock | 662 ++-- Cargo.toml | 42 +- game.db | Bin 12288 -> 0 bytes game/Cargo.lock | 2836 +++++++++++++++++ game/Cargo.toml | 39 + build.rs => game/build.rs | 0 koboldcpp.json => game/koboldcpp.json | 0 {src => game/src}/ai/coherence.rs | 0 {src => game/src}/ai/convo.rs | 0 game/src/ai/gbnf/events.rs | 22 + game/src/ai/gbnf/mod.rs | 0 {src => game/src}/ai/generator.rs | 0 {src => game/src}/ai/logic.rs | 0 {src => game/src}/ai/mod.rs | 1 + game/src/ai/prompts/event_instructions.rs | 11 + .../src}/ai/prompts/execution_prompts.rs | 0 {src => game/src}/ai/prompts/mod.rs | 0 .../src}/ai/prompts/parsing_prompts.rs | 24 +- game/src/ai/prompts/tables.rs | 96 + {src => game/src}/ai/prompts/world_prompts.rs | 0 {src => game/src}/commands/builtins.rs | 0 {src => game/src}/commands/coherence.rs | 0 {src => game/src}/commands/converter.rs | 0 {src => game/src}/commands/mod.rs | 0 {src => game/src}/db/mod.rs | 0 {src => game/src}/db/queries.rs | 0 {src => game/src}/game_loop.rs | 0 {src => game/src}/io.rs | 0 {src => game/src}/kobold_api.rs | 0 {src => game/src}/main.rs | 5 +- {src => game/src}/models/christmas.txt | 0 {src => game/src}/models/coherence/mod.rs | 0 {src => game/src}/models/commands.rs | 6 +- {src => game/src}/models/mod.rs | 0 {src => game/src}/models/world/items.rs | 0 {src => game/src}/models/world/mod.rs | 0 {src => game/src}/models/world/people.rs | 0 {src => game/src}/models/world/raw.rs | 0 {src => game/src}/models/world/scenes.rs | 0 {src => game/src}/state.rs | 0 gbnf/Cargo.toml | 12 + gbnf/src/lib.rs | 386 +++ gbnf_derive/Cargo.toml | 14 + gbnf_derive/src/lib.rs | 110 + src/ai/gbnf/mod.rs | 217 ++ 46 files changed, 4147 insertions(+), 338 deletions(-) delete mode 100644 game.db create mode 100644 game/Cargo.lock create mode 100644 game/Cargo.toml rename build.rs => game/build.rs (100%) rename koboldcpp.json => game/koboldcpp.json (100%) rename {src => game/src}/ai/coherence.rs (100%) rename {src => game/src}/ai/convo.rs (100%) create mode 100644 game/src/ai/gbnf/events.rs create mode 100644 game/src/ai/gbnf/mod.rs rename {src => game/src}/ai/generator.rs (100%) rename {src => game/src}/ai/logic.rs (100%) rename {src => game/src}/ai/mod.rs (86%) create mode 100644 game/src/ai/prompts/event_instructions.rs rename {src => game/src}/ai/prompts/execution_prompts.rs (100%) rename {src => game/src}/ai/prompts/mod.rs (100%) rename {src => game/src}/ai/prompts/parsing_prompts.rs (83%) create mode 100644 game/src/ai/prompts/tables.rs rename {src => game/src}/ai/prompts/world_prompts.rs (100%) rename {src => game/src}/commands/builtins.rs (100%) rename {src => game/src}/commands/coherence.rs (100%) rename {src => game/src}/commands/converter.rs (100%) rename {src => game/src}/commands/mod.rs (100%) rename {src => game/src}/db/mod.rs (100%) rename {src => game/src}/db/queries.rs (100%) rename {src => game/src}/game_loop.rs (100%) rename {src => game/src}/io.rs (100%) rename {src => game/src}/kobold_api.rs (100%) rename {src => game/src}/main.rs (98%) rename {src => game/src}/models/christmas.txt (100%) rename {src => game/src}/models/coherence/mod.rs (100%) rename {src => game/src}/models/commands.rs (97%) rename {src => game/src}/models/mod.rs (100%) rename {src => game/src}/models/world/items.rs (100%) rename {src => game/src}/models/world/mod.rs (100%) rename {src => game/src}/models/world/people.rs (100%) rename {src => game/src}/models/world/raw.rs (100%) rename {src => game/src}/models/world/scenes.rs (100%) rename {src => game/src}/state.rs (100%) create mode 100644 gbnf/Cargo.toml create mode 100644 gbnf/src/lib.rs create mode 100644 gbnf_derive/Cargo.toml create mode 100644 gbnf_derive/src/lib.rs create mode 100644 src/ai/gbnf/mod.rs diff --git a/.gitignore b/.gitignore index a4d5a85..13e3525 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/target +**/target surreal.db/ todo.org config.toml diff --git a/Cargo.lock b/Cargo.lock index ef50587..55fefab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "getrandom", @@ -62,7 +62,9 @@ dependencies = [ "crossterm", "eventsource-client", "futures", - "itertools 0.12.0", + "gbnf", + "gbnf_derive", + "itertools 0.12.1", "polodb_core", "prettyplease", "progenitor", @@ -97,9 +99,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arangors" @@ -108,7 +110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e16853bc26550fe3c09e3c6c77e595108c3634fc6d1161e52408ca786095903" dependencies = [ "async-trait", - "base64 0.21.5", + "base64 0.21.7", "http", "log", "maybe-async", @@ -123,9 +125,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" +checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" dependencies = [ "flate2", "futures-core", @@ -142,18 +144,18 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -162,6 +164,17 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" +[[package]] +name = "auto_impl" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -191,9 +204,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" @@ -203,9 +216,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" dependencies = [ "serde", ] @@ -233,15 +246,15 @@ dependencies = [ [[package]] name = "bson" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c18b51216e1f74b9d769cead6ace2f82b965b807e3d73330aabe9faec31c84" +checksum = "ce21468c1c9c154a85696bb25c20582511438edb6ad67f846ba1378ffdd80222" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", "base64 0.13.1", "bitvec", "hex", - "indexmap 1.9.3", + "indexmap 2.2.2", "js-sys", "once_cell", "rand", @@ -293,15 +306,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -325,9 +338,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -335,9 +348,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -359,9 +372,9 @@ dependencies = [ [[package]] name = "crc64fast" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd3d10c557924c719a61e583165e31a0d8131b20415d6858983e67d1eb8a82bd" +checksum = "26bb92ecea20291efcf0009e2713d64b7e327dedb8ce780545250f24075429e2" [[package]] name = "crossterm" @@ -369,7 +382,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossterm_winapi", "libc", "mio", @@ -462,12 +475,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -500,7 +513,7 @@ checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ "cfg-if", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -536,9 +549,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -551,9 +564,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -566,9 +579,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -576,15 +589,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -593,38 +606,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -638,6 +651,29 @@ dependencies = [ "slab", ] +[[package]] +name = "gbnf" +version = "0.1.0" +dependencies = [ + "auto_impl", + "itertools 0.12.1", + "quote", + "serde", + "serde_derive", + "syn 2.0.48", +] + +[[package]] +name = "gbnf_derive" +version = "0.1.0" +dependencies = [ + "auto_impl", + "gbnf", + "itertools 0.12.1", + "quote", + "syn 2.0.48", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -659,9 +695,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -672,15 +708,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -688,7 +724,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.2.2", "slab", "tokio", "tokio-util", @@ -710,14 +746,14 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.6", + "ahash 0.8.7", ] [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -727,9 +763,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hex" @@ -739,9 +775,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -750,9 +786,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -773,9 +809,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -788,7 +824,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -839,9 +875,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -862,9 +898,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -883,12 +919,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "serde", ] @@ -909,24 +945,24 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -950,9 +986,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linked-hash-map" @@ -962,15 +998,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -993,20 +1029,20 @@ dependencies = [ [[package]] name = "maybe-async" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +checksum = "afc95a651c82daf7004c824405aa1019723644950d488571bd718e3ed84646ed" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -1040,14 +1076,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1084,9 +1120,15 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.17" @@ -1124,42 +1166,42 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openapiv3" -version = "2.0.0-rc.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25316406f0191559189c56d99731b63130775de7284d98df5e976ce67882ca8a" +checksum = "cc02deea53ffe807708244e5914f6b099ad7015a207ee24317c22112e17d9c5c" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.2", "serde", "serde_json", ] [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "foreign-types", "libc", @@ -1176,7 +1218,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1187,9 +1229,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" dependencies = [ "cc", "libc", @@ -1230,15 +1272,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1249,9 +1291,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" @@ -1284,7 +1326,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1300,22 +1342,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1332,9 +1374,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "polodb_core" @@ -1423,17 +1465,17 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "progenitor" -version = "0.4.0" -source = "git+https://github.com/oxidecomputer/progenitor#545266c6f3899c4421e82458bff5dc0e1ae5d7de" +version = "0.5.0" +source = "git+https://github.com/oxidecomputer/progenitor#86b60220b88a2ca3629fb87acf8f83ff35f63aaa" dependencies = [ "progenitor-client", "progenitor-impl", @@ -1443,8 +1485,8 @@ dependencies = [ [[package]] name = "progenitor-client" -version = "0.4.0" -source = "git+https://github.com/oxidecomputer/progenitor#545266c6f3899c4421e82458bff5dc0e1ae5d7de" +version = "0.5.0" +source = "git+https://github.com/oxidecomputer/progenitor#86b60220b88a2ca3629fb87acf8f83ff35f63aaa" dependencies = [ "bytes", "futures-core", @@ -1457,13 +1499,13 @@ dependencies = [ [[package]] name = "progenitor-impl" -version = "0.4.0" -source = "git+https://github.com/oxidecomputer/progenitor#545266c6f3899c4421e82458bff5dc0e1ae5d7de" +version = "0.5.0" +source = "git+https://github.com/oxidecomputer/progenitor#86b60220b88a2ca3629fb87acf8f83ff35f63aaa" dependencies = [ "getopts", "heck", "http", - "indexmap 2.1.0", + "indexmap 2.2.2", "openapiv3", "proc-macro2", "quote", @@ -1471,7 +1513,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "syn 2.0.39", + "syn 2.0.48", "thiserror", "typify", "unicode-ident", @@ -1479,8 +1521,8 @@ dependencies = [ [[package]] name = "progenitor-macro" -version = "0.4.0" -source = "git+https://github.com/oxidecomputer/progenitor#545266c6f3899c4421e82458bff5dc0e1ae5d7de" +version = "0.5.0" +source = "git+https://github.com/oxidecomputer/progenitor#86b60220b88a2ca3629fb87acf8f83ff35f63aaa" dependencies = [ "openapiv3", "proc-macro2", @@ -1491,14 +1533,14 @@ dependencies = [ "serde_json", "serde_tokenstream", "serde_yaml", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1539,15 +1581,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -1579,9 +1612,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -1591,9 +1624,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -1618,12 +1651,12 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ "async-compression", - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -1641,9 +1674,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -1701,15 +1736,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1737,6 +1772,15 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -1745,24 +1789,24 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "chrono", "dyn-clone", @@ -1774,9 +1818,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -1825,9 +1869,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.190" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -1854,13 +1898,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1876,11 +1920,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -1906,7 +1950,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1923,11 +1967,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.27" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -1986,9 +2030,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smawk" @@ -1996,16 +2040,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.5" @@ -2013,7 +2047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2056,7 +2090,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2072,15 +2106,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -2134,15 +2174,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -2158,32 +2198,33 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "time" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -2198,10 +2239,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -2222,9 +2264,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -2234,9 +2276,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2251,13 +2293,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2316,7 +2358,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.2", "toml_datetime", "winnow", ] @@ -2348,9 +2390,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twox-hash" @@ -2381,8 +2423,8 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typify" -version = "0.0.14" -source = "git+https://github.com/oxidecomputer/typify#5f9235d935f66a518879ef6d726c475b1ddda85a" +version = "0.0.15" +source = "git+https://github.com/oxidecomputer/typify#1f97f167923f001818d461b1286f8a5242abf8b1" dependencies = [ "typify-impl", "typify-macro", @@ -2390,8 +2432,8 @@ dependencies = [ [[package]] name = "typify-impl" -version = "0.0.14" -source = "git+https://github.com/oxidecomputer/typify#5f9235d935f66a518879ef6d726c475b1ddda85a" +version = "0.0.15" +source = "git+https://github.com/oxidecomputer/typify#1f97f167923f001818d461b1286f8a5242abf8b1" dependencies = [ "heck", "log", @@ -2400,15 +2442,15 @@ dependencies = [ "regress", "schemars", "serde_json", - "syn 2.0.39", + "syn 2.0.48", "thiserror", "unicode-ident", ] [[package]] name = "typify-macro" -version = "0.0.14" -source = "git+https://github.com/oxidecomputer/typify#5f9235d935f66a518879ef6d726c475b1ddda85a" +version = "0.0.15" +source = "git+https://github.com/oxidecomputer/typify#1f97f167923f001818d461b1286f8a5242abf8b1" dependencies = [ "proc-macro2", "quote", @@ -2416,7 +2458,7 @@ dependencies = [ "serde", "serde_json", "serde_tokenstream", - "syn 2.0.39", + "syn 2.0.48", "typify-impl", ] @@ -2442,9 +2484,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2481,9 +2523,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unsafe-libyaml" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "untrusted" @@ -2493,9 +2535,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -2570,9 +2612,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2580,24 +2622,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -2607,9 +2649,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2617,28 +2659,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-streams" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" dependencies = [ "futures-util", "js-sys", @@ -2649,9 +2691,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -2691,11 +2733,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -2704,7 +2746,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -2713,13 +2764,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -2728,36 +2794,72 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2765,10 +2867,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "winnow" -version = "0.5.32" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "818ce546a11a9986bc24f93d0cdf38a8a1a400f1473ea8c82e59f6e0ffab9249" dependencies = [ "memchr", ] @@ -2780,7 +2888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2803,20 +2911,20 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] diff --git a/Cargo.toml b/Cargo.toml index 2e3029b..c2aba58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,37 +1,7 @@ -[package] -name = "ai-game" -version = "0.1.0" -edition = "2021" +[workspace] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -tokio = { version = "1", features = ["full"] } -anyhow = "1.0.75" -futures = "0.3" -eventsource-client = "0.11.0" -progenitor = { git = "https://github.com/oxidecomputer/progenitor" } -progenitor-client = { git = "https://github.com/oxidecomputer/progenitor" } -reqwest = { version = "0.11", features = ["json", "stream"] } -serde = { version = "1.0", features = ["derive", "rc"] } -serde_json = "1.0" -async-trait = "0.1.74" -reedline = "0.27.1" -async-recursion = "1.0.5" -thiserror = "1.0.53" -strum = {version = "0.25", features = [ "derive" ] } -uuid = {version = "1.6.1", features = [ "std", "v7", "fast-rng" ] } -polodb_core = "4.4.0" -arangors = "0.5.4" -itertools = "0.12.0" -crossterm = "0.27.0" -textwrap = "0.16.0" -config = "0.13.4" -tabled = "0.15.0" - -[build-dependencies] -prettyplease = "0.1.25" -progenitor = { git = "https://github.com/oxidecomputer/progenitor" } -progenitor-client = { git = "https://github.com/oxidecomputer/progenitor" } -serde_json = "1.0" -syn = "1.0" +members = [ + "game", + "gbnf", + "gbnf_derive" +] diff --git a/game.db b/game.db deleted file mode 100644 index 9612f50c8f1fef26357533069269269308c6889d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI$ze~eF6bJCvONxjfI&?2$!KEdNpqsQo!9jn8e~j}`(D zfB*y_009U<00Izz00bZafnN&PC9&SFHx8Sfqh`BKB9bal5gEhdiH_H$1-{9WB0e*U zmN+4`?<*O5Iv~pnjx}v@ve@tQ`^iy(?OYFEhRdtZx8seco67ipQHIKmRXwJ?^T&s) zWXsQWT{YmTiu}MOwR~#fWKm7p>P~XmO)kk}9&|Ap@hIsED_oxEzpW90+f$UDH(0)w zZo2+8u71}cx+;>PXVSj6qlvF6+bC^(MJ0a0a_I8o5SEs*Z)P3c3SFsahE+srkXrRz zo>`nI<_jkYvNq>q9b|j4>Se#xHla58y&8CN{<~QW0Rad=00Izz00bZa0SG_<0{ String { +// CHANGE_SCENE_BNF.to_string() +// } +// } diff --git a/game/src/ai/gbnf/mod.rs b/game/src/ai/gbnf/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ai/generator.rs b/game/src/ai/generator.rs similarity index 100% rename from src/ai/generator.rs rename to game/src/ai/generator.rs diff --git a/src/ai/logic.rs b/game/src/ai/logic.rs similarity index 100% rename from src/ai/logic.rs rename to game/src/ai/logic.rs diff --git a/src/ai/mod.rs b/game/src/ai/mod.rs similarity index 86% rename from src/ai/mod.rs rename to game/src/ai/mod.rs index 4a5dfb9..97f5848 100644 --- a/src/ai/mod.rs +++ b/game/src/ai/mod.rs @@ -1,4 +1,5 @@ pub(self) mod coherence; +pub mod gbnf; pub mod convo; pub mod generator; pub mod prompts; diff --git a/game/src/ai/prompts/event_instructions.rs b/game/src/ai/prompts/event_instructions.rs new file mode 100644 index 0000000..13e283d --- /dev/null +++ b/game/src/ai/prompts/event_instructions.rs @@ -0,0 +1,11 @@ +use super::tables::exit_table; +use crate::models::world::scenes::Scene; + +pub(super) const CHANGE_SCENE: &'static str = r#" +The player is moving to a new scene. Pick the correct scene key from the exits table, based on the place the player wants to go. +"#; + +pub(super) fn change_scene(scene: &Scene) -> String { + // currently have exits table in beginning of prompt. + CHANGE_SCENE.replacen("{EXIT_TABLE}", &exit_table(&scene.exits).to_string(), 1) +} diff --git a/src/ai/prompts/execution_prompts.rs b/game/src/ai/prompts/execution_prompts.rs similarity index 100% rename from src/ai/prompts/execution_prompts.rs rename to game/src/ai/prompts/execution_prompts.rs diff --git a/src/ai/prompts/mod.rs b/game/src/ai/prompts/mod.rs similarity index 100% rename from src/ai/prompts/mod.rs rename to game/src/ai/prompts/mod.rs diff --git a/src/ai/prompts/parsing_prompts.rs b/game/src/ai/prompts/parsing_prompts.rs similarity index 83% rename from src/ai/prompts/parsing_prompts.rs rename to game/src/ai/prompts/parsing_prompts.rs index e03cbe1..3769efb 100644 --- a/src/ai/prompts/parsing_prompts.rs +++ b/game/src/ai/prompts/parsing_prompts.rs @@ -1,18 +1,4 @@ -use crate::ai::convo::AiPrompt; - -pub const COMMAND_BNF: &str = r#" -root ::= Commands -Command ::= "{" ws "\"verb\":" ws string "," ws "\"target\":" ws string "," ws "\"location\":" ws string "," ws "\"using\":" ws string "}" -Commandlist ::= "[]" | "[" ws Command ("," ws Command)* "]" -Commands ::= "{" ws "\"commands\":" ws Commandlist "," ws "\"count\":" ws number "}" -Commandslist ::= "[]" | "[" ws Commands ("," ws Commands)* "]" -string ::= "\"" ([^"]*) "\"" -boolean ::= "true" | "false" -ws ::= [ \t\n]* -number ::= [0-9]+ "."? [0-9]* -stringlist ::= "[" ws "]" | "[" ws string ("," ws string)* ws "]" -numberlist ::= "[" ws "]" | "[" ws string ("," ws number)* ws "]" -"#; +use crate::{ai::convo::AiPrompt, models::commands::ParsedCommands}; pub const INTRO_PROMPT: &'static str = r#" [INST] @@ -104,8 +90,8 @@ Text: `{}` [/INST]"; pub fn intro_prompt(cmd: &str) -> AiPrompt { - let mut prompt = INTRO_PROMPT.replace("{}", cmd); - AiPrompt::new_with_grammar(&prompt, COMMAND_BNF) + let prompt = INTRO_PROMPT.replace("{}", cmd); + AiPrompt::new_with_grammar(&prompt, &ParsedCommands::to_grammar()) } pub fn continuation_prompt(cmd: &str) -> AiPrompt { @@ -116,11 +102,11 @@ pub fn continuation_prompt(cmd: &str) -> AiPrompt { prompt.push_str("[/INST]"); - AiPrompt::new_with_grammar(&prompt, COMMAND_BNF) + AiPrompt::new_with_grammar(&prompt, &ParsedCommands::to_grammar()) } pub fn coherence_prompt() -> AiPrompt { - AiPrompt::new_with_grammar(COHERENCE_PROMPT, COMMAND_BNF) + AiPrompt::new_with_grammar(COHERENCE_PROMPT, &ParsedCommands::to_grammar()) } pub fn find_verbs_prompt(cmd: &str) -> AiPrompt { diff --git a/game/src/ai/prompts/tables.rs b/game/src/ai/prompts/tables.rs new file mode 100644 index 0000000..7748ebd --- /dev/null +++ b/game/src/ai/prompts/tables.rs @@ -0,0 +1,96 @@ +use crate::models::commands::{ + CommandEvent, CommandEventType, EventConversionFailure, ParsedCommand, RawCommandExecution, +}; +use crate::models::world::items::Item; +use crate::models::world::people::Person; +use crate::models::world::scenes::{Exit, Prop, Scene, Stage}; +use crate::models::Insertable; +use itertools::Itertools; + +use tabled::settings::Style; +use tabled::{Table, Tabled}; + +const UNKNOWN: &'static str = "unknown"; +const PERSON: &'static str = "person"; +const ITEM: &'static str = "item"; +const PROP: &'static str = "prop"; +const NO_KEY: &'static str = "n/a"; + +#[derive(Tabled)] +pub struct EntityTableRow<'a> { + name: &'a str, + #[tabled(rename = "type")] + entity_type: &'a str, + key: &'a str, +} + +impl<'a> From<&'a Person> for EntityTableRow<'a> { + fn from(value: &'a Person) -> Self { + EntityTableRow { + name: &value.name, + key: value.key().unwrap_or(UNKNOWN), + entity_type: PERSON, + } + } +} + +impl<'a> From<&'a Item> for EntityTableRow<'a> { + fn from(value: &'a Item) -> Self { + EntityTableRow { + name: &value.name, + key: value.key().unwrap_or(UNKNOWN), + entity_type: ITEM, + } + } +} + +impl<'a> From<&'a Prop> for EntityTableRow<'a> { + fn from(value: &'a Prop) -> Self { + EntityTableRow { + name: &value.name, + entity_type: PROP, + key: NO_KEY, + } + } +} + +#[derive(Tabled)] +pub struct ExitTableRow<'a> { + pub name: &'a str, + pub direction: &'a str, + pub scene_key: &'a str, + pub region: &'a str, +} + +impl<'a> From<&'a Exit> for ExitTableRow<'a> { + fn from(value: &'a Exit) -> Self { + ExitTableRow { + name: &value.name, + direction: &value.direction, + scene_key: &value.scene_key, + region: &value.region, + } + } +} + +pub(super) fn entity_table(stage: &Stage) -> Table { + let people = stage.people.iter().map_into::(); + let items = stage.items.iter().map_into::(); + let props = stage.scene.props.iter().map_into::(); + let entities = people.chain(items).chain(props); + + let mut entities_table = Table::new(entities); + entities_table.with(Style::markdown()); + + entities_table +} + +pub(super) fn exit_table<'a, I>(exits: I) -> Table +where + I: IntoIterator, +{ + let exits = exits.into_iter(); + let mut table = Table::new(exits.map_into::()); + table.with(Style::markdown()); + table +} diff --git a/src/ai/prompts/world_prompts.rs b/game/src/ai/prompts/world_prompts.rs similarity index 100% rename from src/ai/prompts/world_prompts.rs rename to game/src/ai/prompts/world_prompts.rs diff --git a/src/commands/builtins.rs b/game/src/commands/builtins.rs similarity index 100% rename from src/commands/builtins.rs rename to game/src/commands/builtins.rs diff --git a/src/commands/coherence.rs b/game/src/commands/coherence.rs similarity index 100% rename from src/commands/coherence.rs rename to game/src/commands/coherence.rs diff --git a/src/commands/converter.rs b/game/src/commands/converter.rs similarity index 100% rename from src/commands/converter.rs rename to game/src/commands/converter.rs diff --git a/src/commands/mod.rs b/game/src/commands/mod.rs similarity index 100% rename from src/commands/mod.rs rename to game/src/commands/mod.rs diff --git a/src/db/mod.rs b/game/src/db/mod.rs similarity index 100% rename from src/db/mod.rs rename to game/src/db/mod.rs diff --git a/src/db/queries.rs b/game/src/db/queries.rs similarity index 100% rename from src/db/queries.rs rename to game/src/db/queries.rs diff --git a/src/game_loop.rs b/game/src/game_loop.rs similarity index 100% rename from src/game_loop.rs rename to game/src/game_loop.rs diff --git a/src/io.rs b/game/src/io.rs similarity index 100% rename from src/io.rs rename to game/src/io.rs diff --git a/src/kobold_api.rs b/game/src/kobold_api.rs similarity index 100% rename from src/kobold_api.rs rename to game/src/kobold_api.rs diff --git a/src/main.rs b/game/src/main.rs similarity index 98% rename from src/main.rs rename to game/src/main.rs index 19ab6b4..d34952f 100644 --- a/src/main.rs +++ b/game/src/main.rs @@ -1,10 +1,10 @@ +use ai::logic::AiLogic; use anyhow::Result; use config::Config; use game_loop::GameLoop; -use ai::logic::AiLogic; use models::world::scenes::{root_scene_id, Stage}; use state::GameState; -use std::{io::stdout, rc::Rc, time::Duration, str::FromStr}; +use std::{io::stdout, rc::Rc, str::FromStr, time::Duration}; use arangors::Connection; @@ -68,7 +68,6 @@ fn load_config() -> Result { .build() .unwrap(); - let kobold_endpoint = settings .get::>("connection.kobold_endpoint")? .unwrap_or("http://127.0.0.1:5001/api".to_string()); diff --git a/src/models/christmas.txt b/game/src/models/christmas.txt similarity index 100% rename from src/models/christmas.txt rename to game/src/models/christmas.txt diff --git a/src/models/coherence/mod.rs b/game/src/models/coherence/mod.rs similarity index 100% rename from src/models/coherence/mod.rs rename to game/src/models/coherence/mod.rs diff --git a/src/models/commands.rs b/game/src/models/commands.rs similarity index 97% rename from src/models/commands.rs rename to game/src/models/commands.rs index 1ede068..ec165a0 100644 --- a/src/models/commands.rs +++ b/game/src/models/commands.rs @@ -3,6 +3,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use strum::{EnumString, EnumVariantNames}; use thiserror::Error; +use gbnf::prelude::*; +use gbnf_derive::Gbnf; /// Stored in the database to bypass AI 'parsing' when possible. #[derive(Debug, Serialize, Deserialize, Clone)] @@ -12,7 +14,7 @@ pub struct CachedParsedCommand { pub commands: ParsedCommands, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, Gbnf)] pub struct ParsedCommands { #[serde(default)] pub original: String, // The original text entered by the player, set by code. @@ -30,7 +32,7 @@ impl ParsedCommands { } } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, Gbnf)] pub struct ParsedCommand { pub verb: String, pub target: String, diff --git a/src/models/mod.rs b/game/src/models/mod.rs similarity index 100% rename from src/models/mod.rs rename to game/src/models/mod.rs diff --git a/src/models/world/items.rs b/game/src/models/world/items.rs similarity index 100% rename from src/models/world/items.rs rename to game/src/models/world/items.rs diff --git a/src/models/world/mod.rs b/game/src/models/world/mod.rs similarity index 100% rename from src/models/world/mod.rs rename to game/src/models/world/mod.rs diff --git a/src/models/world/people.rs b/game/src/models/world/people.rs similarity index 100% rename from src/models/world/people.rs rename to game/src/models/world/people.rs diff --git a/src/models/world/raw.rs b/game/src/models/world/raw.rs similarity index 100% rename from src/models/world/raw.rs rename to game/src/models/world/raw.rs diff --git a/src/models/world/scenes.rs b/game/src/models/world/scenes.rs similarity index 100% rename from src/models/world/scenes.rs rename to game/src/models/world/scenes.rs diff --git a/src/state.rs b/game/src/state.rs similarity index 100% rename from src/state.rs rename to game/src/state.rs diff --git a/gbnf/Cargo.toml b/gbnf/Cargo.toml new file mode 100644 index 0000000..2313c1b --- /dev/null +++ b/gbnf/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "gbnf" +version = "0.1.0" +edition = "2021" + +[dependencies] +auto_impl = "1.1.2" +syn = { version = "2.0", features = [ "derive", "full", "parsing", "printing", "visit", "visit-mut", "clone-impls", "proc-macro" ] } +quote = "1.0.35" +itertools = "0.12.0" +serde = "1.0.196" +serde_derive = "1.0.196" diff --git a/gbnf/src/lib.rs b/gbnf/src/lib.rs new file mode 100644 index 0000000..b7526b7 --- /dev/null +++ b/gbnf/src/lib.rs @@ -0,0 +1,386 @@ +extern crate proc_macro; + +use itertools::Itertools; +use serde::de::DeserializeOwned; + +pub mod prelude { + pub use crate::gbnf_field; + pub use crate::gbnf_field_type; + pub use crate::AsGbnf; + pub use crate::AsGrammar; + pub use crate::GbnfComplex; + pub use crate::GbnfField; + pub use crate::GbnfFieldType; + pub use crate::GbnfPrimitive; + pub use crate::GbnfRule; + pub use crate::GbnfToken; +} + +// TODOs for this implementation: +// 1. Move primitive definitions (string, bool, etc) to the bottom of generated grammar. +// 2. Implement support for limited values. +// 3. Generate static strings for the gramma rules where possible. +// 4. Properly support optional types (right now they map to non-optional values). + +// Converts GBNF defintions (through the types below) into the grammar +// rules. +pub trait AsGrammar { + fn rules(&self) -> Vec; + fn token(&self) -> String; +} + +/// Trait for regular types to implement to convert themselves to a +/// GBNF value. +pub trait AsGbnf { + fn to_gbnf() -> GbnfFieldType; +} + +macro_rules! define_field_type { + ($type:ty, $gbnf_type:expr) => { + impl AsGbnf for $type { + fn to_gbnf() -> GbnfFieldType { + $gbnf_type + } + } + }; +} + +macro_rules! define_array_blanket_impl { + ($len:expr) => { + impl AsGbnf for [T; $len] + where + T: AsGbnf + DeserializeOwned, + { + fn to_gbnf() -> GbnfFieldType { + use GbnfFieldType::*; + match ::to_gbnf() { + Primitive(primitive_type) => PrimitiveList(primitive_type), + OptionalPrimitive(primitive_type) => PrimitiveList(primitive_type), + Complex(complex_type) => ComplexList(complex_type), + OptionalComplex(complex_type) => ComplexList(complex_type), + Limited(_) => panic!("limited values are not yet supported"), + ComplexList(_) | PrimitiveList(_) => panic!("nested lists not supported"), + } + } + } + }; +} + +#[macro_export] +macro_rules! gbnf_field_type { + ($type:ty) => { + <$type as AsGbnf>::to_gbnf() + }; +} + +#[macro_export] +macro_rules! gbnf_field { + ($field_name:literal, $field_type:ty) => { + GbnfField { + field_name: $field_name.to_string(), + field_type: gbnf_field_type!($field_type), + } + }; +} + +// Implemented field type mappings for common rust types. +define_field_type!(i16, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(u16, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(i32, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(u32, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(i64, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(u64, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(f32, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(f64, GbnfFieldType::Primitive(GbnfPrimitive::Number)); +define_field_type!(usize, GbnfFieldType::Primitive(GbnfPrimitive::Number)); + +define_field_type!(bool, GbnfFieldType::Primitive(GbnfPrimitive::Boolean)); + +define_field_type!(String, GbnfFieldType::Primitive(GbnfPrimitive::String)); +define_field_type!(char, GbnfFieldType::Primitive(GbnfPrimitive::String)); + +// Macro-based blanket impls for arrays +define_array_blanket_impl!(1); +define_array_blanket_impl!(3); +define_array_blanket_impl!(4); +define_array_blanket_impl!(5); +define_array_blanket_impl!(6); +define_array_blanket_impl!(7); +define_array_blanket_impl!(8); +define_array_blanket_impl!(9); +define_array_blanket_impl!(10); +define_array_blanket_impl!(11); +define_array_blanket_impl!(12); +define_array_blanket_impl!(13); +define_array_blanket_impl!(14); +define_array_blanket_impl!(15); +define_array_blanket_impl!(16); + +// Blanket implementations to cover more types +impl AsGbnf for Vec +where + T: AsGbnf, +{ + fn to_gbnf() -> GbnfFieldType { + use GbnfFieldType::*; + match ::to_gbnf() { + Primitive(primitive_type) => PrimitiveList(primitive_type), + OptionalPrimitive(primitive_type) => PrimitiveList(primitive_type), + Complex(complex_type) => ComplexList(complex_type), + OptionalComplex(complex_type) => ComplexList(complex_type), + Limited(_) => panic!("limited values not yet supported"), + ComplexList(_) | PrimitiveList(_) => panic!("nested lists not supported"), + } + } +} + +impl AsGbnf for Option +where + T: AsGbnf, +{ + fn to_gbnf() -> GbnfFieldType { + use GbnfFieldType::*; + match ::to_gbnf() { + Primitive(primitive_type) => OptionalPrimitive(primitive_type), + Complex(complex_type) => OptionalComplex(complex_type), + OptionalPrimitive(_) | OptionalComplex(_) => panic!("nested options are not allowed"), + Limited(_) => panic!("limited values not yet supported"), + _ => panic!("optional type cannot be a list"), + } + } +} + +// Actual GBNF rule itself. Holds rule text for dedup. +#[derive(Debug, Clone, Eq, Hash, PartialEq)] +pub struct GbnfRule { + name: String, + text: String, +} + +impl GbnfRule { + pub fn new(token: String, rule_text: String) -> GbnfRule { + GbnfRule { + name: token, + text: rule_text, + } + } + + pub fn single(token: String, rule_text: String) -> Vec { + vec![GbnfRule::new(token, rule_text)] + } +} + +/// Tokens in the GBNF rule. +pub enum GbnfToken { + Space, +} + +impl GbnfToken { + pub(self) const SPACE: &'static str = r#"[ \t\n]*"#; +} + +impl AsGrammar for GbnfToken { + fn rules(&self) -> Vec { + match self { + Self::Space => GbnfRule::single(self.token(), Self::SPACE.to_string()), + } + } + + fn token(&self) -> String { + match self { + Self::Space => "ws".to_string(), + } + } +} + +/// Represents a primitive value in the GBNF, the simplest possible +/// value a type can hold. +#[derive(Debug)] +pub enum GbnfPrimitive { + String, + Boolean, + Number, +} + +impl GbnfPrimitive { + pub(self) const STRING: &'static str = r#""\"" ([^"]*) "\"""#; + pub(self) const BOOLEAN: &'static str = r#""true" | "false""#; + pub(self) const NUMBER: &'static str = r#"[0-9]+ "."? [0-9]*"#; +} + +impl AsGrammar for GbnfPrimitive { + /// Output the raw GBNF rule of this primitive. + fn rules(&self) -> Vec { + let rule_text = match self { + Self::Boolean => Self::BOOLEAN, + Self::Number => Self::NUMBER, + Self::String => Self::STRING, + }; + + GbnfRule::single(self.token(), rule_text.to_string()) + } + + /// Output the token name of the GBNF rule (to refer to in other + /// rules). + fn token(&self) -> String { + String::from(match self { + Self::Boolean => "boolean", + Self::Number => "number", + Self::String => "string", + }) + } +} + +/// Categorize all types of fields that the generated grammar can +/// handle. +#[derive(Debug)] +pub enum GbnfFieldType { + /// A single property on the type, e.g. myField: i32 + Primitive(GbnfPrimitive), + + /// Can be a value or null. + OptionalPrimitive(GbnfPrimitive), + + /// A list/vec of primitive types. + PrimitiveList(GbnfPrimitive), + + /// A complex type, with its own properties. + Complex(GbnfComplex), + + /// Can be a value or null. + OptionalComplex(GbnfComplex), + + /// A list/vec of complex types. + ComplexList(GbnfComplex), + + /// A single property field, but with limited values allowed, + /// constrained by the primitive type. + Limited(GbnfPrimitive), +} + +impl GbnfFieldType { + pub fn as_complex(self) -> GbnfComplex { + match self { + GbnfFieldType::Complex(complex) => complex, + _ => panic!("Not a GBNF complex type"), + } + } +} + +/// Connect a property name and a field type to generate a GBNF rule. +#[derive(Debug)] +pub struct GbnfField { + pub field_name: String, + pub field_type: GbnfFieldType, +} + +impl GbnfField { + fn list_rule(field_type: &(impl AsGrammar + ?Sized)) -> String { + r#""[]" | "[" {SPACE} {TYPE_NAME} ("," {SPACE} {TYPE_NAME})* "]""# + .replace("{LIST_NAME}", "") + .replace("{SPACE}", &GbnfToken::Space.token()) + .replace("{TYPE_NAME}", &field_type.token()) + } + + fn list_rules(&self, f: &T) -> Vec { + // Create two rules: one for the list and on for its actual type. + let list_rule = GbnfRule::new(self.token(), Self::list_rule(f)); + + let mut rules = vec![list_rule]; + rules.append(&mut f.rules()); + rules + } +} + +impl AsGrammar for GbnfField { + fn token(&self) -> String { + match &self.field_type { + GbnfFieldType::Primitive(f) => f.token(), + GbnfFieldType::OptionalPrimitive(f) => f.token(), + GbnfFieldType::PrimitiveList(f) => format!("{}List", f.token()), + GbnfFieldType::Complex(f) => f.token(), + GbnfFieldType::OptionalComplex(f) => f.token(), + GbnfFieldType::ComplexList(f) => format!("{}List", f.token()), + GbnfFieldType::Limited(f) => f.token(), + _ => "".to_string(), + } + } + + // TODO need to implement optional rules, which probably involves + // wrapping the primitive rule in parens, and then ORing to null. + fn rules(&self) -> Vec { + match &self.field_type { + GbnfFieldType::Complex(f) => f.rules(), + GbnfFieldType::OptionalComplex(f) => f.rules(), + GbnfFieldType::ComplexList(f) => self.list_rules(f), + GbnfFieldType::Primitive(f) => f.rules(), + GbnfFieldType::OptionalPrimitive(f) => f.rules(), + GbnfFieldType::PrimitiveList(f) => self.list_rules(f), + GbnfFieldType::Limited(f) => f.rules(), + } + } +} + +/// The complex type is a direct mapping from a supported Rust struct, +/// and also used to generate the root of a GBNF grammar. +#[derive(Debug)] +pub struct GbnfComplex { + pub name: String, + pub fields: Vec, +} + +impl GbnfComplex { + pub fn to_grammar(&self) -> String { + let mut rules = vec![GbnfRule::new("root".to_string(), self.name.clone())]; + + rules.append(&mut self.rules()); + + for field in &self.fields { + rules.append(&mut field.rules()); + } + + rules + .into_iter() + .unique() + .map(|rule| format!("{} ::= {}", rule.name, rule.text)) + .join("\n") + } +} + +impl AsGrammar for GbnfComplex { + fn rules(&self) -> Vec { + // This will output the full set of rules for the complex type. + // Deduplication handled later. + let mut rule = String::new(); + + rule.push_str(r#""{" "#); + + let field_rules_text = self + .fields + .iter() + .map(|field| { + let mut text = String::new(); + text.push_str(&GbnfToken::Space.token()); + text.push_str(" "); + text.push_str(&format!( + r#""\"{}\":" {} {}"#, + field.field_name, + GbnfToken::Space.token(), + field.token(), + )); + text + }) + .join(r#" "," "#); + + rule.push_str(&field_rules_text); + rule.push_str(r#" "}""#); + + let mut rules = GbnfRule::single(self.token(), rule); + rules.append(&mut GbnfToken::Space.rules()); + rules + } + + fn token(&self) -> String { + self.name.clone() + } +} diff --git a/gbnf_derive/Cargo.toml b/gbnf_derive/Cargo.toml new file mode 100644 index 0000000..6f1444d --- /dev/null +++ b/gbnf_derive/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "gbnf_derive" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +auto_impl = "1.1.2" +syn = { version = "2.0", features = [ "derive", "full", "parsing", "printing", "visit", "visit-mut", "clone-impls", "proc-macro" ] } +quote = "1.0.35" +itertools = "0.12.0" +gbnf = { path = "../gbnf" } \ No newline at end of file diff --git a/gbnf_derive/src/lib.rs b/gbnf_derive/src/lib.rs new file mode 100644 index 0000000..4082504 --- /dev/null +++ b/gbnf_derive/src/lib.rs @@ -0,0 +1,110 @@ +use proc_macro::{Span, TokenStream}; +use quote::{quote, ToTokens}; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; +use syn::{braced, parse_macro_input}; +use syn::{DeriveInput, Field, Ident, LitStr, Token}; + +#[derive(Debug)] +struct GbnfStructDef { + name: Ident, + fields: Punctuated, +} + +impl Parse for GbnfStructDef { + fn parse(input: ParseStream) -> syn::Result { + // let _ = Discard tokens we don't care about. + let _: Option = input.parse()?; + let _: Option = input.parse()?; + + let content; + let name: Ident = input.parse()?; + let _ = braced!(content in input); + + Ok(GbnfStructDef { + name, + fields: content.parse_terminated(Field::parse_named, Token![,])?, + }) + } +} + +fn generate_gbnf(input: TokenStream, create_struct: bool) -> TokenStream { + // To define complex types, we take a struct into the macro, and + // then output a bunch of calls to gbnf_field (wrapped in gbnf + // complex). + + // We could also generate the entire complex type now during macro + // run, and then shove the resulting GBNF rule into the type as a + // static string. + + if let Ok(expr_struct) = syn::parse::(input.clone()) { + let struct_name_str = LitStr::new(&expr_struct.name.to_string(), Span::call_site().into()); + let struct_name = expr_struct.name; + let fields = expr_struct.fields.iter(); + + let gbnfs: Vec<_> = expr_struct + .fields + .iter() + .map(|field| { + let field_type = &field.ty; + let field_ident = field + .ident + .clone() + .map(|i| i.to_string()) + .map(|field_name| LitStr::new(&field_name, Span::call_site().into())) + .expect("no ident"); + + quote! { gbnf_field!(#field_ident, #field_type) } + }) + .collect(); + + let struct_frag = if create_struct { + quote! { + pub struct #struct_name { + #(#fields),* + } + } + } else { + quote! {} + }; + + let code = quote! { + #struct_frag + + impl #struct_name { + pub fn to_grammar() -> String { + Self::to_gbnf().as_complex().to_grammar() + } + } + + impl AsGbnf for #struct_name { + fn to_gbnf() -> gbnf::GbnfFieldType { + GbnfFieldType::Complex( + GbnfComplex { + name: String::from(#struct_name_str), + fields: vec![#(#gbnfs),*] + } + ) + } + } + }; + + code.into() + } else { + panic!("Can only generate GBNF from structs (pub or private)"); + } +} + + +/// Create a GBNF complex type as a Rust struct. +#[proc_macro] +pub fn gbnf_complex(input: TokenStream) -> TokenStream { + generate_gbnf(input, true) +} + +/// Add the ability to convert a Rust type into a GBNF grammar. +#[proc_macro_derive(Gbnf)] +pub fn gbnf(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + generate_gbnf(input.to_token_stream().into(), false) +} diff --git a/src/ai/gbnf/mod.rs b/src/ai/gbnf/mod.rs new file mode 100644 index 0000000..9faf894 --- /dev/null +++ b/src/ai/gbnf/mod.rs @@ -0,0 +1,217 @@ +extern crate proc_macro; + +use auto_impl::auto_impl; +use itertools::Itertools; + +mod events; + +// Actual GBNF rule itself. Holds rule text for dedup. +#[derive(Debug, Clone, Eq, Hash, PartialEq)] +pub struct GbnfRule { + name: String, + text: String, +} + +impl GbnfRule { + pub fn new(token: String, rule_text: String) -> GbnfRule { + GbnfRule { + name: token, + text: rule_text, + } + } + + pub fn single(token: String, rule_text: String) -> Vec { + vec![GbnfRule::new(token, rule_text)] + } +} + +//token() returns the gbnf identifier for the rule. +//rule() returns the rule itself. +#[auto_impl(&, Box)] +pub trait TokenAndRule { + fn rules(&self) -> Vec; + fn token(&self) -> String; +} + +pub enum GbnfToken { + Space, +} + +impl GbnfToken { + pub(self) const SPACE: &'static str = r#"[ \t\n]*"#; +} + +impl TokenAndRule for GbnfToken { + fn rules(&self) -> Vec { + match self { + Self::Space => GbnfRule::single(self.token(), Self::SPACE.to_string()), + } + } + + fn token(&self) -> String { + match self { + Self::Space => "ws".to_string(), + } + } +} + +#[derive(Debug)] +pub enum GbnfPrimitive { + String, + Boolean, + Number, +} + +impl GbnfPrimitive { + pub(self) const STRING: &'static str = r#""\"" ([^"]*) "\""#; + pub(self) const BOOLEAN: &'static str = r#""true" | "false""#; + pub(self) const NUMBER: &'static str = r#"[0-9]+ "."? [0-9]*"#; +} + +impl TokenAndRule for GbnfPrimitive { + /// Output the raw GBNF rule of this primitive. + fn rules(&self) -> Vec { + let rule_text = match self { + Self::Boolean => Self::BOOLEAN, + Self::Number => Self::NUMBER, + Self::String => Self::STRING, + }; + + GbnfRule::single(self.token(), rule_text.to_string()) + } + + /// Output the token name of the GBNF rule (to refer to in other + /// rules). + fn token(&self) -> String { + String::from(match self { + Self::Boolean => "boolean", + Self::Number => "number", + Self::String => "string", + }) + } +} + +#[derive(Debug)] +pub enum FieldType { + /// A single property on the type, e.g. myField: i32 + Primitive(GbnfPrimitive), + + /// A complex property, with its own properties. + Complex(GbnfType), + + /// A list/vec of primitive types. + PrimitiveList(GbnfPrimitive), + + /// A list/vec of complex types. + ComplexList(GbnfType), + + /// A single property field, but with limited values allowed, + /// constrained by the primitive type. + Limited(GbnfPrimitive), +} + +#[derive(Debug)] +pub struct GbnfField { + pub field_name: String, + pub field_type: FieldType, +} + +#[derive(Debug)] +pub struct GbnfType { + pub name: String, + pub fields: Vec, +} + +impl GbnfField { + fn list_rule(field_type: &(impl TokenAndRule + ?Sized)) -> String { + r#""[]" | "[" {SPACE} {TYPE_NAME} ("," {SPACE} {TYPE_NAME})* "]""# + .replace("{LIST_NAME}", "") + .replace("{SPACE}", &GbnfToken::Space.token()) + .replace("{TYPE_NAME}", &field_type.token()) + } + + fn list_rules(&self, f: &T) -> Vec { + // Create two rules: one for the list and on for its actual type. + let list_rule = GbnfRule::new(self.token(), Self::list_rule(f)); + + let mut rules = vec![list_rule]; + rules.append(&mut f.rules()); + rules + } +} + +impl TokenAndRule for GbnfField { + fn token(&self) -> String { + match &self.field_type { + FieldType::Primitive(f) => f.token(), + FieldType::PrimitiveList(f) => format!("{}_List", f.token()), + FieldType::Complex(f) => f.token(), + FieldType::ComplexList(f) => format!("{}_List", f.token()), + FieldType::Limited(f) => f.token(), + _ => "".to_string(), + } + } + + fn rules(&self) -> Vec { + match &self.field_type { + FieldType::ComplexList(f) => self.list_rules(f), + FieldType::Complex(f) => f.rules(), + FieldType::PrimitiveList(f) => self.list_rules(f), + FieldType::Primitive(f) => f.rules(), + FieldType::Limited(f) => f.rules(), + + } + } +} + +impl TokenAndRule for GbnfType { + fn rules(&self) -> Vec { + // This will output the full set of rules for the complex type. + // Deduplication handled later. + let mut rule = String::new(); + + rule.push_str(r#""{ "#); + + let field_rules_text = self + .fields + .iter() + .map(|field| { + let mut text = String::new(); + text.push_str(&GbnfToken::Space.token()); + text.push_str(" "); + text.push_str(&format!( + r#""\"{}\":" {} {}"#, + field.field_name, + GbnfToken::Space.token(), + field.token(), + )); + text + }) + .join(r#" "," "#); + + rule.push_str(&field_rules_text); + rule.push_str(r#" "}""#); + + GbnfRule::single(self.token(), rule) + } + + fn token(&self) -> String { + self.name.clone() + } +} + +pub fn create_gbnf(gbnf_type: GbnfType) -> String { + let mut rules = vec![GbnfRule::new("root".to_string(), gbnf_type.name.clone())]; + + rules.append(&mut gbnf_type.rules()); + + for field in gbnf_type.fields { + rules.append(&mut field.rules()); + } + + rules + .into_iter() + .unique() + .map(|rule| format!("{} ::= {}", rule.name, rule.text)) + .join("\n") +}