pub struct ChatCtx<'a> {Show 50 fields
pub url: &'a str,
pub model: &'a str,
pub kind: BackendKind,
pub api_key: Option<&'a str>,
pub messages: &'a [MemMessage],
pub task: &'a str,
pub workspace: &'a str,
pub color: bool,
pub markdown: bool,
pub tool_offload: bool,
pub spill_store: Option<&'a dyn SpillStore>,
pub compaction_store: Option<&'a dyn SpillStore>,
pub scratchpad: bool,
pub scratchpad_store: Option<&'a dyn ScratchpadStore>,
pub code_search: Option<CodeSearch<'a>>,
pub experience_store: Option<&'a dyn ExperienceStore>,
pub step_ledger: Option<&'a dyn StepLedger>,
pub caveats: &'a Caveats,
pub max_tool_rounds: usize,
pub workflow_grace_rounds: usize,
pub tool_output_lines: usize,
pub debug: bool,
pub trace: bool,
pub num_ctx: Option<u32>,
pub connect_timeout_secs: u64,
pub inference_timeout_secs: u64,
pub mid_loop_trim_threshold: usize,
pub mid_loop_trim_tokens: Option<usize>,
pub max_ok_input: Option<u32>,
pub build_check_cmd: Option<String>,
pub safe_context: Option<u32>,
pub recover_cw_400: Option<RecoverCw400>,
pub note_sink: Option<&'a mut dyn NoteSink>,
pub note_nudge: Option<&'a mut NoteNudge>,
pub recall_source: Option<&'a dyn RecallSource>,
pub memory_source: Option<&'a dyn MemorySource>,
pub summarizer: Option<&'a SummarizeFn>,
pub compress_state: Option<&'a mut CompressState>,
pub tool_events: Option<&'a mut Vec<ToolEvent>>,
pub phantom_reaches: Option<&'a mut Vec<PhantomReach>>,
pub permission_gate: Option<&'a mut dyn PermissionGate>,
pub on_round_usage: Option<&'a mut dyn FnMut(RoundObservation)>,
pub estimate_ratio: Option<f32>,
pub estimation: TokenEstimation,
pub summary_input_cap_floor_chars: usize,
pub exec_floor: Option<&'a Scope<String>>,
pub write_ledger: Option<&'a RefCell<WriteLedger>>,
pub cancel: Option<&'a AtomicBool>,
pub git_tool: Option<&'a dyn GitTool>,
pub crew_runner: Option<&'a dyn CrewRunner>,
}Expand description
Everything one agentic turn needs, resolved once by the caller (the TUI resolves config + capability cache + caveats per turn and threads them in here, so the loop itself never re-reads config from disk).
Fields§
§url: &'a str§model: &'a str§kind: BackendKindWire protocol of the active backend (Ollama vs OpenAI-compatible).
api_key: Option<&'a str>Bearer token for authenticated OpenAI-compatible endpoints.
messages: &'a [MemMessage]Full message list already assembled by MemoryManager::build_messages.
task: &'a str§workspace: &'a str§color: bool§markdown: boolRender assistant Markdown as ANSI in the live stream (Step 25.4, #568).
Resolved by the caller as [tui].markdown (∧ /markdown override) ∧
color. The loop only renders when this is true.
tool_offload: boolOffload oversized tool results to the session spill store (Step 26.3,
#584). The resolved tool_offload composable feature (Step 26.1); false
for headless/eval callers (bit-for-bit unchanged when off).
spill_store: Option<&'a dyn SpillStore>Session spill store for tool_offload (Step 26.3). None = no offload
(and spill: re-reads resolve to a labelled absence). Shared &dyn
(interior mutability) so it serves both the write path and memory_fetch.
compaction_store: Option<&'a dyn SpillStore>Session compaction store (#661 group B): the compressor stores each
evicted (redacted) middle span here and names a compaction:<id> handle
in the marker, so the model can losslessly recover a detail the summary
dropped. SEPARATE store from spill_store (own id space). None =
lossy-only compaction (headless / progressive disclosure off).
scratchpad: boolInject the <state> scratchpad block + advertise the state tools (Step
26.4, #583). The resolved scratchpad feature; false for headless/eval.
scratchpad_store: Option<&'a dyn ScratchpadStore>Session scratchpad store (Step 26.4). None = state tools not advertised
and no <state> injected. Shared &dyn (interior mutability).
code_search: Option<CodeSearch<'a>>Semantic searcher for the code_search tool (Step 26.5.5). None = the
tool is not advertised (semantic off / no index). Bundles embedder+index.
experience_store: Option<&'a dyn ExperienceStore>Experiential store for the record/recall tools (Step 26.6a). None = the
tools are not advertised (experiential off). Shared &dyn (interior mut).
step_ledger: Option<&'a dyn StepLedger>Plan ledger for the update_plan tool (Step 26.6b). None = the tool is
not advertised (scheduled off). Shared &dyn (interior mut).
caveats: &'a Caveats§max_tool_rounds: usizeMaximum tool-call rounds before forcing a final tools-disabled
completion (from [tui].max_tool_rounds, default 40).
workflow_grace_rounds: usizeAdditional progress-aware rounds available after max_tool_rounds when
the active workflow still has incomplete work and the recent rounds show
repair evidence or concrete progress. 0 makes the normal cap hard.
tool_output_lines: usizeMax lines of tool output shown inline (from [tui].tool_output_lines,
default 20). Resolved once per turn and threaded to execute_tool so
the tool loop never re-reads config from disk.
debug: boolEnable per-round diagnostic output. Set via NEWT_DEBUG=1 or the
[tui] debug = true config key.
trace: boolEnable deeper backend compatibility traces. Set via NEWT_TRACE=1 or
the [tui] trace = true config key.
num_ctx: Option<u32>Ollama options.num_ctx — caps KV-cache allocation to prevent VRAM
exhaustion on large models. None → model default (often 131k).
Also feeds the pre-send budget as a hard input ceiling for this turn’s
requests (issue #282): Ollama silently evaluates only the window’s
tail, so anything newt sends must already fit inside the num_ctx it
sends it with. Ignored on the OpenAI path (no such request field).
connect_timeout_secs: u64TCP connect timeout. Short (5 s default) so a down endpoint fails fast
rather than blocking the full inference_timeout_secs.
inference_timeout_secs: u64Total inference timeout. Must be long enough for the model to generate a complete response (120 s default).
mid_loop_trim_threshold: usizeMessage list size at which the agent trims the middle of the in-flight conversation to prevent context overflow mid-turn.
mid_loop_trim_tokens: Option<usize>Estimated-token threshold that also triggers a mid-loop trim, regardless
of message count. Guards against a single huge tool result blowing past
the context window in one round (from [tui].mid_loop_trim_tokens).
None disables token-based trimming. See issue #223.
max_ok_input: Option<u32>Highest input-token count this model has accepted without a 400, from
model-capabilities.json. Used as the pre-send budget gate: requests
estimated to exceed it are trimmed before dispatch. None falls back
to safe_context. See issue #223.
build_check_cmd: Option<String>Shell command run after every successful file write to give the model
immediate ground-truth feedback (e.g. “cargo check -q –workspace”).
None disables auto-checking. Set per-workspace in .newt/config.toml.
safe_context: Option<u32>Empirically derived safe context size for this model (input tokens).
Used to detect likely overflow when the model returns an empty response.
Sourced from model-capabilities.json via ensure_context_window.
None disables overflow detection.
recover_cw_400: Option<RecoverCw400>Hook invoked when a dispatch fails, to recover a hard context-window
400: (error, model, today) → new input-token cap. The TUI wires its
recover_context_window_400 (which parses the endpoint’s real limit
and persists it to model-capabilities.json — that cache stays
TUI-side with the probe module). None disables recovery: the error
propagates exactly as it did when no limit could be parsed. See #223.
note_sink: Option<&'a mut dyn NoteSink>Model-writable note store behind the save_note tool (Step 19.3,
#248). None ⇒ the tool is not advertised and the loop never writes
memory (eval / headless callers unaffected). The TUI passes a sink
over its session MemoryManager, so save_note and /remember
share one store, one security scan, one char budget.
note_nudge: Option<&'a mut NoteNudge>Turn-counted memory-nudge state (NoteNudge), owned by the caller
across user turns and lent to the loop per call. Consulted only when
note_sink is present; None disables the nudge.
recall_source: Option<&'a dyn RecallSource>Read-only search over PAST conversations behind the recall tool
(Step 17.5, #246). None ⇒ the tool is not advertised and the loop
never searches (eval / headless callers unaffected). The TUI passes
a StoreRecallSource over its session ConversationStore —
workspace-fenced, current conversation excluded.
memory_source: Option<&'a dyn MemorySource>Read-only pull of an ADDRESSED memory item behind the memory_fetch
tool (progressive-disclosure memory, Workstream A MVP, #319). None ⇒
the tool is not advertised and the loop never fetches — eval / headless
/ ACP callers (which pass memory_source: None) are unaffected,
bit-for-bit. The TUI passes a StoreMemorySource over its session
NoteStore + ConversationStore (workspace-fenced), so note: and
turn: addresses resolve against the same surfaces /remember and
recall use. Gated exactly like recall_source.
summarizer: Option<&'a SummarizeFn>Compression summarizer (Step 18.4, #247): given the redacted summary
request, returns the summary text — typically one tools-disabled
completion against the same backend (the TUI wires this, mirroring
the Summarizing provider’s with_summarizer injection). None
(eval / headless) ⇒ the compression pipeline degrades to the static
“Summary generation was unavailable” marker instead of an LLM summary.
compress_state: Option<&'a mut CompressState>Session-scoped compression anti-thrash state (CompressState),
owned by the caller across user turns and lent per call (the
note_nudge pattern). None ⇒ a fresh per-turn state.
tool_events: Option<&'a mut Vec<ToolEvent>>Per-turn tool-event recorder (Step 17.6, #246): when present, the
loop pushes one crate::ToolEvent per executed tool call — name,
privacy-preserving args digest (never raw args), outcome, duration
claim — at the same site that renders tool activity live. The TUI
lends a fresh Vec per turn (the note_nudge pattern) and persists
it into the turn’s events column. None (eval / headless) ⇒
nothing is recorded.
phantom_reaches: Option<&'a mut Vec<PhantomReach>>Per-turn phantom-reach recorder (#717): when present, the loop pushes one
crate::PhantomReach for each phantom tool/capability reach (alias
resolve, hallucination, or a real-tool empty-by-design miss). Lent fresh
per turn like tool_events; persisted into the turn’s phantom_reaches.
None (eval / headless) ⇒ nothing recorded.
permission_gate: Option<&'a mut dyn PermissionGate>Prompted ocap grants (issue #263): when present, a capability denial
inside execute_tool consults the human — allow once / session allow
/ deny — instead of failing outright; the loop blocks like a long
tool call while the prompt is pending. None (the default — every
headless caller: ACP worker, newt-eval) keeps each denial exactly
as before, so nothing non-interactive can ever hang on a prompt.
on_round_usage: Option<&'a mut dyn FnMut(RoundObservation)>Per-round capability observation hook (Phase 20,
docs/design/model-self-tuning.md §2.2): the loop reports each
round’s evidence — accepted prompt sizes (with the matching chars/4
estimate for calibration), persistent-empty suspected overflows, the
thinking-only response quirk — at the moment of observation, so the
caller can persist it even when the turn later bails or errors (the
motivating failure discarded an accepted 8,734-token prompt because
the only write-back lived in the TUI’s Ok-arm epilogue). None
(ACP worker, eval, cowork driver) preserves today’s behavior exactly
(spec §5).
estimate_ratio: Option<f32>Learned observed/estimated prompt-token ratio for this model
(Phase 20 §2.3), applied wherever chars/4 estimates meet
backend-reported token budgets — compression triggers, targets, and
the tool-schema overhead. None or out-of-clamp values degrade to
1.0 (no calibration; pre-Phase-20 behavior).
estimation: TokenEstimation[context.estimation] token-estimation heuristic (chars-per-token),
extracted from config so the loop never re-reads it — drives every
chars→token estimate and the budget→chars summary-cap conversion.
summary_input_cap_floor_chars: usize[context] summary_input_cap_floor_chars — floor for the summarizer
input cap so a tight budget never starves the summarizer of material.
exec_floor: Option<&'a Scope<String>>#307 named-permission-preset exec FLOOR. When a /mode preset is active
its exec clamp is threaded here so the --disable-ocap / --yolo
bypass in execute_tool cannot raise exec authority above the preset:
an out-of-floor command falls through to the confined shell and is
denied. None (no active preset, and every headless caller) leaves the
bypass bit-for-bit. The floor is also already meet-ed into caveats,
so the confined-shell and gate paths enforce it too; this field is the
one extra place the otherwise caveats-blind bypass must consult.
write_ledger: Option<&'a RefCell<WriteLedger>>retry technique (R2 action arm): a turn-scoped copy-on-first-write ledger
(crate::verify_gate::WriteLedger) the file-write tools record into before
each write_file / edit_file, so the caller can revert exactly the files
newt wrote this turn (and only those) after the gate runs. Shared via
RefCell so the loop records while the caller reads.
None (every headless caller, and any profile without retry) ⇒ nothing is
recorded and no file is ever reverted — bit-for-bit today’s behavior.
cancel: Option<&'a AtomicBool>User-interrupt flag (Esc / Ctrl-C during a turn). When set mid-turn the
loop abandons at its next checkpoint — the round-loop top, and the two
model awaits (the non-streaming probe and the token stream) — and
returns early. None (every headless / eval caller) ⇒ no interrupt
path, bit-for-bit today’s behavior. The caller owns the AtomicBool,
trips it from a keyboard watcher, and inspects it after the call to tell
an interrupted turn from a genuinely empty reply.
git_tool: Option<&'a dyn GitTool>The injected embedded-git capability (PR4, #461). Some ⇒ the git
tool is advertised and dispatches through it (LocalGitTool in
newt-git, injected by the binary). None (every headless / eval
caller, and any session not in a git repo) ⇒ the tool is never
advertised — bit-for-bit today’s behavior. The trait-injection seam, not
a direct dep, because newt-git depends on newt-core (circular).
crew_runner: Option<&'a dyn CrewRunner>The injected crew/team orchestration capability (#479). Some ⇒ the
compose_roster + crew tools are advertised and dispatch through it
(LocalCrewRunner in newt-cli, injected by the /team toggle). None
⇒ never advertised. Trait-injection seam like git_tool (newt-scheduler
depends on newt-core, so the dep can’t be direct).
Auto Trait Implementations§
impl<'a> !RefUnwindSafe for ChatCtx<'a>
impl<'a> !Send for ChatCtx<'a>
impl<'a> !Sync for ChatCtx<'a>
impl<'a> !UnwindSafe for ChatCtx<'a>
impl<'a> Freeze for ChatCtx<'a>
impl<'a> Unpin for ChatCtx<'a>
impl<'a> UnsafeUnpin for ChatCtx<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more