Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,70 @@ jobs:
- name: Test default features
run: cargo test

# The adapter's `memory-git` feature gates the diff family, and the test
# that the family is *withheld* without it is `#[cfg(not(feature =
# "memory-git"))]`. Both the `--all-features` and default runs above
# compile that test out, so without this step it would be checked by
# nothing — a feature-gated test whose default fate is to be built by one
# job and executed by none.
#
# This is also the configuration that keeps the promise the feature
# exists for: no `git2` / `libgit2-sys` in the graph.
# `api/Cargo.toml` spells out this exact command in a comment and asks
# that the contract crate never link a storage engine, a native library,
# an HTTP client, or an async runtime. It was left as a comment, so
# nothing checked it — and a forbidden dependency arrives transitively,
# through a feature someone enabled two crates away, which is precisely
# the way nobody notices.
#
# The FORWARD form is required. `cargo tree -i <crate> -p tinymemory-api`
# discards the `-p` scope, prints the whole-workspace inverse tree, and
# exits 0 looking clean even when this crate is the one at fault. The
# manifest says so; this runs what it says.
# `cargo build --all-targets` only *compiles* an example. `AGENTS.md`
# promises `cargo run --example basic` works, and a compiled example can
# still panic on its first line — which is the state the repository was in
# before issue #18 §E7, when the command was documented and there was no
# `examples/` directory at all.
- name: Run the bundled example
run: cargo run --example basic

- name: Assert the contract crate stays free of heavy dependencies
run: |
forbidden="$(cargo tree -p tinymemory-api -e normal,build --prefix none \
| grep -Ei 'rusqlite|libsqlite|git2|reqwest|regex|tokio' || true)"
if [ -n "$forbidden" ]; then
echo "tinymemory-api pulled in a dependency its manifest forbids:" >&2
echo "$forbidden" >&2
echo >&2
echo "The contract is what hosts compile against. It must stay free of" >&2
echo "storage engines, native libraries, HTTP clients and async runtimes." >&2
exit 1
fi

# The minimal build has to stay genuinely usable, not merely compile:
# a host that wants the ports wired and nothing retained must be able to
# bind the null driver without pulling an engine in behind it.
- name: Build and bind the minimal configuration
run: |
cargo build -p tinymemory --no-default-features
cargo test -p tinymemory --no-default-features --test null_provider

- name: Lint and test the adapter without its optional engine features
run: |
cargo clippy -p tinymemory-tinycortex --all-targets --no-default-features -- -D warnings
cargo test -p tinymemory-tinycortex --no-default-features

- name: Assert the default adapter build links no native git
run: |
linked="$(cargo tree -p tinymemory-tinycortex --no-default-features \
-e normal --prefix none | grep -cE '^(git2|libgit2-sys)' || true)"
if [ "$linked" -ne 0 ]; then
echo "the default adapter build linked $linked native-git crate(s);" >&2
echo "the memory-git feature exists to keep them out" >&2
exit 1
fi

# The module crate is its own workspace root (see the `exclude` note in the
# root Cargo.toml), so NONE of the steps above touch it: `--all-targets`,
# `--all-features` and `--workspace` all stop at the workspace boundary and
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ target/
**/*.rs.bk
*.pdb

# Stray build artifacts. Two 3.6 MB Linux ELF executables with debug info were
# committed at the repository root before this entry existed; both were produced
# by an ad-hoc build, referenced by nothing, and carried in every clone.
/rust_out
/tmp

# Coverage output
/coverage/
*.profraw
Expand Down
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = [".", "api", "core", "adapters/tinycortex", "adapters/remote"]
default-members = [".", "api", "core", "adapters/tinycortex", "adapters/remote"]
members = [".", "api", "core", "adapters/tinycortex", "adapters/remote", "conformance"]
default-members = [".", "api", "core", "adapters/tinycortex", "adapters/remote", "conformance"]
# `vendor/` holds engine submodules (tinycortex, tinybus, tinyagents), each of
# which is its own workspace with its own lockfile. Same exclusion
# `vendor/tinycortex` uses for its own nested vendor directory.
Expand Down Expand Up @@ -72,6 +72,13 @@ serde = { version = "1", features = ["derive"] }
[dev-dependencies]
# The mandatory-family tests are async.
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
# `TestHostConfig`, for the driver-selection tests. A dev-dependency: the
# facade must not carry a test double into a consumer's graph.
tinymemory-api = { path = "api", features = ["test-support"] }
# The reference driver and the behavioural suite, for the workspace-level
# integration tests. A dev-dependency only: the facade must not carry a test
# harness into a consumer's dependency graph.
tinymemory-conformance = { path = "conformance" }

[features]
default = []
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,30 @@ src/
│ binds as, and the fail-closed external-driver gate
└── mandatory/ the three mandatory capability families, composed once
over the `Memory` storage trait
core/ tinymemory-core — the substance: ingestion, the summary
tree, chunk storage, entities, the graph, the diff
ledger, goals, tool-memory, and the Composio sync layer.
The largest crate here by a wide margin, and the one a
real host actually depends on. Unlike `api/` it is not
dependency-light: today it links the TinyCortex engine,
a bundled SQLite, and an HTTP stack unconditionally.
adapters/
├── tinycortex/ the TinyCortex engine seen through the contract
└── remote/ native HTTP dialects for Supermemory, Mem0, and Cognee
crates/
└── tinymemory-module/ the TinyBus loadable-module driver. Excluded from the
workspace on purpose — see the note in `Cargo.toml`.
vendor/
├── tinycortex/ the engine, pinned as a submodule
├── tinyagents/ pinned TinyAgents submodule
└── tinybus/ pinned TinyBus submodule
```

Run `git submodule update --init --recursive` after cloning. Nothing in the
workspace builds without it — `core` names `tinyagents` and `tinycortex` by
path through `vendor/`, so an uninitialized checkout fails at manifest
resolution rather than at compile time, which reads as a confusing error.

## The contract

`MemoryProvider` is an object-safe trait with **three mandatory** capability
Expand Down
2 changes: 1 addition & 1 deletion adapters/remote/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tinymemory-remote"
publish = false
version = "0.1.0"
edition = "2021"
rust-version = "1.85"
rust-version = "1.96"
license = "MIT"
description = "HTTP adapters for self-hosted Supermemory, Mem0, and Cognee"
repository = "https://github.com/tinyhumansai/tinymemory"
Expand Down
Loading