-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Expand file tree
/
Copy pathCargo.toml
More file actions
1605 lines (1563 loc) · 94.4 KB
/
Copy pathCargo.toml
File metadata and controls
1605 lines (1563 loc) · 94.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[package]
name = "openhuman"
version = "0.63.22"
edition = "2021"
description = "OpenHuman core business logic and RPC server"
# The crate ships a verbatim GPLv3 `LICENSE` file but carried no `license` key,
# which left the grant ambiguous to every tool that reads metadata rather than
# the file (cargo-deny, crates.io, SBOM generators). Declared explicitly as
# `only` — not `or-later` — to match `medulla-public` and the `GPL-3.0-only`
# first-party crates in the closure (`tinyagents`).
license = "GPL-3.0-only"
autobins = false
# build.rs globs tests/raw_coverage/*.rs into the single `raw_coverage_all`
# integration target (see tests/raw_coverage_all.rs). Those files used to be ~76
# individual `tests/*.rs` targets, each statically relinking the whole crate —
# collapsing them into one target removes ~75 full-crate link steps per test run.
build = "build.rs"
# `cargo machete` reports a dependency as unused when no `use` names it, and
# this list is empty because there is nothing left to excuse (#5560).
#
# It used to hold `tinymemory` (the facade) and `tinymemory-tinycortex` (the
# TinyCortex adapter), on the reasoning that both were load-bearing for DRIVER
# ADMISSION — the memory subsystem resolved its engine through `tinymemory`'s
# driver registry, and the adapter made TinyCortex admissible as that engine —
# so that dropping either would compile clean and fail at runtime.
#
# **That reasoning expired rather than being wrong.** `memory::binding::admit`
# is pure string matching against `MODULE_ID` and refuses
# `DriverClass::Embedded` outright, so nothing here resolves an engine through
# the facade's registry any more; the engine runs in the `tinymemory` TinyBus
# module. The facade is deleted and the adapter moved to `[dev-dependencies]`,
# where its only consumers (test fixtures) already lived.
#
# The principle it was written to protect still holds for whatever lands here
# next: an unsuppressed false positive is how a real finding gets ignored the
# time after.
[package.metadata.cargo-machete]
ignored = []
[[bin]]
name = "openhuman-core"
path = "src/main.rs"
[[bin]]
name = "test-mcp-stub"
path = "src/bin/test_mcp_stub.rs"
[[bin]]
name = "openhuman-fleet"
path = "src/bin/fleet.rs"
# The fleet supervisor embeds the axum control-plane server, so it only builds
# with the HTTP transport compiled in (#5048). Under `--no-default-features`
# (no `http-server`) this target is skipped rather than failing to link.
required-features = ["http-server", "bin-tools"]
# Embedded-RSS benchmark harness (#5046). Gated behind the default-OFF
# `rss-bench` feature so no benchmark code enters the shipped build. Build with
# `cargo build --release --features rss-bench --bin rss-bench`.
[[bin]]
name = "rss-bench"
path = "src/bin/rss_bench.rs"
required-features = ["rss-bench"]
# Stateful library profiling workloads (memory ingestion + real sub-agent
# delegation under a hermetic mock provider). Local/dev only.
[[bin]]
name = "library-profile"
path = "src/bin/library_profile/main.rs"
required-features = ["rss-bench"]
# ── Integration tests that need a PRODUCT gate ──────────────────────────────
#
# `[features] default` is the contributor set and no longer turns on `voice`,
# `web3`, `crash-reporting` or `inference`. These four `tests/` targets name
# symbols that only exist behind those gates, so without a `required-features`
# line a bare `cargo test` fails to COMPILE — not skip, fail — and the failure
# is in a file the contributor did not touch.
#
# `required-features` makes cargo skip the target instead, which is the honest
# outcome: the test exercises a domain that build does not contain. The CI
# product lanes pass `--features "$(scripts/ci/product-features.sh)"`, so every
# one of these still runs there, against the code that ships.
#
# Autodiscovery stays on for the other ~59 `tests/*.rs` targets; declaring a
# target explicitly only opts THAT file out of it.
#
# This replaces the per-symbol `#[cfg]` cleanup tracked in #5021 for these four
# files. #5021 is still the right fix for symbols named in the middle of an
# otherwise gate-free target — required-features is the blunt instrument, and
# it costs the whole target when the gate is off.
[[test]]
name = "observability_smoke"
path = "tests/observability_smoke.rs"
# The `is_*_event` Sentry filters are all `#[cfg(feature = "crash-reporting")]`.
required-features = ["crash-reporting"]
[[test]]
name = "x402_twit_sh_live"
path = "tests/x402_twit_sh_live.rs"
# `x402::tools::X402RequestTool` — the x402 domain is part of the web3 family.
required-features = ["web3"]
[[test]]
name = "json_rpc_e2e"
path = "tests/json_rpc_e2e.rs"
# `voice::reply_speech::{test_seam, TEST_SEAM_ENV}` — the reply-speech seam
# only exists in the real voice module, not the stub.
required-features = ["voice"]
[[test]]
name = "raw_coverage_all"
path = "tests/raw_coverage_all.rs"
# The merged raw-coverage target spans ~76 former files, so it reaches the
# widest surface of any single target: `lettre` (pulled in through the voice
# gate's `tinychannels/email`) and the local inference download service.
required-features = ["voice", "inference"]
[lib]
name = "openhuman_core"
crate-type = ["rlib"]
[dependencies]
# tinyhumans-sdk — the typed Rust client for the TinyHumans backend API
# (https://github.com/tinyhumansai/sdk). Vendored as a git submodule under
# `vendor/` beside the other tiny* crates and consumed by path: the crate is not
# published to crates.io, so there is no `[patch.crates-io]` entry for it.
# This is the single source of truth for backend routes — `src/api/` is the
# OpenHuman-local adapter layer (session tokens, config, observability) that
# sits on top of it, not a second HTTP client. Anything missing here belongs
# upstream in the SDK repo, not re-implemented in `src/api/`.
# After cloning: `git submodule update --init vendor/tinyhumans-sdk`.
tinyhumans-sdk = { path = "vendor/tinyhumans-sdk", default-features = false }
# tinyflows — host-agnostic workflow engine (typed node graph → validate → compile →
# run on tinyagents). Powers the "Workflows" feature via the seam in
# `src/openhuman/tinyflows/` + the `flows::` domain. Pulls tinyagents 2.1 transitively
# (same version OpenHuman uses directly, preserving one trait identity). Published
# on crates.io and patched below to the vendored submodule.
#
# `mock` feature: enables `tinyflows::caps::mock::mock_capabilities()` — the
# deterministic in-memory capability bundle the flows `dry_run_workflow` agent
# tool (Phase 5b) runs a *draft* graph against so the workflow-builder agent can
# self-verify a proposal without any real side effects (no real LLM/tool/HTTP/code).
#
# Optional: exclusive to the default-ON `flows` feature (#4797). A slim build
# without `flows` drops this crate and its `jaq-*` JSON-query stack entirely.
tinyflows = { version = "0.8", features = ["mock"], optional = true }
# The saved-flow catalog and its SQLite backend, split out of this crate's
# `flows::` domain so a second host storing workflows does not have to reinvent
# them. `tinyflows-catalog` is the model (flows, revisions, runs, drafts,
# suggestions, the n8n importer, the save/run safety predicates);
# `tinyflows-sqlite` is one storage backend for it plus the engine checkpointer.
#
# Neither is published, so both are path dependencies into the same vendored
# workspace `tinyflows` itself comes from — one checkout, one `tinyflows`
# package, one `WorkflowGraph` type. Optional and exclusive to `flows` for the
# same reason the engine is.
tinyflows-catalog = { path = "vendor/tinyflows/crates/tinyflows-catalog", optional = true }
tinyflows-sqlite = { path = "vendor/tinyflows/crates/tinyflows-sqlite", optional = true }
# The authoring copilot's words: the `workflow_builder` / `flow_discovery`
# standing archetypes and the turn brief that opens a builder turn. Harness-free
# by construction — it names no tool trait and no model client — so this host
# keeps only the wiring: the `Tool` impls, the agent registry entries, and the
# prompt assembly that appends its own runtime sections.
tinyflows-copilot = { path = "vendor/tinyflows/crates/tinyflows-copilot", optional = true }
# TinyAgents — Rust LLM orchestration framework (LangGraph/LangChain-style):
# durable state graphs, agent-loop harness, model/tool registries, REPL +
# `.rag` workflow language. openhuman's agent engine + orchestration run on this
# crate's primitives via the adapter seam in `src/openhuman/agent/tinyagents/` (issue
# #4249): every turn drives through the harness; the workflow phase DAG, team
# member runtime, parallel fan-out, and multi-stage delegation run on graphs.
# We wire openhuman's own Provider/Tool, not the removed bundled openai client.
#
# tinyagents was split into a workspace of focused crates (tinyhumansai/tinyagents
# commit 612ea5e "refactor: split tinyagents into focused crates" and follow-on
# work): there is no longer a single `tinyagents` package. openhuman now depends
# directly on the members it actually uses — `tinyagents-harness` (agent loop,
# tools, middleware), `tinyagents-graph` (durable state graphs), `tinyagents-language`
# (`.rag`), `tinyagents-registry` (capability/model registry), and
# `tinyagents-session` (durable session history + run ledger, previously gated
# behind this crate's own `sqlite` feature — it is its own always-on crate now).
# The `sqlite` feature is enabled on the harness/graph crates now that openhuman's
# direct rusqlite pin is aligned to 0.40, avoiding duplicate `links = "sqlite3"`
# native bindings. Durable graph checkpoints still use `SqlRunLedgerCheckpointer`
# until the migration re-points those rows to the crate checkpointer.
# The `repl` feature/`rhai` scripting engine no longer exists in the split crates
# (see the tinyagents-harness module list) — the comment that used to describe
# `tinyagents/repl` gating `rhai` in for `flows` builds is stale; `rhai` is pulled
# in by `flows`'s own dependency on the `rhai` crate directly, not through tinyagents.
# None of these crates can be dropped: 26+ domains consume tinyagents.
# `multimodal` is not optional here: `agent::multimodal` is kernel surface —
# web chat and the agent harness both resolve attachment markers on every turn
# — so the gate is on for every OpenHuman build. It costs the dependency graph
# nothing: `base64`, `flate2` and `sha2` are all already resolved in the kernel
# profile, so turning it on moves neither the package count nor the native
# build count that `scripts/check-kernel-floor.sh` ratchets.
#
# A large share of the old crate's re-exported surface (Message, ModelRequest/
# Response, ToolCall/ToolSchema, Usage, embeddings, hosted-provider plumbing)
# moved further upstream still, into `tinyinference` (vendored as a submodule
# of vendor/tinyagents at vendor/tinyagents/vendor/tinyinference) — declared
# below as its own path dependency for the same "one checkout, one type
# identity" reason `tinytools` is.
tinyagents-harness = { path = "vendor/tinyagents/crates/tinyagents-harness", features = [
"sqlite",
"multimodal",
] }
tinyagents-graph = { path = "vendor/tinyagents/crates/tinyagents-graph", features = [
"sqlite",
] }
tinyagents-language = { path = "vendor/tinyagents/crates/tinyagents-language" }
tinyagents-registry = { path = "vendor/tinyagents/crates/tinyagents-registry" }
tinyagents-session = { path = "vendor/tinyagents/crates/tinyagents-session" }
tinyinference = { path = "vendor/tinyagents/vendor/tinyinference/crates/tinyinference" }
# TinyTools — the tool vocabulary: the `Tool` trait, `ToolResult`, and the
# permission / scope / timeout classifications this host enforces around a call.
#
# Reached through tinyagents' own vendored checkout **on purpose**, not through
# a second `vendor/tinytools` submodule of our own. Two path dependencies on
# the same repository are two distinct packages to cargo, and
# `tinytools::ToolResult` from one would not be the same type as from the
# other — every tool in this crate would stop satisfying the harness's trait,
# with a type error that names the same path twice. tinyagents declares
# `vendor/tinytools/crates/tinytools` relative to itself, so naming that exact
# path here resolves to one package.
#
# No `[patch.crates-io]` entry: the crate is not published, so the path is the
# whole address — the same arrangement as `tinyhumans-sdk` and the `-bus`
# crates. After cloning: `git submodule update --init --recursive vendor/`.
tinytools = { path = "vendor/tinyagents/vendor/tinytools/crates/tinytools" }
# TinyCortex — Rust core for the memory engine (store/chunks/tree/retrieval/
# queue/ingest/score + long tail), vendored as a git submodule and patched
# below to `vendor/tinycortex`. OpenHuman's memory subsystem migrates onto this
# crate through the adapter seam in `src/openhuman/tinycortex/` (mirroring the
# tinyagents seam): engine logic (including provider sync pipelines) in the
# crate; RPC, agent tools, sync scheduling/credentials/events, security gating,
# and the global singleton stay host-side. rusqlite is aligned to the host pin
# (=0.40) so one bundled SQLite links. The submodule intentionally tracks
# reviewed upstream main commits; keep this semver requirement compatible with
# the vendored crate version.
# `git-diff` and `wiki-git` are NOT here, and there is no longer a gate that
# turns them on: the `memory-git` feature and the `memory::diff` RPC/tool
# surface it guarded were deleted, taking the git2/libgit2-sys/libz-sys cohort
# out of every configuration. tinycortex remains the sole libgit2 link in the
# graph, and nothing in this crate enables it. Everything else tinycortex needs
# is unconditional.
# `tinycortex` has left the product build (openhuman#5560). The engine still
# runs — inside the prebuilt `tinymemory` TinyBus module, which links it and
# enables its `contacts` feature for the macOS address-book reader. This host
# reaches all of it through `tinymemory-api` over the bus.
#
# It is `optional` rather than deleted for one reason only: the two
# `library_profile` bins measure the in-process engine and a `[[bin]]` cannot
# use a dev-dependency, so `rss-bench` turns it on. `rss-bench` is NOT in
# `scripts/ci/product-features.txt`, so nothing shipped enables it. Every test
# that names the crate is served by the [dev-dependencies] entry instead.
#
# Its `[patch]` entry below stays, and that is not the same decision. Dropping
# the direct dependency and dropping the patch are different things: the crate
# is unpublished, and the engine crates still reached as [dev-dependencies]
# name it by version requirement, so removing the patch fails *resolution* with
# "no matching package named `tinycortex-api` found" long before anything is
# compiled.
tinycortex = { version = "0.1", optional = true, features = [
"obsidian",
"persona",
"sync",
] }
# The memory *contract* — value types, the thirteen capability families, the
# `MemoryProvider` driver trait, and the null reference driver. A direct path
# dependency rather than a re-export, because `tinycortex::memory` aliases back
# only `{error, traits, types}`; `capabilities`, `provider`, `null`, `health`,
# `recall`, and `version` are reachable only through the api crate itself.
# Deliberately dependency-light (no rusqlite/git2/reqwest/regex/async runtime)
# so a third-party driver can compile against the contract without pulling in
# the embedded engine. No `[patch.crates-io]` entry is needed: cargo unifies
# this with the `path = "api"` dependency the engine crate already declares.
# `tinycortex-api` is gone with it. It had become a deprecated re-export of
# `tinymemory-bus`, so its one host use (`goals::GoalsDoc`) resolves to the
# identical item through the contract. Its `[patch]` entry stays too, for the
# reason given above.
# tinymemory — the engine-neutral memory layer
# (https://github.com/tinyhumansai/tinymemory). Owns the parts of the memory
# subsystem that are true for *any* engine: the driver-admission rules
# (`tinymemory::registry`) and the three mandatory capability families composed
# over the `Memory` storage trait (`tinymemory::mandatory`). TinyCortex stays
# the engine; this is the layer a second engine would enter through.
#
# Vendored as a git submodule under `vendor/` beside the other tiny* crates and
# consumed by path: the crate is not published to crates.io, so there is no
# `[patch.crates-io]` entry for it, and for the same reason
# `app/src-tauri/Cargo.toml` needs no `../../` twin — an unpublished path
# dependency resolves transitively through this manifest.
#
# `tinymemory-tinycortex` is the seam between TinyCortex's contract types and
# TinyMemory's. It names `tinycortex` by version requirement, so the
# `[patch.crates-io]` entry below unifies it onto *this* checkout's engine
# rather than the one pinned inside the tinymemory submodule.
#
# After cloning: `git submodule update --init --recursive vendor/tinymemory`.
# tinyruntime — the runtime router
# (https://github.com/tinyhumansai/tinyruntime). Only the *contract* crate is
# taken here, never the router itself: the router ships as a loadable TinyBus
# module, and a host that also compiled it would carry the download pipeline, the
# worker pool, and their dependency trees for nothing.
#
# `tinyruntime-bus` is deliberately dependency-light — `serde` and `serde_json`
# and nothing else — which is what makes naming the payload types cost this
# manifest almost nothing. The module's own CI asserts it stays that way.
#
# After cloning: `git submodule update --init --recursive vendor/tinyruntime`.
tinyruntime-bus = { path = "vendor/tinyruntime/crates/tinyruntime-bus" }
# The `tinymemory` facade is gone: no file in `src/` ever named it. It was
# kept for driver admission, but `memory::binding::admit` is pure string
# matching against `MODULE_ID` and refuses `DriverClass::Embedded` outright,
# so nothing here resolves an engine through the facade's registry.
tinymemory-api = { path = "vendor/tinymemory/crates/tinymemory-api" }
# tinyconnectors-bus — the OAuth connector wire contract
# (https://github.com/tinyhumansai/tinyconnectors). Payload types and member
# names for the connector surface, with no transport and no behaviour: this
# crate makes calls into the loaded `tinyconnectors` module and compiles none
# of it.
#
# These types previously came from `tinymemory-api::host::composio`, which held
# them only because two crates needed to name them and there was nowhere else
# both could. That is what this dependency fixes — one definition, owned by the
# crate that produces the shapes.
tinyconnectors-bus = { path = "vendor/tinyconnectors/crates/tinyconnectors-bus" }
# tinymemory-bus is the wire contract (method names, ABI). Normally transitive
# through tinymemory-api, but modules/memory.rs names the method constants
# directly (EXTRACT_ENTITIES, EMBED_TEXT, EMBEDDER_SLUG) — prefer compile
# errors on renaming over MemberNotFound at runtime.
tinymemory-bus = { path = "vendor/tinymemory/crates/tinymemory-bus" }
# DONE 2026-08-31, and the measurement that forced it is worth keeping, because
# it is the trap anyone auditing a shed here will fall into next.
#
# This entry had **no production consumer** — every `tinymemory_tinycortex::`
# reference in the tree is test code (`memory::test_support`,
# `agent::harness::archivist_tests`, `tests/raw_coverage/`) — yet it was a
# **second, independent normal edge onto `tinymemory-core`**: `cargo tree -e
# normal -i tinymemory-core` reported two parents, `openhuman` and this crate.
# Dropping the `tinymemory-core` entry alone would therefore NOT have taken the
# engine out of the shipped graph; this line would still have pulled it. Both
# halves had to move together, and they did.
#
# The general lesson, which the `rss-bench` comment further down states from the
# other direction: **a manifest that reads correctly is not a shed.** Verify with
# `cargo tree -e normal -i <crate>` under the product feature set — it prints
# "nothing to print" when a crate is genuinely gone.
# `tinymemory-tinycortex` is a dev-dependency now (see [dev-dependencies]).
# Its only host uses are the test fixtures that stand up an in-process engine,
# and cargo does not link dev-dependency features into the shipped binary —
# the same precedent the root `tinywallet` crate already sets.
# `tinymemory-core` is the *substance* of the memory subsystem, extracted out of
# `src/openhuman/memory/` — the SQLite/vector store, the markdown summary tree,
# the provider sync pipelines, ingestion, recall/query/search, the ingest queue,
# conversations, people, goals and the tool-memory rules.
#
# What deliberately stayed behind in `src/openhuman/memory/` is the *host layer*
# per the tinymemory README split: the RPC surface (`schemas/`, `read_rpc/`),
# agent tools (`tools/`), the security/taint guard (`guard/`), the driver
# binding (`driver/`), the memory agent, and the config mapping. Those reach
# into this crate; this crate never names an OpenHuman type. Everything it needs
# from the host arrives through the seam traits in `tinymemory_api::host`, whose
# implementations live in `src/openhuman/memory/host.rs`.
#
# The `schemars` feature is enabled because the memory config *section* structs
# (`MemoryConfig`, `MemoryTreeConfig`, …) now live in `tinymemory_api::host` and
# are still fields of OpenHuman's `Config`, which derives `JsonSchema`.
# `tinymemory-core` is optional and reached only by `rss-bench`, which is NOT
# in `scripts/ci/product-features.txt` — so it is absent from the shipped
# build. It is `optional` rather than dev-only because the two
# `library_profile` bins need it and a bin target cannot use a
# dev-dependency; every test is served by the [dev-dependencies] entry below.
tinymemory-core = { path = "vendor/tinymemory/crates/tinymemory-core", optional = true }
# `tinymemory-sources` is the source registry, its types and its readers, in a
# crate of its own. Taken directly rather than through `tinymemory-core`
# (OpenHuman#5560): `tinymemory_core::sources` is a thin layer over it —
# `sources::types` is already a `pub use` of this crate, and `sources::registry`
# is "the host's config path plus a write lock" around a `SourceRegistry` over
# the host's own `sources.toml`. The host owns that file; it does not need the
# engine to read it.
#
# It costs this crate no new dependency: serde, schemars, serde_json, anyhow,
# `tinymemory-api`, async-trait, walkdir, toml and uuid are all already here,
# and `network` adds reqwest / futures / tracing / chrono / tokio, which are
# too. No `rusqlite`, no `tinycortex`.
#
# `network` matches what `tinymemory-core` enables, so the GitHub / RSS /
# web-page readers exist. Their dispatch is deliberately NOT `reader_for` —
# see that module's docs and `memory::sources`'s.
tinymemory-sources = { path = "vendor/tinymemory/crates/tinymemory-sources", features = [
"network",
] }
# tinymcp — the Model Context Protocol client, extracted out of this tree
# (https://github.com/tinyhumansai/tinymcp). Owns both transports, the static
# config-declared server set, the dynamic registry with its store, supervisor
# and OAuth, and the write-audit log. What stays here is the host half: the RPC
# surface, the agent-facing tools, and the prompt-injection scan over remote
# tool definitions, which is host policy.
#
# `tinymcp-bus` is the wire contract — payload types and member names, with no
# transport and no runtime. The `schemars` feature is on because this crate
# generates a settings schema for the desktop application from those types
# rather than from a hand-kept copy.
#
# The path dependency on `tinymcp` itself is still the step-one arrangement. The
# registry entry step two calls for now exists — `src/openhuman/modules/registry.rs`
# pins the v0.3.2 release — but the host still calls the library directly, because
# `tinymcp-bus` v0.3.2 does not yet publish everything this host reaches for:
# `OAuthComplete`, a member returning the already-exported `ConnectedServerOverview`,
# the boot-connect and reconnect-supervisor passes, the `ServerDetail` /
# `AuthDetection` / `AuthKind` reply types, the registry curation helpers, an error
# anchor for the `McpServerNeedsAuth` classifier coupling test, and
# `render_tool_result` / `redact_endpoint` for the ungated `gitbooks` tool. It also
# needs a per-`data_dir` object seam of the shape `modules::memory` already uses,
# since `mcp::host` keys one store per workspace and a module gets one `data_dir` at
# load. Those are upstream work in tinyhumansai/tinymcp.
#
# Correcting what this comment used to promise: dropping the path dependency does
# NOT take reqwest/rusqlite with it. Measured in the kernel profile, `rusqlite` has
# six parents and `reqwest` ten, so `scripts/dep-sim.py --cut tinymcp` projects the
# entire shed at -1 package / -1 name / 0 native builds — the `tinymcp` package and
# nothing beneath it. The boundary buys compilation isolation, not a dependency shed.
#
# After cloning: `git submodule update --init vendor/tinymcp`.
# `default-features = false` drops the TinyBus adapter: this build calls the
# library directly and has no use for a bus inside it.
tinymcp = { path = "vendor/tinymcp/crates/tinymcp", default-features = false, features = [
"rustls-tls",
] }
tinymcp-bus = { path = "vendor/tinymcp/crates/tinymcp-bus", features = ["schemars"] }
# The transport-free channel vocabulary: inbound envelopes, outbound intents,
# the config schema, controller metadata, relay frames and the session-key
# rules. UNCONDITIONAL, and deliberately so — `DomainEvent` embeds
# `ChannelInboundEnvelope`, `config/schema/channels.rs` re-exports the config
# types and `security/pairing.rs` re-exports the pairing helpers, so this
# vocabulary is always-on kernel surface. It costs serde/schemars and nothing
# this build did not already have.
tinychannels-bus = { version = "0.1", path = "vendor/tinychannels/crates/tinychannels-bus" }
# The provider stack that IMPLEMENTS that vocabulary — Telegram, Discord,
# Slack, IMAP, WhatsApp, the relay transport loop. Optional: it owns the
# `reqwest` / `rusqlite` / `rustls` / `tokio-tungstenite` cohort, which a
# workflow-only build has no use for. Enabled by `channels`, and by `voice`
# for `EmailChannel` alone.
tinychannels = { version = "0.1", features = ["relay-websocket"], optional = true }
# tinybus — the message bus. Owns what `src/core/event_bus/` used to: the typed
# pub/sub surface (`EventBus`, `EventHandler`, `SubscriptionHandle`), the
# in-process zero-serialization request registry (`NativeRegistry`), and peer
# version negotiation. Vendored as a git submodule beside the other tiny*
# crates and consumed by path.
#
# `DomainEvent` stays here, in `src/core/events.rs`: the catalog is OpenHuman's
# own vocabulary and a generic bus crate must not know it. tinybus is generic
# over the event type and `DomainEvent` implements `tinybus::Event`.
#
# After cloning: `git submodule update --init vendor/tinybus`.
# `uds` is on so the kernel can join a broker that out-of-process integrations
# are already attached to (`core::bus::init_over_socket`). `cli` is not: the
# `tinybus` binary is a developer tool, not something the kernel links.
#
# The dynamic module loader is NOT enabled here. It arrives through this
# crate's own default-ON `modules` feature, which forwards `tinybus/modules`.
# Enabling it unconditionally would put a `dlopen` loader in the kernel
# profile — `tinybus` is always-on surface, so `--no-default-features
# --features flows` would carry `ureq` and the archive stack for a host that
# never loads a module. The kernel-floor ratchet catches exactly that, and did.
tinybus = { path = "vendor/tinybus/crates/tinybus", default-features = false, features = ["macros", "uds"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_repr = "0.1"
serde_yaml = "0.9"
# dhat — heap profiler for the offline `library-profile` benchmark binary only.
# Default-OFF, dev-only: pulled in solely by the `rss-bench-dhat` feature so it
# never enters the shipped desktop/library build (same posture as `rss-bench`).
dhat = { version = "0.3", optional = true }
# (Removed `html2md` dep. dhat-rs profiling on real Gmail inboxes
# showed `html2md::walk` and `html2md::tables::handle` allocating
# ~894 MB peak heap on a 10 KB HTML input from Otter.ai-style emails
# (deeply-nested table-as-layout HTML). Cause: recursive walker holding
# per-frame Vec state across nesting layers + 5 sequential
# `regex::replace_all` passes in `clean_markdown` each producing a
# fresh full-size String. We now use a linear-time tag-and-entity
# stripper (`fast_html_to_text` in
# providers/gmail/post_process.rs) and prefer the email's
# `text/plain` MIME part when available.)
# TLS: rustls only in the base declaration, so Linux/macOS — including the
# headless embedding target (#5046) — link a single TLS stack + cert set
# (Mozilla webpki-roots). Windows re-adds `native-tls` via the
# `[target.'cfg(windows)'.dependencies]` block below (Cargo unions features
# per target), because `src/openhuman/tls/mod.rs` deliberately routes the
# Windows client through the SChannel/OS cert store for corporate MITM +
# AV root CAs. So the two TLS backends coexist only on Windows, never on
# the RAM-sensitive platforms.
reqwest = { version = "0.12", default-features = false, features = ["json", "blocking", "rustls-tls", "stream", "http2", "multipart", "socks"] }
# Already in-tree via reqwest/hyper; named directly so `IntegrationClient::get_bytes`
# can return `bytes::Bytes` without a copy.
bytes = "1"
tokio = { version = "1", features = ["full"] }
once_cell = "1.19"
parking_lot = "0.12"
log = "0.4"
libc = "0.2"
nu-ansi-term = "0.46"
env_logger = { version = "0.11", optional = true }
base64 = "0.22"
aes-gcm = "0.10"
argon2 = "0.5"
rand = "0.10"
dirs = "5"
sha2 = "0.10"
# NO `git2` HERE, DELIBERATELY — do not add it back. Every use of libgit2 in
# the memory stack lives in tinycortex: the diff ledger, the wiki mirror
# (`memory::store::content::wiki_git`), and the persona git-history reader.
# This crate never touches a repository itself, so a direct dependency here
# would be a declaration with no `use` behind it. It also invites a second
# major pin, and `git2` sets `links = "git2"` — two majors in one graph is a
# hard cargo error, not a warning. Nothing here now enables tinycortex's
# `git-diff` / `wiki-git` features either, so libgit2 is out of the graph
# entirely; re-adding a gate for it means re-adding the cohort.
hmac = "0.12"
# Archive handling for the Piper voice installer and the document tools. The
# Node.js and Python toolchain archives are no longer unpacked here — the
# `tinyruntime` module owns that — which is what let `xz2` and its static
# liblzma C build leave this manifest entirely.
tar = "0.4"
zip = { version = "2", default-features = false, features = ["deflate"] }
# gzip decoder for the Piper tar.gz binary releases on macOS / Linux. Already
# pulled in transitively by zip's `deflate` feature; declared directly so
# the installer module can `use flate2::read::GzDecoder`.
flate2 = "1"
# Real timeout around a blocking child wait, for the Claude Code auth probe.
# Guards against a broken binary on PATH hanging the caller forever.
wait-timeout = "0.2"
uuid = { version = "1", features = ["v4"] }
anyhow = "1.0"
async-trait = "0.1"
chacha20poly1305 = "0.10"
# Wipe master keys / decrypted secret buffers from memory on drop (audit C9).
# Already present transitively (resolved to 1.8.x via the *-dalek / cipher
# crates); declared directly so the keyring module can `use zeroize::Zeroizing`.
zeroize = "1"
x25519-dalek = { version = "2", features = ["static_secrets"] }
hkdf = "0.12"
hex = "0.4"
tokio-util = { version = "0.7", features = ["rt", "io"] }
# tokio-tungstenite is declared per-target below so the TLS backend
# (native-tls on Windows, rustls on macOS / Linux) matches the reqwest
# backend selected at each TLS call site.
futures = "0.3"
rusqlite = { version = "=0.40.2", features = ["bundled"] }
chrono = { version = "0.4", features = ["serde"] }
iana-time-zone = "0.1"
cron = "0.12"
futures-util = "0.3"
directories = "6"
toml = "1.0"
schemars = "1.2"
tracing = { version = "0.1", default-features = false }
tracing-log = { version = "0.2", optional = true }
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter"] }
tracing-appender = { version = "0.2", optional = true }
urlencoding = "2.1"
motosan-ai-oauth = { version = "0.2", features = ["codex"] }
thiserror = "2.0"
chrono-tz = "0.10"
dotenvy = "0.15"
regex = "1.10"
# Multi-pattern fixed-string DFA matcher used by `routing::quality` for
# refusal/empty-noise detection on local-model responses. Already in the
# dep graph transitively via `regex` (which uses it for literal
# optimization); declared directly here so `openhuman` owns the
# version pin and the import isn't an unstable transitive surface.
aho-corasick = "1.1"
walkdir = "2"
glob = "0.3"
hostname = "0.4.2"
rustls = { version = "0.23", default-features = false, features = ["ring"] }
sysinfo = { version = "0.33", default-features = false, features = ["system"] }
keyring = { version = "3", features = ["apple-native", "windows-native", "linux-native"] }
clap = { version = "4.5", features = ["derive"], optional = true }
lettre = { version = "0.11.22", default-features = false, features = ["builder", "smtp-transport", "rustls-tls"], optional = true }
# HTTP + Socket.IO server transport — the `/rpc` JSON-RPC endpoint, `/v1`
# OpenAI-compat router, agentbox/http_host sub-servers, and the Socket.IO
# live-event bridge. Exclusive to the default-ON `http-server` feature (#5048):
# a slim/embedded build without it (`--no-default-features`) sheds `axum` +
# `socketioxide` and never binds a listener — the core still runs background
# services and answers over the CLI/native dispatch surface. See the
# `http-server` feature note below and `src/core/http_server_status.rs`.
axum = { version = "0.8", default-features = false, features = ["http1", "json", "tokio", "query", "ws", "macros"], optional = true }
sentry = { version = "0.47.0", default-features = false, optional = true, features = ["backtrace", "contexts", "panic", "tracing", "debug-images", "httpdate"] }
tokio-stream = { version = "0.1.18", default-features = false, features = ["sync"] }
url = "2"
socketioxide = { version = "0.15", features = ["extensions"], optional = true }
tempfile = "3"
cpal = { version = "0.15", optional = true }
enigo = { version = "0.3", optional = true }
arboard = { version = "3", optional = true }
rdev = { version = "0.5", optional = true }
fs2 = "0.4"
# Cross-platform battery probe for the scheduler gate. Maintained fork of
# the abandoned `battery` crate; same `use battery::*;` API surface. Used
# only by `openhuman::scheduler_gate::signals` to decide when to throttle
# background LLM work on laptops.
starship-battery = { version = "0.10", optional = true }
# Multi-chain wallet signing.
# - bitcoin: P2WPKH PSBT build/sign/broadcast (includes secp256k1).
# - ed25519-dalek: Solana transaction signing.
# - bs58: Solana base58 addresses + Tron base58check addresses.
ed25519-dalek = { version = "2", default-features = false, features = ["std", "rand_core"] }
bs58 = { version = "0.5", default-features = false, features = ["std", "check"] }
# Shared BIP-39 mnemonic → seed for non-EVM chains (BTC P2WPKH derivation,
# Tron secp256k1 derivation, Solana ed25519 SLIP-0010 derivation). Same crate
# ethers-signers uses internally, exposed as a direct dep so we can derive
# off the recovery phrase without going through the EVM signer wrapper.
coins-bip39 = { version = "0.8", optional = true }
# Solana off-curve check for ATA derivation (find_program_address).
curve25519-dalek = { version = "4", default-features = false, features = ["alloc"], optional = true }
fantoccini = { version = "0.22.0", optional = true, default-features = false, features = ["rustls-tls"] }
# The WhatsApp Web provider (and its `whatsapp-rust` / `wacore` / `serde-big-array`
# stack) now lives in the tinychannels crate; the `whatsapp-web` feature forwards
# to `tinychannels/whatsapp-web`.
# Terminal chat UI (`openhuman tui` / `chat`). Exclusive to the default-ON
# `tui` feature (see `[features]` below): a slim / headless build without `tui`
# drops both `ratatui` and `crossterm`. Kept in lockstep — ratatui 0.30
# re-exports crossterm 0.29, so declaring crossterm directly at the same major
# unifies to a single crossterm in the dep graph. Only compiled into
# `src/tui/` behind `#[cfg(feature = "tui")]`.
ratatui = { version = "0.30", optional = true }
crossterm = { version = "0.29", optional = true }
# Terminal column-width measurement for the `tui` chat renderer
# (`src/tui/render.rs`); only compiled behind `#[cfg(feature = "tui")]`.
unicode-width = { version = "0.2", optional = true }
# TinyDocs — the document wire contract, and nothing else.
#
# `tinydocs-bus` is the whole dependency: the spec types, their size limits,
# the validation rules, the PNG/JPEG header reader, the error vocabulary and
# the member names. It is `serde` + `thiserror` and nothing else — no writer,
# no `tinybus`, no runtime. Synthesis happens in the `tinydocs` TinyBus module
# (`src/openhuman/modules/`), so this build carries the shape of a document
# without carrying the code that produces one, which is why `docx-rs`,
# `ppt-rs` and `pdf-extract` are absent from the graph entirely rather than
# merely gated.
#
# Sharing the contract rather than re-declaring it is the point. The specs are
# what an LLM is shown as a JSON tool schema and what the module validates
# against; two definitions of that would drift, and the drift would be a tool
# description promising limits the module does not enforce. This crate carried
# a verbatim copy of the contract for exactly that reason and paid exactly that
# risk — `src/openhuman/tools/impl/document/format/` was 1,873 lines that
# differed from `crates/tinydocs-bus/src/` only in doc-link paths.
#
# Vendored as a path dependency like `tinyhumans-sdk`: the crate is not
# published to crates.io, so there is no `[patch.crates-io]` entry for it.
# After cloning: `git submodule update --init vendor/tinydocs`.
#
# Optional: exclusive to the `documents` feature, which is **default-OFF,
# product-ON** — `[features] default` is the contributor set and this is not in
# it; `scripts/ci/product-features.txt` is what the shipped desktop app has, and
# it is. The comment here said "default-ON", which was true before #4919 split
# the two sets and has been wrong since.
tinydocs-bus = { path = "vendor/tinydocs/crates/tinydocs-bus", optional = true }
# TinyVoice — the voice wire contract, and nothing else.
#
# Same arrangement as `tinydocs-bus`: member names, the payload types the
# module answers with, and the contract version, at a cost of `serde`. The
# processing lives in the `tinyvoice` TinyBus module, so nothing here decodes
# audio. `src/openhuman/modules/voice.rs` used to redeclare these types with a
# comment saying it did so because this crate did not depend on TinyVoice;
# it does now.
#
# After cloning: `git submodule update --init vendor/tinyvoice`.
#
# Optional: exclusive to the `voice` feature — default-OFF, product-ON, the
# same split as `documents` above.
tinyvoice-bus = { path = "vendor/tinyvoice/crates/tinyvoice-bus", optional = true }
# TinyJuice — the compression wire contract, and nothing else.
#
# Same arrangement as `tinydocs-bus` and `tinyvoice-bus`: the payload types, the
# request and response envelopes, the member names and the contract version, at
# a cost of `serde`. The router, the compressors, the CCR cache and the rule
# engine all live in the `tinyjuice` module and are not in this build.
#
# `src/openhuman/inference/tokenjuice/types.rs` was a 259-line hand-copy of
# these types headed "Stable wire types shared with the separately compiled
# TinyJuice module" — shared by convention and checked by nobody. It is a
# re-export now.
#
# Not optional: `inference::tokenjuice` is always compiled (the compression
# middleware sits in the agent turn path, which is kernel), so the contract has
# no gate to hang off.
#
# After cloning: `git submodule update --init vendor/tinyjuice`.
tinyjuice-bus = { path = "vendor/tinyjuice/crates/tinyjuice-bus" }
# TinyHosts — the unified hosting API: one `Host` trait over a hosting provider,
# and the `launch` flow that puts a Next.js application, its database, its
# environment and its domains on it in the one order that works.
#
# The provider vocabulary stops inside the crate. What OpenHuman gets is the
# model — sites, deployments, databases, domains, analytics — so which provider
# a user pastes a key for is a config value here rather than a code path.
#
# Taken with the `vercel` provider only, which is the one that exists.
#
# Vendored as a path dependency like `tinyhumans-sdk`: the crate is not
# published to crates.io, so there is no `[patch.crates-io]` entry for it.
# After cloning: `git submodule update --init vendor/tinyhosts`.
#
# Optional: exclusive to the default-OFF `hosting` feature.
tinyhosts = { path = "vendor/tinyhosts", default-features = false, features = ["vercel"], optional = true }
# TinyWallet — host-agnostic multi-chain wallet primitives. Owns the address
# formats themselves: parsing, validation, and the conversions between their
# encodings for Bitcoin, EVM chains, Solana and Tron. Nothing about "is this a
# well-formed Solana address" is OpenHuman-specific, so the rules live where
# any host can reach them. What stays in `src/openhuman/web3/` is everything
# the crate deliberately refuses to own: RPC endpoint resolution, transaction
# assembly and broadcast, and key custody.
#
# Vendored as a path dependency like `tinyhumans-sdk`: the crate is not
# published to crates.io, so there is no `[patch.crates-io]` entry for it.
# After cloning: `git submodule update --init vendor/tinywallet`.
#
# Optional: exclusive to the `web3` feature — OFF in the contributor set
# (`[features] default`) and ON in the product set
# (`scripts/ci/product-features.txt`), so it ships but a bare `cargo check` does
# not pay for it. See the two-set note above `default`.
#
# Taken as `tinywallet-bus`, the contract crate, and NOT the root `tinywallet`
# crate. The root crate is where key derivation, transaction building, signing
# and the chain clients live, and those are the gates that pull the `bitcoin`
# crate and its native secp256k1 build; all of it happens inside the loaded
# `tinywallet` module now, so this binary links none of it. What the contract
# crate carries is exactly what a host still runs itself: the wire types that
# cross the bus, the bus member names, address validation, the EIP-712 and ERC-20
# encoders the x402 payment path builds with, the `Transport` seam this crate
# implements, and the Tron verifier that checks what a node handed back before
# a transaction is sent for signing.
#
# The root crate is still taken under [dev-dependencies], where test fixtures
# derive a known account. Dev-dependency features are not linked into the
# shipped binary, so that does not undo the shed.
tinywallet-bus = { path = "vendor/tinywallet/crates/tinywallet-bus", default-features = false, features = ["btc", "evm", "solana", "tron", "keccak", "net", "wire", "eip712", "abi", "tx-codec"], optional = true }
# secp256k1 signing over the digests the wallet module hands back. Pure Rust,
# and already in the graph beneath `coins-bip32` (which derives the key being
# used, via tinywallet's `key` gate), so naming it directly costs nothing and
# is what lets `bitcoin` go.
k256 = { version = "0.13", default-features = false, features = ["std", "ecdsa"], optional = true }
[target.'cfg(windows)'.dependencies]
# Windows: tokio-tungstenite uses native-tls (schannel) so wss://
# connections honor the Windows cert store, including corporate CAs
# installed by AV / TLS-inspection proxies. See run-dev-win.sh notes.
tokio-tungstenite = { version = "0.29", default-features = false, features = ["connect", "handshake", "native-tls"] }
# Windows re-adds reqwest's native-tls backend (dropped from the base decl in
# `[dependencies]`) so `tls::tls_client_builder()` can call `.use_native_tls()`
# and reach the SChannel/OS cert store — same rationale as tokio-tungstenite
# above. Cargo unions these features with the base rustls decl, so on Windows
# reqwest carries both backends; Linux/macOS keep rustls only.
reqwest = { version = "0.12", default-features = false, features = ["native-tls"] }
# AppContainer / process-jail backend in `openhuman::cwd_jail`.
# Feature list mirrors the Win32 surface used by cwd_jail/windows.rs:
# AppContainer profile APIs, ACL editing, STARTUPINFOEXW process spawn,
# and the GENERIC_* file access masks.
windows-sys = { version = "0.61", features = [
"Win32_Foundation",
"Win32_Security",
"Win32_Security_Authorization",
"Win32_Security_Isolation",
"Win32_Storage_FileSystem",
"Win32_System_Memory",
"Win32_System_Threading",
] }
[target.'cfg(not(windows))'.dependencies]
# macOS / Linux: keep rustls + Mozilla webpki-roots — the historical
# default. Avoids pulling OpenSSL as a runtime dep on Linux.
tokio-tungstenite = { version = "0.29", default-features = false, features = ["connect", "handshake", "rustls-tls-webpki-roots"] }
[target.'cfg(target_os = "linux")'.dependencies]
landlock = { version = "0.4", optional = true }
rppal = { version = "0.22", optional = true }
[dev-dependencies]
# Turns on `tinyflows-sqlite`'s `test-fixtures` gate for test builds only: the
# flows test suite stages a terminal run flipped back to `running` and a
# `graph_json` column that does not deserialize, neither of which any production
# write path can produce. Declared here rather than in `[dependencies]` so the
# shipped binary never carries those two writers.
tinyflows-sqlite = { path = "vendor/tinyflows/crates/tinyflows-sqlite", features = ["test-fixtures"] }
# Test fixtures derive a known account from the BIP-39 vector phrase. Production
# does not derive at all — see the note on the main `tinywallet` entry. Cargo
# does not link dev-dependency features into the shipped binary, so enabling
# `key` here does not put the derivation stack back into the product.
tinywallet = { path = "vendor/tinywallet", default-features = false, features = ["key", "btc", "evm", "solana", "tron"] }
k256 = { version = "0.13", default-features = false, features = ["std", "ecdsa"] }
coins-bip39 = { version = "0.8" }
# The host's own tests drive `tinymemory-core`'s test helpers
# (`chat::test_override`, `StaticChatProvider`, `tool_memory::test_helpers`).
# They were `#[cfg(test)]` items in this crate before the memory extraction; a
# downstream test harness cannot see those across a crate boundary, so the
# extracted crate exposes them behind `test-support` instead.
tinymemory-core = { path = "vendor/tinymemory/crates/tinymemory-core", features = ["test-support"] }
# `tinycortex` itself, for the ~11 test files that name it directly —
# `memory::read_rpc`, the sync-pipeline and tree e2e suites, the archivist and
# session suites, the composio user-scope tests. They reach engine-internal
# canonicalisation and sync-state items (`memory::ingest::canonicalize::chat`,
# `memory::sync::state::STATE_NAMESPACE`, `memory::tree::runtime`) that no
# contract family exposes. The normal entry above is `optional` and off outside
# `rss-bench`, so this is what keeps the crate available to `cargo test` — and
# cargo does not link dev-dependency features into the shipped binary, which is
# the whole point of the split.
tinycortex = { version = "0.1", features = ["obsidian", "persona", "sync"] }
# `tinymemory-tinycortex` moved here from `[dependencies]` (#5560). It is the
# adapter between TinyCortex's contract types and TinyMemory's, and every
# surviving host use of it is a test fixture standing up an in-process engine —
# `memory::test_support`, `memory::ops::test_support` and the archivist /
# session suites. Cargo does not link dev-dependency features into the shipped
# binary, so this keeps the adapter (and the `tinycortex` it names by version
# requirement) out of the product while the tests that need a real engine keep
# working.
tinymemory-tinycortex = { path = "vendor/tinymemory/crates/tinymemory-tinycortex" }
# Dual-declared on purpose (same shape as the `sentry`/`axum` entries): the
# optional dependency above is bin-only behind `bin-tools`, but
# `agent_orchestration::tools::tools_e2e_tests` (a #[cfg(test)] LIB module),
# `tests/memory_graph_sync_e2e.rs`, `tests/x402_twit_sh_live.rs` and
# `examples/embed_headless.rs` all call it with no feature #[cfg]. Without this
# line the test build breaks the moment `bin-tools` is off.
env_logger = "0.11"
# Enable sentry's TestTransport for runtime smoke of the observability
# before_send filter (see tests/observability_smoke.rs). `default-features
# = false` here is load-bearing — sentry's default feature set pulls in
# actix-web / actix-http / actix-server / sentry-actix and ~13 transitive
# crates we never use (and that bloat the dev Cargo.lock noticeably).
# TestTransport only needs the `test` feature.
sentry = { version = "0.47.0", default-features = false, features = ["test"] }
# axum is optional in `[dependencies]` (exclusive to the default-ON
# `http-server` feature, #5048), but ~17 `#[cfg(test)]` modules stand up
# in-process axum mock servers / call `build_core_http_router` regardless of
# the feature set under test. Declaring a plain (non-optional) dev-dep keeps
# those tests compiling in ALL test builds without per-file `#[cfg]` — mirrors
# the `sentry` dual-declaration above. The prod fns those tests exercise are
# still gated, so the *tests* naming them carry `#[cfg(feature = "http-server")]`.
axum = { version = "0.8", default-features = false, features = ["http1", "json", "tokio", "query", "ws", "macros"] }
# `tower` was a plain runtime dep only for its re-exports in the axum server
# path; with `http-server` optional it is test-only (tower::ServiceExt::oneshot
# drives the mock routers), so it lives here as a dev-dep now.
tower = { version = "0.5", default-features = false }
# Mock HTTP server for provider E2E tests (inference_provider_e2e).
wiremock = "0.6"
# Used in json_rpc_e2e to backdate mtime on stale lock files.
filetime = "0.2"
# `test-util` enables tokio's paused virtual clock (`start_paused`,
# `time::advance`) so the #4270 inference-heartbeat tests assert the periodic
# beat without real-time waits. Test-only — the runtime feature set in
# `[dependencies]` (`full`) intentionally excludes it.
tokio = { version = "1", features = ["test-util"] }
# Property-based testing for the adversarial-input surfaces (command classifier,
# encryption round-trip) — plan.md §6.3. Version already resolved in Cargo.lock.
proptest = "1"
[features]
# THE CONTRIBUTOR SET — not the product set.
#
# This list is what a bare `cargo check`, `cargo test` and rust-analyzer
# compile. It is deliberately SMALLER than what the desktop app ships: the
# product set lives in `scripts/ci/product-features.txt` and is forwarded
# explicitly by `app/src-tauri/Cargo.toml`, with
# `scripts/ci/check-feature-forwarding.mjs` asserting the two are equal in both
# directions. Read that file's header before changing either list.
#
# Why the split: the gates left ON below cost almost nothing to compile, so
# keeping them on means `cargo check` and rust-analyzer still typecheck nearly
# all of the tree. The gates turned OFF are the ones that carry the graph —
# web3's ethers/secp256k1 cohort, `documents`' zstd/bzip2 native builds,
# `voice`+`inference`'s cpal/lettre/arboard/enigo/rdev stack, `contacts`'
# macOS objc2 cohort, `crash-reporting`'s sentry tree, and `tui`'s
# ratatui/crossterm. Turning them off takes a
# bare `cargo check` from 540 packages / 7 native builds down to ~350 / 2, which
# is the inner loop every contributor pays on every edit.
#
# THIS DOES NOT CHANGE WHAT SHIPS. The desktop shell has always set
# `default-features = false` (#1061), so it never inherited this list to begin
# with — that is exactly why the forwarding guard had to exist. What DOES
# change is that a lane relying on default features no longer covers the
# gated-off domains, so every CI lane that builds or tests "the product" now
# passes `--features "$(scripts/ci/product-features.sh)"`. If you add a lane,
# decide which of the two sets it is testing and say so.
# `modules` is in this list because the memory seam is not optional at test
# time. `memory::binding::module_provider` has a `#[cfg(not(feature =
# "modules"))]` arm that binds `NullMemoryProvider`, so without the gate a bare
# `cargo test --lib -- memory::` fails 26 tests, every one of them a "null vs
# module" assertion, and 15 further module-gated tests do not exist at all
# (582 passed / 26 failed, versus 623 passed / 0 failed with the gate on).
# A default set that cannot run its own test suite is not a usable inner loop.
# The cost is the smallest of any gate here: +9 packages / +5 unique names
# (`ureq`, `ureq-proto`, `utf8-zero`, `toml_edit`, `toml_write`) and **zero**
# new native builds — the native list is byte-identical with the gate on and
# off. That is nothing like the cohorts #4919 moved out of `default`, and it
# also brings the build in line with what AGENTS.md has always documented
# (`modules`: Contrib=ON, Product=ON) and with `scripts/ci/product-features.txt`,
# which already lists it. This does NOT move the kernel floor: that profile is
# `--no-default-features --features flows` and never reads this list.
default = ["media", "skills", "flows", "mcp", "channels", "medulla", "http-server", "scheduler-gate", "file-logging", "modules", "memory-engine-seams"]
# Compiles `memory::host_impls` and turns the optional `tinymemory-core` on with
# it (openhuman#5560). Default-ON, product-OFF, allow-listed in
# `INTENTIONALLY_NOT_FORWARDED` — forwarding it to the shell would undo the shed.
#
# **Why a feature and not `#[cfg(test)]`.** The seams install into an in-process
# engine, and the crate's own unit tests reach them through `cfg(test)` happily.
# A `tests/*.rs` integration target cannot: it links this lib as an ordinary
# dependency, where `cfg(test)` is false and the module is invisible *however
# the engine is declared*. Two dozen of those targets call
# `install_memory_host_seams`, and the archivist / session-turn / memory-sync
# cases in `raw_coverage_all` genuinely drive a real engine — they fail with
# "no EmbeddingHost installed" when it is absent, which is the same failure the
# first attempt at #5560 shipped to users. So the module needs a *feature*, and
# a feature that turns the engine dependency on.
#
# **Why `default` and not the test lane.** Three separate places compose the
# test feature string (`scripts/test-rust-with-mock.sh`,
# `test-reusable.yml`, `scripts/ci/rust-coverage-changed.sh`) and one
# `raw_coverage_all` invocation passes `--features` not at all. None of them
# passes `--no-default-features`, so `default` reaches every one; a
# test-lane-only feature would have to be added to each and would fail
# confusingly wherever it was missed. It costs the contributor inner loop
# nothing it was not already paying: before this change `tinycortex` and
# `tinymemory-core` were unconditional normal dependencies, so a bare
# `cargo check` linked them regardless.
memory-engine-seams = ["dep:tinymemory-core"]
# HTTP + Socket.IO server transport (#5048): the `/rpc` JSON-RPC endpoint and
# its auth middleware/CORS layer (`core::jsonrpc`, `core::auth`), the `/v1`
# OpenAI-compatible router (`inference::http`), the ad-hoc static-dir file
# server (`openhuman::http_host`), the AgentBox `/run` HTTP surface
# (`agentbox::http`), the WebSocket dictation stream
# (`inference::voice::streaming`), the `openhuman text-input run` dev server,
# the MCP Streamable-HTTP transport (`mcp::server::http`, additionally gated by
# `mcp`), and the Socket.IO live-event bridge (`core::socketio`). Default-ON —
# the desktop shell REQUIRES it (see the `HTTP_SERVER_COMPILED_IN` compile
# assert in `app/src-tauri/src/lib.rs`). Slim / headless-embedding builds opt
# out via `--no-default-features --features "<explicit list without
# http-server>"`, which drops the exclusive `axum` + `socketioxide` deps; the
# core then runs background services without binding a listener (`serve()`
# returns early) and is driven over the CLI / native dispatch surface instead.
#
# TYPE CARVE-OUT (see AGENTS.md): `core::socketio`'s inert event payload types
# (`WebChannelEvent`, `TurnUsagePayload`, `SubagentUsagePayload`,
# `SubagentProgressDetail`) stay compiled in BOTH builds — ~10 always-on
# domains construct them — so `pub mod socketio;` is UNGATED and only the
# socketioxide/axum-touching bodies are gated. Likewise `inference::http::types`
# and `EXTERNAL_OPENAI_COMPAT_PROVIDER` stay compiled for `core::auth`.
# Git-backed memory diff: snapshots as commits, checkpoints as tags, read
# markers as refs, diffs as git tree diffs (`openhuman::memory::diff`), plus the
# git-backed wiki content format in `memory::store::content::wiki_git`.
# Default-OFF, product-ON.
#
# The most expensive gate in the tree by native-build cost: it turns on
# tinycortex's `git-diff`/`wiki-git`, which carry `git2` with vendored libgit2,
# so turning it off drops `git2` + `libgit2-sys` + `libz-sys` and takes the
# kernel profile from 5 native C builds to 3. The cohort enters the graph
# through tinycortex only — this crate declares no `git2` of its own (see the
# note where it used to sit in `[dependencies]`).
#
# TYPE CARVE-OUT (see AGENTS.md): `memory::diff::types` stays compiled in BOTH
# builds. It re-exports tinycortex's `serde`-only diff wire types, which the
# always-on subconscious memory profile renders into prompts; a stub copy would
# be a second definition of one serde shape, free to drift. tinycortex makes the
# same split — its `memory::diff::{types,source}` are ungated, and only the
# git-touching `ledger`/`DiffEngine` half sits behind `git-diff`.
#
# Off-state: the `memory_diff` RPC namespace is unknown-method and absent from
# `/schema`; the `memory_diff` agent tool is absent from the tool list; the
# embedded driver stops advertising `Capability::Diff` and `as_diff()` returns
# `None`; and the three `ops` entry points always-on code calls return a
# build-fact error, so a post-sync snapshot or a subconscious diff is logged and
# skipped rather than silently reported as "nothing changed".
http-server = ["dep:axum", "dep:socketioxide"]
# Local audio-device access: the `cpal` capture stack behind voice recording
# and the accessibility microphone-permission probe. Default-ON. Slim /
# headless builds opt out via `--no-default-features --features "<explicit list
# without inference>"`, which drops the exclusive `cpal` dependency; the
# microphone probe then reports `Unknown`. `voice` requires this gate, so
# building `voice` always pulls `inference` in transitively.
#
# NOTE ON THE NAME (do not "fix" it to `audio`): this gate used to cover the
# bundled whisper.cpp STT engine (`whisper-rs` + the `whisper-rs-sys` CRT
# patch) as well. That engine is gone — STT is now cloud/engine-configurable
# only (`voice_server.stt_engine`, `voice::factory`) — so `cpal` is all that is
# left behind the gate. The gate name stays `inference` because it is forwarded
# by name from `app/src-tauri/Cargo.toml`, asserted by `INFERENCE_COMPILED_IN`,
# and referenced from `desktop::accessibility::permissions`; renaming it buys