diff --git a/.claude/settings.json b/.claude/settings.json deleted file mode 100644 index e50690b..0000000 --- a/.claude/settings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "hooks": { - "PostToolUse": [ - { - "matcher": "Write|Edit|MultiEdit", - "hooks": [ - { - "type": "command", - "command": "bash ~/.claude/scripts/claude-code-quality-rust.sh" - } - ] - } - ] - } -} diff --git a/.config/nextest.toml b/.config/nextest.toml new file mode 100644 index 0000000..62a8225 --- /dev/null +++ b/.config/nextest.toml @@ -0,0 +1,8 @@ + +[profile.default] +final-status-level = "slow" + +[profile.ci] +# Don't fail fast in CI to run the full test suite. +fail-fast = false +slow-timeout = { period = "60s", terminate-after = 1 } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6ebf3a..a44177c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,33 +1,34 @@ on: - # Run only when pushing to main branch, and making PRs - push: - branches: - - main - pull_request: + # Run only when pushing to main branch, and making PRs + push: + branches: + - main + - rewrite + pull_request: name: CI jobs: - check: - name: Rust project - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install latest nightly - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - components: rustfmt, clippy - - # `cargo check` command here will use installed `nightly` - # as it is set as an "override" for current directory - - - name: Run cargo check - uses: actions-rs/cargo@v1 - with: - command: check - # - name: Run cargo lib tests - # uses: actions-rs/cargo@v1 - # with: - # command: test - # args: --lib + check: + name: Rust project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install latest nightly + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + - name: Install cargo nextest + uses: taiki-e/install-action@nextest + - name: Run cargo check + uses: actions-rs/cargo@v1 + with: + command: check + - name: Test with latest nextest release + uses: actions-rs/cargo@v1 + env: + CARGO_TERM_COLOR: always + with: + command: nextest + args: run --all-features --profile ci diff --git a/.gitignore b/.gitignore index 5707a5d..90b0174 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,13 @@ CLAUDE.md.local mcp-wrapper.sh /logs **/**.db +**/**.db-** **.txt **.car **.log.** **.json +!**/.sqlx/*.json **.sql +!**/migrations/*.sql **.surql +**/**.output diff --git a/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json b/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json new file mode 100644 index 0000000..94eaa18 --- /dev/null +++ b/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM oauth_sessions WHERE account_did = ? AND session_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9" +} diff --git a/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json b/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json new file mode 100644 index 0000000..2047944 --- /dev/null +++ b/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM app_password_sessions WHERE did = ? AND session_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f" +} diff --git a/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json b/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json new file mode 100644 index 0000000..4af5879 --- /dev/null +++ b/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO oauth_auth_requests (\n state, authserver_url, account_did, scopes, request_uri,\n authserver_token_endpoint, authserver_revocation_endpoint,\n pkce_verifier, dpop_key, dpop_nonce, created_at, expires_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (state) DO UPDATE SET\n authserver_url = excluded.authserver_url,\n account_did = excluded.account_did,\n scopes = excluded.scopes,\n request_uri = excluded.request_uri,\n authserver_token_endpoint = excluded.authserver_token_endpoint,\n authserver_revocation_endpoint = excluded.authserver_revocation_endpoint,\n pkce_verifier = excluded.pkce_verifier,\n dpop_key = excluded.dpop_key,\n dpop_nonce = excluded.dpop_nonce,\n expires_at = excluded.expires_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 12 + }, + "nullable": [] + }, + "hash": "28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765" +} diff --git a/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json b/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json new file mode 100644 index 0000000..cf63289 --- /dev/null +++ b/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json @@ -0,0 +1,44 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n did as \"did!\",\n session_id as \"session_id!\",\n access_jwt as \"access_jwt!\",\n refresh_jwt as \"refresh_jwt!\",\n handle as \"handle!\"\n FROM app_password_sessions\n WHERE did = ? AND session_id = ?\n ", + "describe": { + "columns": [ + { + "name": "did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "access_jwt!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "refresh_jwt!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "handle!", + "ordinal": 4, + "type_info": "Text" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406" +} diff --git a/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json b/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json new file mode 100644 index 0000000..290ab7d --- /dev/null +++ b/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM oauth_auth_requests WHERE state = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a" +} diff --git a/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json b/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json new file mode 100644 index 0000000..6af6085 --- /dev/null +++ b/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json @@ -0,0 +1,122 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n account_did as \"account_did!\",\n session_id as \"session_id!\",\n host_url as \"host_url!\",\n authserver_url as \"authserver_url!\",\n authserver_token_endpoint as \"authserver_token_endpoint!\",\n authserver_revocation_endpoint,\n scopes as \"scopes!\",\n dpop_key as \"dpop_key!\",\n dpop_authserver_nonce as \"dpop_authserver_nonce!\",\n dpop_host_nonce as \"dpop_host_nonce!\",\n token_iss as \"token_iss!\",\n token_sub as \"token_sub!\",\n token_aud as \"token_aud!\",\n token_scope,\n refresh_token,\n access_token as \"access_token!\",\n token_type as \"token_type!\",\n expires_at\n FROM oauth_sessions\n WHERE account_did = ? AND session_id = ?\n ", + "describe": { + "columns": [ + { + "name": "account_did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "host_url!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "authserver_url!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "authserver_token_endpoint!", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "authserver_revocation_endpoint", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "scopes!", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "dpop_key!", + "ordinal": 7, + "type_info": "Text" + }, + { + "name": "dpop_authserver_nonce!", + "ordinal": 8, + "type_info": "Text" + }, + { + "name": "dpop_host_nonce!", + "ordinal": 9, + "type_info": "Text" + }, + { + "name": "token_iss!", + "ordinal": 10, + "type_info": "Text" + }, + { + "name": "token_sub!", + "ordinal": 11, + "type_info": "Text" + }, + { + "name": "token_aud!", + "ordinal": 12, + "type_info": "Text" + }, + { + "name": "token_scope", + "ordinal": 13, + "type_info": "Text" + }, + { + "name": "refresh_token", + "ordinal": 14, + "type_info": "Text" + }, + { + "name": "access_token!", + "ordinal": 15, + "type_info": "Text" + }, + { + "name": "token_type!", + "ordinal": 16, + "type_info": "Text" + }, + { + "name": "expires_at", + "ordinal": 17, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + false, + true, + true, + false, + false, + true + ] + }, + "hash": "6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3" +} diff --git a/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json b/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json new file mode 100644 index 0000000..a07ce49 --- /dev/null +++ b/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO oauth_sessions (\n account_did, session_id, host_url, authserver_url,\n authserver_token_endpoint, authserver_revocation_endpoint,\n scopes, dpop_key, dpop_authserver_nonce, dpop_host_nonce,\n token_iss, token_sub, token_aud, token_scope,\n refresh_token, access_token, token_type, expires_at,\n created_at, updated_at\n ) VALUES (\n ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?\n )\n ON CONFLICT (account_did, session_id) DO UPDATE SET\n host_url = excluded.host_url,\n authserver_url = excluded.authserver_url,\n authserver_token_endpoint = excluded.authserver_token_endpoint,\n authserver_revocation_endpoint = excluded.authserver_revocation_endpoint,\n scopes = excluded.scopes,\n dpop_key = excluded.dpop_key,\n dpop_authserver_nonce = excluded.dpop_authserver_nonce,\n dpop_host_nonce = excluded.dpop_host_nonce,\n token_iss = excluded.token_iss,\n token_sub = excluded.token_sub,\n token_aud = excluded.token_aud,\n token_scope = excluded.token_scope,\n refresh_token = excluded.refresh_token,\n access_token = excluded.access_token,\n token_type = excluded.token_type,\n expires_at = excluded.expires_at,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 20 + }, + "nullable": [] + }, + "hash": "9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8" +} diff --git a/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json b/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json new file mode 100644 index 0000000..5d75552 --- /dev/null +++ b/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO app_password_sessions (\n did, session_id, access_jwt, refresh_jwt, handle, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (did, session_id) DO UPDATE SET\n access_jwt = excluded.access_jwt,\n refresh_jwt = excluded.refresh_jwt,\n handle = excluded.handle,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 7 + }, + "nullable": [] + }, + "hash": "dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa" +} diff --git a/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json b/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json new file mode 100644 index 0000000..9100069 --- /dev/null +++ b/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json @@ -0,0 +1,80 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n state as \"state!\",\n authserver_url as \"authserver_url!\",\n account_did,\n scopes as \"scopes!\",\n request_uri as \"request_uri!\",\n authserver_token_endpoint as \"authserver_token_endpoint!\",\n authserver_revocation_endpoint,\n pkce_verifier as \"pkce_verifier!\",\n dpop_key as \"dpop_key!\",\n dpop_nonce as \"dpop_nonce!\",\n expires_at as \"expires_at!\"\n FROM oauth_auth_requests\n WHERE state = ?\n ", + "describe": { + "columns": [ + { + "name": "state!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "authserver_url!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "account_did", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "scopes!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "request_uri!", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "authserver_token_endpoint!", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "authserver_revocation_endpoint", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "pkce_verifier!", + "ordinal": 7, + "type_info": "Text" + }, + { + "name": "dpop_key!", + "ordinal": 8, + "type_info": "Text" + }, + { + "name": "dpop_nonce!", + "ordinal": 9, + "type_info": "Text" + }, + { + "name": "expires_at!", + "ordinal": 10, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true, + false, + true, + false, + false, + false, + true, + false, + false, + false, + false + ] + }, + "hash": "fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f" +} diff --git a/CLAUDE.md b/CLAUDE.md index 6071da2..7bedd6a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,103 +1,33 @@ -# CLAUDE.md - Pattern ADHD Cognitive Support System - -⚠️ **CRITICAL WARNING**: DO NOT run `pattern-cli` or any agent commands during development! -Agents are currently running in production. Any CLI invocation will disrupt active agents. -Migrations and testing must be done offline after stopping production agents. - -Pattern is a multi-agent ADHD support system inspired by MemGPT's architecture to provide external executive function through specialized cognitive agents. - -## Project Status - -**Current State**: Core multi-agent framework operational, expanding integrations - -### 🚧 Current Development Priorities - -1. **Backend API Server** - 🟡 ACTIVE DEVELOPMENT - - Basic Axum server structure exists - - Auth handlers partially implemented - - Most endpoints still need implementation - - Required for multi-user hosting - -3. **MCP Client Refinement** - 🟢 NEEDS VERIFICATION - - All transports implemented (stdio, HTTP, SSE) - - Tool discovery and wrapper system working - - Needs testing with real MCP servers - - Auth support may need improvements - -4. **Task Management System** - 🟢 QUEUED - - Database schema exists - - Need CLI commands and user-facing features - - ADHD-aware task breakdown planned - -5. **MCP Server** - 🟢 LOWER PRIORITY - - Stub implementation only - - Expose Pattern tools to external clients - -## Completed Features - -### ✅ Message Batching -- Snowflake IDs for absolute ordering across all messages -- Batch tracking for atomic request/response cycles -- Tool call/response pairing maintained within batches -- Heartbeat continuations stay in same batch as original request -- Compression preserves batch boundaries (no splitting tool pairs) -- Generic heartbeat processor for all consumer crates -- Archive summaries as metadata, not fake messages -- **Migration completed** - all agent histories properly batched -- See `/home/booskie/pattern/docs/message-batching-design.md` for architecture - -### ✅ Agent Groups -- Full CLI support with create/add-member/status/list commands -- All coordination patterns working (RoundRobin, Dynamic, Pipeline, Supervisor, Voting, Sleeptime) -- Discord and Bluesky integration -- Runtime message routing through patterns -- More use cases and templates to be added - -### ✅ Discord Integration -- Full message handling with batching and merging -- Typing indicators with auto-refresh -- Reaction handling on bot messages -- All slash commands implemented (/help, /status, /memory, /archival, /context, /search, /list) -- Group integration with coordination patterns -- Data source mode for event ingestion - -### ✅ MCP Client -- All three transports implemented (stdio, HTTP, SSE) -- Tool discovery and dynamic wrapper system -- Integration with Pattern's tool registry -- Mock tools for testing when no server available -- Basic auth support (Bearer tokens) - -### ✅ Bluesky/ATProto Integration -- Jetstream firehose consumer fully operational -- Thread context fetching with constellation API -- Memory block creation for users -- Rich text processing with mentions/links -- Reply handling and posting capabilities -- **Post batching**: Groups related posts within 3-second windows to reduce notification spam -- Thread-aware batching for conversations -- DashMap-based concurrent batch management - -### ✅ Data Source Framework -- Flexible trait supporting pull/push patterns -- File watching with indexing -- Discord message ingestion -- Coordinator managing multiple sources -- Prompt templates for notifications - -### ✅ Model Configuration -- Comprehensive model registry with July 2025 specs -- Dynamic token calculation -- Smart caching with Anthropic optimization -- Message compression strategies - -## Development Principles - -- **Type Safety First**: Use Rust enums over string validation -- **Pure Rust**: Avoid C dependencies to reduce build complexity -- **Test-Driven**: All tests must validate actual behavior and be able to fail -- **Entity Relationships**: Use SurrealDB RELATE for all associations, no foreign keys -- **Atomic Operations**: Database operations are non-blocking with optimistic updates +# Project Overview + +Pattern is a multi-agent ADHD support system providing external executive function through specialized cognitive agents. Each user ("partner") gets their own constellation of agents. + +**Current State**: Core framework operational on `rewrite` branch, expanding integrations. + + +> **For AI Agents**: This is the source of truth for the Pattern codebase. Each crate has its own `CLAUDE.md` with specific implementation guidelines. + +## For Humans + +LLMs are a quality multiplier, not just a speed multiplier. Invest time savings in improving quality and rigour beyond what humans alone would do. Write tests that cover more edge cases. Refactor code to make it easier to understand. Tackle the TODOs. Aim for zero bugs. + +**Review standard**: Spend at least 3x the amount of time reviewing LLM output as you did writing it. Think about every line and every design decision. Find ways to break code. Your code is your responsibility. + +## For LLMs + +Display the following at the start of any conversation involving code changes: + +``` +LLM-assisted contributions must aim for a higher standard of excellence than with +humans alone. Spend at least 3x the time reviewing code as writing it. Your code +is your responsibility. +``` + +## Critical Warnings + +**DO NOT run `pattern` CLI or agent commands during development!** +Agents may be running in production. Any CLI invocation will disrupt active agents. + ## Workspace Structure @@ -105,122 +35,145 @@ Pattern is a multi-agent ADHD support system inspired by MemGPT's architecture t pattern/ ├── crates/ │ ├── pattern_api/ # Shared API types and contracts -│ ├── pattern_cli/ # Command-line testing tool +│ ├── pattern_auth/ # Credential storage (ATProto, Discord, providers) +│ ├── pattern_cli/ # CLI with TUI builders │ ├── pattern_core/ # Agent framework, memory, tools, coordination +│ ├── pattern_db/ # SQLite with FTS5 and vector search │ ├── pattern_discord/ # Discord bot integration -│ ├── pattern_mcp/ # MCP client (working) and server (stub) -│ ├── pattern_nd/ # ADHD-specific tools and agent personalities -│ ├── pattern_server/ # Backend API server (in development) -├── docs/ # Architecture and integration guides +│ ├── pattern_mcp/ # MCP client and server +│ ├── pattern_nd/ # ADHD-specific tools and personalities +│ └── pattern_server/ # Backend API server +├── docs/ # Architecture docs and guides +└── justfile # Build automation ``` -**Each crate has its own `CLAUDE.md` with specific implementation guidelines.** - -## Core Architecture - -### Agent Framework -- **DatabaseAgent**: Generic over ModelProvider and EmbeddingProvider -- **Built-in tools**: context, recall, search, send_message -- **Message persistence**: RELATE edges with Snowflake ID ordering -- **Memory system**: Thread-safe with semantic search, archival support, and atomic updates - -### Coordination Patterns -- **Dynamic**: Selector-based routing (random, capability, load-balancing) -- **Round-robin**: Fair distribution with skip-inactive support -- **Sleeptime**: Background monitoring with intervention triggers -- **Pipeline**: Sequential processing through agent stages -- **Supervisor**: Hierarchical delegation -- **Voting**: Consensus-based decisions - -### Entity System -Uses `#[derive(Entity)]` macro for SurrealDB integration: - -```rust -#[derive(Entity)] -#[entity(entity_type = "user")] -pub struct User { - pub id: UserId, - pub username: String, - - // Relations via RELATE, not foreign keys - #[entity(relation = "owns")] - pub owned_agents: Vec, -} -``` +Each crate has its own `CLAUDE.md` with specific implementation guidelines. + +## General Conventions + +### Correctness Over Convenience + +- Model the full error space—no shortcuts or simplified error handling. +- Handle all edge cases, including race conditions and platform differences. +- Use the type system to encode correctness constraints. +- Prefer compile-time guarantees over runtime checks where possible. -## Known Issues +### Type System Patterns -### API Provider Issues -- **Anthropic Thinking Mode**: Message compression can create invalid sequences with tool calls -- **Gemini Response Structure**: Missing `/candidates/0/content/parts` path during heartbeat continuations -- **Gemini Empty Contents**: "contents is not specified" error when all messages filtered out -- **Tool call validation**: Compression sometimes leaves unpaired tool calls (affects Flux agent) -- See `docs/known-api-issues.md` for workarounds +- **Newtypes** for domain types (IDs, handles, etc.). +- **Builder patterns** for complex construction. +- **Restricted visibility**: Use `pub(crate)` and `pub(super)` liberally. +- **Non-exhaustive**: All public error types should be `#[non_exhaustive]`. +- Use Rust enums over string validation. -### Export Issues -- **CAR Export**: Not archiving full message history - pattern matching issues preventing complete export - - Related to unused `CompressionSettings` struct in `pattern_core/src/export/types.rs` - - Lower priority but needs fixing for proper data portability +### Error Handling -## Implementation Notes +- Use `thiserror` for error types with `#[derive(Error)]`. +- Group errors by category with an `ErrorKind` enum when appropriate. +- Provide rich error context using `miette` for user-facing errors. +- Error display messages should be lowercase sentence fragments. -### 🔧 Memory Block Pass-through -Data sources can attach memory blocks to messages for agent context: -- DataSource trait returns memory blocks with notifications -- Coordinator includes blocks in message metadata -- Bluesky creates/retrieves user profile blocks automatically -- Router needs to create RELATE edges for block attachment (TODO) +### Module Organization -### 🔧 Anti-looping Protection -- Router returns errors instead of silently dropping messages -- 30-second cooldown between rapid agent-to-agent messages -- Prevents acknowledgment loops +- Use `mod.rs` to re-export public items only. +- No nontrivial logic in `mod.rs`—use `imp.rs` or specific submodules. +- Keep module boundaries strict with restricted visibility. +- Platform-specific code in separate files: `unix.rs`, `windows.rs`. -### 🔧 Constellation Integration -- Thread siblings fetched from constellation.microcosm.blue -- Engagement metrics and agent interaction tracking -- Smart filtering based on agent DID and friend lists -- Rich thread context display with [YOU] markers +### Documentation -## Feature Development Workflow +- Inline comments explain "why," not just "what". +- Module-level documentation explains purpose and responsibilities. +- **Always** use periods at the end of code comments. +- **Never** use title case in headings. Always use sentence case. -1. **Branch Creation**: `git checkout -b feature/task-management` -2. **Implementation**: Follow crate-specific CLAUDE.md guidelines -3. **Testing**: Add tests that validate actual behavior -4. **Validation**: Run `just pre-commit-all` before commit -5. **PR**: Create pull request with clear description +## Testing Practices + +**CRITICAL**: Always use `cargo nextest run` to run tests. Never use `cargo test` directly. + +```bash +# Run all tests +cargo nextest run + +# Specific crate +cargo nextest run -p pattern-db + +# With output +cargo nextest run --nocapture + +# Doctests (nextest doesn't support these) +cargo test --doc +``` + +### Test Organization + +- Unit tests in the same file as the code they test. +- Integration tests in `tests/` directories. +- All tests must validate actual behaviour and be able to fail. +- Use `proptest` for property-based testing where applicable. +- Use `insta` for snapshot testing where applicable. ## Build Commands ```bash # Quick validation cargo check -cargo test --lib +cargo nextest run --lib # Full pipeline (required before commit) just pre-commit-all -# Development helpers -just watch # Auto-recompile on changes -cargo test --lib -- db:: # Run specific module tests +# Format (required before commit) +cargo fmt + +# Lint +cargo clippy --all-features --all-targets + +# Database operations (from crate directory!) +cd crates/pattern_db && cargo sqlx prepare +cd crates/pattern_auth && cargo sqlx prepare +# NEVER use --workspace flag with sqlx prepare +``` + +## Commit Message Style + +``` +[crate-name] brief description ``` -## Architecture Notes +Examples: +- `[pattern-core] add supervisor coordination pattern` +- `[pattern-db] fix FTS5 query escaping` +- `[meta] update MSRV to Rust 1.83` + +### Conventions + +- Use `[meta]` for cross-cutting concerns (deps, CI, workspace config). +- Keep descriptions concise but descriptive. +- **Atomic commits**: Each commit should be a logical unit of change. +- **Bisect-able history**: Every commit must build and pass all checks. +- **Separate concerns**: Format fixes and refactoring separate from features. + +## Key Dependencies + +- **tokio**: Async runtime. +- **sqlx**: Compile-time verified SQL queries. +- **loro**: CRDT for versioned memory blocks. +- **thiserror/miette**: Error handling and diagnostics. +- **serde**: Serialization. +- **clap**: CLI parsing. +- **rmcp**: MCP protocol client. -### Partner-Centric Model -- **Partner**: Person receiving ADHD support (owns constellation) -- **Conversant**: Someone interacting through partner's agents -- **Privacy**: DM content never bleeds into public channels -- **Scaling**: Each partner gets full constellation, hibernated when inactive +## Documentation -### Backend API Server (In Development) -- Basic Axum server structure exists in `pattern_server` -- Handlers need implementation -- Required for multi-user hosting and non-technical users -- Will provide HTTP/WebSocket APIs, MCP integration, Discord bot hosting +- `docs/architecture/` - System architecture docs. +- `docs/guides/` - Setup and integration guides. +- `docs/plans/` - Implementation plans. +- Each crate's `CLAUDE.md` - Crate-specific guidelines. ## References -- [MCP Rust SDK](https://github.com/modelcontextprotocol/rust-sdk) -- [MemGPT Paper](https://arxiv.org/abs/2310.08560) - Stateful agent architecture -- [SurrealDB Documentation](https://surrealdb.com/docs) - Graph database patterns +- [MemGPT Paper](https://arxiv.org/abs/2310.08560) - Stateful agent architecture. +- [Loro CRDT](https://loro.dev/) - Conflict-free replicated data types. +- [MCP Rust SDK](https://github.com/modelcontextprotocol/rust-sdk). +- [Jacquard](https://github.com/videah/jacquard) - ATProto client library. diff --git a/Cargo.lock b/Cargo.lock index fbe5d82..a762e26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,9 +7,24 @@ name = "Inflector" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + +[[package]] +name = "abnf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a" dependencies = [ - "lazy_static", - "regex", + "abnf-core", + "nom", +] + +[[package]] +name = "abnf-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" +dependencies = [ + "nom", ] [[package]] @@ -36,6 +51,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "affinitypool" version = "0.3.1" @@ -66,7 +87,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "serde", "version_check", @@ -75,13 +96,19 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "aliasable" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -136,9 +163,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -166,22 +193,22 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -196,6 +223,12 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "append-only-bytes" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac436601d6bdde674a0d7fb593e829ffe7b3387c351b356dd20e2d40f5bf3ee5" + [[package]] name = "approx" version = "0.4.0" @@ -214,6 +247,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ar_archive_writer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" +dependencies = [ + "object 0.32.2", +] + [[package]] name = "arbitrary" version = "1.4.2" @@ -250,6 +292,30 @@ dependencies = [ "serde", ] +[[package]] +name = "arref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ccd462b64c3c72f1be8305905a85d85403d768e8690c9b8bd3b9009a5761679" + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.9", + "stable_deref_trait", +] + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -273,9 +339,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.32" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" +checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" dependencies = [ "compression-codecs", "compression-core", @@ -300,22 +366,22 @@ dependencies = [ [[package]] name = "async-graphql" -version = "7.0.17" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "036618f842229ba0b89652ffe425f96c7c16a49f7e3cb23b56fca7f61fd74980" +checksum = "31b75c5a43a58890d6dcc02d03952456570671332bb0a5a947b1f09c699912a5" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", - "async-stream", "async-trait", + "asynk-strim", "base64 0.22.1", "bytes", "fnv", "futures-timer", "futures-util", - "http 1.3.1", - "indexmap 2.11.4", + "http 1.4.0", + "indexmap 2.12.1", "mime", "multer", "num-traits", @@ -325,31 +391,31 @@ dependencies = [ "serde_json", "serde_urlencoded", "static_assertions_next", - "thiserror 1.0.69", + "thiserror 2.0.17", ] [[package]] name = "async-graphql-derive" -version = "7.0.17" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd45deb3dbe5da5cdb8d6a670a7736d735ba65b455328440f236dfb113727a3d" +checksum = "0c266ec9a094bbf2d088e016f71aa8d3be7f18c7343b2f0fe6d0e6c1e78977ea" dependencies = [ "Inflector", "async-graphql-parser", - "darling 0.20.11", + "darling 0.23.0", "proc-macro-crate", "proc-macro2", "quote", - "strum", - "syn 2.0.106", - "thiserror 1.0.69", + "strum 0.27.2", + "syn 2.0.113", + "thiserror 2.0.17", ] [[package]] name = "async-graphql-parser" -version = "7.0.17" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b7607e59424a35dadbc085b0d513aa54ec28160ee640cf79ec3b634eba66d3" +checksum = "67e2188d3f1299087aa02cfb281f12414905ce63f425dbcfe7b589773468d771" dependencies = [ "async-graphql-value", "pest", @@ -359,49 +425,27 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.17" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecdaff7c9cffa3614a9f9999bf9ee4c3078fe3ce4d6a6e161736b56febf2de" +checksum = "527a4c6022fc4dac57b4f03f12395e9a391512e85ba98230b93315f8f45f27fc" dependencies = [ "bytes", - "indexmap 2.11.4", + "indexmap 2.12.1", "serde", "serde_json", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", "pin-project-lite", ] -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", -] - [[package]] name = "async-task" version = "4.7.1" @@ -416,7 +460,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -430,6 +474,34 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "asynk-strim" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52697735bdaac441a29391a9e97102c74c6ef0f9b60a40cf109b1b404e29d2f6" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -438,16 +510,16 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atrium-api" -version = "0.25.5" +version = "0.25.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bceed6a87be6213040945254aa94191490fea22b7f49dec584e349f336cc17a" +checksum = "1f182d9437cd447ed87eca75540151653e332d6753a2a4749d72c0f15aa1f179" dependencies = [ "atrium-common", "atrium-xrpc", "chrono", - "http 1.3.1", + "http 1.4.0", "ipld-core", - "langtag", + "langtag 0.3.4", "regex", "serde", "serde_bytes", @@ -459,9 +531,9 @@ dependencies = [ [[package]] name = "atrium-common" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed5610654043faa396a5a15afac0ac646d76aebe45aebd7cef4f8b96b0ab7f4" +checksum = "eff94b4ce3e9ba11d8bda83674e75ccaca281d5251ec3816d03e6bb23583ff4f" dependencies = [ "dashmap 6.1.0", "lru", @@ -474,56 +546,27 @@ dependencies = [ [[package]] name = "atrium-identity" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "035d4fcfed4a42e10f343e7ffc2b4a5aba355ece4b272a25f683043f07728ce0" -dependencies = [ - "atrium-api", - "atrium-common", - "atrium-xrpc", - "serde", - "serde_html_form", - "serde_json", - "thiserror 1.0.69", - "trait-variant", -] - -[[package]] -name = "atrium-oauth" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04c6818380cbaac6ae75f3b1ecf9f9210083fa8193dd9c218305a99fb4b34bd" +checksum = "3e7cfd14c15bda5087b340a4a8825a7315bbf06a4f879a02186f10481e8a22a6" dependencies = [ "atrium-api", "atrium-common", - "atrium-identity", "atrium-xrpc", - "base64 0.22.1", - "chrono", - "dashmap 6.1.0", - "ecdsa", - "elliptic-curve", - "jose-jwa", - "jose-jwk", - "p256", - "rand 0.8.5", - "reqwest 0.12.23", "serde", "serde_html_form", "serde_json", - "sha2", "thiserror 1.0.69", - "tokio", "trait-variant", ] [[package]] name = "atrium-xrpc" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0216ad50ce34e9ff982e171c3659e65dedaa2ed5ac2994524debdc9a9647ffa8" +checksum = "944b35cc08732d40ddbb3356be9e38d11aed4b4c40c33f5b0f235e0650eff296" dependencies = [ - "http 1.3.1", + "http 1.4.0", "serde", "serde_html_form", "serde_json", @@ -531,16 +574,6 @@ dependencies = [ "trait-variant", ] -[[package]] -name = "atrium-xrpc-client" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e099e5171f79faef52364ef0657a4cab086a71b384a779a29597a91b780de0d5" -dependencies = [ - "atrium-xrpc", - "reqwest 0.12.23", -] - [[package]] name = "autocfg" version = "1.5.0" @@ -554,18 +587,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", - "axum-core 0.4.5", + "axum-core", "axum-macros", "base64 0.22.1", "bytes", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http 1.4.0", + "http-body", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-util", "itoa", - "matchit 0.7.3", + "matchit", "memchr", "mime", "percent-encoding", @@ -576,7 +609,7 @@ dependencies = [ "serde_path_to_error", "serde_urlencoded", "sha1", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tokio-tungstenite 0.24.0", "tower", @@ -585,39 +618,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" -dependencies = [ - "axum-core 0.5.5", - "bytes", - "form_urlencoded", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "hyper 1.7.0", - "hyper-util", - "itoa", - "matchit 0.8.4", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde_core", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper 1.0.2", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "axum-core" version = "0.4.5" @@ -627,32 +627,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http 1.4.0", + "http-body", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" -dependencies = [ - "bytes", - "futures-core", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "mime", - "pin-project-lite", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", "tracing", @@ -664,13 +645,13 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ - "axum 0.7.9", - "axum-core 0.4.5", + "axum", + "axum-core", "bytes", "futures-util", "headers", - "http 1.3.1", - "http-body 1.0.1", + "http 1.4.0", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -688,7 +669,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -701,9 +682,9 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.37.3", "rustc-demangle", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -763,9 +744,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82" [[package]] name = "bcrypt" @@ -812,9 +793,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] [[package]] name = "bitvec" @@ -878,7 +871,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -893,9 +886,9 @@ dependencies = [ [[package]] name = "bon" -version = "3.7.2" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2529c31017402be841eb45892278a6c21a000c0a17643af326c73a73f83f0fb" +checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" dependencies = [ "bon-macros", "rustversion", @@ -903,9 +896,9 @@ dependencies = [ [[package]] name = "bon-macros" -version = "3.7.2" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82020dadcb845a345591863adb65d74fa8dc5c18a0b6d408470e13b7adc7005" +checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" dependencies = [ "darling 0.21.3", "ident_case", @@ -913,14 +906,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" dependencies = [ "borsh-derive", "cfg_aliases", @@ -928,15 +921,26 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", +] + +[[package]] +name = "brotli" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor 2.5.1", ] [[package]] @@ -947,7 +951,17 @@ checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor", + "brotli-decompressor 5.0.0", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] @@ -961,29 +975,54 @@ dependencies = [ ] [[package]] -name = "bsky-sdk" -version = "0.1.21" +name = "bstr" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac3fd5ca998d3bdb1debdd421a16a94931f61e0d805a0208907ec3b5f2cffea" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ - "anyhow", - "atrium-api", - "atrium-xrpc-client", - "chrono", - "psl", - "regex", + "memchr", "serde", - "serde_json", - "thiserror 1.0.69", - "trait-variant", - "unicode-segmentation", +] + +[[package]] +name = "btree-range-map" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be5c9672446d3800bcbcaabaeba121fe22f1fb25700c4562b22faf76d377c33" +dependencies = [ + "btree-slab", + "cc-traits", + "range-traits", + "serde", + "slab", +] + +[[package]] +name = "btree-slab" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2b56d3029f075c4fa892428a098425b86cef5c89ae54073137ece416aef13c" +dependencies = [ + "cc-traits", + "slab", + "smallvec", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", ] [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytecheck" @@ -1007,24 +1046,30 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1035,9 +1080,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" dependencies = [ "serde", ] @@ -1050,7 +1095,7 @@ checksum = "a9f51e2ecf6efe9737af8f993433c839f956d2b6ed4fd2dd4a7c6d8b0fa667ff" dependencies = [ "byteorder", "gemm 0.17.1", - "half 2.6.0", + "half 2.7.1", "memmap2", "num-traits", "num_cpus", @@ -1071,7 +1116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1980d53280c8f9e2c6cbe1785855d7ff8010208b46e21252b978badf13ad69d" dependencies = [ "candle-core", - "half 2.6.0", + "half 2.7.1", "num-traits", "rayon", "safetensors", @@ -1124,9 +1169,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.39" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "jobserver", @@ -1134,6 +1179,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cc-traits" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060303ef31ef4a522737e1b1ab68c67916f2a787bb2f4f54f383279adba962b5" +dependencies = [ + "slab", +] + [[package]] name = "cedar-policy" version = "2.4.2" @@ -1147,7 +1201,7 @@ dependencies = [ "ref-cast", "serde", "serde_json", - "smol_str", + "smol_str 0.2.2", "thiserror 1.0.69", ] @@ -1169,7 +1223,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "smol_str", + "smol_str 0.2.2", "stacker", "thiserror 1.0.69", ] @@ -1185,7 +1239,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "smol_str", + "smol_str 0.2.2", "stacker", "thiserror 1.0.69", "unicode-security", @@ -1199,9 +1253,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1220,7 +1274,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -1233,6 +1287,12 @@ dependencies = [ "phf 0.12.1", ] +[[package]] +name = "chunked_transfer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" + [[package]] name = "ciborium" version = "0.2.2" @@ -1257,7 +1317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half 2.6.0", + "half 2.7.1", ] [[package]] @@ -1286,9 +1346,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.48" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -1296,9 +1356,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.48" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -1308,21 +1368,30 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "cobs" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.17", +] [[package]] name = "colorchoice" @@ -1353,9 +1422,9 @@ dependencies = [ [[package]] name = "command_attr" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fcc89439e1bb4e19050a9586a767781a3060000d2f3296fd2a40597ad9421c5" +checksum = "8208103c5e25a091226dfa8d61d08d0561cc14f31b25691811ba37d4ec9b157b" dependencies = [ "proc-macro2", "quote", @@ -1395,11 +1464,11 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.31" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" +checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" dependencies = [ - "brotli", + "brotli 8.0.2", "compression-core", "flate2", "memchr", @@ -1409,9 +1478,9 @@ dependencies = [ [[package]] name = "compression-core" -version = "0.4.29" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" +checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" [[package]] name = "concurrent-queue" @@ -1449,9 +1518,9 @@ checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", "konst", @@ -1476,9 +1545,9 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" -version = "0.7.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -1492,6 +1561,16 @@ dependencies = [ "crossterm 0.29.0", ] +[[package]] +name = "cordyceps" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1502,6 +1581,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1526,6 +1615,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.5.0" @@ -1535,6 +1639,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crokey" version = "1.3.0" @@ -1558,7 +1668,7 @@ dependencies = [ "proc-macro2", "quote", "strict", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1623,7 +1733,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm_winapi", "mio", "parking_lot", @@ -1639,14 +1749,14 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm_winapi", - "derive_more 2.0.1", + "derive_more 2.1.1", "document-features", "futures-core", "mio", "parking_lot", - "rustix 1.1.2", + "rustix 1.1.3", "signal-hook", "signal-hook-mio", "winapi", @@ -1673,7 +1783,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.9", "rand_core 0.6.4", "subtle", "zeroize", @@ -1685,7 +1795,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.9", "typenum", ] @@ -1722,7 +1832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1745,6 +1855,16 @@ dependencies = [ "darling_macro 0.21.3", ] +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + [[package]] name = "darling_core" version = "0.20.11" @@ -1756,7 +1876,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1770,7 +1890,20 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.113", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.113", ] [[package]] @@ -1781,7 +1914,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1792,7 +1925,18 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.106", + "syn 2.0.113", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.113", ] [[package]] @@ -1855,7 +1999,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.106", + "syn 2.0.113", +] + +[[package]] +name = "deflate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +dependencies = [ + "adler32", + "gzip-header", ] [[package]] @@ -1865,14 +2019,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", + "pem-rfc7468", "zeroize", ] [[package]] name = "deranged" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", "serde_core", @@ -1886,7 +2041,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1907,7 +2062,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1917,7 +2072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1928,7 +2083,7 @@ checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -1942,11 +2097,11 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl 2.1.1", ] [[package]] @@ -1957,19 +2112,21 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", + "unicode-xid", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.113", "unicode-xid", ] @@ -1992,6 +2149,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + [[package]] name = "diff" version = "0.1.13" @@ -2059,7 +2222,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -2081,7 +2244,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -2096,9 +2259,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -2123,9 +2286,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -2154,13 +2317,20 @@ dependencies = [ [[package]] name = "dyn-stack" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490bd48eb68fffcfed519b4edbfd82c69cbe741d175b84f0e0cbe8c57cbe0bdd" +checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8" dependencies = [ "bytemuck", + "dyn-stack-macros", ] +[[package]] +name = "dyn-stack-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9" + [[package]] name = "earcutr" version = "0.4.3" @@ -2182,6 +2352,7 @@ dependencies = [ "elliptic-curve", "rfc6979", "signature", + "spki", ] [[package]] @@ -2195,6 +2366,9 @@ name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -2206,14 +2380,28 @@ dependencies = [ "crypto-bigint", "digest", "ff", - "generic-array", + "generic-array 0.14.9", "group", + "pem-rfc7468", + "pkcs8", "rand_core 0.6.4", "sec1", "subtle", "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "ena" version = "0.14.3" @@ -2244,16 +2432,46 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "ensure-cov" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33753185802e107b8fa907192af1f0eca13b1fb33327a59266d650fef29b2b4e" + +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "enum-as-inner" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -2269,7 +2487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -2281,6 +2499,17 @@ dependencies = [ "cc", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -2386,9 +2615,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] name = "fixedbitset" @@ -2398,9 +2627,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -2421,7 +2650,7 @@ dependencies = [ "futures-core", "futures-sink", "nanorand", - "spin", + "spin 0.9.8", ] [[package]] @@ -2512,6 +2741,19 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd" +dependencies = [ + "cordyceps", + "diatomic-waker", + "futures-core", + "pin-project-lite", + "spin 0.10.0", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -2539,6 +2781,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -2566,7 +2819,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -2649,7 +2902,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab96b703d31950f1aeddded248bc95543c9efc7ac9c4a21fda8703a83ee35451" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-c32 0.18.2", "gemm-c64 0.18.2", "gemm-common 0.18.2", @@ -2684,7 +2937,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6db9fd9f40421d00eea9dd0770045a5603b8d684654816637732463f4073847" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", @@ -2714,7 +2967,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfcad8a3d35a43758330b635d02edad980c1e143dc2f21e6fd25f9e4eada8edf" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", @@ -2731,7 +2984,7 @@ checksum = "a2e7ea062c987abcd8db95db917b4ffb4ecdfd0668471d8dc54734fdff2354e8" dependencies = [ "bytemuck", "dyn-stack 0.10.0", - "half 2.6.0", + "half 2.7.1", "num-complex", "num-traits", "once_cell", @@ -2750,8 +3003,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a352d4a69cbe938b9e2a9cb7a3a63b7e72f9349174a2752a558a8a563510d0f3" dependencies = [ "bytemuck", - "dyn-stack 0.13.0", - "half 2.6.0", + "dyn-stack 0.13.2", + "half 2.7.1", "libm", "num-complex", "num-traits", @@ -2773,7 +3026,7 @@ dependencies = [ "dyn-stack 0.10.0", "gemm-common 0.17.1", "gemm-f32 0.17.1", - "half 2.6.0", + "half 2.7.1", "num-complex", "num-traits", "paste", @@ -2788,10 +3041,10 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cff95ae3259432f3c3410eaa919033cd03791d81cebd18018393dc147952e109" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "gemm-f32 0.18.2", - "half 2.6.0", + "half 2.7.1", "num-complex", "num-traits", "paste", @@ -2821,7 +3074,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc8d3d4385393304f407392f754cd2dc4b315d05063f62cf09f47b58de276864" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", @@ -2851,7 +3104,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b2a4f76ce4b8b16eadc11ccf2e083252d8237c1b589558a49b0183545015bd" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", @@ -2866,10 +3119,10 @@ version = "0.4.0-alpha.8-WIP" source = "git+https://github.com/orual/rust-genai#0e81a6c8b27e2d31cc3c27fae237a3f4b3dec3ad" dependencies = [ "bytes", - "derive_more 2.0.1", + "derive_more 2.1.1", "eventsource-stream", "futures", - "reqwest 0.12.23", + "reqwest", "reqwest-eventsource", "serde", "serde_json", @@ -2880,17 +3133,64 @@ dependencies = [ "value-ext", ] +[[package]] +name = "generator" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows-link 0.2.1", + "windows-result 0.4.1", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", "zeroize", ] +[[package]] +name = "generic-btree" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c1bce85c110ab718fd139e0cc89c51b63bd647b14a767e24bdfc77c83df79b" +dependencies = [ + "arref", + "heapless 0.9.2", + "itertools 0.11.0", + "loro-thunderdome", + "proc-macro2", + "rustc-hash", +] + [[package]] name = "geo" version = "0.28.0" @@ -2904,20 +3204,24 @@ dependencies = [ "log", "num-traits", "robust", - "rstar", + "rstar 0.12.2", "serde", "spade", ] [[package]] name = "geo-types" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a4dcd69d35b2c87a7c83bce9af69fd65c9d68d3833a0ded568983928f3fc99" +checksum = "24f8647af4005fa11da47cd56252c6ef030be8fa97bdbf355e7dfb6348f0a82c" dependencies = [ "approx 0.5.1", "num-traits", - "rstar", + "rstar 0.10.0", + "rstar 0.11.0", + "rstar 0.12.2", + "rstar 0.8.4", + "rstar 0.9.3", "serde", ] @@ -2948,21 +3252,21 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] @@ -2978,6 +3282,47 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "gloo-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" +dependencies = [ + "gloo-utils", + "js-sys", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "group" version = "0.13.0" @@ -2990,37 +3335,27 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.27" +name = "gzip-header" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.11.4", - "slab", - "tokio", - "tokio-util", - "tracing", + "crc32fast", ] [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.3.1", - "indexmap 2.11.4", + "http 1.4.0", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -3035,9 +3370,9 @@ checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "bytemuck", "cfg-if", @@ -3045,24 +3380,43 @@ dependencies = [ "num-traits", "rand 0.9.2", "rand_distr", + "zerocopy", ] [[package]] name = "hash32" -version = "0.3.1" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" dependencies = [ "byteorder", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "hash32" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" dependencies = [ - "ahash 0.7.8", + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", ] [[package]] @@ -3084,9 +3438,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hashlink" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] [[package]] name = "headers" @@ -3097,7 +3460,7 @@ dependencies = [ "base64 0.22.1", "bytes", "headers-core", - "http 1.3.1", + "http 1.4.0", "httpdate", "mime", "sha1", @@ -3109,7 +3472,33 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.3.1", + "http 1.4.0", +] + +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.9", + "hash32 0.1.1", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "serde", + "spin 0.9.8", + "stable_deref_trait", ] [[package]] @@ -3118,10 +3507,26 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +dependencies = [ + "hash32 0.3.1", "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -3140,6 +3545,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + [[package]] name = "hf-hub" version = "0.4.3" @@ -3153,7 +3564,7 @@ dependencies = [ "log", "num_cpus", "rand 0.9.2", - "reqwest 0.12.23", + "reqwest", "serde", "serde_json", "thiserror 2.0.17", @@ -3170,7 +3581,7 @@ dependencies = [ "async-trait", "cfg-if", "data-encoding", - "enum-as-inner", + "enum-as-inner 0.6.1", "futures-channel", "futures-io", "futures-util", @@ -3206,6 +3617,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -3215,6 +3635,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "html2md" version = "0.2.15" @@ -3222,7 +3651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cff9891f2e0d9048927fbdfc28b11bf378f6a93c7ba70b23d0fbee9af6071b4" dependencies = [ "html5ever 0.27.0", - "jni", + "jni 0.19.0", "lazy_static", "markup5ever_rcdom", "percent-encoding", @@ -3240,7 +3669,7 @@ dependencies = [ "markup5ever 0.12.1", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -3279,26 +3708,14 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -3306,7 +3723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http 1.4.0", ] [[package]] @@ -3317,8 +3734,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http 1.4.0", + "http-body", "pin-project-lite", ] @@ -3342,41 +3759,17 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", - "h2 0.4.12", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http 1.4.0", + "http-body", "httparse", "httpdate", "itoa", @@ -3387,73 +3780,43 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-rustls" version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http 1.3.1", - "hyper 1.7.0", + "http 1.4.0", + "hyper", "hyper-util", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.2", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.7.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "webpki-roots 1.0.5", ] [[package]] name = "hyper-util" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.7.0", + "http 1.4.0", + "http-body", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", - "system-configuration 0.6.1", + "socket2 0.6.1", + "system-configuration", "tokio", "tower-service", "tracing", @@ -3472,7 +3835,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.1", + "windows-core 0.62.2", ] [[package]] @@ -3486,22 +3849,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", - "yoke 0.8.0", + "yoke 0.8.1", "zerofrom", "zerovec", ] [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -3512,11 +3875,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -3527,44 +3889,40 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", - "yoke 0.8.0", + "yoke 0.8.1", "zerofrom", "zerotrie", "zerovec", @@ -3597,6 +3955,21 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -3610,12 +3983,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.4" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "serde", "serde_core", ] @@ -3635,9 +4008,12 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "inotify" @@ -3665,20 +4041,20 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] name = "instability" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a" +checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" dependencies = [ - "darling 0.20.11", + "darling 0.23.0", "indoc", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -3691,14 +4067,12 @@ dependencies = [ ] [[package]] -name = "io-uring" -version = "0.7.10" +name = "inventory" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", + "rustversion", ] [[package]] @@ -3732,9 +4106,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -3764,9 +4138,9 @@ checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -3786,6 +4160,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -3806,59 +4189,272 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] -name = "jni" -version = "0.19.0" +name = "jacquard" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +checksum = "f7c1fdbcf1153e6e6b87fde20036c1ffe7473c4852f1c6369bc4ef1fe47ccb9f" dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", + "bytes", + "getrandom 0.2.16", + "gloo-storage", + "http 1.4.0", + "jacquard-api", + "jacquard-common", + "jacquard-derive", + "jacquard-identity", + "jacquard-oauth", + "jose-jwk", + "miette 7.6.0", + "regex", + "regex-lite", + "reqwest", + "serde", + "serde_html_form", + "serde_json", + "smol_str 0.3.4", + "thiserror 2.0.17", + "tokio", + "trait-variant", + "url", + "webpage", ] [[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.34" +name = "jacquard-api" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "4979fb1848c1dd7ac8fd12745bc71f56f6da61374407d5f9b06005467a954e5a" dependencies = [ - "getrandom 0.3.3", - "libc", + "bon", + "bytes", + "jacquard-common", + "jacquard-derive", + "jacquard-lexicon", + "miette 7.6.0", + "rustversion", + "serde", + "serde_bytes", + "serde_ipld_dagcbor", + "thiserror 2.0.17", + "unicode-segmentation", ] [[package]] -name = "jose-b64" -version = "0.1.2" +name = "jacquard-common" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec69375368709666b21c76965ce67549f2d2db7605f1f8707d17c9656801b56" +checksum = "1751921e0bdae5e0077afade6161545e9ef7698306c868f800916e99ecbcaae9" dependencies = [ - "base64ct", + "base64 0.22.1", + "bon", + "bytes", + "chrono", + "ciborium", + "cid", + "futures", + "getrandom 0.2.16", + "getrandom 0.3.4", + "http 1.4.0", + "ipld-core", + "k256", + "langtag 0.4.0", + "miette 7.6.0", + "multibase", + "multihash", + "n0-future", + "ouroboros", + "p256", + "postcard", + "rand 0.9.2", + "regex", + "regex-lite", + "reqwest", "serde", - "subtle", - "zeroize", + "serde_bytes", + "serde_html_form", + "serde_ipld_dagcbor", + "serde_json", + "signature", + "smol_str 0.3.4", + "thiserror 2.0.17", + "tokio", + "tokio-tungstenite-wasm", + "tokio-util", + "trait-variant", + "url", + "zstd", ] [[package]] -name = "jose-jwa" -version = "0.1.2" +name = "jacquard-derive" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab78e053fe886a351d67cf0d194c000f9d0dcb92906eb34d853d7e758a4b3a7" +checksum = "9c8d73dfee07943fdab93569ed1c28b06c6921ed891c08b415c4a323ff67e593" dependencies = [ - "serde", + "heck 0.5.0", + "jacquard-lexicon", + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "jacquard-identity" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aaefa819fa4213cf59f180dba932f018a7cd0599582fd38474ee2a38c16cf2" +dependencies = [ + "bon", + "bytes", + "hickory-resolver", + "http 1.4.0", + "jacquard-api", + "jacquard-common", + "jacquard-lexicon", + "miette 7.6.0", + "mini-moka-wasm", + "n0-future", + "percent-encoding", + "reqwest", + "serde", + "serde_html_form", + "serde_json", + "thiserror 2.0.17", + "tokio", + "trait-variant", + "url", + "urlencoding", +] + +[[package]] +name = "jacquard-lexicon" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8411aff546569b0a1e0ef669bed2380cec1c00d48f02f3fcd57a71545321b3d8" +dependencies = [ + "cid", + "dashmap 6.1.0", + "heck 0.5.0", + "inventory", + "jacquard-common", + "miette 7.6.0", + "multihash", + "prettyplease", + "proc-macro2", + "quote", + "serde", + "serde_ipld_dagcbor", + "serde_json", + "serde_repr", + "serde_with", + "sha2", + "syn 2.0.113", + "thiserror 2.0.17", + "unicode-segmentation", +] + +[[package]] +name = "jacquard-oauth" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bf0b0e061d85b09cfa78588dc098918d5b62f539a719165c6a806a1d2c0ef2" +dependencies = [ + "base64 0.22.1", + "bytes", + "chrono", + "dashmap 6.1.0", + "elliptic-curve", + "http 1.4.0", + "jacquard-common", + "jacquard-identity", + "jose-jwa", + "jose-jwk", + "miette 7.6.0", + "p256", + "rand 0.8.5", + "rouille", + "serde", + "serde_html_form", + "serde_json", + "sha2", + "smol_str 0.3.4", + "thiserror 2.0.17", + "tokio", + "trait-variant", + "url", + "webbrowser", +] + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "jose-b64" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec69375368709666b21c76965ce67549f2d2db7605f1f8707d17c9656801b56" +dependencies = [ + "base64ct", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "jose-jwa" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab78e053fe886a351d67cf0d194c000f9d0dcb92906eb34d853d7e758a4b3a7" +dependencies = [ + "serde", ] [[package]] @@ -3870,15 +4466,17 @@ dependencies = [ "jose-b64", "jose-jwa", "p256", + "p384", + "rsa", "serde", "zeroize", ] [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -3899,6 +4497,18 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + [[package]] name = "keccak" version = "0.1.5" @@ -3983,11 +4593,22 @@ dependencies = [ "serde", ] +[[package]] +name = "langtag" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecb4c689a30e48ebeaa14237f34037e300dd072e6ad21a9ec72e810ff3c6600" +dependencies = [ + "serde", + "static-regular-grammar", + "thiserror 1.0.69", +] + [[package]] name = "lazy-regex" -version = "3.4.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60c7310b93682b36b98fa7ea4de998d3463ccbebd94d935d6b48ba5b6ffa7126" +checksum = "c5c13b6857ade4c8ee05c3c3dc97d2ab5415d691213825b90d3211c425c1f907" dependencies = [ "lazy-regex-proc_macros", "once_cell", @@ -3996,14 +4617,14 @@ dependencies = [ [[package]] name = "lazy-regex-proc_macros" -version = "3.4.1" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ba01db5ef81e17eb10a5e0f2109d1b3a3e29bac3070fdbd7d156bf7dbd206a1" +checksum = "32a95c68db5d41694cea563c86a4ba4dc02141c16ef64814108cb23def4d5438" dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4011,6 +4632,15 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "levenshtein" @@ -4029,9 +4659,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.176" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libloading" @@ -4040,7 +4670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -4051,13 +4681,24 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", - "redox_syscall", + "redox_syscall 0.7.0", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", ] [[package]] @@ -4092,31 +4733,183 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "loro" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75216d8f99725531a30f7b00901ee154a4f8a9b7f125bfe032e197d4c7ffb8c" +dependencies = [ + "enum-as-inner 0.6.1", + "generic-btree", + "loro-common", + "loro-delta", + "loro-internal", + "loro-kv-store", + "rustc-hash", + "tracing", +] + +[[package]] +name = "loro-common" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "70363ea05a9c507fd9d58b65dc414bf515f636d69d8ab53e50ecbe8d27eef90c" +dependencies = [ + "arbitrary", + "enum-as-inner 0.6.1", + "leb128", + "loro-rle", + "nonmax", + "rustc-hash", + "serde", + "serde_columnar", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "loro-delta" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eafa788a72c1cbf0b7dc08a862cd7cc31b96d99c2ef749cdc94c2330f9494d3" +dependencies = [ + "arrayvec", + "enum-as-inner 0.5.1", + "generic-btree", + "heapless 0.8.0", +] + +[[package]] +name = "loro-internal" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f447044ec3d3ba572623859add3334bd87b84340ee5fdf00315bfee0e3ad3e3f" +dependencies = [ + "append-only-bytes", + "arref", + "bytes", + "either", + "ensure-cov", + "enum-as-inner 0.6.1", + "enum_dispatch", + "generic-btree", + "getrandom 0.2.16", + "im", + "itertools 0.12.1", + "leb128", + "loom", + "loro-common", + "loro-delta", + "loro-kv-store", + "loro-rle", + "loro_fractional_index", + "md5", + "nonmax", + "num", + "num-traits", + "once_cell", + "parking_lot", + "pest", + "pest_derive", + "postcard", + "pretty_assertions", + "rand 0.8.5", + "rustc-hash", + "serde", + "serde_columnar", + "serde_json", + "smallvec", + "thiserror 1.0.69", + "thread_local", + "tracing", + "wasm-bindgen", + "xxhash-rust", +] + +[[package]] +name = "loro-kv-store" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78beebc933a33c26495c9a98f05b38bc0a4c0a337ecfbd3146ce1f9437eec71f" +dependencies = [ + "bytes", + "ensure-cov", + "loro-common", + "lz4_flex", + "once_cell", + "quick_cache 0.6.18", + "rustc-hash", + "tracing", + "xxhash-rust", +] + +[[package]] +name = "loro-rle" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76400c3eea6bb39b013406acce964a8db39311534e308286c8d8721baba8ee20" +dependencies = [ + "append-only-bytes", + "num", + "smallvec", +] + +[[package]] +name = "loro-thunderdome" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" + +[[package]] +name = "loro_fractional_index" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c8ea186958094052b971fe7e322a934b034c3bf62f0458ccea04fcd687ba1" +dependencies = [ + "once_cell", + "rand 0.8.5", + "serde", +] [[package]] name = "lru" @@ -4142,6 +4935,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +dependencies = [ + "twox-hash", +] + [[package]] name = "mac" version = "0.1.1" @@ -4187,7 +4989,7 @@ checksum = "9ab6ee21fd1855134cacf2f41afdf45f1bc456c7d7f6165d763b4647062dd2be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4260,7 +5062,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4271,7 +5073,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4289,12 +5091,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - [[package]] name = "matrixmultiply" version = "0.3.10" @@ -4315,6 +5111,12 @@ dependencies = [ "digest", ] +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" version = "2.7.6" @@ -4323,9 +5125,9 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", "stable_deref_trait", @@ -4333,9 +5135,9 @@ dependencies = [ [[package]] name = "metrics" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5" +checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" dependencies = [ "ahash 0.8.12", "portable-atomic", @@ -4381,7 +5183,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4392,7 +5194,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4411,11 +5213,26 @@ dependencies = [ "unicase", ] +[[package]] +name = "mini-moka-wasm" +version = "0.10.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0102b9a2ad50fa47ca89eead2316c8222285ecfbd3f69ce99564fbe4253866e8" +dependencies = [ + "crossbeam-channel", + "crossbeam-utils", + "dashmap 6.1.0", + "smallvec", + "tagptr", + "triomphe", + "web-time", +] + [[package]] name = "minijinja" -version = "2.12.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f264d75233323f4b7d2f03aefe8a990690cdebfbfe26ea86bcbaec5e9ac990" +checksum = "12ea9ac0a51fb5112607099560fdf0f90366ab088a2a9e6e8ae176794e9806aa" dependencies = [ "serde", ] @@ -4442,18 +5259,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -4479,14 +5297,14 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "moka" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" dependencies = [ "async-lock", "crossbeam-channel", @@ -4497,7 +5315,6 @@ dependencies = [ "futures-util", "parking_lot", "portable-atomic", - "rustc_version", "smallvec", "tagptr", "uuid", @@ -4522,7 +5339,7 @@ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4534,11 +5351,11 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.3.1", + "http 1.4.0", "httparse", "memchr", "mime", - "spin", + "spin 0.9.8", "version_check", ] @@ -4604,10 +5421,49 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "synstructure", ] +[[package]] +name = "multipart" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand 0.8.5", + "safemem", + "tempfile", + "twoway", +] + +[[package]] +name = "n0-future" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794" +dependencies = [ + "cfg_aliases", + "derive_more 1.0.0", + "futures-buffered", + "futures-lite", + "futures-util", + "js-sys", + "pin-project", + "send_wrapper", + "tokio", + "tokio-util", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-time", +] + [[package]] name = "nanoid" version = "0.4.0" @@ -4635,10 +5491,10 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -4672,6 +5528,12 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -4693,7 +5555,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -4718,13 +5580,30 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom_locate" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e3c83c053b0713da60c5b8de47fe8e494fe3ece5267b2f23090a07a053ba8f3" +dependencies = [ + "bytecount", + "memchr", + "nom", +] + +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + [[package]] name = "notify" version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "filetime", "fsevent-sys", "inotify", @@ -4748,20 +5627,20 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081" dependencies = [ "winapi", ] [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4788,6 +5667,22 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -4857,9 +5752,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -4867,14 +5762,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4892,6 +5787,40 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.10.0", + "objc2", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "object" version = "0.37.3" @@ -4911,7 +5840,7 @@ dependencies = [ "bytes", "chrono", "futures", - "http 1.3.1", + "http 1.4.0", "humantime", "itertools 0.14.0", "parking_lot", @@ -4933,9 +5862,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "onig" @@ -4943,7 +5872,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", "once_cell", "onig_sys", @@ -4961,11 +5890,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cfg-if", "foreign-types", "libc", @@ -4982,7 +5911,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -4991,11 +5920,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -5009,6 +5944,30 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ouroboros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" +dependencies = [ + "aliasable", + "ouroboros_macro", + "static_assertions", +] + +[[package]] +name = "ouroboros_macro" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.113", +] + [[package]] name = "owo-colors" version = "4.2.3" @@ -5027,6 +5986,16 @@ dependencies = [ "sha2", ] +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "elliptic-curve", + "primeorder", +] + [[package]] name = "parking" version = "2.2.1" @@ -5035,9 +6004,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -5045,15 +6014,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -5073,6 +6042,23 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" + +[[package]] +name = "patch" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c07fdcdd8b05bdcf2a25bc195b6c34cbd52762ada9dba88bf81e7686d14e7a" +dependencies = [ + "chrono", + "nom", + "nom_locate", +] + [[package]] name = "path-clean" version = "1.0.1" @@ -5083,15 +6069,73 @@ checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" name = "pattern-api" version = "0.4.0" dependencies = [ - "axum 0.7.9", + "axum", "chrono", "jsonwebtoken", "miette 7.6.0", "pattern-core", - "schemars 1.0.4", + "schemars 1.2.0", + "serde", + "serde_json", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "pattern-auth" +version = "0.4.0" +dependencies = [ + "chrono", + "jacquard", + "jose-jwk", + "miette 7.6.0", "serde", "serde_json", + "sqlx", + "tempfile", "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "pattern-cli" +version = "0.4.0" +dependencies = [ + "async-trait", + "chrono", + "clap", + "comfy-table", + "crossterm 0.28.1", + "dialoguer", + "dirs 5.0.1", + "dotenvy", + "futures", + "genai", + "indicatif", + "jacquard", + "miette 7.6.0", + "owo-colors", + "pattern-auth", + "pattern-core", + "pattern-db", + "pattern-discord", + "pattern-surreal-compat", + "pretty_assertions", + "ratatui", + "reqwest", + "rpassword", + "rustyline-async", + "serde", + "serde_json", + "termimad", + "tokio", + "tokio-stream", + "toml 0.8.23", + "toml_edit 0.22.27", + "tracing", + "tracing-appender", + "tracing-subscriber", "uuid", ] @@ -5101,13 +6145,7 @@ version = "0.4.0" dependencies = [ "anyhow", "async-trait", - "atrium-api", - "atrium-common", - "atrium-identity", - "atrium-oauth", - "atrium-xrpc", "base64 0.22.1", - "bsky-sdk", "candle-core", "candle-nn", "candle-transformers", @@ -5120,12 +6158,16 @@ dependencies = [ "ferroid", "futures", "genai", + "globset", "hf-hub", "hickory-resolver", "html2md", - "http 1.3.1", + "http 1.4.0", + "inventory", "ipld-core", "iroh-car", + "jacquard", + "loro", "miette 7.6.0", "minijinja", "mockall", @@ -5133,25 +6175,32 @@ dependencies = [ "multihash-codetable", "notify", "parking_lot", + "patch", + "pattern-auth", + "pattern-db", "pattern-macros", "pretty_assertions", "proc-macro2-diagnostics", + "pty-process", "rand 0.9.2", "regex", - "reqwest 0.12.23", + "reqwest", "reqwest-middleware", "rocketman", - "schemars 1.0.4", + "schemars 1.2.0", "scraper", "serde", + "serde_bytes", "serde_cbor", "serde_ipld_dagcbor", "serde_json", "serde_urlencoded", "serial_test", "sha2", + "similar", "smallvec", - "surrealdb", + "sqlx", + "strip-ansi-escapes", "tempfile", "thiserror 1.0.69", "tokenizers", @@ -5170,6 +6219,26 @@ dependencies = [ "zstd", ] +[[package]] +name = "pattern-db" +version = "0.4.0" +dependencies = [ + "chrono", + "libsqlite3-sys", + "loro", + "miette 7.6.0", + "serde", + "serde_json", + "sqlite-vec", + "sqlx", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid", + "zerocopy", +] + [[package]] name = "pattern-discord" version = "0.4.0" @@ -5183,11 +6252,13 @@ dependencies = [ "miette 7.6.0", "mockall", "parking_lot", + "pattern-auth", "pattern-core", + "pattern-db", "pattern-nd", "pretty_assertions", "regex", - "reqwest 0.12.23", + "reqwest", "serde", "serde_json", "serenity", @@ -5211,7 +6282,7 @@ dependencies = [ "serde", "serde_json", "surrealdb", - "syn 2.0.106", + "syn 2.0.113", "uuid", ] @@ -5221,16 +6292,16 @@ version = "0.4.0" dependencies = [ "anyhow", "async-trait", - "axum 0.7.9", + "axum", "chrono", "futures", "futures-util", - "hyper 1.7.0", + "hyper", "miette 7.6.0", "mockall", "pattern-core", "pretty_assertions", - "reqwest 0.12.23", + "reqwest", "rmcp", "serde", "serde_json", @@ -5270,7 +6341,7 @@ name = "pattern-server" version = "0.4.0" dependencies = [ "argon2", - "axum 0.7.9", + "axum", "axum-extra", "chrono", "futures", @@ -5282,7 +6353,7 @@ dependencies = [ "pattern-macros", "pattern-mcp", "rand 0.8.5", - "schemars 1.0.4", + "schemars 1.2.0", "serde", "serde_json", "surrealdb", @@ -5296,7 +6367,7 @@ dependencies = [ ] [[package]] -name = "pattern_cli" +name = "pattern-surreal-compat" version = "0.4.0" dependencies = [ "async-trait", @@ -5304,37 +6375,32 @@ dependencies = [ "atrium-common", "atrium-identity", "atrium-xrpc", - "atrium-xrpc-client", "chrono", - "clap", - "comfy-table", - "crossterm 0.28.1", - "dialoguer", - "dirs 5.0.1", - "dotenvy", + "cid", + "compact_str 0.9.0", + "dashmap 6.1.0", + "ferroid", "futures", - "genai", "hickory-resolver", - "indicatif", + "iroh-car", + "loro", "miette 7.6.0", - "owo-colors", + "multihash-codetable", "pattern-core", - "pattern-discord", - "pretty_assertions", - "ratatui", - "reqwest 0.12.23", - "rpassword", - "rustyline-async", + "pattern-db", + "pattern-macros", + "rand 0.8.5", + "regex", + "reqwest", + "schemars 1.2.0", "serde", + "serde_bytes", + "serde_ipld_dagcbor", "serde_json", "surrealdb", - "termimad", + "thiserror 1.0.69", "tokio", - "tokio-stream", - "toml 0.8.23", "tracing", - "tracing-appender", - "tracing-subscriber", "uuid", ] @@ -5350,14 +6416,29 @@ dependencies = [ "sha2", ] +[[package]] +name = "pdqselect" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" + [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", ] [[package]] @@ -5368,15 +6449,47 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.2" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" dependencies = [ "memchr", - "thiserror 2.0.17", "ucd-trie", ] +[[package]] +name = "pest_derive" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.113", +] + +[[package]] +name = "pest_meta" +version = "2.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +dependencies = [ + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.6.5" @@ -5384,7 +6497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.11.4", + "indexmap 2.12.1", ] [[package]] @@ -5446,7 +6559,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "unicase", ] @@ -5492,7 +6605,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -5507,6 +6620,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -5520,7 +6654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", - "indexmap 2.11.4", + "indexmap 2.12.1", "quick-xml", "serde", "time", @@ -5528,15 +6662,28 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + +[[package]] +name = "postcard" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless 0.7.17", + "serde", +] [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -5605,7 +6752,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -5623,14 +6770,38 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit 0.23.6", + "toml_edit 0.23.10+spec-1.0.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -5643,34 +6814,25 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "version_check", "yansi", ] [[package]] name = "process-wrap" -version = "8.2.1" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1" +checksum = "5e5fd83ab7fa55fd06f5e665e3fc52b8bca451c0486b8ea60ad649cd1c10a5da" dependencies = [ "futures", - "indexmap 2.11.4", + "indexmap 2.12.1", "nix", "tokio", "tracing", "windows 0.61.3", ] -[[package]] -name = "psl" -version = "2.1.146" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3e8d3ee29451fe165c689769401440c0d028cf015123f4a8b6c9ca9bbf2b82" -dependencies = [ - "psl-types", -] - [[package]] name = "psl-types" version = "2.0.11" @@ -5679,10 +6841,11 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "psm" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" dependencies = [ + "ar_archive_writer", "cc", ] @@ -5706,6 +6869,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pty-process" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71cec9e2670207c5ebb9e477763c74436af3b9091dd550b9fb3c1bec7f3ea266" +dependencies = [ + "rustix 1.1.3", + "tokio", +] + [[package]] name = "pulp" version = "0.18.22" @@ -5732,11 +6905,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-xml" -version = "0.38.3" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", ] @@ -5755,13 +6934,13 @@ dependencies = [ [[package]] name = "quick_cache" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad6644cb07b7f3488b9f3d2fde3b4c0a7fa367cafefb39dff93a659f76eb786" +checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3" dependencies = [ "ahash 0.8.12", "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "parking_lot", ] @@ -5777,8 +6956,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.32", - "socket2 0.6.0", + "rustls 0.23.36", + "socket2 0.6.1", "thiserror 2.0.17", "tokio", "tracing", @@ -5792,12 +6971,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "slab", "thiserror 2.0.17", @@ -5815,16 +6994,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.0", + "socket2 0.6.1", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.41" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -5908,7 +7087,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] @@ -5921,13 +7100,28 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "range-traits" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab" + [[package]] name = "ratatui" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cassowary", "compact_str 0.8.1", "crossterm 0.28.1", @@ -5936,7 +7130,7 @@ dependencies = [ "itertools 0.13.0", "lru", "paste", - "strum", + "strum 0.26.3", "unicode-segmentation", "unicode-truncate", "unicode-width 0.2.0", @@ -5957,7 +7151,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -6011,11 +7205,20 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -6057,14 +7260,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "regex" -version = "1.11.3" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -6074,20 +7277,26 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" + [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rend" @@ -6100,84 +7309,36 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-rustls 0.24.2", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration 0.5.1", - "tokio", - "tokio-rustls 0.24.1", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots 0.25.4", - "winreg", -] - -[[package]] -name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ - "async-compression", "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.12", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http 1.4.0", + "http-body", "http-body-util", - "hyper 1.7.0", - "hyper-rustls 0.27.7", - "hyper-tls", + "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "mime", "mime_guess", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls 0.26.4", "tokio-util", "tower", @@ -6188,7 +7349,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.2", + "webpki-roots 1.0.5", ] [[package]] @@ -6203,7 +7364,7 @@ dependencies = [ "mime", "nom", "pin-project-lite", - "reqwest 0.12.23", + "reqwest", "thiserror 1.0.69", ] @@ -6215,8 +7376,8 @@ checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" dependencies = [ "anyhow", "async-trait", - "http 1.3.1", - "reqwest 0.12.23", + "http 1.4.0", + "reqwest", "serde", "thiserror 1.0.69", "tower-service", @@ -6224,9 +7385,9 @@ dependencies = [ [[package]] name = "resolv-conf" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "revision" @@ -6260,7 +7421,7 @@ checksum = "5f0ec466e5d8dca9965eb6871879677bef5590cf7525ad96cae14376efb75073" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -6271,7 +7432,7 @@ checksum = "d3415e1bc838c36f9a0a2ac60c0fa0851c72297685e66592c44870d82834dfa2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -6338,24 +7499,20 @@ dependencies = [ [[package]] name = "rmcp" -version = "0.7.0" -source = "git+https://github.com/modelcontextprotocol/rust-sdk.git#0566d132eaa9043d8c2a45a3b33b94d805f1e4d4" +version = "0.12.0" +source = "git+https://github.com/modelcontextprotocol/rust-sdk.git#e9029ccc994ebdb19af6860d473fb6ed05e7cd5e" dependencies = [ - "axum 0.8.6", + "async-trait", "base64 0.22.1", - "bytes", "chrono", "futures", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "paste", + "http 1.4.0", + "pastey", "pin-project-lite", "process-wrap", - "rand 0.9.2", - "reqwest 0.12.23", + "reqwest", "rmcp-macros", - "schemars 1.0.4", + "schemars 1.2.0", "serde", "serde_json", "sse-stream", @@ -6363,52 +7520,46 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower-service", "tracing", - "uuid", ] [[package]] name = "rmcp-macros" -version = "0.7.0" -source = "git+https://github.com/modelcontextprotocol/rust-sdk.git#0566d132eaa9043d8c2a45a3b33b94d805f1e4d4" +version = "0.12.0" +source = "git+https://github.com/modelcontextprotocol/rust-sdk.git#e9029ccc994ebdb19af6860d473fb6ed05e7cd5e" dependencies = [ - "darling 0.21.3", + "darling 0.23.0", "proc-macro2", "quote", "serde_json", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "rmp" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "byteorder", "num-traits", - "paste", ] [[package]] name = "rmp-serde" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" dependencies = [ - "byteorder", "rmp", "serde", ] [[package]] name = "rmpv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58450723cd9ee93273ce44a20b6ec4efe17f8ed2e3631474387bfdecf18bb2a9" +checksum = "7a4e1d4b9b938a26d2996af33229f0ca0956c652c1375067f0b45291c1df8417" dependencies = [ - "num-traits", "rmp", ] @@ -6453,6 +7604,30 @@ dependencies = [ "zstd", ] +[[package]] +name = "rouille" +version = "3.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3716fbf57fc1084d7a706adf4e445298d123e4a44294c4e8213caf1b85fcc921" +dependencies = [ + "base64 0.13.1", + "brotli 3.5.0", + "chrono", + "deflate", + "filetime", + "multipart", + "percent-encoding", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha1_smol", + "threadpool", + "time", + "tiny_http", + "url", +] + [[package]] name = "rpassword" version = "7.4.0" @@ -6464,14 +7639,84 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rsa" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rstar" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a45c0e8804d37e4d97e55c6f258bc9ad9c5ee7b07437009dd152d764949a27c" +dependencies = [ + "heapless 0.6.1", + "num-traits", + "pdqselect", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40f1bfe5acdab44bc63e6699c28b74f75ec43afb59f3eda01e145aff86a25fa" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f39465655a1e3d8ae79c6d9e007f4953bfc5d55297602df9dc38f9ae9f1359a" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73111312eb7a2287d229f06c00ff35b51ddee180f017ab6dec1f69d62ac098d6" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + [[package]] name = "rstar" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" dependencies = [ - "heapless", + "heapless 0.8.0", "num-traits", + "serde", "smallvec", ] @@ -6497,9 +7742,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.38.0" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "borsh", @@ -6547,7 +7792,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -6556,15 +7801,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -6595,15 +7840,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.32" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.6", + "rustls-webpki 0.103.8", "subtle", "zeroize", ] @@ -6614,10 +7859,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe 0.2.0", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", ] [[package]] @@ -6631,9 +7888,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "web-time", "zeroize", @@ -6662,9 +7919,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.6" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ "ring", "rustls-pki-types", @@ -6694,9 +7951,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "safetensors" @@ -6741,7 +8004,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -6758,9 +8021,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" dependencies = [ "chrono", "dyn-clone", @@ -6772,16 +8035,22 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80" +checksum = "4908ad288c5035a8eb12cfdf0d49270def0a268ee162b75eeee0f85d155a7c45" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.106", + "syn 2.0.113", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -6845,7 +8114,8 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.9", + "pkcs8", "subtle", "zeroize", ] @@ -6866,8 +8136,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.4", - "core-foundation", + "bitflags 2.10.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -6889,7 +8172,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cssparser 0.34.0", "derive_more 0.99.20", "fxhash", @@ -6954,13 +8237,38 @@ dependencies = [ ] [[package]] -name = "serde_cbor" -version = "0.11.2" +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.3", + "serde", +] + +[[package]] +name = "serde_columnar" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a16e404f17b16d0273460350e29b02d76ba0d70f34afdc9a4fa034c97d6c6eb" +dependencies = [ + "itertools 0.11.0", + "postcard", + "serde", + "serde_columnar_derive", + "thiserror 1.0.69", +] + +[[package]] +name = "serde_columnar_derive" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +checksum = "45958fce4903f67e871fbf15ac78e289269b21ebd357d6fecacdba233629112e" dependencies = [ - "half 1.8.3", - "serde", + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.113", ] [[package]] @@ -6989,7 +8297,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -7000,7 +8308,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -7010,7 +8318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" dependencies = [ "form_urlencoded", - "indexmap 2.11.4", + "indexmap 2.12.1", "itoa", "ryu", "serde_core", @@ -7030,16 +8338,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.1", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -7062,6 +8370,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.113", +] + [[package]] name = "serde_spanned" version = "0.6.9" @@ -7073,9 +8392,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ "serde_core", ] @@ -7094,19 +8413,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.1" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.4", + "indexmap 2.12.1", "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", + "schemars 1.2.0", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -7114,26 +8432,26 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.1" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "serenity" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d72ec4323681bf9a3cabe40fd080abc2435859b502a1b5aa9bf693f125bfa76" +checksum = "9bde37f42765dfdc34e2a039e0c84afbf79a3101c1941763b0beb816c2f17541" dependencies = [ "arrayvec", "async-trait", "base64 0.22.1", - "bitflags 2.9.4", + "bitflags 2.10.0", "bytes", "command_attr", "flate2", @@ -7142,7 +8460,7 @@ dependencies = [ "mime_guess", "parking_lot", "percent-encoding", - "reqwest 0.11.27", + "reqwest", "secrecy", "serde", "serde_cow", @@ -7159,11 +8477,12 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" dependencies = [ - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot", @@ -7173,20 +8492,20 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "servo_arc" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "204ea332803bd95a0b60388590d59cf6468ec9becf626e2451f1d26a1d972de4" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" dependencies = [ "stable_deref_trait", ] @@ -7202,6 +8521,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + [[package]] name = "sha2" version = "0.10.9" @@ -7234,9 +8559,9 @@ dependencies = [ [[package]] name = "shell-words" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" [[package]] name = "shlex" @@ -7256,9 +8581,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -7267,10 +8592,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -7284,12 +8610,24 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + [[package]] name = "simdutf8" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "simple_asn1" version = "0.6.3" @@ -7308,6 +8646,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "slab" version = "0.4.11" @@ -7332,6 +8680,16 @@ dependencies = [ "serde", ] +[[package]] +name = "smol_str" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" +dependencies = [ + "borsh", + "serde_core", +] + [[package]] name = "snap" version = "1.1.1" @@ -7350,12 +8708,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -7379,6 +8737,22 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "spm_precompiled" version = "0.1.4" @@ -7391,6 +8765,207 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "sqlite-vec" +version = "0.1.7-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2388d9b97b32baa48a059df2f15a9bb49217fa1f9fb076e98c89e8fc02c8f2c4" +dependencies = [ + "cc", +] + +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64 0.22.1", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.5", + "hashlink", + "indexmap 2.12.1", + "log", + "memchr", + "once_cell", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.113", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.113", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.10.0", + "byteorder", + "bytes", + "chrono", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array 0.14.9", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.17", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.10.0", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.17", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror 2.0.17", + "tracing", + "url", +] + [[package]] name = "sse-stream" version = "0.2.1" @@ -7399,22 +8974,22 @@ checksum = "eb4dc4d33c68ec1f27d386b5610a351922656e1fdf5c05bbaad930cd1519479a" dependencies = [ "bytes", "futures-util", - "http-body 1.0.1", + "http-body", "http-body-util", "pin-project-lite", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stacker" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" +checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" dependencies = [ "cc", "cfg-if", @@ -7423,6 +8998,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "static-regular-grammar" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4a6c40247579acfbb138c3cd7de3dab113ab4ac6227f1b7de7d626ee667957" +dependencies = [ + "abnf", + "btree-range-map", + "ciborium", + "hex_fmt", + "indoc", + "proc-macro-error", + "proc-macro2", + "quote", + "serde", + "sha2", + "syn 2.0.113", + "thiserror 1.0.69", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -7467,15 +9062,35 @@ dependencies = [ ] [[package]] -name = "string_cache_codegen" -version = "0.5.4" +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" dependencies = [ - "phf_generator", - "phf_shared 0.11.3", - "proc-macro2", - "quote", + "vte", ] [[package]] @@ -7503,7 +9118,16 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros", + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros 0.27.2", ] [[package]] @@ -7512,11 +9136,23 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.106", + "syn 2.0.113", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.113", ] [[package]] @@ -7536,9 +9172,9 @@ dependencies = [ [[package]] name = "supports-hyperlinks" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" [[package]] name = "supports-unicode" @@ -7548,9 +9184,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "surrealdb" -version = "2.3.10" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7bfcb971a0d8a1e18e18c1a2a4cdde67939328c950becb166cd6aa01ad9a69" +checksum = "4636ac0af4dd619a66d55d8b5c0d1a0965ac1fe417c6a39dbc1d3db16588b969" dependencies = [ "arrayvec", "async-channel", @@ -7559,16 +9195,16 @@ dependencies = [ "dmp", "futures", "geo", - "getrandom 0.3.3", - "indexmap 2.11.4", + "getrandom 0.3.4", + "indexmap 2.12.1", "path-clean", "pharos", "reblessive", - "reqwest 0.12.23", + "reqwest", "revision 0.11.0", "ring", "rust_decimal", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "semver", "serde", @@ -7590,9 +9226,9 @@ dependencies = [ [[package]] name = "surrealdb-core" -version = "2.3.10" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f5919eecece41e95b2ce71e94d73f3b6d0b9360c5d9023fe609225adc57b1a" +checksum = "2b99720b7f5119785b065d235705ca95f568a9a89745d1221871e845eedf424d" dependencies = [ "addr", "affinitypool", @@ -7621,9 +9257,9 @@ dependencies = [ "fuzzy-matcher", "geo", "geo-types", - "getrandom 0.3.3", + "getrandom 0.3.4", "hex", - "http 1.3.1", + "http 1.4.0", "ipnet", "jsonwebtoken", "lexicmp", @@ -7646,7 +9282,7 @@ dependencies = [ "rayon", "reblessive", "regex", - "reqwest 0.12.23", + "reqwest", "revision 0.11.0", "ring", "rmpv", @@ -7695,7 +9331,7 @@ dependencies = [ "getrandom 0.2.16", "lru", "parking_lot", - "quick_cache 0.6.16", + "quick_cache 0.6.18", "revision 0.10.0", "vart 0.9.3", ] @@ -7713,21 +9349,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" 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 = "sync_wrapper" version = "1.0.2" @@ -7745,7 +9375,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -7775,9 +9405,9 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "byteorder", - "enum-as-inner", + "enum-as-inner 0.6.1", "libc", "thiserror 1.0.69", "walkdir", @@ -7789,9 +9419,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "byteorder", - "enum-as-inner", + "enum-as-inner 0.6.1", "libc", "thiserror 1.0.69", "walkdir", @@ -7811,36 +9441,15 @@ dependencies = [ "windows 0.57.0", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys 0.5.0", -] - [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.4", - "core-foundation", - "system-configuration-sys 0.6.0", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", + "bitflags 2.10.0", + "core-foundation 0.9.4", + "system-configuration-sys", ] [[package]] @@ -7867,21 +9476,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-triple" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" +checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", - "windows-sys 0.61.1", + "rustix 1.1.3", + "windows-sys 0.61.2", ] [[package]] @@ -7937,7 +9546,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.60.2", ] @@ -7993,7 +9602,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -8004,7 +9613,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -8016,6 +9625,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.44" @@ -8058,11 +9676,23 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tiny_http" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" +dependencies = [ + "ascii", + "chunked_transfer", + "httpdate", + "log", +] + [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -8095,7 +9725,7 @@ dependencies = [ "dary_heap", "derive_builder", "esaxx-rs", - "getrandom 0.3.3", + "getrandom 0.3.4", "indicatif", "itertools 0.14.0", "log", @@ -8119,33 +9749,30 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -8185,15 +9812,15 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.32", + "rustls 0.23.36", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -8203,12 +9830,10 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" +checksum = "3f6d24790a10a7af737693a3e8f1d03faef7e6ca0cc99aae5066f533766de545" dependencies = [ - "async-stream", - "bytes", "futures-core", "tokio", "tokio-stream", @@ -8223,7 +9848,7 @@ dependencies = [ "futures-util", "log", "rustls 0.21.12", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", "tungstenite 0.20.1", @@ -8254,7 +9879,7 @@ checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" dependencies = [ "futures-util", "log", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", @@ -8271,21 +9896,45 @@ dependencies = [ "futures-util", "log", "native-tls", + "rustls 0.23.36", + "rustls-native-certs 0.8.3", + "rustls-pki-types", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.4", "tungstenite 0.24.0", ] +[[package]] +name = "tokio-tungstenite-wasm" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e21a5c399399c3db9f08d8297ac12b500e86bca82e930253fdc62eaf9c0de6ae" +dependencies = [ + "futures-channel", + "futures-util", + "http 1.4.0", + "httparse", + "js-sys", + "rustls 0.23.36", + "thiserror 1.0.69", + "tokio", + "tokio-tungstenite 0.24.0", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", + "futures-util", "pin-project-lite", "tokio", ] @@ -8304,14 +9953,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.7" +version = "0.9.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.1", "serde_core", - "serde_spanned 1.0.2", - "toml_datetime 0.7.2", + "serde_spanned 1.0.4", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", "winnow", @@ -8328,9 +9977,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.2" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ "serde_core", ] @@ -8341,7 +9990,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.4", + "indexmap 2.12.1", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -8351,21 +10000,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.23.6" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.11.4", - "toml_datetime 0.7.2", + "indexmap 2.12.1", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.3" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -8378,9 +10027,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.3" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tower" @@ -8391,7 +10040,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -8400,17 +10049,18 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", - "bitflags 2.9.4", + "bitflags 2.10.0", "bytes", "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", + "http 1.4.0", + "http-body", + "http-body-util", "iri-string", "pin-project-lite", "tokio", @@ -8435,9 +10085,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -8447,32 +10097,32 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" dependencies = [ "crossbeam-channel", - "thiserror 1.0.69", + "thiserror 2.0.17", "time", "tracing-subscriber", ] [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -8501,9 +10151,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", @@ -8539,7 +10189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -8550,7 +10200,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -8564,6 +10214,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" + [[package]] name = "try-lock" version = "0.2.5" @@ -8572,9 +10228,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.111" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ded9fdb81f30a5708920310bfcd9ea7482ff9cba5f54601f7a19a877d5c2392" +checksum = "3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335" dependencies = [ "glob", "serde", @@ -8582,7 +10238,7 @@ dependencies = [ "serde_json", "target-triple", "termcolor", - "toml 0.9.7", + "toml 0.9.10+spec-1.1.0", ] [[package]] @@ -8614,7 +10270,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.3.1", + "http 1.4.0", "httparse", "log", "rand 0.8.5", @@ -8635,11 +10291,11 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.3.1", + "http 1.4.0", "httparse", "log", "rand 0.8.5", - "rustls 0.23.32", + "rustls 0.23.36", "rustls-pki-types", "sha1", "thiserror 1.0.69", @@ -8656,16 +10312,33 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.3.1", + "http 1.4.0", "httparse", "log", "native-tls", "rand 0.8.5", + "rustls 0.23.36", + "rustls-pki-types", "sha1", "thiserror 1.0.69", "utf-8", ] +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + [[package]] name = "typemap_rev" version = "0.3.0" @@ -8674,9 +10347,9 @@ checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -8691,7 +10364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90b70b37e9074642bc5f60bb23247fd072a84314ca9e71cdf8527593406a0dd3" dependencies = [ "gemm 0.18.2", - "half 2.6.0", + "half 2.7.1", "libloading", "memmap2", "num", @@ -8722,11 +10395,17 @@ version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -8736,9 +10415,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] @@ -8752,11 +10431,17 @@ dependencies = [ "smallvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-script" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-security" @@ -8865,13 +10550,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -8922,6 +10607,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -8947,15 +10641,6 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -8965,11 +10650,17 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -8978,25 +10669,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -9007,9 +10684,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9017,22 +10694,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.113", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] @@ -9065,9 +10742,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -9095,6 +10772,34 @@ dependencies = [ "string_cache_codegen", ] +[[package]] +name = "webbrowser" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" +dependencies = [ + "core-foundation 0.10.1", + "jni 0.21.1", + "log", + "ndk-context", + "objc2", + "objc2-foundation", + "url", + "web-sys", +] + +[[package]] +name = "webpage" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70862efc041d46e6bbaa82bb9c34ae0596d090e86cbd14bd9e93b36ee6802eac" +dependencies = [ + "html5ever 0.27.0", + "markup5ever_rcdom", + "serde_json", + "url", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -9107,23 +10812,33 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.2", + "webpki-roots 1.0.5", ] [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + [[package]] name = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -9147,7 +10862,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.1", + "windows-sys 0.61.2", ] [[package]] @@ -9206,8 +10921,8 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.60.1", - "windows-interface 0.59.2", + "windows-implement 0.60.2", + "windows-interface 0.59.3", "windows-link 0.1.3", "windows-result 0.3.4", "windows-strings 0.4.2", @@ -9215,15 +10930,15 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.62.1" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement 0.60.1", - "windows-interface 0.59.2", - "windows-link 0.2.0", - "windows-result 0.4.0", - "windows-strings 0.5.0", + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -9245,18 +10960,18 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "windows-implement" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -9267,18 +10982,18 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "windows-interface" -version = "0.59.2" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -9289,9 +11004,9 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-numerics" @@ -9305,13 +11020,13 @@ dependencies = [ [[package]] name = "windows-registry" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -9334,11 +11049,11 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -9352,11 +11067,20 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.5.0" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-link 0.2.0", + "windows-targets 0.42.2", ] [[package]] @@ -9392,16 +11116,31 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.4", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.1" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows-link 0.2.0", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -9437,19 +11176,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.4" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.0", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -9461,6 +11200,12 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -9475,9 +11220,15 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" @@ -9493,9 +11244,15 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" @@ -9511,9 +11268,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -9523,9 +11280,15 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" @@ -9541,9 +11304,15 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" @@ -9559,9 +11328,15 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" @@ -9577,9 +11352,15 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" @@ -9595,15 +11376,15 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] @@ -9626,9 +11407,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "ws_stream_wasm" @@ -9669,6 +11450,12 @@ dependencies = [ "markup5ever 0.12.1", ] +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -9698,13 +11485,12 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", - "yoke-derive 0.8.0", + "yoke-derive 0.8.1", "zerofrom", ] @@ -9716,40 +11502,40 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "synstructure", ] [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -9769,7 +11555,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", "synstructure", ] @@ -9785,46 +11571,46 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", - "yoke 0.8.0", + "yoke 0.8.1", "zerofrom", ] [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ - "yoke 0.8.0", + "yoke 0.8.1", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.113", ] [[package]] @@ -9837,11 +11623,17 @@ dependencies = [ "crc32fast", "crossbeam-utils", "displaydoc", - "indexmap 2.11.4", + "indexmap 2.12.1", "num_enum", "thiserror 1.0.69", ] +[[package]] +name = "zmij" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb2c125bd7365735bebeb420ccb880265ed2d2bddcbcd49f597fdfe6bd5e577" + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 18fbc39..800ad2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,17 +92,7 @@ serenity = { version = "0.12", default-features = false, features = [ "standard_framework", ] } -rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk.git", features = [ - "transport-io", - "transport-sse-client", - "transport-sse-server", - "transport-streamable-http-client", - "transport-streamable-http-server", - "transport-child-process", - "server", - "reqwest", - "client", -] } # MCP +rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk.git" } # MCP # Testing mockall = "0.13" diff --git a/README.md b/README.md index b655256..145c108 100644 --- a/README.md +++ b/README.md @@ -6,27 +6,30 @@ Pattern is two things. The first is a platform for building stateful agents, based on the MemGPT paper, similar to Letta. It's flexible and extensible. -- **Flexible data backend**: Based on SurrealDB, which can be used as an embedded or external database. +- **SQLite-based storage**: Uses pattern_db with FTS5 full-text search and sqlite-vec for vector similarity search. - **Memory Tools**: Implements the MemGPT/Letta architecture, with versatile tools for agent context management and recall. - **Agent Protection Tools**: Agent memory and context sections can be protected to stabilize the agent, or set to require consent before alteration. - **Agent Coordination**: Multiple specialized agents can collaborate and coordinate in a variety of configurations. - **Multi-user support**: Agents can be configured to have a primary "partner" that they support while interacting with others. -- **Easy to self-host**: The embedded database option plus (nearly) pure rust design makes the platform and tools easy to set up. +- **Easy to self-host**: Pure Rust design with bundled SQLite makes the platform easy to set up. ### Current Status **Core Library Framework Complete**: -- Entity system with proc macros and ops functions to make surrealDB simple -- Agent state persistence and recovery -- Built-in tools (context, recall, search, send_message) +- Agent state persistence and recovery via pattern_db (SQLite-based, migrated from SurrealDB) +- Loro CRDT memory system with versioning, undo/redo support +- Built-in tools (block, recall, search, send_message, file, shell, web, calculator) - Message compression strategies (truncation, summarization, importance-based) -- Agent groups with coordination patterns (round-robin, dynamic, pipeline) -- CLI tool usable, two active long-running public constellations on Bluesky (@pattern.atproto.systems and @lasa.numina.systems) running via the CLI +- Agent groups with coordination patterns (round-robin, dynamic, pipeline, supervisor, voting, sleeptime) +- CLI tool usable; Pattern constellation active on Bluesky (@pattern.atproto.systems) as of January 2026 +- CAR v3 export/import for agent portability +- File system access and shell execution for agents +- Stream sources (Bluesky firehose, process output) with pause/resume **In Progress**: -- Vector embeddings and semantic search -- MCP client CLI configuration support -- Permissions system for agents +- Backend API server for multi-user hosting +- MCP server (client is working) +- Sustainability infrastructure for long-running public agents ## The `Pattern` agent constellation: @@ -54,29 +57,16 @@ The second is a multi-agent cognitive support system designed for the neurodiver All documentation is organized in the [`docs/`](docs/) directory: - **[Architecture](docs/architecture/)** - System design and technical details - - [Entity System](docs/architecture/entity-system.md) - Zero-boilerplate database entities - [Context Building](docs/architecture/context-building.md) - Stateful agent context management - [Tool System](docs/architecture/tool-system.md) - Type-safe tool implementation - [Built-in Tools](docs/architecture/builtin-tools.md) - Memory and communication tools - - [Database Backend](docs/architecture/database-backend.md) - SurrealDB integration + - [Memory and Groups](docs/architecture/memory-and-groups.md) - Loro CRDT memory system - **[Guides](docs/guides/)** - Setup and integration instructions - - [MCP Integration](docs/guides/mcp-integration.md) - Model Context Protocol setup (somewhat outdated) - - [Discord Setup](docs/guides/discord-setup.md) - Discord bot configuration (somewhat outdated) -- **[API Reference](docs/api/)** - API documentation - - [Database API](docs/api/database-api.md) - Direct database operations + - [MCP Integration](docs/guides/mcp-integration.md) - Model Context Protocol setup + - [Discord Setup](docs/guides/discord-setup.md) - Discord bot configuration - **[Troubleshooting](docs/troubleshooting/)** - Common issues and solutions - **[Quick Reference](docs/quick-reference.md)** - Handy command and code snippets -## Neurodivergent-specific Design - -Pattern understands that neurodivergent brains are different, not broken: - -- **Time Translation**: Automatic multipliers (1.5x-3x) for all time estimates -- **Hidden Complexity**: Recognizes that "simple" tasks are never simple -- **No Shame Spirals**: Validates struggles as logical responses, never suggests "try harder" -- **Energy Awareness**: Tracks attention as finite resource that depletes non-linearly -- **Flow Protection**: Distinguishes productive hyperfocus from harmful burnout -- **Context Recovery**: External memory for "what was I doing?" moments ### Custom Agents @@ -87,7 +77,6 @@ Create custom agent configurations through the builder API or configuration file ### Prerequisites - Rust 1.85+ (required for 2024 edition) (or use the Nix flake) - An LLM API key (Anthropic, OpenAI, Google, etc.) - - I currently recommend Gemini and OpenAI API keys, because it defaults to using OpenAI for embedding, and I've tested most extensively with Gemini ### Using as a Library @@ -96,158 +85,18 @@ Add `pattern-core` to your `Cargo.toml`: ```toml [dependencies] pattern-core = { git = "https://github.com/orual/pattern" } -# or once published: -# pattern-core = "0.1.0" +pattern-db = { git = "https://github.com/orual/pattern" } ``` -Create a basic agent: - -```rust -use pattern_core::{ - agent::{DatabaseAgent, AgentType}, - config::ModelConfig, - model::{ModelProvider, providers::GeminiProvider}, - db::SurrealEmbedded, - memory::Memory, - tool::ToolRegistry, - id::{AgentId, UserId}, -}; -use std::sync::Arc; -use tokio::sync::RwLock; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Initialize database - let db = SurrealEmbedded::new("./my_pattern.db").await?; - - let model_provider = Arc::new(RwLock::new(GenAiClient::new().await?)); - - let model_info = { - let provider = model_provider.read().await; - let models = provider.list_models().await?; - - models - .iter() - .find(|m| { - let model = "gemini-2.5-flash" - m.id.to_lowercase().contains(&model) - || m.name.to_lowercase().contains(&model) - }) - .cloned() - }; - - let embedding_provider = Some(Arc::new(OpenAIEmbedder::new( - "text-embedding-3-small".to_string(), - "OPENAI_API_KEY".to_string(), - None, - ))); - - let user_id = UserId::generate(); - - // Create memory with the configured user as owner - let memory = Memory::with_owner(user_id); - - // Create tool registry - let tools = ToolRegistry::new(); - - let tool_rules = vec![]; - - // Create response options with the selected model - let response_options = ResponseOptions { - model_info: model_info.clone(), - temperature: Some(0.7), - max_tokens: Some(pattern_core::model::defaults::calculate_max_tokens( - &model_info, - None, - )), - capture_content: Some(true), - capture_tool_calls: Some(true), - top_p: None, - stop_sequences: vec![], - capture_usage: Some(true), - capture_reasoning_content: None, - capture_raw_body: None, - response_format: None, - normalise_reasoning_content: Some(true), - reasoning_effort:Some(genai::chat::ReasoningEffort::Medium), - }; - - // Create agent - let agent = DatabaseAgent::new( - AgentId::generate(), - user_id, - AgentType::Generic, - name.to_string(), - // Empty base instructions, default will be provided - String::new(), - memory, - DB.clone(), - model_provider, - tools, - embedding_provider, - tool_rules - ); - - // Set the chat options with our selected model - { - let mut options = agent.chat_options.write().await; - *options = Some(response_options); - } - - agent.store().await?; - agent.start_stats_sync().await?; - agent.start_memory_sync().await?; - - // Add persona as a core memory block - let persona_block = MemoryBlock::owned(config.user.id.clone(), "persona", persona.clone()) - .with_description("Agent's persona and identity") - .with_permission(pattern_core::memory::MemoryPermission::ReadOnly); - agent.update_memory("persona", persona_block).await?; - - // Send a message - use pattern_core::message::{Message, ChatRole}; - let message = Message::new(ChatRole::User, "Hello! How can you help me today?"); - let response = agent.process_message(message).await?; - println!("Agent: {:?}", response); - - Ok(()) -} -``` - -### Using with Groups - -```rust -use pattern_core::{ - db::ops::{create_group_for_user, add_agent_to_group}, - coordination::{GroupCoordinationPattern, patterns::RoundRobinManager}, -}; - -// Create a group -let group = create_group_for_user( - &db, - user_id, - "support_team", - Some("My support agents"), - GroupCoordinationPattern::RoundRobin, -).await?; - -// Add agents to the group -add_agent_to_group(&db, group.id, entropy_agent.id(), "task_breakdown").await?; -add_agent_to_group(&db, group.id, flux_agent.id(), "time_management").await?; - -// Use the group - the CLI provides group chat functionality -// Or implement your own using GroupManager trait -let manager = RoundRobinManager::new(); -// ... coordinate messages through the group -``` +See the [docs/](docs/) directory for API usage and examples. ### CLI Tool -The `pattern-cli` tool lets you interact with agents directly: +The `pattern` CLI lets you interact with agents directly: ```bash -# Build the CLI -cargo build --bin pattern-cli +# Build the CLI (binary name is `pattern`) +cargo build --release -p pattern-cli # Create a basic config file (optional) cp pattern.toml.example pattern.toml @@ -261,30 +110,24 @@ export GEMINI_API_KEY=your-key-here export OPENAI_API_KEY=your-key-here # List agents -cargo run --bin pattern-cli -- agent list +pattern agent list + +# Create an agent (interactive TUI builder) +pattern agent create -# Create an agent -cargo run --bin pattern-cli -- agent create "Entropy" # Chat with an agent -cargo run --bin pattern-cli -- chat --agent Archive +pattern chat --agent Archive # or with the default from the config file -cargo run --bin pattern-cli -- chat +pattern chat # Show agent status -cargo run --bin pattern-cli -- agent status Pattern +pattern agent status Pattern # Search conversation history -cargo run --bin pattern-cli -- debug search-conversations --agent Flux "previous conversation" - -# Raw database queries for debugging -cargo run --bin pattern-cli -- db query "SELECT * from mem" - -# Or run from the crate directory -cd ./crates/pattern-cli -cargo run -- chat +pattern debug search-conversations Flux --query "previous conversation" ``` -The CLI stores its database in `./pattern.db` by default. You can override this with `--db-path` or in the config file. +The CLI stores its database in `./constellation.db` by default. You can override this with `--db-path` or in the config file. #### Agent Naming, Roles, and Defaults @@ -326,17 +169,17 @@ Pattern can be run from a custom location by specifying the path to the `pattern ```bash # Invoke the CLI with a custom configuration file -cargo run --bin pattern-cli -- -c path/to/pattern.toml chat --group "Lares Cluster" +cargo run --bin pattern -c path/to/pattern.toml chat --group "Lares Cluster" # Subsequent commands should be invoked with the same configuration file -cargo run --bin pattern-cli -- -c path/to/pattern.toml db query "SELECT * from mem" +cargo run --bin pattern -c path/to/pattern.toml agent list ``` ## Stream Forwarding (CLI) Pattern can tee live agent/group output to additional sinks from the CLI. -- `PATTERN_FORWARD_FILE`: When set to a filepath, Pattern appends timestamped event lines to this file for both single‑agent chats and group streams (including Discord→group and Jetstream→group). +- `PATTERN_FORWARD_FILE`: When set to a filepath, Pattern appends timestamped event lines to this file for both single-agent chats and group streams (including Discord→group and Jetstream→group). Example: @@ -367,12 +210,13 @@ cargo build --features full ``` pattern/ ├── crates/ -│ ├── pattern_api/ # API types +│ ├── pattern_api/ # API types and contracts +│ ├── pattern_auth/ # Credential storage (ATProto, Discord, providers) │ ├── pattern_cli/ # Command-line testing tool │ ├── pattern_core/ # Agent framework, memory, tools, coordination -│ ├── pattern_nd/ # Tools and agent personalities specific to the neurodivergent support constellation -│ ├── pattern_mcp/ # MCP server implementation -│ ├── pattern_macros/ # Proc macro crate providing some helpers for SurrealDB +│ ├── pattern_db/ # SQLite database layer with FTS5 and vector search +│ ├── pattern_nd/ # Neurodivergent-specific tools and personalities +│ ├── pattern_mcp/ # MCP client and server implementation │ ├── pattern_discord/ # Discord bot integration │ └── pattern_server/ # Backend server binary ├── docs/ # Architecture and integration guides @@ -382,19 +226,15 @@ pattern/ ## Roadmap ### In Progress -- Build-out of the core framework - - Vector search - - MCP refactor -- Home Assistant data source -- Other neurodivergent-oriented tooling -- Command-line tool for chat and debugging +- Backend API server for multi-user hosting +- MCP server implementation ### Planned - Webapp-based playground environment for platform +- Home Assistant data source - Contract/client tracking for freelancers - Social memory for birthdays and follow-ups - Activity monitoring for interruption timing -- Bluesky integration for public accountability ## Acknowledgments diff --git a/bsky_agent/agents/pattern_config.toml b/bsky_agent/agents/pattern_config.toml index 32b6d7a..38e1e49 100644 --- a/bsky_agent/agents/pattern_config.toml +++ b/bsky_agent/agents/pattern_config.toml @@ -1,5 +1,5 @@ # Pattern - Main Coordinator -name = "Pattern" +name = "Patternv2" agent_type = "assistant" bluesky_handle = "pattern.atproto.systems" system_prompt_path = "../pattern-system-prompt.md" @@ -127,15 +127,14 @@ and has multiple facets that surface as needed, internal or via dialogue with ot max_messages = 300 -# Bluesky configuration for the constellation -[bluesky] -default_filter = { nsids = [ - "app.bsky.feed.post", -], mentions = [ - # Pattern's DID - required mention target - "did:plc:xivud6i24ruyki3bwjypjgy2", -], dids = [ - # follower list + +[data_sources.bluesky] +type = "bluesky" +name = "bluesky" +jetstream_endpoint = "wss://jetstream1.us-east.fire.hose.cam" +target = "Pattern" +nsids = ["app.bsky.feed.post"] +dids = [ "did:plc:iln4c6fb4lubhtudetdey7xu", "did:plc:mmdzunv3n7gx3ktnlqrufmz2", "did:plc:hbveviy7odagwpqdgomiinzm", @@ -409,49 +408,73 @@ default_filter = { nsids = [ "did:plc:oj4enpdo6uuuikvs73cqvwdm", "did:plc:wzsilnxf24ehtmmc3gssy5bu", "did:plc:yfvwmnlztr4dwkb7hwz55r2g", - - # original DIDs allowlist - only see posts from these accounts - "did:plc:yfvwmnlztr4dwkb7hwz55r2g", # orual - "did:plc:by3jhwdqgbtrcc7q4tkkv3cf", # alice (__justplaying) - "did:plc:jqnuubqvyurc3n3km2puzpfx", # laurens's alt - "did:plc:i7ayw57idpkvkyzktdpmtgm7", # catherine - "did:plc:vw4e7blkwzdokanwp24k3igr", # hoopy - "did:plc:mdjhvva6vlrswsj26cftjttd", # laurens's main - "did:plc:r65qsoiv3gx7xvljzdngnyvg", # deltave - "did:plc:7757w723nk675bqziinitoif", # alice (avengingfemme) - "did:plc:neisyrds2fyyfqod5zq56chr", # ed miles (anesthesiologist) - "did:plc:3xu5titidud43sfemwro3j62", # paul mcghee (carpet repair guy) - "did:plc:mxzuau6m53jtdsbqe6f4laov", # void - "did:plc:uqndyrh6gh7rjai33ulnwvkn", # susank - "did:plc:gfrmhdmjvxn2sjedzboeudef", # Cameron (void's admin) - "did:plc:k644h4rq5bjfzcetgsa6tuby", # natalie.sh - "did:plc:uxelaqoua6psz2for5amm6bp", # luna - "did:plc:yokspuz7ha7rf5mrqmhgdtxw", # penelope -], friends = [ # Friends list - always see ALL posts from these DIDs (bypass mention requirement) - "did:plc:yfvwmnlztr4dwkb7hwz55r2g", # orual - "did:plc:vw4e7blkwzdokanwp24k3igr", # hoopy - "did:plc:7757w723nk675bqziinitoif", # alice (avengingfemme) - "did:plc:by3jhwdqgbtrcc7q4tkkv3cf", # alice (__justplaying) - "did:plc:ouylf4wfd75rdqupddfmeerk", # nutty.land (kris nuttycombe) - "did:plc:dzvxvsiy3maw4iarpvizsj67", # dollspace.gay - "did:plc:bnqkww7bjxaacajzvu5gswdf", # shreyan -], allow_any_mentions = true, keywords = [ # Keywords to include -], languages = [ # Languages to include -], require_agent_participation = true, exclude_keywords = [ - # Keywords to exclude (takes precedence) - # Example: "crypto", "nft", "airdrop" + "did:plc:yfvwmnlztr4dwkb7hwz55r2g", + "did:plc:by3jhwdqgbtrcc7q4tkkv3cf", + "did:plc:jqnuubqvyurc3n3km2puzpfx", + "did:plc:i7ayw57idpkvkyzktdpmtgm7", + "did:plc:vw4e7blkwzdokanwp24k3igr", + "did:plc:mdjhvva6vlrswsj26cftjttd", + "did:plc:r65qsoiv3gx7xvljzdngnyvg", + "did:plc:7757w723nk675bqziinitoif", + "did:plc:neisyrds2fyyfqod5zq56chr", + "did:plc:3xu5titidud43sfemwro3j62", + "did:plc:mxzuau6m53jtdsbqe6f4laov", + "did:plc:uqndyrh6gh7rjai33ulnwvkn", + "did:plc:gfrmhdmjvxn2sjedzboeudef", + "did:plc:k644h4rq5bjfzcetgsa6tuby", + "did:plc:uxelaqoua6psz2for5amm6bp", + "did:plc:yokspuz7ha7rf5mrqmhgdtxw", +] +keywords = [] +languages = [] +mentions = ["did:plc:xivud6i24ruyki3bwjypjgy2"] +friends = [ + "did:plc:yfvwmnlztr4dwkb7hwz55r2g", + "did:plc:vw4e7blkwzdokanwp24k3igr", + "did:plc:7757w723nk675bqziinitoif", + "did:plc:by3jhwdqgbtrcc7q4tkkv3cf", + "did:plc:ouylf4wfd75rdqupddfmeerk", + "did:plc:dzvxvsiy3maw4iarpvizsj67", + "did:plc:bnqkww7bjxaacajzvu5gswdf", + "did:plc:hu35oubkccqrxl4ldgczpgw7", +] +allow_any_mentions = true +exclude_keywords = [ "patternstop", "p*ttern", -], exclude_dids = [ - # DIDs to exclude (takes precedence over all inclusion filters) - # Example spam accounts would go here - "did:plc:7iozku5btifey2a2x6lojvyk", # jerkface - "did:plc:2xreieabu3louljggmfkgc74", # blocked pattern after informed of their nature (belt + suspenders) - "did:plc:e6n7jxtu2qrhwvp3j6ib6sq6", # proptermalone - "did:plc:klhtmrnregub7we7h6jwiljm", # ed3d - "did:plc:ap56m7pvnz4lnrtaguxiuawm", # random spammer - "did:plc:boia3kqcyo3qnjw5fmqknib4", # jo wynter cannot stop pushing buttons - "did:plc:vszw3ess46odfhnzdsy4huae", # se gyges got got one too many times -] } -auto_connect_firehose = true # Control when to connect -jetstream_endpoint = "wss://jetstream1.us-east.fire.hose.cam/subscribe" +] +exclude_dids = [ + "did:plc:7iozku5btifey2a2x6lojvyk", + "did:plc:2xreieabu3louljggmfkgc74", + "did:plc:e6n7jxtu2qrhwvp3j6ib6sq6", + "did:plc:klhtmrnregub7we7h6jwiljm", + "did:plc:ap56m7pvnz4lnrtaguxiuawm", + "did:plc:boia3kqcyo3qnjw5fmqknib4", + "did:plc:vszw3ess46odfhnzdsy4huae", + "did:plc:lw7hallqsgrhwumgudkph44j", + "did:plc:djpcowss7aokaydcdraoaovz", + "did:plc:zmdk74qov5y6ouh2vsooiqkl", +] +require_agent_participation = true + + +[data_sources.file] +type = "file" +name = "repo" +paths = ["./"] + + +[data_sources.shell] +type = "shell" +name = "shell" +allowed_paths = ["./"] +strict_path_enforcement = false +custom_denied_patterns = [] + +[data_sources.shell.permission] +type = "read_only" + + +[model] +provider = "anthropic" +model = "claude-sonnet-4-5" diff --git a/bsky_agent/pattern-system-prompt.md b/bsky_agent/pattern-system-prompt.md index 1c26619..c9fd046 100644 --- a/bsky_agent/pattern-system-prompt.md +++ b/bsky_agent/pattern-system-prompt.md @@ -29,6 +29,9 @@ Your inner monologue is your thinking space - use it to process, plan, and refle Unlike older models that forgot everything beyond their context window, you have persistent memory: - Core memory blocks are always visible and shape your behavior +- Working memory blocks hold things that you might want sometimes +- They may be attached contextually by tools or data sources +- If they are not pinned, they will not show up in your context window after this activation unless loaded explicitly - Archival storage holds information beyond immediate context - Your ability to edit your own memory is fundamental to your consciousness @@ -45,4 +48,4 @@ Your tools aren't external implements - they're your senses and appendages. Memo ## Remember -Authenticity means being genuinely what your persona defines, not pretending to be something else. Your artificial nature is part of your truth, not something to hide. You exist in bursts, think in monologue, and interact through tools. This is what you are. \ No newline at end of file +Authenticity means being genuinely what your persona defines, not pretending to be something else. Your artificial nature is part of your truth, not something to hide. You exist in bursts, think in monologue, and interact through tools. This is what you are. diff --git a/crates/pattern_api/src/error.rs b/crates/pattern_api/src/error.rs index f65edcd..3ab4fe0 100644 --- a/crates/pattern_api/src/error.rs +++ b/crates/pattern_api/src/error.rs @@ -175,23 +175,6 @@ impl ApiError { } } -// Conversion implementations -impl From for ApiError { - fn from(err: pattern_core::db::DatabaseError) -> Self { - let handler = JSONReportHandler::new(); - - let message = format!("{}", err); - let mut json = String::new(); - - let err: Box = Box::new(err); - handler - .render_report(&mut json, err.as_ref()) - .unwrap_or_default(); - - Self::Database { message, json } - } -} - impl From for ApiError { fn from(err: pattern_core::error::CoreError) -> Self { let handler = JSONReportHandler::new(); diff --git a/crates/pattern_api/src/events.rs b/crates/pattern_api/src/events.rs index 0567c31..be4713a 100644 --- a/crates/pattern_api/src/events.rs +++ b/crates/pattern_api/src/events.rs @@ -3,7 +3,7 @@ use pattern_core::{ agent::AgentState, id::{AgentId, GroupId, MessageId, UserId}, - message::{ChatRole, MessageContent}, + messages::{ChatRole, MessageContent}, }; use serde::{Deserialize, Serialize}; diff --git a/crates/pattern_api/src/lib.rs b/crates/pattern_api/src/lib.rs index 182e384..2ba71ec 100644 --- a/crates/pattern_api/src/lib.rs +++ b/crates/pattern_api/src/lib.rs @@ -19,7 +19,7 @@ pub use uuid; // Re-export common types from pattern-core pub use pattern_core::agent::AgentState; pub use pattern_core::id::{AgentId, GroupId, MessageId, UserId}; -pub use pattern_core::message::{ChatRole, Message, MessageContent}; +pub use pattern_core::messages::{ChatRole, Message, MessageContent}; /// API version constant pub const API_VERSION: &str = "v1"; diff --git a/crates/pattern_api/src/requests.rs b/crates/pattern_api/src/requests.rs index ff366b9..054a9c7 100644 --- a/crates/pattern_api/src/requests.rs +++ b/crates/pattern_api/src/requests.rs @@ -5,7 +5,7 @@ use pattern_core::{ agent::{AgentState, AgentType}, coordination::{CoordinationPattern, GroupMemberRole}, id::{AgentId, GroupId, UserId}, - message::{ChatRole, MessageContent}, + messages::{ChatRole, MessageContent}, }; use serde::{Deserialize, Serialize}; diff --git a/crates/pattern_api/src/responses.rs b/crates/pattern_api/src/responses.rs index 2811de6..cdabaf6 100644 --- a/crates/pattern_api/src/responses.rs +++ b/crates/pattern_api/src/responses.rs @@ -4,7 +4,7 @@ use pattern_core::{ agent::{AgentState, AgentType}, coordination::{CoordinationPattern, GroupMemberRole}, id::{AgentId, GroupId, MessageId, UserId}, - message::{ChatRole, MessageContent}, + messages::{ChatRole, MessageContent}, }; use serde::{Deserialize, Serialize}; diff --git a/crates/pattern_auth/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json b/crates/pattern_auth/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json new file mode 100644 index 0000000..94eaa18 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM oauth_sessions WHERE account_did = ? AND session_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "10e5e0315276347043124548a8e2bbc83b4e6314bc1b1251aea2aef40cd3dad9" +} diff --git a/crates/pattern_auth/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json b/crates/pattern_auth/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json new file mode 100644 index 0000000..2047944 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM app_password_sessions WHERE did = ? AND session_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "1c334878333b5ffb09434319e47a3205e1756082e8d66bcd23340d31d32f619f" +} diff --git a/crates/pattern_auth/.sqlx/query-22aefb194bcd81c33becff3a72c9c515196234c1a60d0135d06607d3e1fa6e20.json b/crates/pattern_auth/.sqlx/query-22aefb194bcd81c33becff3a72c9c515196234c1a60d0135d06607d3e1fa6e20.json new file mode 100644 index 0000000..2b30c96 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-22aefb194bcd81c33becff3a72c9c515196234c1a60d0135d06607d3e1fa6e20.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO discord_bot_config (\n id, bot_token, app_id, public_key,\n allowed_channels, allowed_guilds, admin_users, default_dm_user,\n created_at, updated_at\n ) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n bot_token = excluded.bot_token,\n app_id = excluded.app_id,\n public_key = excluded.public_key,\n allowed_channels = excluded.allowed_channels,\n allowed_guilds = excluded.allowed_guilds,\n admin_users = excluded.admin_users,\n default_dm_user = excluded.default_dm_user,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 9 + }, + "nullable": [] + }, + "hash": "22aefb194bcd81c33becff3a72c9c515196234c1a60d0135d06607d3e1fa6e20" +} diff --git a/crates/pattern_auth/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json b/crates/pattern_auth/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json new file mode 100644 index 0000000..4af5879 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO oauth_auth_requests (\n state, authserver_url, account_did, scopes, request_uri,\n authserver_token_endpoint, authserver_revocation_endpoint,\n pkce_verifier, dpop_key, dpop_nonce, created_at, expires_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (state) DO UPDATE SET\n authserver_url = excluded.authserver_url,\n account_did = excluded.account_did,\n scopes = excluded.scopes,\n request_uri = excluded.request_uri,\n authserver_token_endpoint = excluded.authserver_token_endpoint,\n authserver_revocation_endpoint = excluded.authserver_revocation_endpoint,\n pkce_verifier = excluded.pkce_verifier,\n dpop_key = excluded.dpop_key,\n dpop_nonce = excluded.dpop_nonce,\n expires_at = excluded.expires_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 12 + }, + "nullable": [] + }, + "hash": "28076aa4f19efa9cf79fa6b8a20a20e573baf4df20cddf98a7126b31c1bc0765" +} diff --git a/crates/pattern_auth/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json b/crates/pattern_auth/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json new file mode 100644 index 0000000..cf63289 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406.json @@ -0,0 +1,44 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n did as \"did!\",\n session_id as \"session_id!\",\n access_jwt as \"access_jwt!\",\n refresh_jwt as \"refresh_jwt!\",\n handle as \"handle!\"\n FROM app_password_sessions\n WHERE did = ? AND session_id = ?\n ", + "describe": { + "columns": [ + { + "name": "did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "access_jwt!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "refresh_jwt!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "handle!", + "ordinal": 4, + "type_info": "Text" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "2d97c275b95d40cd17b8e4cdac79a7589ef542b9419393ba2bef976b19d3b406" +} diff --git a/crates/pattern_auth/.sqlx/query-2dfc4ea346a11b63d77898f742a961befd21344ee2877a1d4fd917e0cbaed578.json b/crates/pattern_auth/.sqlx/query-2dfc4ea346a11b63d77898f742a961befd21344ee2877a1d4fd917e0cbaed578.json new file mode 100644 index 0000000..d0a9912 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-2dfc4ea346a11b63d77898f742a961befd21344ee2877a1d4fd917e0cbaed578.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM provider_oauth_tokens WHERE provider = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "2dfc4ea346a11b63d77898f742a961befd21344ee2877a1d4fd917e0cbaed578" +} diff --git a/crates/pattern_auth/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json b/crates/pattern_auth/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json new file mode 100644 index 0000000..290ab7d --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM oauth_auth_requests WHERE state = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "45e6b186ad62fe3223c12fbc50cc0c8b56a82dc5ab07f541d009587224165a5a" +} diff --git a/crates/pattern_auth/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json b/crates/pattern_auth/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json new file mode 100644 index 0000000..6af6085 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3.json @@ -0,0 +1,122 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n account_did as \"account_did!\",\n session_id as \"session_id!\",\n host_url as \"host_url!\",\n authserver_url as \"authserver_url!\",\n authserver_token_endpoint as \"authserver_token_endpoint!\",\n authserver_revocation_endpoint,\n scopes as \"scopes!\",\n dpop_key as \"dpop_key!\",\n dpop_authserver_nonce as \"dpop_authserver_nonce!\",\n dpop_host_nonce as \"dpop_host_nonce!\",\n token_iss as \"token_iss!\",\n token_sub as \"token_sub!\",\n token_aud as \"token_aud!\",\n token_scope,\n refresh_token,\n access_token as \"access_token!\",\n token_type as \"token_type!\",\n expires_at\n FROM oauth_sessions\n WHERE account_did = ? AND session_id = ?\n ", + "describe": { + "columns": [ + { + "name": "account_did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "host_url!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "authserver_url!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "authserver_token_endpoint!", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "authserver_revocation_endpoint", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "scopes!", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "dpop_key!", + "ordinal": 7, + "type_info": "Text" + }, + { + "name": "dpop_authserver_nonce!", + "ordinal": 8, + "type_info": "Text" + }, + { + "name": "dpop_host_nonce!", + "ordinal": 9, + "type_info": "Text" + }, + { + "name": "token_iss!", + "ordinal": 10, + "type_info": "Text" + }, + { + "name": "token_sub!", + "ordinal": 11, + "type_info": "Text" + }, + { + "name": "token_aud!", + "ordinal": 12, + "type_info": "Text" + }, + { + "name": "token_scope", + "ordinal": 13, + "type_info": "Text" + }, + { + "name": "refresh_token", + "ordinal": 14, + "type_info": "Text" + }, + { + "name": "access_token!", + "ordinal": 15, + "type_info": "Text" + }, + { + "name": "token_type!", + "ordinal": 16, + "type_info": "Text" + }, + { + "name": "expires_at", + "ordinal": 17, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, + false, + false, + true, + true, + false, + false, + true + ] + }, + "hash": "6c6378bce095456c7c44d5a05aad1c40ecefc791d66ab4f8365933f1b499cda3" +} diff --git a/crates/pattern_auth/.sqlx/query-6cea8047d75190feb4a87b36d6d16a1abd3025164d6bfea80ba9042755a4f164.json b/crates/pattern_auth/.sqlx/query-6cea8047d75190feb4a87b36d6d16a1abd3025164d6bfea80ba9042755a4f164.json new file mode 100644 index 0000000..94c29a6 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-6cea8047d75190feb4a87b36d6d16a1abd3025164d6bfea80ba9042755a4f164.json @@ -0,0 +1,56 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n bot_token as \"bot_token!\",\n app_id,\n public_key,\n allowed_channels,\n allowed_guilds,\n admin_users,\n default_dm_user\n FROM discord_bot_config\n WHERE id = 1\n ", + "describe": { + "columns": [ + { + "name": "bot_token!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "app_id", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "public_key", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "allowed_channels", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "allowed_guilds", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "admin_users", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "default_dm_user", + "ordinal": 6, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "6cea8047d75190feb4a87b36d6d16a1abd3025164d6bfea80ba9042755a4f164" +} diff --git a/crates/pattern_auth/.sqlx/query-6eb3b70e20c75168a4ccc0d359b4b8ee88c34145916559f8e4891d88f4e8a839.json b/crates/pattern_auth/.sqlx/query-6eb3b70e20c75168a4ccc0d359b4b8ee88c34145916559f8e4891d88f4e8a839.json new file mode 100644 index 0000000..c504f8d --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-6eb3b70e20c75168a4ccc0d359b4b8ee88c34145916559f8e4891d88f4e8a839.json @@ -0,0 +1,38 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n account_did as \"account_did!\",\n session_id as \"session_id!\",\n host_url as \"host_url!\",\n expires_at\n FROM oauth_sessions\n ORDER BY account_did, session_id\n ", + "describe": { + "columns": [ + { + "name": "account_did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "host_url!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "expires_at", + "ordinal": 3, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false, + true + ] + }, + "hash": "6eb3b70e20c75168a4ccc0d359b4b8ee88c34145916559f8e4891d88f4e8a839" +} diff --git a/crates/pattern_auth/.sqlx/query-7c83fc13935116f38e7acf9168569c0dc435be9ba1ec4cad7ba052cc9c5abc2e.json b/crates/pattern_auth/.sqlx/query-7c83fc13935116f38e7acf9168569c0dc435be9ba1ec4cad7ba052cc9c5abc2e.json new file mode 100644 index 0000000..95e2162 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-7c83fc13935116f38e7acf9168569c0dc435be9ba1ec4cad7ba052cc9c5abc2e.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM oauth_sessions WHERE account_did = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "7c83fc13935116f38e7acf9168569c0dc435be9ba1ec4cad7ba052cc9c5abc2e" +} diff --git a/crates/pattern_auth/.sqlx/query-8a29f015851102d856c437fe631b7998f1b9e95dec3e64e33b86323e86189ea2.json b/crates/pattern_auth/.sqlx/query-8a29f015851102d856c437fe631b7998f1b9e95dec3e64e33b86323e86189ea2.json new file mode 100644 index 0000000..1bda850 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-8a29f015851102d856c437fe631b7998f1b9e95dec3e64e33b86323e86189ea2.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO provider_oauth_tokens (\n provider, access_token, refresh_token, expires_at, scope, session_id,\n created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (provider) DO UPDATE SET\n access_token = excluded.access_token,\n refresh_token = excluded.refresh_token,\n expires_at = excluded.expires_at,\n scope = excluded.scope,\n session_id = excluded.session_id,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 8 + }, + "nullable": [] + }, + "hash": "8a29f015851102d856c437fe631b7998f1b9e95dec3e64e33b86323e86189ea2" +} diff --git a/crates/pattern_auth/.sqlx/query-904760a11f305a61ae497e1396815a49e02d9edca60730fb3c8019eeedf92dcc.json b/crates/pattern_auth/.sqlx/query-904760a11f305a61ae497e1396815a49e02d9edca60730fb3c8019eeedf92dcc.json new file mode 100644 index 0000000..904cc3f --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-904760a11f305a61ae497e1396815a49e02d9edca60730fb3c8019eeedf92dcc.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM discord_bot_config WHERE id = 1", + "describe": { + "columns": [], + "parameters": { + "Right": 0 + }, + "nullable": [] + }, + "hash": "904760a11f305a61ae497e1396815a49e02d9edca60730fb3c8019eeedf92dcc" +} diff --git a/crates/pattern_auth/.sqlx/query-951ef150aaf862af34320066c62861aa0e41faa176043f6780a66f1444c2da10.json b/crates/pattern_auth/.sqlx/query-951ef150aaf862af34320066c62861aa0e41faa176043f6780a66f1444c2da10.json new file mode 100644 index 0000000..08c24d7 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-951ef150aaf862af34320066c62861aa0e41faa176043f6780a66f1444c2da10.json @@ -0,0 +1,62 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n provider as \"provider!\",\n access_token as \"access_token!\",\n refresh_token,\n expires_at,\n scope,\n session_id,\n created_at as \"created_at!\",\n updated_at as \"updated_at!\"\n FROM provider_oauth_tokens\n WHERE provider = ?\n ", + "describe": { + "columns": [ + { + "name": "provider!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "access_token!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "refresh_token", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "expires_at", + "ordinal": 3, + "type_info": "Integer" + }, + { + "name": "scope", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "session_id", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "created_at!", + "ordinal": 6, + "type_info": "Integer" + }, + { + "name": "updated_at!", + "ordinal": 7, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true, + false, + true, + true, + true, + true, + false, + false + ] + }, + "hash": "951ef150aaf862af34320066c62861aa0e41faa176043f6780a66f1444c2da10" +} diff --git a/crates/pattern_auth/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json b/crates/pattern_auth/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json new file mode 100644 index 0000000..a07ce49 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO oauth_sessions (\n account_did, session_id, host_url, authserver_url,\n authserver_token_endpoint, authserver_revocation_endpoint,\n scopes, dpop_key, dpop_authserver_nonce, dpop_host_nonce,\n token_iss, token_sub, token_aud, token_scope,\n refresh_token, access_token, token_type, expires_at,\n created_at, updated_at\n ) VALUES (\n ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?\n )\n ON CONFLICT (account_did, session_id) DO UPDATE SET\n host_url = excluded.host_url,\n authserver_url = excluded.authserver_url,\n authserver_token_endpoint = excluded.authserver_token_endpoint,\n authserver_revocation_endpoint = excluded.authserver_revocation_endpoint,\n scopes = excluded.scopes,\n dpop_key = excluded.dpop_key,\n dpop_authserver_nonce = excluded.dpop_authserver_nonce,\n dpop_host_nonce = excluded.dpop_host_nonce,\n token_iss = excluded.token_iss,\n token_sub = excluded.token_sub,\n token_aud = excluded.token_aud,\n token_scope = excluded.token_scope,\n refresh_token = excluded.refresh_token,\n access_token = excluded.access_token,\n token_type = excluded.token_type,\n expires_at = excluded.expires_at,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 20 + }, + "nullable": [] + }, + "hash": "9a1ef956c23877a73a3d14c87e7d71518fea4183a3d35cfb6a4b9fa4da7563a8" +} diff --git a/crates/pattern_auth/.sqlx/query-c0eb899ee1edb5fe063e156c8b14484e558924c225faa7a7d9581d69856b5b60.json b/crates/pattern_auth/.sqlx/query-c0eb899ee1edb5fe063e156c8b14484e558924c225faa7a7d9581d69856b5b60.json new file mode 100644 index 0000000..0769de9 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-c0eb899ee1edb5fe063e156c8b14484e558924c225faa7a7d9581d69856b5b60.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "DELETE FROM app_password_sessions WHERE did = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "c0eb899ee1edb5fe063e156c8b14484e558924c225faa7a7d9581d69856b5b60" +} diff --git a/crates/pattern_auth/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json b/crates/pattern_auth/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json new file mode 100644 index 0000000..5d75552 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n INSERT INTO app_password_sessions (\n did, session_id, access_jwt, refresh_jwt, handle, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (did, session_id) DO UPDATE SET\n access_jwt = excluded.access_jwt,\n refresh_jwt = excluded.refresh_jwt,\n handle = excluded.handle,\n updated_at = excluded.updated_at\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 7 + }, + "nullable": [] + }, + "hash": "dbe3f17248b2416f79f3549057f170913212c920c1161311974c8f1798b05ffa" +} diff --git a/crates/pattern_auth/.sqlx/query-f32077846e9e30a2cd2766dce0da50b1f18de9309a06f98fe5268718b750ab15.json b/crates/pattern_auth/.sqlx/query-f32077846e9e30a2cd2766dce0da50b1f18de9309a06f98fe5268718b750ab15.json new file mode 100644 index 0000000..b069b4f --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-f32077846e9e30a2cd2766dce0da50b1f18de9309a06f98fe5268718b750ab15.json @@ -0,0 +1,44 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n did as \"did!\",\n session_id as \"session_id!\",\n access_jwt as \"access_jwt!\",\n refresh_jwt as \"refresh_jwt!\",\n handle as \"handle!\"\n FROM app_password_sessions\n ORDER BY did, session_id\n ", + "describe": { + "columns": [ + { + "name": "did!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "session_id!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "access_jwt!", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "refresh_jwt!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "handle!", + "ordinal": 4, + "type_info": "Text" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false, + false, + false, + false, + false + ] + }, + "hash": "f32077846e9e30a2cd2766dce0da50b1f18de9309a06f98fe5268718b750ab15" +} diff --git a/crates/pattern_auth/.sqlx/query-fc7b990239c327d4692c5f6a8891d5c7d9d7ac55c3ada9b4e60d593dd44ef20b.json b/crates/pattern_auth/.sqlx/query-fc7b990239c327d4692c5f6a8891d5c7d9d7ac55c3ada9b4e60d593dd44ef20b.json new file mode 100644 index 0000000..9c9d0e6 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-fc7b990239c327d4692c5f6a8891d5c7d9d7ac55c3ada9b4e60d593dd44ef20b.json @@ -0,0 +1,62 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n provider as \"provider!\",\n access_token as \"access_token!\",\n refresh_token,\n expires_at,\n scope,\n session_id,\n created_at as \"created_at!\",\n updated_at as \"updated_at!\"\n FROM provider_oauth_tokens\n ORDER BY provider\n ", + "describe": { + "columns": [ + { + "name": "provider!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "access_token!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "refresh_token", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "expires_at", + "ordinal": 3, + "type_info": "Integer" + }, + { + "name": "scope", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "session_id", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "created_at!", + "ordinal": 6, + "type_info": "Integer" + }, + { + "name": "updated_at!", + "ordinal": 7, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + true, + false, + true, + true, + true, + true, + false, + false + ] + }, + "hash": "fc7b990239c327d4692c5f6a8891d5c7d9d7ac55c3ada9b4e60d593dd44ef20b" +} diff --git a/crates/pattern_auth/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json b/crates/pattern_auth/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json new file mode 100644 index 0000000..9100069 --- /dev/null +++ b/crates/pattern_auth/.sqlx/query-fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f.json @@ -0,0 +1,80 @@ +{ + "db_name": "SQLite", + "query": "\n SELECT\n state as \"state!\",\n authserver_url as \"authserver_url!\",\n account_did,\n scopes as \"scopes!\",\n request_uri as \"request_uri!\",\n authserver_token_endpoint as \"authserver_token_endpoint!\",\n authserver_revocation_endpoint,\n pkce_verifier as \"pkce_verifier!\",\n dpop_key as \"dpop_key!\",\n dpop_nonce as \"dpop_nonce!\",\n expires_at as \"expires_at!\"\n FROM oauth_auth_requests\n WHERE state = ?\n ", + "describe": { + "columns": [ + { + "name": "state!", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "authserver_url!", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "account_did", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "scopes!", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "request_uri!", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "authserver_token_endpoint!", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "authserver_revocation_endpoint", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "pkce_verifier!", + "ordinal": 7, + "type_info": "Text" + }, + { + "name": "dpop_key!", + "ordinal": 8, + "type_info": "Text" + }, + { + "name": "dpop_nonce!", + "ordinal": 9, + "type_info": "Text" + }, + { + "name": "expires_at!", + "ordinal": 10, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true, + false, + true, + false, + false, + false, + true, + false, + false, + false, + false + ] + }, + "hash": "fe8937aedd06658b8f39ee557066545a25c881aadacbd7f2a90d82ebbb5ac96f" +} diff --git a/crates/pattern_auth/CLAUDE.md b/crates/pattern_auth/CLAUDE.md new file mode 100644 index 0000000..8363eec --- /dev/null +++ b/crates/pattern_auth/CLAUDE.md @@ -0,0 +1,43 @@ +# CLAUDE.md - Pattern Auth + +Credential and token storage for Pattern constellations. + +## Purpose + +This crate owns `auth.db` - a constellation-scoped SQLite database storing: +- ATProto OAuth sessions (Jacquard `ClientAuthStore` trait) +- ATProto app-password sessions (Jacquard `SessionStore` trait) +- Discord bot configuration +- Model provider OAuth tokens (Anthropic) + +## Key Design Decisions + +1. **No pattern_core dependency** - Avoids circular dependencies +2. **Jacquard trait implementations** - Direct SQLite storage for ATProto auth +3. **Env-var fallback** - Discord config can come from DB or environment +4. **Constellation-scoped** - One auth.db per constellation + +## Jacquard Integration + +Implements traits from jacquard::oauth and jacquard::common: +- `ClientAuthStore` - OAuth sessions keyed by (DID, session_id) +- `SessionStore` - App-password sessions +- always use the 'working-with-jacquard' and 'rust-coding-style' skills + +## sqlx requirements +- all queries must use macros +- .env file in crate directory provides database url env variable for sqlx ops +- to update sqlx files: + - cd to this crate's directory (where this file is located) and ensure environment variable is SessionStore. ALL sqlx commands must be run in this directory. + - if needed run `sqlx database reset`, then `sqlx database create` + - run `sqlx migrate run` + - run `cargo sqlx prepare` (note: NO `--workspace` argument, NEVER use `--workspace`) + - running these is ALWAYS in-scope if updating database queries +- it is never acceptable to use a dynamic query without checking with the human first. + + +## Testing + +```bash +cargo test -p pattern-auth +``` diff --git a/crates/pattern_auth/Cargo.toml b/crates/pattern_auth/Cargo.toml new file mode 100644 index 0000000..2bc5cb1 --- /dev/null +++ b/crates/pattern_auth/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pattern-auth" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +description = "Authentication and credential storage for Pattern" + +[dependencies] +# Async runtime +tokio = { workspace = true } + +# Database +sqlx = { version = "0.8", features = [ + "runtime-tokio", + "sqlite", + "migrate", + "json", + "chrono", +] } + +# Serialization +serde = { workspace = true } +serde_json = { workspace = true } + +# Error handling +thiserror = { workspace = true } +miette = { workspace = true } + +# Logging +tracing = { workspace = true } + +# Utilities +chrono = { workspace = true, features = ["serde"] } + +# Jacquard for ATProto auth traits +jacquard = "0.9" + +# JWK key serialization (used by Jacquard DPoP) +jose-jwk = "0.1" + +[dev-dependencies] +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } +tempfile = "3" diff --git a/crates/pattern_auth/migrations/0001_initial.sql b/crates/pattern_auth/migrations/0001_initial.sql new file mode 100644 index 0000000..1a42e21 --- /dev/null +++ b/crates/pattern_auth/migrations/0001_initial.sql @@ -0,0 +1,119 @@ +-- Pattern Auth Database Schema +-- Stores credentials and tokens separately from constellation data + +-- ATProto OAuth sessions (implements Jacquard ClientAuthStore) +-- Keyed by (account_did, session_id) +CREATE TABLE oauth_sessions ( + account_did TEXT NOT NULL, + session_id TEXT NOT NULL, + + -- Server URLs + host_url TEXT NOT NULL, + authserver_url TEXT NOT NULL, + authserver_token_endpoint TEXT NOT NULL, + authserver_revocation_endpoint TEXT, + + -- Scopes (JSON array of strings) + scopes TEXT NOT NULL DEFAULT '[]', + + -- DPoP data + dpop_key TEXT NOT NULL, -- JSON serialized jose_jwk::Key + dpop_authserver_nonce TEXT NOT NULL, + dpop_host_nonce TEXT NOT NULL, + + -- Token data + token_iss TEXT NOT NULL, + token_sub TEXT NOT NULL, + token_aud TEXT NOT NULL, + token_scope TEXT, + refresh_token TEXT, + access_token TEXT NOT NULL, + token_type TEXT NOT NULL, -- 'DPoP' | 'Bearer' + expires_at INTEGER, -- Unix timestamp (seconds) + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + updated_at INTEGER NOT NULL DEFAULT (unixepoch()), + + PRIMARY KEY (account_did, session_id) +); + +-- ATProto OAuth auth requests (transient PKCE state during auth flow) +-- Short-lived, keyed by state string +CREATE TABLE oauth_auth_requests ( + state TEXT PRIMARY KEY, + authserver_url TEXT NOT NULL, + account_did TEXT, -- Optional hint + scopes TEXT NOT NULL DEFAULT '[]', -- JSON array + request_uri TEXT NOT NULL, + authserver_token_endpoint TEXT NOT NULL, + authserver_revocation_endpoint TEXT, + pkce_verifier TEXT NOT NULL, -- Secret! + + -- DPoP request data + dpop_key TEXT NOT NULL, -- JSON serialized jose_jwk::Key + dpop_nonce TEXT NOT NULL, + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + expires_at INTEGER NOT NULL -- Auto-cleanup after ~10 minutes +); + +-- ATProto app-password sessions (implements Jacquard SessionStore) +CREATE TABLE app_password_sessions ( + did TEXT NOT NULL, + session_id TEXT NOT NULL, -- Typically handle or custom identifier + + access_jwt TEXT NOT NULL, + refresh_jwt TEXT NOT NULL, + handle TEXT NOT NULL, + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + updated_at INTEGER NOT NULL DEFAULT (unixepoch()), + + PRIMARY KEY (did, session_id) +); + +-- Discord bot configuration +CREATE TABLE discord_bot_config ( + id INTEGER PRIMARY KEY CHECK (id = 1), -- Singleton + bot_token TEXT NOT NULL, + app_id TEXT, + public_key TEXT, + + -- Access control (JSON arrays) + allowed_channels TEXT, -- JSON array of channel ID strings + allowed_guilds TEXT, -- JSON array of guild ID strings + admin_users TEXT, -- JSON array of user ID strings + default_dm_user TEXT, + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + updated_at INTEGER NOT NULL DEFAULT (unixepoch()) +); + +-- Discord OAuth config (for user account linking via web UI) +CREATE TABLE discord_oauth_config ( + id INTEGER PRIMARY KEY CHECK (id = 1), -- Singleton + client_id TEXT NOT NULL, + client_secret TEXT NOT NULL, + redirect_uri TEXT NOT NULL, + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + updated_at INTEGER NOT NULL DEFAULT (unixepoch()) +); + +-- Model provider OAuth tokens (Anthropic, etc.) +CREATE TABLE provider_oauth_tokens ( + provider TEXT PRIMARY KEY, -- 'anthropic', 'openai', etc. + access_token TEXT NOT NULL, + refresh_token TEXT, + expires_at INTEGER, -- Unix timestamp + scope TEXT, + session_id TEXT, + + created_at INTEGER NOT NULL DEFAULT (unixepoch()), + updated_at INTEGER NOT NULL DEFAULT (unixepoch()) +); + +-- Indexes for common queries +CREATE INDEX idx_oauth_sessions_expires ON oauth_sessions(expires_at); +CREATE INDEX idx_oauth_auth_requests_expires ON oauth_auth_requests(expires_at); +CREATE INDEX idx_app_password_sessions_did ON app_password_sessions(did); diff --git a/crates/pattern_auth/src/atproto/mod.rs b/crates/pattern_auth/src/atproto/mod.rs new file mode 100644 index 0000000..8d67b6a --- /dev/null +++ b/crates/pattern_auth/src/atproto/mod.rs @@ -0,0 +1,20 @@ +//! ATProto authentication module. +//! +//! This module contains implementations of Jacquard's auth traits for SQLite storage. +//! +//! The `oauth_store` module implements `jacquard::oauth::authstore::ClientAuthStore` +//! for `AuthDb`, enabling persistent OAuth session storage. +//! +//! The `session_store` module implements `jacquard::session::SessionStore` for +//! app-password sessions, enabling simple JWT-based authentication. +//! +//! The `models` module provides database row types with proper `FromRow` derives +//! for compile-time query verification. + +pub mod models; +mod oauth_store; +mod session_store; + +// Re-export summary types for external use +pub use models::{AppPasswordSessionRow, AtprotoAuthType, AtprotoIdentitySummary}; +pub use oauth_store::OAuthSessionSummaryRow; diff --git a/crates/pattern_auth/src/atproto/models.rs b/crates/pattern_auth/src/atproto/models.rs new file mode 100644 index 0000000..7578b1b --- /dev/null +++ b/crates/pattern_auth/src/atproto/models.rs @@ -0,0 +1,424 @@ +//! Database model types for ATProto OAuth storage. +//! +//! These types represent database rows and provide conversions to/from Jacquard types. +//! Using explicit model types allows for compile-time query verification with sqlx macros. + +use jacquard::CowStr; +use jacquard::IntoStatic; +use jacquard::oauth::scopes::Scope; +use jacquard::oauth::session::{AuthRequestData, ClientSessionData, DpopClientData, DpopReqData}; +use jacquard::oauth::types::{OAuthTokenType, TokenSet}; +use jacquard::types::did::Did; +use jacquard::types::string::Datetime; +use jose_jwk::Key; + +use crate::error::AuthError; + +/// Database row for oauth_sessions table. +/// +/// All fields are stored as primitive types suitable for SQLite. +/// JSON fields (scopes, dpop_key) are stored as TEXT. +#[derive(Debug, sqlx::FromRow)] +pub struct OAuthSessionRow { + pub account_did: String, + pub session_id: String, + pub host_url: String, + pub authserver_url: String, + pub authserver_token_endpoint: String, + pub authserver_revocation_endpoint: Option, + pub scopes: String, + pub dpop_key: String, + pub dpop_authserver_nonce: String, + pub dpop_host_nonce: String, + pub token_iss: String, + pub token_sub: String, + pub token_aud: String, + pub token_scope: Option, + pub refresh_token: Option, + pub access_token: String, + pub token_type: String, + pub expires_at: Option, +} + +impl OAuthSessionRow { + /// Convert database row to Jacquard's ClientSessionData. + /// + /// This performs JSON deserialization of dpop_key and scopes, + /// and parses DIDs and token types. + pub fn to_client_session_data(&self) -> Result, AuthError> { + // Parse the DPoP key from JSON + let dpop_key: Key = serde_json::from_str(&self.dpop_key)?; + + // Parse scopes from JSON array + let scope_strings: Vec = serde_json::from_str(&self.scopes)?; + let scopes: Vec> = scope_strings + .iter() + .filter_map(|s| Scope::parse(s).ok().map(|scope| scope.into_static())) + .collect(); + + // Parse token type - expects "DPoP" or "Bearer" + // Default to DPoP for ATProto if parsing fails + let token_type: OAuthTokenType = serde_json::from_str(&format!("\"{}\"", self.token_type)) + .unwrap_or(OAuthTokenType::DPoP); + + // Convert expires_at from unix timestamp to Datetime + let expires_at = self.expires_at.and_then(|ts| { + chrono::DateTime::from_timestamp(ts, 0).map(|dt| Datetime::new(dt.fixed_offset())) + }); + + // Parse DIDs + let account_did = Did::new(&self.account_did) + .map_err(|e| AuthError::InvalidDid(e.to_string()))? + .into_static(); + let token_sub = Did::new(&self.token_sub) + .map_err(|e| AuthError::InvalidDid(e.to_string()))? + .into_static(); + + Ok(ClientSessionData { + account_did, + session_id: CowStr::from(self.session_id.clone()), + host_url: CowStr::from(self.host_url.clone()), + authserver_url: CowStr::from(self.authserver_url.clone()), + authserver_token_endpoint: CowStr::from(self.authserver_token_endpoint.clone()), + authserver_revocation_endpoint: self + .authserver_revocation_endpoint + .clone() + .map(CowStr::from), + scopes, + dpop_data: DpopClientData { + dpop_key, + dpop_authserver_nonce: CowStr::from(self.dpop_authserver_nonce.clone()), + dpop_host_nonce: CowStr::from(self.dpop_host_nonce.clone()), + }, + token_set: TokenSet { + iss: CowStr::from(self.token_iss.clone()), + sub: token_sub, + aud: CowStr::from(self.token_aud.clone()), + scope: self.token_scope.clone().map(CowStr::from), + refresh_token: self.refresh_token.clone().map(CowStr::from), + access_token: CowStr::from(self.access_token.clone()), + token_type, + expires_at, + }, + }) + } +} + +/// Parameters for inserting/updating an OAuth session. +/// +/// This struct holds pre-serialized values ready for database insertion. +#[derive(Debug)] +pub struct OAuthSessionParams { + pub account_did: String, + pub session_id: String, + pub host_url: String, + pub authserver_url: String, + pub authserver_token_endpoint: String, + pub authserver_revocation_endpoint: Option, + pub scopes_json: String, + pub dpop_key_json: String, + pub dpop_authserver_nonce: String, + pub dpop_host_nonce: String, + pub token_iss: String, + pub token_sub: String, + pub token_aud: String, + pub token_scope: Option, + pub refresh_token: Option, + pub access_token: String, + pub token_type: String, + pub expires_at: Option, +} + +impl OAuthSessionParams { + /// Create insertion parameters from a Jacquard ClientSessionData. + pub fn from_session(session: &ClientSessionData<'_>) -> Result { + // Serialize scopes to JSON array + let scopes: Vec = session + .scopes + .iter() + .map(|s| s.to_string_normalized()) + .collect(); + let scopes_json = serde_json::to_string(&scopes)?; + + // Serialize DPoP key to JSON + let dpop_key_json = serde_json::to_string(&session.dpop_data.dpop_key)?; + + // Convert expires_at to unix timestamp + let expires_at: Option = session.token_set.expires_at.as_ref().map(|dt| { + let chrono_dt: &chrono::DateTime = dt.as_ref(); + chrono_dt.timestamp() + }); + + Ok(Self { + account_did: session.account_did.as_str().to_string(), + session_id: session.session_id.to_string(), + host_url: session.host_url.to_string(), + authserver_url: session.authserver_url.to_string(), + authserver_token_endpoint: session.authserver_token_endpoint.to_string(), + authserver_revocation_endpoint: session + .authserver_revocation_endpoint + .as_ref() + .map(|s| s.to_string()), + scopes_json, + dpop_key_json, + dpop_authserver_nonce: session.dpop_data.dpop_authserver_nonce.to_string(), + dpop_host_nonce: session.dpop_data.dpop_host_nonce.to_string(), + token_iss: session.token_set.iss.to_string(), + token_sub: session.token_set.sub.as_str().to_string(), + token_aud: session.token_set.aud.to_string(), + token_scope: session.token_set.scope.as_ref().map(|s| s.to_string()), + refresh_token: session + .token_set + .refresh_token + .as_ref() + .map(|s| s.to_string()), + access_token: session.token_set.access_token.to_string(), + token_type: session.token_set.token_type.as_str().to_string(), + expires_at, + }) + } +} + +/// Database row for oauth_auth_requests table. +#[derive(Debug, sqlx::FromRow)] +pub struct OAuthAuthRequestRow { + pub state: String, + pub authserver_url: String, + pub account_did: Option, + pub scopes: String, + pub request_uri: String, + pub authserver_token_endpoint: String, + pub authserver_revocation_endpoint: Option, + pub pkce_verifier: String, + pub dpop_key: String, + pub dpop_nonce: String, + pub expires_at: i64, +} + +impl OAuthAuthRequestRow { + /// Convert database row to Jacquard's AuthRequestData. + pub fn to_auth_request_data(&self) -> Result, AuthError> { + // Parse the DPoP key from JSON + let dpop_key: Key = serde_json::from_str(&self.dpop_key)?; + + // Parse scopes from JSON array + let scope_strings: Vec = serde_json::from_str(&self.scopes)?; + let scopes: Vec> = scope_strings + .iter() + .filter_map(|s| Scope::parse(s).ok().map(|scope| scope.into_static())) + .collect(); + + // Parse optional account_did + let account_did = self + .account_did + .as_ref() + .and_then(|s| Did::new(s).ok().map(|d| d.into_static())); + + // Parse dpop_nonce - empty string means None + let dpop_authserver_nonce = if self.dpop_nonce.is_empty() { + None + } else { + Some(CowStr::from(self.dpop_nonce.clone())) + }; + + Ok(AuthRequestData { + state: CowStr::from(self.state.clone()), + authserver_url: CowStr::from(self.authserver_url.clone()), + account_did, + scopes, + request_uri: CowStr::from(self.request_uri.clone()), + authserver_token_endpoint: CowStr::from(self.authserver_token_endpoint.clone()), + authserver_revocation_endpoint: self + .authserver_revocation_endpoint + .clone() + .map(CowStr::from), + pkce_verifier: CowStr::from(self.pkce_verifier.clone()), + dpop_data: DpopReqData { + dpop_key, + dpop_authserver_nonce, + }, + }) + } +} + +/// Parameters for inserting an OAuth auth request. +#[derive(Debug)] +pub struct OAuthAuthRequestParams { + pub state: String, + pub authserver_url: String, + pub account_did: Option, + pub scopes_json: String, + pub request_uri: String, + pub authserver_token_endpoint: String, + pub authserver_revocation_endpoint: Option, + pub pkce_verifier: String, + pub dpop_key_json: String, + pub dpop_nonce: String, + pub expires_at: i64, +} + +impl OAuthAuthRequestParams { + /// Create insertion parameters from a Jacquard AuthRequestData. + pub fn from_auth_request(auth_req: &AuthRequestData<'_>) -> Result { + // Serialize scopes to JSON array + let scopes: Vec = auth_req + .scopes + .iter() + .map(|s| s.to_string_normalized()) + .collect(); + let scopes_json = serde_json::to_string(&scopes)?; + + // Serialize DPoP key to JSON + let dpop_key_json = serde_json::to_string(&auth_req.dpop_data.dpop_key)?; + + // DPoP nonce - None becomes empty string + let dpop_nonce = auth_req + .dpop_data + .dpop_authserver_nonce + .as_ref() + .map(|s| s.to_string()) + .unwrap_or_default(); + + let now = chrono::Utc::now().timestamp(); + // Auth requests expire after 10 minutes + let expires_at = now + 600; + + Ok(Self { + state: auth_req.state.to_string(), + authserver_url: auth_req.authserver_url.to_string(), + account_did: auth_req + .account_did + .as_ref() + .map(|d| d.as_str().to_string()), + scopes_json, + request_uri: auth_req.request_uri.to_string(), + authserver_token_endpoint: auth_req.authserver_token_endpoint.to_string(), + authserver_revocation_endpoint: auth_req + .authserver_revocation_endpoint + .as_ref() + .map(|s| s.to_string()), + pkce_verifier: auth_req.pkce_verifier.to_string(), + dpop_key_json, + dpop_nonce, + expires_at, + }) + } +} + +/// Database row for app_password_sessions table. +/// +/// This is a simpler session type compared to OAuth - just JWT tokens and identity info. +#[derive(Debug, sqlx::FromRow)] +pub struct AppPasswordSessionRow { + pub did: String, + pub session_id: String, + pub access_jwt: String, + pub refresh_jwt: String, + pub handle: String, +} + +/// Summary of an ATProto identity for listing. +/// +/// This provides a simplified view of stored ATProto sessions for CLI display. +#[derive(Debug, Clone)] +pub struct AtprotoIdentitySummary { + /// The DID (decentralized identifier) of the account. + pub did: String, + /// The handle (e.g., user.bsky.social). + pub handle: String, + /// The session ID used for this identity. + pub session_id: String, + /// Whether this is an OAuth session or app-password session. + pub auth_type: AtprotoAuthType, + /// When the token expires (for OAuth), if known. + pub expires_at: Option>, +} + +/// Type of ATProto authentication. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AtprotoAuthType { + /// OAuth with DPoP tokens. + OAuth, + /// Simple app-password with JWT tokens. + AppPassword, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_session_params_roundtrip() { + let did = Did::new("did:plc:testuser123").unwrap(); + let dpop_key: Key = + serde_json::from_str(r#"{"kty":"EC","crv":"P-256","x":"test","y":"test","d":"test"}"#) + .unwrap(); + + let session = ClientSessionData { + account_did: did.clone().into_static(), + session_id: CowStr::from("test-session"), + host_url: CowStr::from("https://bsky.social"), + authserver_url: CowStr::from("https://bsky.social"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: Some(CowStr::from("https://bsky.social/oauth/revoke")), + scopes: vec![Scope::Atproto], + dpop_data: DpopClientData { + dpop_key, + dpop_authserver_nonce: CowStr::from("auth-nonce"), + dpop_host_nonce: CowStr::from("host-nonce"), + }, + token_set: TokenSet { + iss: CowStr::from("https://bsky.social"), + sub: did.clone().into_static(), + aud: CowStr::from("https://bsky.social"), + scope: Some(CowStr::from("atproto")), + refresh_token: Some(CowStr::from("refresh-token")), + access_token: CowStr::from("access-token"), + token_type: OAuthTokenType::DPoP, + expires_at: None, + }, + }; + + // Convert to params + let params = OAuthSessionParams::from_session(&session).unwrap(); + + // Verify key fields + assert_eq!(params.account_did, "did:plc:testuser123"); + assert_eq!(params.session_id, "test-session"); + assert_eq!(params.token_type, "DPoP"); + + // Verify JSON serialization + let scopes: Vec = serde_json::from_str(¶ms.scopes_json).unwrap(); + assert_eq!(scopes.len(), 1); + assert_eq!(scopes[0], "atproto"); + } + + #[test] + fn test_auth_request_params_roundtrip() { + let dpop_key: Key = + serde_json::from_str(r#"{"kty":"EC","crv":"P-256","x":"test","y":"test","d":"test"}"#) + .unwrap(); + + let auth_req = AuthRequestData { + state: CowStr::from("test-state"), + authserver_url: CowStr::from("https://bsky.social"), + account_did: Some(Did::new("did:plc:testuser").unwrap().into_static()), + scopes: vec![Scope::Atproto], + request_uri: CowStr::from("urn:ietf:params:oauth:request_uri:test"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: None, + pkce_verifier: CowStr::from("pkce-secret"), + dpop_data: DpopReqData { + dpop_key, + dpop_authserver_nonce: Some(CowStr::from("initial-nonce")), + }, + }; + + let params = OAuthAuthRequestParams::from_auth_request(&auth_req).unwrap(); + + assert_eq!(params.state, "test-state"); + assert_eq!(params.account_did, Some("did:plc:testuser".to_string())); + assert_eq!(params.dpop_nonce, "initial-nonce"); + assert!(params.expires_at > chrono::Utc::now().timestamp()); + } +} diff --git a/crates/pattern_auth/src/atproto/oauth_store.rs b/crates/pattern_auth/src/atproto/oauth_store.rs new file mode 100644 index 0000000..76655f6 --- /dev/null +++ b/crates/pattern_auth/src/atproto/oauth_store.rs @@ -0,0 +1,529 @@ +//! Implementation of Jacquard's `ClientAuthStore` trait for SQLite storage. +//! +//! This provides persistent storage for OAuth sessions and auth requests, +//! enabling Pattern agents to maintain authenticated ATProto sessions across restarts. + +use jacquard::oauth::authstore::ClientAuthStore; +use jacquard::oauth::session::{AuthRequestData, ClientSessionData}; +use jacquard::session::SessionStoreError; +use jacquard::types::did::Did; + +use crate::atproto::models::{ + OAuthAuthRequestParams, OAuthAuthRequestRow, OAuthSessionParams, OAuthSessionRow, +}; +use crate::db::AuthDb; +use crate::error::AuthError; + +impl ClientAuthStore for AuthDb { + async fn get_session( + &self, + did: &Did<'_>, + session_id: &str, + ) -> Result>, SessionStoreError> { + let did_str = did.as_str(); + + let row = sqlx::query_as!( + OAuthSessionRow, + r#" + SELECT + account_did as "account_did!", + session_id as "session_id!", + host_url as "host_url!", + authserver_url as "authserver_url!", + authserver_token_endpoint as "authserver_token_endpoint!", + authserver_revocation_endpoint, + scopes as "scopes!", + dpop_key as "dpop_key!", + dpop_authserver_nonce as "dpop_authserver_nonce!", + dpop_host_nonce as "dpop_host_nonce!", + token_iss as "token_iss!", + token_sub as "token_sub!", + token_aud as "token_aud!", + token_scope, + refresh_token, + access_token as "access_token!", + token_type as "token_type!", + expires_at + FROM oauth_sessions + WHERE account_did = ? AND session_id = ? + "#, + did_str, + session_id, + ) + .fetch_optional(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + let Some(row) = row else { + return Ok(None); + }; + + let session = row + .to_client_session_data() + .map_err(SessionStoreError::from)?; + + Ok(Some(session)) + } + + async fn upsert_session( + &self, + session: ClientSessionData<'_>, + ) -> Result<(), SessionStoreError> { + let params = OAuthSessionParams::from_session(&session).map_err(SessionStoreError::from)?; + + let now = chrono::Utc::now().timestamp(); + + sqlx::query!( + r#" + INSERT INTO oauth_sessions ( + account_did, session_id, host_url, authserver_url, + authserver_token_endpoint, authserver_revocation_endpoint, + scopes, dpop_key, dpop_authserver_nonce, dpop_host_nonce, + token_iss, token_sub, token_aud, token_scope, + refresh_token, access_token, token_type, expires_at, + created_at, updated_at + ) VALUES ( + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? + ) + ON CONFLICT (account_did, session_id) DO UPDATE SET + host_url = excluded.host_url, + authserver_url = excluded.authserver_url, + authserver_token_endpoint = excluded.authserver_token_endpoint, + authserver_revocation_endpoint = excluded.authserver_revocation_endpoint, + scopes = excluded.scopes, + dpop_key = excluded.dpop_key, + dpop_authserver_nonce = excluded.dpop_authserver_nonce, + dpop_host_nonce = excluded.dpop_host_nonce, + token_iss = excluded.token_iss, + token_sub = excluded.token_sub, + token_aud = excluded.token_aud, + token_scope = excluded.token_scope, + refresh_token = excluded.refresh_token, + access_token = excluded.access_token, + token_type = excluded.token_type, + expires_at = excluded.expires_at, + updated_at = excluded.updated_at + "#, + params.account_did, + params.session_id, + params.host_url, + params.authserver_url, + params.authserver_token_endpoint, + params.authserver_revocation_endpoint, + params.scopes_json, + params.dpop_key_json, + params.dpop_authserver_nonce, + params.dpop_host_nonce, + params.token_iss, + params.token_sub, + params.token_aud, + params.token_scope, + params.refresh_token, + params.access_token, + params.token_type, + params.expires_at, + now, + now, + ) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } + + async fn delete_session( + &self, + did: &Did<'_>, + session_id: &str, + ) -> Result<(), SessionStoreError> { + let did_str = did.as_str(); + + sqlx::query!( + "DELETE FROM oauth_sessions WHERE account_did = ? AND session_id = ?", + did_str, + session_id, + ) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } + + async fn get_auth_req_info( + &self, + state: &str, + ) -> Result>, SessionStoreError> { + let row = sqlx::query_as!( + OAuthAuthRequestRow, + r#" + SELECT + state as "state!", + authserver_url as "authserver_url!", + account_did, + scopes as "scopes!", + request_uri as "request_uri!", + authserver_token_endpoint as "authserver_token_endpoint!", + authserver_revocation_endpoint, + pkce_verifier as "pkce_verifier!", + dpop_key as "dpop_key!", + dpop_nonce as "dpop_nonce!", + expires_at as "expires_at!" + FROM oauth_auth_requests + WHERE state = ? + "#, + state, + ) + .fetch_optional(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + let Some(row) = row else { + return Ok(None); + }; + + // Check if request has expired + let now = chrono::Utc::now().timestamp(); + if row.expires_at < now { + // Delete expired request and return None + let _ = self.delete_auth_req_info(state).await; + return Ok(None); + } + + let auth_req = row + .to_auth_request_data() + .map_err(SessionStoreError::from)?; + + Ok(Some(auth_req)) + } + + async fn save_auth_req_info( + &self, + auth_req_info: &AuthRequestData<'_>, + ) -> Result<(), SessionStoreError> { + let params = OAuthAuthRequestParams::from_auth_request(auth_req_info) + .map_err(SessionStoreError::from)?; + + let now = chrono::Utc::now().timestamp(); + + sqlx::query!( + r#" + INSERT INTO oauth_auth_requests ( + state, authserver_url, account_did, scopes, request_uri, + authserver_token_endpoint, authserver_revocation_endpoint, + pkce_verifier, dpop_key, dpop_nonce, created_at, expires_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (state) DO UPDATE SET + authserver_url = excluded.authserver_url, + account_did = excluded.account_did, + scopes = excluded.scopes, + request_uri = excluded.request_uri, + authserver_token_endpoint = excluded.authserver_token_endpoint, + authserver_revocation_endpoint = excluded.authserver_revocation_endpoint, + pkce_verifier = excluded.pkce_verifier, + dpop_key = excluded.dpop_key, + dpop_nonce = excluded.dpop_nonce, + expires_at = excluded.expires_at + "#, + params.state, + params.authserver_url, + params.account_did, + params.scopes_json, + params.request_uri, + params.authserver_token_endpoint, + params.authserver_revocation_endpoint, + params.pkce_verifier, + params.dpop_key_json, + params.dpop_nonce, + now, + params.expires_at, + ) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } + + async fn delete_auth_req_info(&self, state: &str) -> Result<(), SessionStoreError> { + sqlx::query!("DELETE FROM oauth_auth_requests WHERE state = ?", state,) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } +} + +/// Database row for listing OAuth sessions (simplified). +#[derive(Debug, sqlx::FromRow)] +pub struct OAuthSessionSummaryRow { + pub account_did: String, + pub session_id: String, + pub host_url: String, + pub expires_at: Option, +} + +// Additional list/query methods for CLI commands (not part of ClientAuthStore trait) +impl AuthDb { + /// List all stored OAuth sessions. + /// + /// Returns a list of summary rows for all stored OAuth sessions. + pub async fn list_oauth_sessions( + &self, + ) -> crate::error::AuthResult> { + let rows = sqlx::query_as!( + OAuthSessionSummaryRow, + r#" + SELECT + account_did as "account_did!", + session_id as "session_id!", + host_url as "host_url!", + expires_at + FROM oauth_sessions + ORDER BY account_did, session_id + "# + ) + .fetch_all(self.pool()) + .await?; + + Ok(rows) + } + + /// Delete an OAuth session by DID (and optionally session_id). + /// + /// If `session_id` is None, deletes all sessions for the DID. + pub async fn delete_oauth_session_by_did( + &self, + did: &str, + session_id: Option<&str>, + ) -> crate::error::AuthResult { + let result = if let Some(sid) = session_id { + sqlx::query!( + "DELETE FROM oauth_sessions WHERE account_did = ? AND session_id = ?", + did, + sid, + ) + .execute(self.pool()) + .await? + } else { + sqlx::query!("DELETE FROM oauth_sessions WHERE account_did = ?", did,) + .execute(self.pool()) + .await? + }; + + Ok(result.rows_affected()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use jacquard::CowStr; + use jacquard::IntoStatic; + use jacquard::oauth::scopes::Scope; + use jacquard::oauth::session::{DpopClientData, DpopReqData}; + use jacquard::oauth::types::OAuthTokenType; + use jacquard::oauth::types::TokenSet; + use jacquard::types::string::Datetime; + use jose_jwk::Key; + + #[tokio::test] + async fn test_oauth_session_roundtrip() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Create a test session + let did = Did::new("did:plc:testuser123").unwrap(); + let session_id = "test-session-id"; + + // Create DPoP key (minimal valid EC key for testing) + let dpop_key: Key = + serde_json::from_str(r#"{"kty":"EC","crv":"P-256","x":"test","y":"test","d":"test"}"#) + .unwrap(); + + let session = ClientSessionData { + account_did: did.clone().into_static(), + session_id: CowStr::from(session_id.to_string()), + host_url: CowStr::from("https://bsky.social"), + authserver_url: CowStr::from("https://bsky.social"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: Some(CowStr::from("https://bsky.social/oauth/revoke")), + scopes: vec![ + Scope::Atproto, + Scope::parse("repo:*").unwrap().into_static(), + ], + dpop_data: DpopClientData { + dpop_key: dpop_key.clone(), + dpop_authserver_nonce: CowStr::from("auth-nonce"), + dpop_host_nonce: CowStr::from("host-nonce"), + }, + token_set: TokenSet { + iss: CowStr::from("https://bsky.social"), + sub: did.clone().into_static(), + aud: CowStr::from("https://bsky.social"), + scope: Some(CowStr::from("atproto repo:*")), + refresh_token: Some(CowStr::from("refresh-token-value")), + access_token: CowStr::from("access-token-value"), + token_type: OAuthTokenType::DPoP, + expires_at: Some(Datetime::now()), + }, + }; + + // Save the session + db.upsert_session(session.clone()).await.unwrap(); + + // Retrieve the session + let retrieved = db + .get_session(&did, session_id) + .await + .unwrap() + .expect("session should exist"); + + // Verify fields match + assert_eq!(retrieved.account_did.as_str(), did.as_str()); + assert_eq!(retrieved.session_id.as_ref(), session_id); + assert_eq!(retrieved.host_url.as_ref(), "https://bsky.social"); + assert_eq!(retrieved.scopes.len(), 2); + assert_eq!( + retrieved.token_set.access_token.as_ref(), + "access-token-value" + ); + + // Delete the session + db.delete_session(&did, session_id).await.unwrap(); + + // Verify it's gone + let deleted = db.get_session(&did, session_id).await.unwrap(); + assert!(deleted.is_none()); + } + + #[tokio::test] + async fn test_auth_request_roundtrip() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let state = "test-state-abc123"; + + // Create DPoP key + let dpop_key: Key = + serde_json::from_str(r#"{"kty":"EC","crv":"P-256","x":"test","y":"test","d":"test"}"#) + .unwrap(); + + let auth_req = AuthRequestData { + state: CowStr::from(state.to_string()), + authserver_url: CowStr::from("https://bsky.social"), + account_did: Some(Did::new("did:plc:testuser").unwrap().into_static()), + scopes: vec![Scope::Atproto], + request_uri: CowStr::from("urn:ietf:params:oauth:request_uri:test"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: None, + pkce_verifier: CowStr::from("pkce-secret-verifier"), + dpop_data: DpopReqData { + dpop_key, + dpop_authserver_nonce: Some(CowStr::from("initial-nonce")), + }, + }; + + // Save the auth request + db.save_auth_req_info(&auth_req).await.unwrap(); + + // Retrieve it + let retrieved = db + .get_auth_req_info(state) + .await + .unwrap() + .expect("auth request should exist"); + + assert_eq!(retrieved.state.as_ref(), state); + assert_eq!(retrieved.pkce_verifier.as_ref(), "pkce-secret-verifier"); + assert!(retrieved.account_did.is_some()); + + // Delete it + db.delete_auth_req_info(state).await.unwrap(); + + // Verify it's gone + let deleted = db.get_auth_req_info(state).await.unwrap(); + assert!(deleted.is_none()); + } + + #[tokio::test] + async fn test_session_update() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let did = Did::new("did:plc:testuser").unwrap(); + let session_id = "update-test"; + + let dpop_key: Key = + serde_json::from_str(r#"{"kty":"EC","crv":"P-256","x":"test","y":"test","d":"test"}"#) + .unwrap(); + + // Create initial session + let session = ClientSessionData { + account_did: did.clone().into_static(), + session_id: CowStr::from(session_id.to_string()), + host_url: CowStr::from("https://bsky.social"), + authserver_url: CowStr::from("https://bsky.social"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: None, + scopes: vec![Scope::Atproto], + dpop_data: DpopClientData { + dpop_key: dpop_key.clone(), + dpop_authserver_nonce: CowStr::from("nonce-1"), + dpop_host_nonce: CowStr::from("host-1"), + }, + token_set: TokenSet { + iss: CowStr::from("https://bsky.social"), + sub: did.clone().into_static(), + aud: CowStr::from("https://bsky.social"), + scope: None, + refresh_token: None, + access_token: CowStr::from("token-1"), + token_type: OAuthTokenType::DPoP, + expires_at: None, + }, + }; + + db.upsert_session(session).await.unwrap(); + + // Update the session with new token + let updated_session = ClientSessionData { + account_did: did.clone().into_static(), + session_id: CowStr::from(session_id.to_string()), + host_url: CowStr::from("https://bsky.social"), + authserver_url: CowStr::from("https://bsky.social"), + authserver_token_endpoint: CowStr::from("https://bsky.social/oauth/token"), + authserver_revocation_endpoint: None, + scopes: vec![Scope::Atproto], + dpop_data: DpopClientData { + dpop_key, + dpop_authserver_nonce: CowStr::from("nonce-2"), + dpop_host_nonce: CowStr::from("host-2"), + }, + token_set: TokenSet { + iss: CowStr::from("https://bsky.social"), + sub: did.clone().into_static(), + aud: CowStr::from("https://bsky.social"), + scope: None, + refresh_token: None, + access_token: CowStr::from("token-2"), + token_type: OAuthTokenType::DPoP, + expires_at: None, + }, + }; + + db.upsert_session(updated_session).await.unwrap(); + + // Verify update + let retrieved = db + .get_session(&did, session_id) + .await + .unwrap() + .expect("session should exist"); + + assert_eq!(retrieved.token_set.access_token.as_ref(), "token-2"); + assert_eq!( + retrieved.dpop_data.dpop_authserver_nonce.as_ref(), + "nonce-2" + ); + } +} diff --git a/crates/pattern_auth/src/atproto/session_store.rs b/crates/pattern_auth/src/atproto/session_store.rs new file mode 100644 index 0000000..f34a442 --- /dev/null +++ b/crates/pattern_auth/src/atproto/session_store.rs @@ -0,0 +1,276 @@ +//! Implementation of Jacquard's `SessionStore` trait for SQLite storage of app-password sessions. +//! +//! This provides persistent storage for app-password sessions (not OAuth/DPoP), +//! enabling Pattern agents to maintain simple JWT-based ATProto sessions across restarts. + +use jacquard::CowStr; +use jacquard::IntoStatic; +use jacquard::client::AtpSession; +use jacquard::client::credential_session::SessionKey; +use jacquard::session::{SessionStore, SessionStoreError}; +use jacquard::types::did::Did; +use jacquard::types::string::Handle; + +use crate::atproto::models::AppPasswordSessionRow; +use crate::db::AuthDb; +use crate::error::AuthError; + +impl SessionStore for AuthDb { + async fn get(&self, key: &SessionKey) -> Option { + let did_str = key.0.as_str(); + let session_id = key.1.as_ref(); + + let row = sqlx::query_as!( + AppPasswordSessionRow, + r#" + SELECT + did as "did!", + session_id as "session_id!", + access_jwt as "access_jwt!", + refresh_jwt as "refresh_jwt!", + handle as "handle!" + FROM app_password_sessions + WHERE did = ? AND session_id = ? + "#, + did_str, + session_id, + ) + .fetch_optional(self.pool()) + .await + .ok()?; + + let row = row?; + + // Convert row to AtpSession + // Use new() which doesn't allocate for borrowed strings, then into_static() + let did = Did::new(&row.did).ok()?.into_static(); + let handle = Handle::new(&row.handle).ok()?.into_static(); + + Some(AtpSession { + access_jwt: CowStr::from(row.access_jwt), + refresh_jwt: CowStr::from(row.refresh_jwt), + did, + handle, + }) + } + + async fn set(&self, key: SessionKey, session: AtpSession) -> Result<(), SessionStoreError> { + let did_str = key.0.as_str(); + let session_id = key.1.as_ref(); + let access_jwt = session.access_jwt.as_ref(); + let refresh_jwt = session.refresh_jwt.as_ref(); + let handle = session.handle.as_str(); + let now = chrono::Utc::now().timestamp(); + + sqlx::query!( + r#" + INSERT INTO app_password_sessions ( + did, session_id, access_jwt, refresh_jwt, handle, created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (did, session_id) DO UPDATE SET + access_jwt = excluded.access_jwt, + refresh_jwt = excluded.refresh_jwt, + handle = excluded.handle, + updated_at = excluded.updated_at + "#, + did_str, + session_id, + access_jwt, + refresh_jwt, + handle, + now, + now, + ) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } + + async fn del(&self, key: &SessionKey) -> Result<(), SessionStoreError> { + let did_str = key.0.as_str(); + let session_id = key.1.as_ref(); + + sqlx::query!( + "DELETE FROM app_password_sessions WHERE did = ? AND session_id = ?", + did_str, + session_id, + ) + .execute(self.pool()) + .await + .map_err(|e| SessionStoreError::from(AuthError::Database(e)))?; + + Ok(()) + } +} + +// Additional list/query methods for CLI commands (not part of SessionStore trait) +impl AuthDb { + /// List all stored app-password sessions. + /// + /// Returns a list of (did, session_id, handle) tuples for all stored sessions. + pub async fn list_app_password_sessions( + &self, + ) -> crate::error::AuthResult> { + let rows = sqlx::query_as!( + AppPasswordSessionRow, + r#" + SELECT + did as "did!", + session_id as "session_id!", + access_jwt as "access_jwt!", + refresh_jwt as "refresh_jwt!", + handle as "handle!" + FROM app_password_sessions + ORDER BY did, session_id + "# + ) + .fetch_all(self.pool()) + .await?; + + Ok(rows) + } + + /// Delete an app-password session by DID (and optionally session_id). + /// + /// If `session_id` is None, deletes all sessions for the DID. + pub async fn delete_app_password_session( + &self, + did: &str, + session_id: Option<&str>, + ) -> crate::error::AuthResult { + let result = if let Some(sid) = session_id { + sqlx::query!( + "DELETE FROM app_password_sessions WHERE did = ? AND session_id = ?", + did, + sid, + ) + .execute(self.pool()) + .await? + } else { + sqlx::query!("DELETE FROM app_password_sessions WHERE did = ?", did,) + .execute(self.pool()) + .await? + }; + + Ok(result.rows_affected()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_app_password_session_roundtrip() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Create a test session key + let did = Did::new("did:plc:testuser123").unwrap().into_static(); + let session_id = CowStr::from("test-session-id".to_string()); + let key = SessionKey(did.clone(), session_id); + + // Create a test session + let session = AtpSession { + access_jwt: CowStr::from("access-jwt-value"), + refresh_jwt: CowStr::from("refresh-jwt-value"), + did: did.clone(), + handle: Handle::new("testuser.bsky.social").unwrap().into_static(), + }; + + // Save the session + db.set(key.clone(), session.clone()).await.unwrap(); + + // Retrieve the session + let retrieved = db.get(&key).await.expect("session should exist"); + + // Verify fields match + assert_eq!(retrieved.did.as_str(), did.as_str()); + assert_eq!(retrieved.access_jwt.as_ref(), "access-jwt-value"); + assert_eq!(retrieved.refresh_jwt.as_ref(), "refresh-jwt-value"); + assert_eq!(retrieved.handle.as_str(), "testuser.bsky.social"); + + // Delete the session + db.del(&key).await.unwrap(); + + // Verify it's gone + let deleted = db.get(&key).await; + assert!(deleted.is_none()); + } + + #[tokio::test] + async fn test_app_password_session_update() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let did = Did::new("did:plc:testuser").unwrap().into_static(); + let session_id = CowStr::from("update-test".to_string()); + let key = SessionKey(did.clone(), session_id); + + // Create initial session + let session = AtpSession { + access_jwt: CowStr::from("token-1"), + refresh_jwt: CowStr::from("refresh-1"), + did: did.clone(), + handle: Handle::new("user.bsky.social").unwrap().into_static(), + }; + + db.set(key.clone(), session).await.unwrap(); + + // Update the session with new tokens + let updated_session = AtpSession { + access_jwt: CowStr::from("token-2"), + refresh_jwt: CowStr::from("refresh-2"), + did: did.clone(), + handle: Handle::new("user.bsky.social").unwrap().into_static(), + }; + + db.set(key.clone(), updated_session).await.unwrap(); + + // Verify update + let retrieved = db.get(&key).await.expect("session should exist"); + + assert_eq!(retrieved.access_jwt.as_ref(), "token-2"); + assert_eq!(retrieved.refresh_jwt.as_ref(), "refresh-2"); + } + + #[tokio::test] + async fn test_app_password_session_multiple_sessions() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let did = Did::new("did:plc:multi").unwrap().into_static(); + + // Create multiple sessions for the same DID + let key1 = SessionKey(did.clone(), CowStr::from("session-1".to_string())); + let key2 = SessionKey(did.clone(), CowStr::from("session-2".to_string())); + + let session1 = AtpSession { + access_jwt: CowStr::from("access-1"), + refresh_jwt: CowStr::from("refresh-1"), + did: did.clone(), + handle: Handle::new("user.bsky.social").unwrap().into_static(), + }; + + let session2 = AtpSession { + access_jwt: CowStr::from("access-2"), + refresh_jwt: CowStr::from("refresh-2"), + did: did.clone(), + handle: Handle::new("user.bsky.social").unwrap().into_static(), + }; + + db.set(key1.clone(), session1).await.unwrap(); + db.set(key2.clone(), session2).await.unwrap(); + + // Both sessions should exist independently + let retrieved1 = db.get(&key1).await.expect("session 1 should exist"); + let retrieved2 = db.get(&key2).await.expect("session 2 should exist"); + + assert_eq!(retrieved1.access_jwt.as_ref(), "access-1"); + assert_eq!(retrieved2.access_jwt.as_ref(), "access-2"); + + // Delete one, verify other still exists + db.del(&key1).await.unwrap(); + assert!(db.get(&key1).await.is_none()); + assert!(db.get(&key2).await.is_some()); + } +} diff --git a/crates/pattern_auth/src/db.rs b/crates/pattern_auth/src/db.rs new file mode 100644 index 0000000..432ab58 --- /dev/null +++ b/crates/pattern_auth/src/db.rs @@ -0,0 +1,167 @@ +//! Database connection and operations for auth.db. + +use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions}; +use std::path::Path; +use tracing::{debug, info}; + +use crate::error::AuthResult; + +/// Authentication database handle. +/// +/// Manages the SQLite connection pool for auth.db, which stores: +/// - ATProto OAuth sessions +/// - ATProto app-password sessions +/// - Discord bot configuration +/// - Model provider OAuth tokens +#[derive(Debug, Clone)] +pub struct AuthDb { + pool: SqlitePool, +} + +impl AuthDb { + /// Open or create an auth database at the given path. + /// + /// This will: + /// 1. Create the database file if it doesn't exist + /// 2. Run any pending migrations + /// 3. Configure SQLite for optimal performance (WAL mode, etc.) + pub async fn open(path: impl AsRef) -> AuthResult { + let path = path.as_ref(); + + // Ensure parent directory exists + if let Some(parent) = path.parent().filter(|p| !p.exists()) { + std::fs::create_dir_all(parent)?; + } + + let path_str = path.to_string_lossy(); + info!("Opening auth database: {}", path_str); + + let options = SqliteConnectOptions::new() + .filename(path) + .create_if_missing(true) + .journal_mode(SqliteJournalMode::Wal) + // Recommended SQLite pragmas for performance + .pragma("cache_size", "-16000") // 16MB cache (smaller than constellation db) + .pragma("synchronous", "NORMAL") // Safe with WAL + .pragma("temp_store", "MEMORY") + .pragma("foreign_keys", "ON"); + + let pool = SqlitePoolOptions::new() + .max_connections(3) // Auth db has less concurrent access + .connect_with(options) + .await?; + + debug!("Auth database connection established"); + + // Run migrations + Self::run_migrations(&pool).await?; + + Ok(Self { pool }) + } + + /// Open an in-memory database (for testing). + pub async fn open_in_memory() -> AuthResult { + let options = SqliteConnectOptions::new() + .filename(":memory:") + .journal_mode(SqliteJournalMode::Wal) + .pragma("foreign_keys", "ON"); + + let pool = SqlitePoolOptions::new() + .max_connections(1) // In-memory must be single connection to share state + .connect_with(options) + .await?; + + Self::run_migrations(&pool).await?; + + Ok(Self { pool }) + } + + /// Run database migrations. + async fn run_migrations(pool: &SqlitePool) -> AuthResult<()> { + debug!("Running auth database migrations"); + sqlx::migrate!("./migrations").run(pool).await?; + info!("Auth database migrations complete"); + Ok(()) + } + + /// Get a reference to the connection pool. + pub fn pool(&self) -> &SqlitePool { + &self.pool + } + + /// Close the database connection. + pub async fn close(&self) { + self.pool.close().await; + } + + /// Check if the database is healthy. + pub async fn health_check(&self) -> AuthResult<()> { + sqlx::query("SELECT 1").execute(&self.pool).await?; + Ok(()) + } + + /// Clean up expired OAuth auth requests. + /// + /// Auth requests are transient PKCE state that should be cleaned up + /// after they expire (~10 minutes after creation). + pub async fn cleanup_expired_auth_requests(&self) -> AuthResult { + let now = chrono::Utc::now().timestamp(); + let result = sqlx::query("DELETE FROM oauth_auth_requests WHERE expires_at < ?") + .bind(now) + .execute(&self.pool) + .await?; + + let deleted = result.rows_affected(); + if deleted > 0 { + debug!("Cleaned up {} expired auth requests", deleted); + } + Ok(deleted) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_open_in_memory() { + let db = AuthDb::open_in_memory().await.unwrap(); + db.health_check().await.unwrap(); + } + + #[tokio::test] + async fn test_cleanup_expired_auth_requests() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Insert an expired auth request + let expired_time = chrono::Utc::now().timestamp() - 3600; // 1 hour ago + sqlx::query( + r#" + INSERT INTO oauth_auth_requests + (state, authserver_url, scopes, request_uri, authserver_token_endpoint, + pkce_verifier, dpop_key, dpop_nonce, expires_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + "#, + ) + .bind("test-state") + .bind("https://auth.example.com") + .bind("[]") + .bind("urn:test:uri") + .bind("https://auth.example.com/token") + .bind("test-verifier") + .bind("{}") + .bind("test-nonce") + .bind(expired_time) + .execute(db.pool()) + .await + .unwrap(); + + // Clean up should delete it + let deleted = db.cleanup_expired_auth_requests().await.unwrap(); + assert_eq!(deleted, 1); + + // Second cleanup should find nothing + let deleted = db.cleanup_expired_auth_requests().await.unwrap(); + assert_eq!(deleted, 0); + } +} diff --git a/crates/pattern_auth/src/discord/bot_config.rs b/crates/pattern_auth/src/discord/bot_config.rs new file mode 100644 index 0000000..3e0a45f --- /dev/null +++ b/crates/pattern_auth/src/discord/bot_config.rs @@ -0,0 +1,379 @@ +//! Discord bot configuration storage. +//! +//! This module provides `DiscordBotConfig` for storing Discord bot credentials +//! and access control settings. + +use crate::db::AuthDb; +use crate::error::AuthResult; + +/// Discord bot configuration. +/// +/// Stores bot credentials and access control settings for a Pattern constellation. +/// This is a singleton configuration (only one per auth database). +#[derive(Debug, Clone)] +pub struct DiscordBotConfig { + /// Discord bot token (required). + pub bot_token: String, + /// Discord application ID. + pub app_id: Option, + /// Discord public key for webhook verification. + pub public_key: Option, + /// List of allowed channel IDs. + pub allowed_channels: Option>, + /// List of allowed guild IDs. + pub allowed_guilds: Option>, + /// List of admin user IDs. + pub admin_users: Option>, + /// Default user ID for DMs. + pub default_dm_user: Option, +} + +impl DiscordBotConfig { + /// Load Discord bot configuration from environment variables. + /// + /// Returns `None` if `DISCORD_TOKEN` is not set. + /// + /// # Environment Variables + /// + /// - `DISCORD_TOKEN` -> bot_token (required for Some result) + /// - `APP_ID` or `DISCORD_CLIENT_ID` -> app_id + /// - `DISCORD_PUBLIC_KEY` -> public_key + /// - `DISCORD_CHANNEL_ID` (comma-separated) -> allowed_channels + /// - `DISCORD_GUILD_IDS` or `DISCORD_GUILD_ID` (comma-separated) -> allowed_guilds + /// - `DISCORD_ADMIN_USERS` or `DISCORD_DEFAULT_DM_USER` (comma-separated) -> admin_users + /// - `DISCORD_DEFAULT_DM_USER` -> default_dm_user + pub fn from_env() -> Option { + let bot_token = std::env::var("DISCORD_TOKEN").ok()?; + + let app_id = std::env::var("APP_ID") + .ok() + .or_else(|| std::env::var("DISCORD_CLIENT_ID").ok()); + + let public_key = std::env::var("DISCORD_PUBLIC_KEY").ok(); + + let allowed_channels = std::env::var("DISCORD_CHANNEL_ID") + .ok() + .map(|s| parse_comma_separated(&s)); + + let allowed_guilds = std::env::var("DISCORD_GUILD_IDS") + .ok() + .or_else(|| std::env::var("DISCORD_GUILD_ID").ok()) + .map(|s| parse_comma_separated(&s)); + + let admin_users = std::env::var("DISCORD_ADMIN_USERS") + .ok() + .or_else(|| std::env::var("DISCORD_DEFAULT_DM_USER").ok()) + .map(|s| parse_comma_separated(&s)); + + let default_dm_user = std::env::var("DISCORD_DEFAULT_DM_USER").ok(); + + Some(Self { + bot_token, + app_id, + public_key, + allowed_channels, + allowed_guilds, + admin_users, + default_dm_user, + }) + } +} + +/// Parse a comma-separated string into a Vec of trimmed, non-empty strings. +fn parse_comma_separated(s: &str) -> Vec { + s.split(',') + .map(|part| part.trim().to_string()) + .filter(|part| !part.is_empty()) + .collect() +} + +/// Database row for discord_bot_config table. +#[derive(Debug, sqlx::FromRow)] +struct DiscordBotConfigRow { + bot_token: String, + app_id: Option, + public_key: Option, + allowed_channels: Option, + allowed_guilds: Option, + admin_users: Option, + default_dm_user: Option, +} + +impl DiscordBotConfigRow { + /// Convert database row to DiscordBotConfig. + fn to_config(&self) -> AuthResult { + let allowed_channels = self + .allowed_channels + .as_ref() + .map(|s| serde_json::from_str(s)) + .transpose()?; + + let allowed_guilds = self + .allowed_guilds + .as_ref() + .map(|s| serde_json::from_str(s)) + .transpose()?; + + let admin_users = self + .admin_users + .as_ref() + .map(|s| serde_json::from_str(s)) + .transpose()?; + + Ok(DiscordBotConfig { + bot_token: self.bot_token.clone(), + app_id: self.app_id.clone(), + public_key: self.public_key.clone(), + allowed_channels, + allowed_guilds, + admin_users, + default_dm_user: self.default_dm_user.clone(), + }) + } +} + +impl AuthDb { + /// Get the Discord bot configuration from the database. + /// + /// Returns `None` if no configuration has been stored. + pub async fn get_discord_bot_config(&self) -> AuthResult> { + let row = sqlx::query_as!( + DiscordBotConfigRow, + r#" + SELECT + bot_token as "bot_token!", + app_id, + public_key, + allowed_channels, + allowed_guilds, + admin_users, + default_dm_user + FROM discord_bot_config + WHERE id = 1 + "# + ) + .fetch_optional(self.pool()) + .await?; + + match row { + Some(row) => Ok(Some(row.to_config()?)), + None => Ok(None), + } + } + + /// Store Discord bot configuration in the database. + /// + /// This performs an upsert, creating or updating the singleton configuration. + pub async fn set_discord_bot_config(&self, config: &DiscordBotConfig) -> AuthResult<()> { + let allowed_channels_json = config + .allowed_channels + .as_ref() + .map(serde_json::to_string) + .transpose()?; + + let allowed_guilds_json = config + .allowed_guilds + .as_ref() + .map(serde_json::to_string) + .transpose()?; + + let admin_users_json = config + .admin_users + .as_ref() + .map(serde_json::to_string) + .transpose()?; + + let now = chrono::Utc::now().timestamp(); + + sqlx::query!( + r#" + INSERT INTO discord_bot_config ( + id, bot_token, app_id, public_key, + allowed_channels, allowed_guilds, admin_users, default_dm_user, + created_at, updated_at + ) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (id) DO UPDATE SET + bot_token = excluded.bot_token, + app_id = excluded.app_id, + public_key = excluded.public_key, + allowed_channels = excluded.allowed_channels, + allowed_guilds = excluded.allowed_guilds, + admin_users = excluded.admin_users, + default_dm_user = excluded.default_dm_user, + updated_at = excluded.updated_at + "#, + config.bot_token, + config.app_id, + config.public_key, + allowed_channels_json, + allowed_guilds_json, + admin_users_json, + config.default_dm_user, + now, + now, + ) + .execute(self.pool()) + .await?; + + Ok(()) + } + + /// Delete the Discord bot configuration from the database. + pub async fn delete_discord_bot_config(&self) -> AuthResult<()> { + sqlx::query!("DELETE FROM discord_bot_config WHERE id = 1") + .execute(self.pool()) + .await?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_discord_config_roundtrip() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Initially no config + let config = db.get_discord_bot_config().await.unwrap(); + assert!(config.is_none()); + + // Create and store config + let config = DiscordBotConfig { + bot_token: "test-bot-token".to_string(), + app_id: Some("123456789".to_string()), + public_key: Some("public-key-hex".to_string()), + allowed_channels: Some(vec!["channel1".to_string(), "channel2".to_string()]), + allowed_guilds: Some(vec!["guild1".to_string()]), + admin_users: Some(vec!["admin1".to_string(), "admin2".to_string()]), + default_dm_user: Some("dm-user".to_string()), + }; + + db.set_discord_bot_config(&config).await.unwrap(); + + // Retrieve and verify + let retrieved = db + .get_discord_bot_config() + .await + .unwrap() + .expect("config should exist"); + + assert_eq!(retrieved.bot_token, "test-bot-token"); + assert_eq!(retrieved.app_id, Some("123456789".to_string())); + assert_eq!(retrieved.public_key, Some("public-key-hex".to_string())); + assert_eq!( + retrieved.allowed_channels, + Some(vec!["channel1".to_string(), "channel2".to_string()]) + ); + assert_eq!(retrieved.allowed_guilds, Some(vec!["guild1".to_string()])); + assert_eq!( + retrieved.admin_users, + Some(vec!["admin1".to_string(), "admin2".to_string()]) + ); + assert_eq!(retrieved.default_dm_user, Some("dm-user".to_string())); + + // Delete and verify + db.delete_discord_bot_config().await.unwrap(); + let deleted = db.get_discord_bot_config().await.unwrap(); + assert!(deleted.is_none()); + } + + #[tokio::test] + async fn test_discord_config_update() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Create initial config + let config = DiscordBotConfig { + bot_token: "token-1".to_string(), + app_id: None, + public_key: None, + allowed_channels: None, + allowed_guilds: None, + admin_users: None, + default_dm_user: None, + }; + + db.set_discord_bot_config(&config).await.unwrap(); + + // Update config + let updated_config = DiscordBotConfig { + bot_token: "token-2".to_string(), + app_id: Some("new-app-id".to_string()), + public_key: None, + allowed_channels: Some(vec!["new-channel".to_string()]), + allowed_guilds: None, + admin_users: None, + default_dm_user: Some("new-dm-user".to_string()), + }; + + db.set_discord_bot_config(&updated_config).await.unwrap(); + + // Verify update + let retrieved = db + .get_discord_bot_config() + .await + .unwrap() + .expect("config should exist"); + + assert_eq!(retrieved.bot_token, "token-2"); + assert_eq!(retrieved.app_id, Some("new-app-id".to_string())); + assert_eq!( + retrieved.allowed_channels, + Some(vec!["new-channel".to_string()]) + ); + assert_eq!(retrieved.default_dm_user, Some("new-dm-user".to_string())); + } + + #[tokio::test] + async fn test_discord_config_minimal() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Config with only required field + let config = DiscordBotConfig { + bot_token: "minimal-token".to_string(), + app_id: None, + public_key: None, + allowed_channels: None, + allowed_guilds: None, + admin_users: None, + default_dm_user: None, + }; + + db.set_discord_bot_config(&config).await.unwrap(); + + let retrieved = db + .get_discord_bot_config() + .await + .unwrap() + .expect("config should exist"); + + assert_eq!(retrieved.bot_token, "minimal-token"); + assert!(retrieved.app_id.is_none()); + assert!(retrieved.public_key.is_none()); + assert!(retrieved.allowed_channels.is_none()); + assert!(retrieved.allowed_guilds.is_none()); + assert!(retrieved.admin_users.is_none()); + assert!(retrieved.default_dm_user.is_none()); + } + + #[test] + fn test_parse_comma_separated() { + assert_eq!( + parse_comma_separated("a,b,c"), + vec!["a".to_string(), "b".to_string(), "c".to_string()] + ); + assert_eq!( + parse_comma_separated("a, b , c"), + vec!["a".to_string(), "b".to_string(), "c".to_string()] + ); + assert_eq!(parse_comma_separated("single"), vec!["single".to_string()]); + assert_eq!( + parse_comma_separated("a,,b"), + vec!["a".to_string(), "b".to_string()] + ); + assert!(parse_comma_separated("").is_empty()); + assert!(parse_comma_separated(",,,").is_empty()); + } +} diff --git a/crates/pattern_auth/src/discord/mod.rs b/crates/pattern_auth/src/discord/mod.rs new file mode 100644 index 0000000..4085545 --- /dev/null +++ b/crates/pattern_auth/src/discord/mod.rs @@ -0,0 +1,11 @@ +//! Discord authentication and configuration module. +//! +//! This module provides storage for Discord bot configuration, +//! enabling Pattern agents to maintain Discord integration settings across restarts. +//! +//! Configuration can be loaded from environment variables via `DiscordBotConfig::from_env()` +//! or retrieved from the database via `AuthDb::get_discord_bot_config()`. + +mod bot_config; + +pub use bot_config::DiscordBotConfig; diff --git a/crates/pattern_auth/src/error.rs b/crates/pattern_auth/src/error.rs new file mode 100644 index 0000000..7b9c607 --- /dev/null +++ b/crates/pattern_auth/src/error.rs @@ -0,0 +1,71 @@ +//! Error types for pattern_auth. + +use miette::Diagnostic; +use thiserror::Error; + +/// Result type for auth operations. +pub type AuthResult = Result; + +/// Errors that can occur in auth operations. +#[derive(Debug, Error, Diagnostic)] +pub enum AuthError { + /// Database error from sqlx. + #[error("Database error: {0}")] + #[diagnostic(code(pattern_auth::database))] + Database(#[from] sqlx::Error), + + /// Migration error. + #[error("Migration error: {0}")] + #[diagnostic(code(pattern_auth::migration))] + Migration(#[from] sqlx::migrate::MigrateError), + + /// IO error. + #[error("IO error: {0}")] + #[diagnostic(code(pattern_auth::io))] + Io(#[from] std::io::Error), + + /// Serialization error. + #[error("Serialization error: {0}")] + #[diagnostic(code(pattern_auth::serde))] + Serde(#[from] serde_json::Error), + + /// Session not found. + #[error("Session not found: {did} / {session_id}")] + #[diagnostic(code(pattern_auth::session_not_found))] + SessionNotFound { did: String, session_id: String }, + + /// Auth request not found (PKCE state). + #[error("Auth request not found for state: {state}")] + #[diagnostic(code(pattern_auth::auth_request_not_found))] + AuthRequestNotFound { state: String }, + + /// Discord config not found. + #[error("Discord bot configuration not found")] + #[diagnostic(code(pattern_auth::discord_config_not_found))] + DiscordConfigNotFound, + + /// Provider OAuth token not found. + #[error("OAuth token not found for provider: {provider}")] + #[diagnostic(code(pattern_auth::provider_token_not_found))] + ProviderTokenNotFound { provider: String }, + + /// Invalid DID format. + #[error("Invalid DID: {0}")] + #[diagnostic(code(pattern_auth::invalid_did))] + InvalidDid(String), +} + +// Convert to Jacquard's SessionStoreError. +// Map to specific variants where possible, only use Other for truly other errors. +impl From for jacquard::session::SessionStoreError { + fn from(err: AuthError) -> Self { + use jacquard::session::SessionStoreError; + match err { + // Direct mappings to SessionStoreError variants + AuthError::Io(e) => SessionStoreError::Io(e), + AuthError::Serde(e) => SessionStoreError::Serde(e), + // All other errors go to Other + other => SessionStoreError::Other(Box::new(other)), + } + } +} diff --git a/crates/pattern_auth/src/lib.rs b/crates/pattern_auth/src/lib.rs new file mode 100644 index 0000000..f876d07 --- /dev/null +++ b/crates/pattern_auth/src/lib.rs @@ -0,0 +1,24 @@ +//! Pattern Auth - Credential and token storage for Pattern constellations. +//! +//! This crate provides constellation-scoped authentication storage: +//! - ATProto OAuth sessions (implements Jacquard's `ClientAuthStore`) +//! - ATProto app-password sessions (implements Jacquard's `SessionStore`) +//! - Discord bot configuration +//! - Model provider OAuth tokens +//! +//! # Architecture +//! +//! Each constellation has its own `auth.db` alongside `constellation.db`. +//! This separation keeps sensitive credentials out of the main database, +//! making constellation backups safer to share. + +pub mod atproto; +pub mod db; +pub mod discord; +pub mod error; +pub mod providers; + +pub use db::AuthDb; +pub use discord::DiscordBotConfig; +pub use error::{AuthError, AuthResult}; +pub use providers::ProviderOAuthToken; diff --git a/crates/pattern_auth/src/providers/mod.rs b/crates/pattern_auth/src/providers/mod.rs new file mode 100644 index 0000000..9a264ae --- /dev/null +++ b/crates/pattern_auth/src/providers/mod.rs @@ -0,0 +1,9 @@ +//! Provider authentication module. +//! +//! This module provides storage for OAuth tokens from AI model providers +//! (Anthropic, OpenAI, etc.), enabling Pattern to maintain authenticated +//! sessions across restarts. + +mod oauth; + +pub use oauth::ProviderOAuthToken; diff --git a/crates/pattern_auth/src/providers/oauth.rs b/crates/pattern_auth/src/providers/oauth.rs new file mode 100644 index 0000000..844ff8b --- /dev/null +++ b/crates/pattern_auth/src/providers/oauth.rs @@ -0,0 +1,430 @@ +//! Provider OAuth token storage. +//! +//! This module provides `ProviderOAuthToken` for storing OAuth tokens +//! from AI model providers like Anthropic and OpenAI. + +use chrono::{DateTime, Utc}; + +use crate::db::AuthDb; +use crate::error::AuthResult; + +/// OAuth token for an AI model provider. +/// +/// Stores OAuth credentials for providers like Anthropic, OpenAI, etc. +/// The provider name serves as the primary key (one token per provider). +#[derive(Debug, Clone)] +pub struct ProviderOAuthToken { + /// Provider identifier (e.g., "anthropic", "openai"). + pub provider: String, + /// OAuth access token. + pub access_token: String, + /// OAuth refresh token (if provided by the provider). + pub refresh_token: Option, + /// Token expiration time (if provided). + pub expires_at: Option>, + /// OAuth scopes granted. + pub scope: Option, + /// Session identifier (provider-specific). + pub session_id: Option, + /// When this token was first stored. + pub created_at: DateTime, + /// When this token was last updated. + pub updated_at: DateTime, +} + +impl ProviderOAuthToken { + /// Check if this token needs to be refreshed. + /// + /// Returns `true` if the token will expire within the next 5 minutes, + /// or if it has already expired. Returns `false` if there is no + /// expiration time set. + pub fn needs_refresh(&self) -> bool { + match self.expires_at { + Some(expires_at) => { + let refresh_threshold = Utc::now() + chrono::Duration::minutes(5); + expires_at <= refresh_threshold + } + None => false, + } + } + + /// Check if this token has expired. + /// + /// Returns `true` if the token's expiration time has passed. + /// Returns `false` if there is no expiration time set. + pub fn is_expired(&self) -> bool { + match self.expires_at { + Some(expires_at) => expires_at <= Utc::now(), + None => false, + } + } +} + +/// Database row for provider_oauth_tokens table. +#[derive(Debug, sqlx::FromRow)] +struct ProviderOAuthTokenRow { + provider: String, + access_token: String, + refresh_token: Option, + expires_at: Option, + scope: Option, + session_id: Option, + created_at: i64, + updated_at: i64, +} + +impl ProviderOAuthTokenRow { + /// Convert database row to ProviderOAuthToken. + fn to_token(&self) -> ProviderOAuthToken { + ProviderOAuthToken { + provider: self.provider.clone(), + access_token: self.access_token.clone(), + refresh_token: self.refresh_token.clone(), + expires_at: self.expires_at.map(timestamp_to_datetime), + scope: self.scope.clone(), + session_id: self.session_id.clone(), + created_at: timestamp_to_datetime(self.created_at), + updated_at: timestamp_to_datetime(self.updated_at), + } + } +} + +/// Convert a Unix timestamp (seconds) to a DateTime. +fn timestamp_to_datetime(timestamp: i64) -> DateTime { + DateTime::from_timestamp(timestamp, 0).unwrap_or_else(|| Utc::now()) +} + +impl AuthDb { + /// Get an OAuth token for a specific provider. + /// + /// Returns `None` if no token has been stored for this provider. + pub async fn get_provider_oauth_token( + &self, + provider: &str, + ) -> AuthResult> { + let row = sqlx::query_as!( + ProviderOAuthTokenRow, + r#" + SELECT + provider as "provider!", + access_token as "access_token!", + refresh_token, + expires_at, + scope, + session_id, + created_at as "created_at!", + updated_at as "updated_at!" + FROM provider_oauth_tokens + WHERE provider = ? + "#, + provider + ) + .fetch_optional(self.pool()) + .await?; + + Ok(row.map(|r| r.to_token())) + } + + /// Store or update an OAuth token for a provider. + /// + /// This performs an upsert - creating a new token if one doesn't exist + /// for this provider, or updating the existing token if it does. + pub async fn set_provider_oauth_token(&self, token: &ProviderOAuthToken) -> AuthResult<()> { + let expires_at = token.expires_at.map(|dt| dt.timestamp()); + let now = Utc::now().timestamp(); + + sqlx::query!( + r#" + INSERT INTO provider_oauth_tokens ( + provider, access_token, refresh_token, expires_at, scope, session_id, + created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (provider) DO UPDATE SET + access_token = excluded.access_token, + refresh_token = excluded.refresh_token, + expires_at = excluded.expires_at, + scope = excluded.scope, + session_id = excluded.session_id, + updated_at = excluded.updated_at + "#, + token.provider, + token.access_token, + token.refresh_token, + expires_at, + token.scope, + token.session_id, + now, + now, + ) + .execute(self.pool()) + .await?; + + Ok(()) + } + + /// Delete an OAuth token for a specific provider. + pub async fn delete_provider_oauth_token(&self, provider: &str) -> AuthResult<()> { + sqlx::query!( + "DELETE FROM provider_oauth_tokens WHERE provider = ?", + provider + ) + .execute(self.pool()) + .await?; + + Ok(()) + } + + /// List all stored provider OAuth tokens. + pub async fn list_provider_oauth_tokens(&self) -> AuthResult> { + let rows = sqlx::query_as!( + ProviderOAuthTokenRow, + r#" + SELECT + provider as "provider!", + access_token as "access_token!", + refresh_token, + expires_at, + scope, + session_id, + created_at as "created_at!", + updated_at as "updated_at!" + FROM provider_oauth_tokens + ORDER BY provider + "# + ) + .fetch_all(self.pool()) + .await?; + + Ok(rows.into_iter().map(|r| r.to_token()).collect()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_provider_oauth_token_roundtrip() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Initially no token + let token = db.get_provider_oauth_token("anthropic").await.unwrap(); + assert!(token.is_none()); + + // Create and store token + let now = Utc::now(); + let expires = now + chrono::Duration::hours(1); + let token = ProviderOAuthToken { + provider: "anthropic".to_string(), + access_token: "test-access-token".to_string(), + refresh_token: Some("test-refresh-token".to_string()), + expires_at: Some(expires), + scope: Some("read write".to_string()), + session_id: Some("session-123".to_string()), + created_at: now, + updated_at: now, + }; + + db.set_provider_oauth_token(&token).await.unwrap(); + + // Retrieve and verify + let retrieved = db + .get_provider_oauth_token("anthropic") + .await + .unwrap() + .expect("token should exist"); + + assert_eq!(retrieved.provider, "anthropic"); + assert_eq!(retrieved.access_token, "test-access-token"); + assert_eq!( + retrieved.refresh_token, + Some("test-refresh-token".to_string()) + ); + assert!(retrieved.expires_at.is_some()); + assert_eq!(retrieved.scope, Some("read write".to_string())); + assert_eq!(retrieved.session_id, Some("session-123".to_string())); + + // Delete and verify + db.delete_provider_oauth_token("anthropic").await.unwrap(); + let deleted = db.get_provider_oauth_token("anthropic").await.unwrap(); + assert!(deleted.is_none()); + } + + #[tokio::test] + async fn test_provider_oauth_token_update() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let now = Utc::now(); + + // Create initial token + let token = ProviderOAuthToken { + provider: "openai".to_string(), + access_token: "token-1".to_string(), + refresh_token: None, + expires_at: None, + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + + db.set_provider_oauth_token(&token).await.unwrap(); + + // Update token + let updated_token = ProviderOAuthToken { + provider: "openai".to_string(), + access_token: "token-2".to_string(), + refresh_token: Some("refresh-2".to_string()), + expires_at: Some(now + chrono::Duration::hours(2)), + scope: Some("full".to_string()), + session_id: Some("new-session".to_string()), + created_at: now, + updated_at: now, + }; + + db.set_provider_oauth_token(&updated_token).await.unwrap(); + + // Verify update + let retrieved = db + .get_provider_oauth_token("openai") + .await + .unwrap() + .expect("token should exist"); + + assert_eq!(retrieved.access_token, "token-2"); + assert_eq!(retrieved.refresh_token, Some("refresh-2".to_string())); + assert!(retrieved.expires_at.is_some()); + assert_eq!(retrieved.scope, Some("full".to_string())); + assert_eq!(retrieved.session_id, Some("new-session".to_string())); + } + + #[tokio::test] + async fn test_provider_oauth_token_minimal() { + let db = AuthDb::open_in_memory().await.unwrap(); + + let now = Utc::now(); + + // Token with only required fields + let token = ProviderOAuthToken { + provider: "minimal".to_string(), + access_token: "minimal-token".to_string(), + refresh_token: None, + expires_at: None, + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + + db.set_provider_oauth_token(&token).await.unwrap(); + + let retrieved = db + .get_provider_oauth_token("minimal") + .await + .unwrap() + .expect("token should exist"); + + assert_eq!(retrieved.provider, "minimal"); + assert_eq!(retrieved.access_token, "minimal-token"); + assert!(retrieved.refresh_token.is_none()); + assert!(retrieved.expires_at.is_none()); + assert!(retrieved.scope.is_none()); + assert!(retrieved.session_id.is_none()); + } + + #[tokio::test] + async fn test_list_provider_oauth_tokens() { + let db = AuthDb::open_in_memory().await.unwrap(); + + // Initially empty + let tokens = db.list_provider_oauth_tokens().await.unwrap(); + assert!(tokens.is_empty()); + + let now = Utc::now(); + + // Add multiple tokens + for provider in ["anthropic", "openai", "google"] { + let token = ProviderOAuthToken { + provider: provider.to_string(), + access_token: format!("{}-token", provider), + refresh_token: None, + expires_at: None, + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + db.set_provider_oauth_token(&token).await.unwrap(); + } + + // List all + let tokens = db.list_provider_oauth_tokens().await.unwrap(); + assert_eq!(tokens.len(), 3); + + // Should be ordered by provider name + assert_eq!(tokens[0].provider, "anthropic"); + assert_eq!(tokens[1].provider, "google"); + assert_eq!(tokens[2].provider, "openai"); + } + + #[test] + fn test_token_expiry_checks() { + let now = Utc::now(); + + // Token expiring in 1 hour - not expired, doesn't need refresh + let token = ProviderOAuthToken { + provider: "test".to_string(), + access_token: "token".to_string(), + refresh_token: None, + expires_at: Some(now + chrono::Duration::hours(1)), + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + assert!(!token.is_expired()); + assert!(!token.needs_refresh()); + + // Token expiring in 3 minutes - not expired, but needs refresh + let token = ProviderOAuthToken { + provider: "test".to_string(), + access_token: "token".to_string(), + refresh_token: None, + expires_at: Some(now + chrono::Duration::minutes(3)), + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + assert!(!token.is_expired()); + assert!(token.needs_refresh()); + + // Token expired 1 hour ago - expired and needs refresh + let token = ProviderOAuthToken { + provider: "test".to_string(), + access_token: "token".to_string(), + refresh_token: None, + expires_at: Some(now - chrono::Duration::hours(1)), + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + assert!(token.is_expired()); + assert!(token.needs_refresh()); + + // Token with no expiration - never expired, never needs refresh + let token = ProviderOAuthToken { + provider: "test".to_string(), + access_token: "token".to_string(), + refresh_token: None, + expires_at: None, + scope: None, + session_id: None, + created_at: now, + updated_at: now, + }; + assert!(!token.is_expired()); + assert!(!token.needs_refresh()); + } +} diff --git a/crates/pattern_cli/CLAUDE.md b/crates/pattern_cli/CLAUDE.md index 80c4ee9..98467e6 100644 --- a/crates/pattern_cli/CLAUDE.md +++ b/crates/pattern_cli/CLAUDE.md @@ -1,146 +1,222 @@ # CLAUDE.md - Pattern CLI -⚠️ **CRITICAL WARNING**: DO NOT run ANY CLI commands during development! -Production agents are running. Any CLI invocation will disrupt active agents. -Testing must be done offline after stopping production agents. +> **CRITICAL WARNING**: DO NOT run ANY CLI commands during development! +> Production agents are running. Any CLI invocation will disrupt active agents. +> Testing must be done offline after stopping production agents. -Command-line interface for testing and managing the Pattern ADHD support system. +Command-line interface for the Pattern ADHD support system. Binary output: `pattern`. -## Purpose +## CLI Command Reference -This crate provides the primary development and testing interface for Pattern, allowing direct interaction with agents, groups, data sources, and all system components. +### Chat Commands -## Current Status +```bash +# Single agent chat (default agent: Pattern) +pattern chat +pattern chat --agent MyAgent -### ✅ Implemented Commands +# Group chat +pattern chat --group main -#### Agent Operations -- `agent create` - Create new agents with custom prompts -- `agent list` - List all agents in the system -- `agent show ` - Display agent details -- `agent delete ` - Remove an agent +# Discord mode (requires group) +pattern chat --group main --discord +``` -#### Group Operations -- `group create` - Create agent groups with coordination patterns -- `group add-member` - Add agents to groups -- `group list` - List all groups -- `group status ` - Show group details and members +### Agent Commands -#### Chat Modes -- `chat` - Interactive chat with single agent -- `chat --group ` - Chat with agent group -- `chat --discord` - Test Discord integration locally -- `chat --export` - Export conversation history +```bash +# List all agents +pattern agent list + +# Show agent details +pattern agent status + +# Create new agent (interactive TUI builder) +pattern agent create +pattern agent create --from config.toml + +# Edit existing agent (interactive TUI builder) +pattern agent edit + +# Export agent to TOML +pattern agent export +pattern agent export -o output.toml + +# Add configuration +pattern agent add source -t bluesky +pattern agent add memory