[package]
name = "newt-core"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
authors.workspace = true
description = "Newt-Agent core types, errors, and the NeMoCode-style tier router"
keywords = ["newt", "agent", "router", "llm", "nemo"]
categories = ["api-bindings", "text-processing"]

[dependencies]
anyhow.workspace = true
async-trait.workspace = true
# OCAP disclosure filter (ocap.rs): catch a known secret value in its common
# re-encodings (base64), not just raw — filter by value, not by shape.
base64.workspace = true
# Gitignore-aware recursive walking for the embedded `find` tool (#496) — lets
# agents search the workspace without the shell, which can be unavailable in a
# given build (the stub-shell case that motivated the issue).
ignore.workspace = true
# Step 19.2 (issue #248): the write-time security scan's injection-pattern
# table (notes_scan.rs). Already a workspace dep used by newt-eval/newt-tools.
regex.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
toml.workspace = true
# #904: comment/format-preserving TOML edits for the interactive "allow
# permanently" grant (append a host to `[tui.permissions] net` without the
# whole-config clobber that `Config::save`/`toml::to_string` would cause).
toml_edit = "0.25"
serde_yaml.workspace = true
tracing.workspace = true
uuid.workspace = true

# Step 9.7: the agentic loop (`agentic` module) moved here from `newt-tui`
# so the same loop can serve the TUI and the ACP worker (Step 9.8). The
# loop's dependency closure comes with it:
#  - reqwest/tokio/chrono — the HTTP loop itself (and `retry`, also moved
#    here from `newt-inference` to break a would-be dependency cycle),
#  - crossterm — the inline progress the loop prints (tool calls, retries,
#    trim notices); headless callers run with `color: false`,
#  - newt-skills — the `use_skill` tool body loader,
#  - agent-bridle — the Caveats-confined `shell` / `web_fetch` tools that
#    `execute_tool` routes `run_command` / `web_fetch` through.
chrono.workspace = true
crossterm.workspace = true
newt-skills.workspace = true
reqwest.workspace = true
tokio.workspace = true
# `host-shell` = the sandboxed-host engine (`/bin/sh -c` in the L3 jail, ADR 0019)
# selectable via `[shell] engine = "host"`; `os-sandbox` enables every OS L3
# backend (Landlock/Seatbelt/AppContainer — each inert off its target OS).
agent-bridle = { version = "0.7", features = ["shell", "web", "host-shell", "os-sandbox", "brush", "carried-coreutils"] }

# Step 25.1 (#568 follow-on): Markdown → ANSI rendering for assistant output,
# behind the default `markdown` feature. Stripped under --no-default-features
# (the headless wyvern tier) by the passthrough shim in `agentic::markdown`.
pulldown-cmark = { workspace = true, optional = true }
unicode-width = { workspace = true, optional = true }
# Step 25.5 (#568 follow-on): optional plain-text GFM-table-pipe alignment for
# the headless wyvern tier. Off by default (pulls comrak + wasm-bindgen).
markdown-table-formatter = { workspace = true, optional = true }
# Step 25.6 (#568 follow-on): optional syntect code-block highlighting. Off by
# default (heavy syntax/theme assets); pure-Rust (default-fancy, no onig C dep).
syntect = { workspace = true, optional = true }

# Issue #95: the `Caveats` / `CountBound` / `Scope` types are re-exported
# straight from the published `agent-mesh-protocol` crate (registry pin,
# not the path dep that keeps newt-mesh out of the default workspace).
# This kills the hand-mirrored `caveats` module and the JSON bridge in
# `newt-mesh::plugin_envelope` — the signed wire type and the
# enforcement-side type are now literally the same Rust type.
agent-mesh-protocol = { workspace = true }

# Step 18.3 (issue #247): content hashing for the structural-prune
# duplicate-collapse pass. Already in newt-core's build graph transitively
# via agent-mesh-protocol — promoting it to a direct dep adds no new crate.
# Step 17.1a (issue #246) also uses it for the §6 turn content chain
# (`prev_hash` = BLAKE3 of the prior turn's canonical encoding) and the
# per-install writer fingerprint.
blake3 = "1"

# Step 17.1a (issue #246): the SQLite backend for `ConversationStore`
# (`store` module) — the one new dependency of Phase 17. Grounds (design
# doc §Phase 17): the JSON store rewrites the whole pretty-printed record
# on every turn (O(record) appends, measured 3.4 ms p50 at 1000 turns in
# the B1 baseline); 17.3+ tool-event recall needs an index, not a grep;
# FTS5 `snippet()` quality is the difference between a usable `recall`
# and noise. NOT grounds: scale or lineage. `bundled` (no system SQLite);
# `fts5` is deferred to 17.3. Version pinned at the workspace level for
# MSRV 1.75 — see the root Cargo.toml comment.
rusqlite.workspace = true

# TODO: depend on thoon-core once it publishes (currently path-only in hermes-thoon).
# thoon-core = "0.5"

# Optional PyO3 bindings — opt in only via the umbrella `newt-agent-py`
# crate; default builds stay Python-free.
pyo3 = { workspace = true, optional = true }

[features]
default = ["markdown"]
# Markdown → ANSI rendering of assistant output (Step 25.1). On by default for
# the human-facing binaries; compiled out (passthrough shim) for the headless
# wyvern strip via --no-default-features.
markdown = ["dep:pulldown-cmark", "dep:unicode-width"]
# Step 25.5: plain-text GFM-table-pipe alignment for the headless wyvern tier.
# Off by default — only wyvern/headless consumers opt in (pulls comrak +
# wasm-bindgen). `tidy_markdown_tables` is identity without this feature.
markdown-table-formatter = ["dep:markdown-table-formatter"]
# Step 25.6: per-language syntax highlighting in fenced code blocks via syntect.
# Requires `markdown` (the code-block renderer lives in the markdown module).
# Off by default to keep the binary lean.
markdown-syntect = ["markdown", "dep:syntect"]
pyo3 = ["dep:pyo3"]

[dev-dependencies]
tempfile = "3"
tokio = { workspace = true }
# The store integration tests (tests/store.rs) open conversations.db
# directly to tamper with rows / build drifted schemas — exercising the
# §6 chain-integrity detection and the schema-diff migration. Same crate
# as the runtime dep; adds nothing to the build graph.
rusqlite.workspace = true
# HTTP mocking for the agentic-loop tests that moved here with the loop
# (Step 9.7) — same pattern as newt-inference / the old newt-tui suites.
wiremock.workspace = true

[lints]
workspace = true
