Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1684788fe6 | |||
|
4b7e242998
|
|||
| f69aba2dd8 | |||
| c3487ecd0e | |||
|
db75391fb6
|
|||
|
e3815af69b
|
|||
| 66a485f924 | |||
| 49d7204f89 | |||
|
bbcae1fc2b
|
@@ -1,3 +1,59 @@
|
|||||||
|
## v0.7.2 (2026-06-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- usql version upgrade
|
||||||
|
|
||||||
|
## v0.7.1 (2026-06-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- sbx mixins must be passed in directories, not as files and the files must be named spec.yaml per new sbx version
|
||||||
|
|
||||||
|
## v0.7.0 (2026-06-18)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- added configurable cache path via the COYOTE_CACHE_PATH environment variable
|
||||||
|
- added a memory option to .set tab completions
|
||||||
|
- Added a diagnostic .info tools subcommand to make it easier to see what tools are enabled in all contexts
|
||||||
|
- Added additional info outputs for enabled skills and sbx directories
|
||||||
|
- directly execute shell commands from within the REPL
|
||||||
|
- created mixin kit for built-in functions and MCP servers
|
||||||
|
- Added sbx mixins for the secrets providers so users can also bootstrap those as well.
|
||||||
|
- added support for loading sbx mixins that are dynamically discovered in the users workspace and config directory
|
||||||
|
- Added a --fresh flag to let users create a truly bare bones sandbox without bootstrapping their config
|
||||||
|
- initial built-in sandboxing support powered by Docker sbx
|
||||||
|
- Added the ability to auto-bootstrap workspace memory when in git repos
|
||||||
|
- Added explicit guardrail handling for pending agents
|
||||||
|
- auto-append memory to memory index and don't necessarily require the LLM to remember to do it after a write
|
||||||
|
- Added an --init-memory [global|workspace] flag to easily and quickly enable memory
|
||||||
|
- added memory global configuration settings to the output of --info and .info
|
||||||
|
- added .set memory REPL commands to control memory injection and applied formatting
|
||||||
|
- Create the built-in memory management tools
|
||||||
|
- Append the memory system prompts (readonly or r/w) to the system prompt when applicable
|
||||||
|
- Created the --no-memory CLI flag to disable memory for this invocation
|
||||||
|
- Added the memory configuration properties and storage to the main app config, roles, sessions, and agents.
|
||||||
|
- initial scaffolding of a memory system
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- rebuild the tool scope after dynamically updating the skills_enabled value in the REPL
|
||||||
|
- properly resolve Windows-based local vault password file locations and bootstrap them into the sandbox when possible
|
||||||
|
- auto-translation of user-prefixed Mac and Linux paths for the vault password file when running inside a sandbox
|
||||||
|
- don't attempt to auto complete .vault list in the REPL; that's the end of the command
|
||||||
|
- buffer tool stdout as well as stderr so that any tools that error to stdout are captured and included in the response to the model, enabling the model to see what went wrong and to reason about how to fix it.
|
||||||
|
- auto-bootstrapped memory was accidentally putting the MEMORY.md directly in the repo root rather than .coyote/memory/MEMORY.md
|
||||||
|
- improved the fs_patch script description and added improved error handling to it.
|
||||||
|
- added in forgotten require_max_tokens to the fable model
|
||||||
|
- append memory functions to non-graph based agents on init
|
||||||
|
- when auto_continue is disabled via the .set auto_continue false command, it should strip the todo functions from the list of functions
|
||||||
|
- use rawPredict for non-streaming Claude requests
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Migrated the .skills command completion to use StateFlags and updated the help messages
|
||||||
|
|
||||||
## v0.6.0 (2026-06-05)
|
## v0.6.0 (2026-06-05)
|
||||||
|
|
||||||
### Feat
|
### Feat
|
||||||
|
|||||||
Generated
+56
-201
@@ -555,7 +555,7 @@ dependencies = [
|
|||||||
"aws-smithy-runtime-api",
|
"aws-smithy-runtime-api",
|
||||||
"aws-smithy-types",
|
"aws-smithy-types",
|
||||||
"h2 0.3.27",
|
"h2 0.3.27",
|
||||||
"h2 0.4.14",
|
"h2 0.4.15",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
@@ -1011,9 +1011,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes-utils"
|
name = "bytes-utils"
|
||||||
@@ -1060,9 +1060,9 @@ checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.64"
|
version = "1.2.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
|
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -1402,7 +1402,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coyote-ai"
|
name = "coyote-ai"
|
||||||
version = "0.6.0"
|
version = "0.7.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_colours",
|
"ansi_colours",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -2406,16 +2406,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
|
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi 6.0.0",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
"wasip2",
|
|
||||||
"wasip3",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2500,9 +2498,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.14"
|
version = "0.4.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
|
checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2780,7 +2778,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"h2 0.4.14",
|
"h2 0.4.15",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -2981,12 +2979,6 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "id-arena"
|
|
||||||
version = "2.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -3120,11 +3112,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_executable"
|
name = "is_executable"
|
||||||
version = "1.0.5"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baabb8b4867b26294d818bf3f651a454b6901431711abb96e296245888d6e8c4"
|
checksum = "82cb6a9f675da968c63b6208c641b9dca58fc0133ae53375736b1767b0cab8bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3242,9 +3234,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.100"
|
version = "0.3.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162"
|
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -3296,12 +3288,6 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "leb128fmt"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.186"
|
version = "0.2.186"
|
||||||
@@ -3926,9 +3912,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.80"
|
version = "0.10.81"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967"
|
checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -3966,9 +3952,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.116"
|
version = "0.9.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4"
|
checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -4507,7 +4493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chacha20 0.10.0",
|
"chacha20 0.10.0",
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.4.3",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4715,7 +4701,7 @@ dependencies = [
|
|||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.4.14",
|
"h2 0.4.15",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@@ -5561,9 +5547,9 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smawk"
|
name = "smawk"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
|
checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@@ -5709,9 +5695,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -5813,7 +5799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.4.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
@@ -6121,7 +6107,7 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"h2 0.4.14",
|
"h2 0.4.15",
|
||||||
"http 1.4.2",
|
"http 1.4.2",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@@ -6522,7 +6508,7 @@ version = "1.23.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7"
|
checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.4.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
@@ -6611,27 +6597,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.3+wasi-0.2.9"
|
version = "1.0.4+wasi-0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
|
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen 0.57.1",
|
"wit-bindgen",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasip3"
|
|
||||||
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
|
||||||
dependencies = [
|
|
||||||
"wit-bindgen 0.51.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.123"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563"
|
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -6642,9 +6619,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.73"
|
version = "0.4.75"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54568702fabf5d4849ce2b90fadfa64168a097eaf4b351ce9df8b687a0086aaf"
|
checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -6652,9 +6629,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.123"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc"
|
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -6662,9 +6639,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.123"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b"
|
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -6675,35 +6652,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.123"
|
version = "0.2.125"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92"
|
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-encoder"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
|
||||||
dependencies = [
|
|
||||||
"leb128fmt",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-metadata"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"indexmap 2.14.0",
|
|
||||||
"wasm-encoder",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-streams"
|
name = "wasm-streams"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -6730,18 +6685,6 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasmparser"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"hashbrown 0.15.5",
|
|
||||||
"indexmap 2.14.0",
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.3.15"
|
version = "0.3.15"
|
||||||
@@ -6769,9 +6712,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols"
|
name = "wayland-protocols"
|
||||||
version = "0.32.12"
|
version = "0.32.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f"
|
checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -6814,9 +6757,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.100"
|
version = "0.3.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e0871acf327f283dc6da28a1696cdc64fb355ba9f935d052021fa77f35cce69"
|
checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -6834,27 +6777,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-root-certs"
|
name = "webpki-root-certs"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
|
checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
|
checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "8.0.3"
|
version = "8.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c789537cf2f7f55be8e6192f92e464174ee55f91af622777f7f1ceb0dbccd03e"
|
checksum = "48d7cd18d4acb58fb3cdfe9ea54e6cd96a4e7d4cc45c56338b236e82dad47248"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -7237,100 +7180,12 @@ version = "0.53.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
||||||
dependencies = [
|
|
||||||
"wit-bindgen-rust-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.57.1"
|
version = "0.57.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-core"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"heck",
|
|
||||||
"wit-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-rust"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"heck",
|
|
||||||
"indexmap 2.14.0",
|
|
||||||
"prettyplease",
|
|
||||||
"syn",
|
|
||||||
"wasm-metadata",
|
|
||||||
"wit-bindgen-core",
|
|
||||||
"wit-component",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-rust-macro"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wit-bindgen-core",
|
|
||||||
"wit-bindgen-rust",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-component"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"bitflags",
|
|
||||||
"indexmap 2.14.0",
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"wasm-encoder",
|
|
||||||
"wasm-metadata",
|
|
||||||
"wasmparser",
|
|
||||||
"wit-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-parser"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"id-arena",
|
|
||||||
"indexmap 2.14.0",
|
|
||||||
"log",
|
|
||||||
"semver",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"unicode-xid",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wl-clipboard-rs"
|
name = "wl-clipboard-rs"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
@@ -7477,18 +7332,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.8.2"
|
version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zeroize_derive",
|
"zeroize_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize_derive"
|
name = "zeroize_derive"
|
||||||
version = "1.4.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
|
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "coyote-ai"
|
name = "coyote-ai"
|
||||||
version = "0.6.0"
|
version = "0.7.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
description = "An all-in-one, batteries included LLM CLI Tool"
|
description = "An all-in-one, batteries included LLM CLI Tool"
|
||||||
|
|||||||
@@ -257,17 +257,18 @@ commands:
|
|||||||
description: Install uv (required for Python-based custom tools)
|
description: Install uv (required for Python-based custom tools)
|
||||||
- command: |
|
- command: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
USQL_VERSION="0.19.20"
|
USQL_VERSION=$(curl -sSL https://api.github.com/repos/xo/usql/releases/latest | jq -r .tag_name | sed 's/^v//')
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
case "$ARCH" in
|
case "$ARCH" in
|
||||||
x86_64) USQL_ARCH=amd64 ;;
|
x86_64) USQL_ARCH=amd64 ;;
|
||||||
aarch64) USQL_ARCH=arm64 ;;
|
aarch64) USQL_ARCH=arm64 ;;
|
||||||
*) echo "Unsupported arch for usql install: $ARCH" >&2; exit 1 ;;
|
*) echo "Unsupported arch for usql install: $ARCH" >&2; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
curl -sSL "https://github.com/xo/usql/releases/download/v${USQL_VERSION}/usql_static-${USQL_VERSION}-linux-${USQL_ARCH}.tar.bz2" -o /tmp/usql.tar.bz2
|
TMPDIR=$(mktemp -d)
|
||||||
sudo tar -xjf /tmp/usql.tar.bz2 -C /usr/local/bin
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
sudo chmod +x /usr/local/bin/usql
|
curl -sSL "https://github.com/xo/usql/releases/download/v${USQL_VERSION}/usql_static-${USQL_VERSION}-linux-${USQL_ARCH}.tar.bz2" -o "$TMPDIR/usql.tar.bz2"
|
||||||
rm -f /tmp/usql.tar.bz2
|
tar -xjf "$TMPDIR/usql.tar.bz2" -C "$TMPDIR"
|
||||||
|
sudo install -m 0755 "$TMPDIR/usql_static" /usr/local/bin/usql
|
||||||
user: "1000"
|
user: "1000"
|
||||||
description: Install the usql universal SQL CLI (used by the built-in sql agent and execute_sql_code tool)
|
description: Install the usql universal SQL CLI (used by the built-in sql agent and execute_sql_code tool)
|
||||||
- command: |
|
- command: |
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ const SBX_KIT_DIR_NAME: &str = "sbx-kit";
|
|||||||
const SBX_KIT_HASH_FILE: &str = "kit.sha256";
|
const SBX_KIT_HASH_FILE: &str = "kit.sha256";
|
||||||
const SBX_MIXIN_FILE_NAME: &str = "sbx-mixin.yaml";
|
const SBX_MIXIN_FILE_NAME: &str = "sbx-mixin.yaml";
|
||||||
const SBX_VAULT_MIXINS_DIR_NAME: &str = "sbx-vault-mixins";
|
const SBX_VAULT_MIXINS_DIR_NAME: &str = "sbx-vault-mixins";
|
||||||
|
const SBX_MIXIN_KITS_DIR_NAME: &str = "sbx-mixin-kits";
|
||||||
const GIT_DIR_NAME: &str = ".git";
|
const GIT_DIR_NAME: &str = ".git";
|
||||||
const GITIGNORE_FILE_NAME: &str = ".gitignore";
|
const GITIGNORE_FILE_NAME: &str = ".gitignore";
|
||||||
const DEFAULT_VISIBLE_TOOLS: [&str; 18] = [
|
const DEFAULT_VISIBLE_TOOLS: [&str; 18] = [
|
||||||
|
|||||||
+14
-4
@@ -4,8 +4,8 @@ use super::{
|
|||||||
ENV_FILE_NAME, FUNCTIONS_BIN_DIR_NAME, FUNCTIONS_DIR_NAME, GLOBAL_TOOLS_DIR_NAME,
|
ENV_FILE_NAME, FUNCTIONS_BIN_DIR_NAME, FUNCTIONS_DIR_NAME, GLOBAL_TOOLS_DIR_NAME,
|
||||||
GLOBAL_TOOLS_UTILS_DIR_NAME, MACROS_DIR_NAME, MCP_FILE_NAME, MEMORY_DIR_NAME,
|
GLOBAL_TOOLS_UTILS_DIR_NAME, MACROS_DIR_NAME, MCP_FILE_NAME, MEMORY_DIR_NAME,
|
||||||
MEMORY_INDEX_FILE_NAME, ModelsOverride, RAGS_DIR_NAME, ROLES_DIR_NAME, SBX_KIT_DIR_NAME,
|
MEMORY_INDEX_FILE_NAME, ModelsOverride, RAGS_DIR_NAME, ROLES_DIR_NAME, SBX_KIT_DIR_NAME,
|
||||||
SBX_KIT_HASH_FILE, SBX_MIXIN_FILE_NAME, SBX_VAULT_MIXINS_DIR_NAME, SKILLS_DIR_NAME,
|
SBX_KIT_HASH_FILE, SBX_MIXIN_FILE_NAME, SBX_MIXIN_KITS_DIR_NAME, SBX_VAULT_MIXINS_DIR_NAME,
|
||||||
WORKSPACE_MEMORY_DIR_NAME,
|
SKILLS_DIR_NAME, WORKSPACE_MEMORY_DIR_NAME,
|
||||||
};
|
};
|
||||||
use crate::client::ProviderModels;
|
use crate::client::ProviderModels;
|
||||||
use crate::utils::{get_env_name, list_file_names, normalize_env_name};
|
use crate::utils::{get_env_name, list_file_names, normalize_env_name};
|
||||||
@@ -33,8 +33,14 @@ pub fn local_path(name: &str) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn cache_path() -> PathBuf {
|
pub fn cache_path() -> PathBuf {
|
||||||
let base_dir = dirs::cache_dir().unwrap_or_else(env::temp_dir);
|
if let Ok(v) = env::var(get_env_name("cache_dir")) {
|
||||||
base_dir.join(env!("CARGO_CRATE_NAME"))
|
PathBuf::from(v)
|
||||||
|
} else if let Ok(v) = env::var("XDG_CACHE_HOME") {
|
||||||
|
PathBuf::from(v).join(env!("CARGO_CRATE_NAME"))
|
||||||
|
} else {
|
||||||
|
let base_dir = dirs::cache_dir().unwrap_or_else(env::temp_dir);
|
||||||
|
base_dir.join(env!("CARGO_CRATE_NAME"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sandbox_kit_override() -> Option<PathBuf> {
|
pub fn sandbox_kit_override() -> Option<PathBuf> {
|
||||||
@@ -148,6 +154,10 @@ pub fn sbx_vault_mixins_hash_file() -> PathBuf {
|
|||||||
sbx_vault_mixins_dir().join(SBX_KIT_HASH_FILE)
|
sbx_vault_mixins_dir().join(SBX_KIT_HASH_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sbx_mixin_kits_dir() -> PathBuf {
|
||||||
|
cache_path().join(SBX_MIXIN_KITS_DIR_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn config_file() -> PathBuf {
|
pub fn config_file() -> PathBuf {
|
||||||
match env::var(get_env_name("config_file")) {
|
match env::var(get_env_name("config_file")) {
|
||||||
Ok(value) => PathBuf::from(value),
|
Ok(value) => PathBuf::from(value),
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
use std::fs::{read_dir, read_to_string};
|
use std::fs::{read_dir, read_to_string};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde_yaml::Value;
|
use serde_yaml::Value;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
use crate::config::paths;
|
use crate::config::paths;
|
||||||
|
|
||||||
const SBX_MIXIN_FILE_NAME: &str = "sbx-mixin.yaml";
|
const SBX_MIXIN_FILE_NAME: &str = "sbx-mixin.yaml";
|
||||||
|
const KIT_SPEC_FILE_NAME: &str = "spec.yaml";
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DiscoveredMixin {
|
pub struct DiscoveredMixin {
|
||||||
@@ -17,6 +20,46 @@ pub struct DiscoveredMixin {
|
|||||||
pub domain_count: usize,
|
pub domain_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DiscoveredMixin {
|
||||||
|
pub fn kit_path(&self) -> Result<PathBuf> {
|
||||||
|
if self.path.is_dir() {
|
||||||
|
return Ok(self.path.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_mixin_as_kit(&self.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wrap_mixin_as_kit(mixin_path: &Path) -> Result<PathBuf> {
|
||||||
|
let bytes = fs::read(mixin_path)
|
||||||
|
.with_context(|| format!("Failed to read sbx mixin {}", mixin_path.display()))?;
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(&bytes);
|
||||||
|
let hash = format!("{:x}", hasher.finalize());
|
||||||
|
|
||||||
|
let kit_dir = paths::sbx_mixin_kits_dir().join(&hash);
|
||||||
|
let spec_path = kit_dir.join(KIT_SPEC_FILE_NAME);
|
||||||
|
|
||||||
|
if let Ok(existing) = fs::read(&spec_path)
|
||||||
|
&& existing == bytes
|
||||||
|
{
|
||||||
|
return Ok(kit_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::create_dir_all(&kit_dir)
|
||||||
|
.with_context(|| format!("Failed to create mixin kit dir {}", kit_dir.display()))?;
|
||||||
|
fs::write(&spec_path, &bytes)
|
||||||
|
.with_context(|| format!("Failed to write {}", spec_path.display()))?;
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"Wrapped mixin {} as kit at {}",
|
||||||
|
mixin_path.display(),
|
||||||
|
kit_dir.display()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(kit_dir)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn discover() -> Result<Vec<DiscoveredMixin>> {
|
pub fn discover() -> Result<Vec<DiscoveredMixin>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
|
|
||||||
@@ -234,4 +277,166 @@ network:
|
|||||||
let found = collect_subdir_mixins(&absent);
|
let found = collect_subdir_mixins(&absent);
|
||||||
assert!(found.is_empty());
|
assert!(found.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod wrap_as_kit {
|
||||||
|
use super::*;
|
||||||
|
use serial_test::serial;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
|
||||||
|
struct TestCacheDirGuard {
|
||||||
|
key: String,
|
||||||
|
previous: Option<OsString>,
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestCacheDirGuard {
|
||||||
|
fn new() -> Self {
|
||||||
|
let key = crate::utils::get_env_name("cache_dir");
|
||||||
|
let previous = env::var_os(&key);
|
||||||
|
let nanos = time::SystemTime::now()
|
||||||
|
.duration_since(time::UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_nanos();
|
||||||
|
let path = env::temp_dir().join(format!("coyote-mixin-wrap-cache-{nanos}"));
|
||||||
|
fs::create_dir_all(&path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
env::set_var(&key, &path);
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
key,
|
||||||
|
previous,
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestCacheDirGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
match &self.previous {
|
||||||
|
Some(v) => env::set_var(&self.key, v),
|
||||||
|
None => env::remove_var(&self.key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = fs::remove_dir_all(&self.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_mixin(name: &str, content: &str) -> PathBuf {
|
||||||
|
let root = unique_root(&format!("wrap-src-{name}"));
|
||||||
|
let path = root.join("sbx-mixin.yaml");
|
||||||
|
fs::write(&path, content).unwrap();
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn wrap_mixin_as_kit_creates_spec_yaml_with_original_content() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let content = "schemaVersion: \"1\"\nkind: mixin\nname: probe\n";
|
||||||
|
let mixin = write_mixin("content", content);
|
||||||
|
|
||||||
|
let kit_dir = wrap_mixin_as_kit(&mixin).unwrap();
|
||||||
|
let spec = kit_dir.join("spec.yaml");
|
||||||
|
|
||||||
|
assert!(spec.exists(), "spec.yaml must exist in wrapped kit dir");
|
||||||
|
assert_eq!(fs::read_to_string(&spec).unwrap(), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn wrap_mixin_as_kit_is_deterministic_for_identical_content() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let content = "schemaVersion: \"1\"\nkind: mixin\nname: probe\n";
|
||||||
|
let mixin_one = write_mixin("dedup-1", content);
|
||||||
|
let mixin_two = write_mixin("dedup-2", content);
|
||||||
|
|
||||||
|
let kit_a = wrap_mixin_as_kit(&mixin_one).unwrap();
|
||||||
|
let kit_b = wrap_mixin_as_kit(&mixin_two).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
kit_a, kit_b,
|
||||||
|
"same content should share the same content-addressed kit dir"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn wrap_mixin_as_kit_different_content_yields_different_dirs() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let mixin_a = write_mixin("diff-a", "kind: mixin\nname: a\n");
|
||||||
|
let mixin_b = write_mixin("diff-b", "kind: mixin\nname: b\n");
|
||||||
|
|
||||||
|
let kit_a = wrap_mixin_as_kit(&mixin_a).unwrap();
|
||||||
|
let kit_b = wrap_mixin_as_kit(&mixin_b).unwrap();
|
||||||
|
|
||||||
|
assert_ne!(
|
||||||
|
kit_a, kit_b,
|
||||||
|
"different content must hash to different kit dirs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn wrap_mixin_as_kit_is_idempotent_on_cache_hit() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let mixin = write_mixin("idempotent", "kind: mixin\nname: probe\n");
|
||||||
|
|
||||||
|
let kit_first = wrap_mixin_as_kit(&mixin).unwrap();
|
||||||
|
let spec = kit_first.join("spec.yaml");
|
||||||
|
let mtime_first = fs::metadata(&spec).unwrap().modified().unwrap();
|
||||||
|
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
|
|
||||||
|
let kit_second = wrap_mixin_as_kit(&mixin).unwrap();
|
||||||
|
let mtime_second = fs::metadata(kit_second.join("spec.yaml"))
|
||||||
|
.unwrap()
|
||||||
|
.modified()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(kit_first, kit_second);
|
||||||
|
assert_eq!(
|
||||||
|
mtime_first, mtime_second,
|
||||||
|
"cache hit must not rewrite spec.yaml"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn kit_path_passes_through_existing_directory() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let dir = unique_root("kit-path-dir-passthrough");
|
||||||
|
|
||||||
|
let m = DiscoveredMixin {
|
||||||
|
path: dir.clone(),
|
||||||
|
label: "vault".into(),
|
||||||
|
install_count: 1,
|
||||||
|
domain_count: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(m.kit_path().unwrap(), dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn kit_path_wraps_file_into_kit_dir() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
|
let mixin = write_mixin("kit-path-wrap", "kind: mixin\nname: probe\n");
|
||||||
|
|
||||||
|
let m = DiscoveredMixin {
|
||||||
|
path: mixin.clone(),
|
||||||
|
label: mixin.display().to_string(),
|
||||||
|
install_count: 0,
|
||||||
|
domain_count: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let wrapped = m.kit_path().unwrap();
|
||||||
|
assert!(wrapped.is_dir(), "kit_path of a file should be a directory");
|
||||||
|
assert!(wrapped.join("spec.yaml").exists());
|
||||||
|
assert_ne!(
|
||||||
|
wrapped, mixin,
|
||||||
|
"kit_path should not return the original file path"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-8
@@ -347,12 +347,13 @@ fn build_create_args(
|
|||||||
];
|
];
|
||||||
|
|
||||||
for mixin in mixins {
|
for mixin in mixins {
|
||||||
let mixin_str = mixin
|
let mixin_kit = mixin.kit_path()?;
|
||||||
.path
|
let mixin_str = mixin_kit
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or_else(|| anyhow!("Mixin path is not valid UTF-8: {}", mixin.path.display()))?;
|
.ok_or_else(|| anyhow!("Mixin kit path is not valid UTF-8: {}", mixin_kit.display()))?
|
||||||
|
.to_string();
|
||||||
args.push("--kit".to_string());
|
args.push("--kit".to_string());
|
||||||
args.push(mixin_str.to_string());
|
args.push(mixin_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
args.push(SANDBOX_AGENT.to_string());
|
args.push(SANDBOX_AGENT.to_string());
|
||||||
@@ -590,15 +591,24 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn build_create_args_emits_base_kit_before_mixins() {
|
fn build_create_args_emits_base_kit_before_mixins() {
|
||||||
let kit = PathBuf::from("/cache/sbx-kit");
|
let kit = PathBuf::from("/cache/sbx-kit");
|
||||||
|
let unique = std::time::SystemTime::now()
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_nanos();
|
||||||
|
let dir_a = env::temp_dir().join(format!("coyote-mixin-a-{unique}"));
|
||||||
|
let dir_b = env::temp_dir().join(format!("coyote-mixin-b-{unique}"));
|
||||||
|
fs::create_dir_all(&dir_a).unwrap();
|
||||||
|
fs::create_dir_all(&dir_b).unwrap();
|
||||||
|
|
||||||
let mixins = vec![
|
let mixins = vec![
|
||||||
DiscoveredMixin {
|
DiscoveredMixin {
|
||||||
path: PathBuf::from("/cfg/sbx-mixin.yaml"),
|
path: dir_a.clone(),
|
||||||
label: "user".into(),
|
label: "user".into(),
|
||||||
install_count: 0,
|
install_count: 0,
|
||||||
domain_count: 0,
|
domain_count: 0,
|
||||||
},
|
},
|
||||||
DiscoveredMixin {
|
DiscoveredMixin {
|
||||||
path: PathBuf::from("/cfg/agents/sql/sbx-mixin.yaml"),
|
path: dir_b.clone(),
|
||||||
label: "sql".into(),
|
label: "sql".into(),
|
||||||
install_count: 0,
|
install_count: 0,
|
||||||
domain_count: 0,
|
domain_count: 0,
|
||||||
@@ -614,15 +624,18 @@ mod tests {
|
|||||||
"--kit".to_string(),
|
"--kit".to_string(),
|
||||||
"/cache/sbx-kit".to_string(),
|
"/cache/sbx-kit".to_string(),
|
||||||
"--kit".to_string(),
|
"--kit".to_string(),
|
||||||
"/cfg/sbx-mixin.yaml".to_string(),
|
dir_a.display().to_string(),
|
||||||
"--kit".to_string(),
|
"--kit".to_string(),
|
||||||
"/cfg/agents/sql/sbx-mixin.yaml".to_string(),
|
dir_b.display().to_string(),
|
||||||
"coyote".to_string(),
|
"coyote".to_string(),
|
||||||
"--name".to_string(),
|
"--name".to_string(),
|
||||||
"my-box".to_string(),
|
"my-box".to_string(),
|
||||||
".".to_string(),
|
".".to_string(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let _ = fs::remove_dir_all(&dir_a);
|
||||||
|
let _ = fs::remove_dir_all(&dir_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -645,6 +658,7 @@ mod tests {
|
|||||||
|
|
||||||
mod vault_mixins {
|
mod vault_mixins {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::utils::get_env_name;
|
||||||
use gman::providers::aws_secrets_manager::AwsSecretsManagerProvider;
|
use gman::providers::aws_secrets_manager::AwsSecretsManagerProvider;
|
||||||
use gman::providers::azure_key_vault::AzureKeyVaultProvider;
|
use gman::providers::azure_key_vault::AzureKeyVaultProvider;
|
||||||
use gman::providers::gcp_secret_manager::GcpSecretManagerProvider;
|
use gman::providers::gcp_secret_manager::GcpSecretManagerProvider;
|
||||||
@@ -652,6 +666,46 @@ mod tests {
|
|||||||
use gman::providers::local::LocalProvider;
|
use gman::providers::local::LocalProvider;
|
||||||
use gman::providers::one_password::OnePasswordProvider;
|
use gman::providers::one_password::OnePasswordProvider;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
struct TestCacheDirGuard {
|
||||||
|
key: String,
|
||||||
|
previous: Option<std::ffi::OsString>,
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestCacheDirGuard {
|
||||||
|
fn new() -> Self {
|
||||||
|
let key = get_env_name("cache_dir");
|
||||||
|
let previous = env::var_os(&key);
|
||||||
|
let unique = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_nanos();
|
||||||
|
let path = env::temp_dir().join(format!("coyote-sandbox-vault-tests-{unique}"));
|
||||||
|
fs::create_dir_all(&path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
env::set_var(&key, &path);
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
key,
|
||||||
|
previous,
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestCacheDirGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
match &self.previous {
|
||||||
|
Some(v) => env::set_var(&self.key, v),
|
||||||
|
None => env::remove_var(&self.key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = fs::remove_dir_all(&self.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn returns_none_for_local() {
|
fn returns_none_for_local() {
|
||||||
@@ -664,6 +718,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn returns_some_for_aws() {
|
fn returns_some_for_aws() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
let p = SupportedProvider::AwsSecretsManager {
|
let p = SupportedProvider::AwsSecretsManager {
|
||||||
provider_def: AwsSecretsManagerProvider {
|
provider_def: AwsSecretsManagerProvider {
|
||||||
aws_profile: None,
|
aws_profile: None,
|
||||||
@@ -680,6 +735,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn returns_some_for_gcp() {
|
fn returns_some_for_gcp() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
let p = SupportedProvider::GcpSecretManager {
|
let p = SupportedProvider::GcpSecretManager {
|
||||||
provider_def: GcpSecretManagerProvider {
|
provider_def: GcpSecretManagerProvider {
|
||||||
gcp_project_id: None,
|
gcp_project_id: None,
|
||||||
@@ -695,6 +751,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn returns_some_for_one_password() {
|
fn returns_some_for_one_password() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
let p = SupportedProvider::OnePassword {
|
let p = SupportedProvider::OnePassword {
|
||||||
provider_def: OnePasswordProvider {
|
provider_def: OnePasswordProvider {
|
||||||
vault: None,
|
vault: None,
|
||||||
@@ -711,6 +768,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn returns_some_for_azure() {
|
fn returns_some_for_azure() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
let p = SupportedProvider::AzureKeyVault {
|
let p = SupportedProvider::AzureKeyVault {
|
||||||
provider_def: AzureKeyVaultProvider { vault_name: None },
|
provider_def: AzureKeyVaultProvider { vault_name: None },
|
||||||
};
|
};
|
||||||
@@ -724,6 +782,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn returns_some_for_gopass() {
|
fn returns_some_for_gopass() {
|
||||||
|
let _guard = TestCacheDirGuard::new();
|
||||||
let p = SupportedProvider::Gopass {
|
let p = SupportedProvider::Gopass {
|
||||||
provider_def: GopassProvider { store: None },
|
provider_def: GopassProvider { store: None },
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user