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
//! The process-scoped substrate every workspace borrows.
//!
//! ADR-0018's split. [`Workspace`](crate::Workspace) used to conflate two
//! lifetimes: half its configuration was process infrastructure — a privately
//! built mentra runtime, provider and credential resolution, the history store
//! policy, the host's interceptors — and half was repository discovery. A host
//! opening N workspaces paid the process costs N times. This module is the
//! noun the first half was missing.
//!
//! - **[`Runtime`]** owns mentra's runtime, the provider/credential/base-URL
//! and model *policy*, the history store policy, and the host's
//! interceptors. Build one with [`Runtime::builder`], share it with
//! [`WorkspaceBuilder::with_runtime`](crate::WorkspaceBuilder::with_runtime).
//! - **[`Workspace`](crate::Workspace)** keeps what the repository says —
//! context, skills, templates, hooks, `.mcp.json` — and borrows the runtime
//! through an `Arc`. MCP *connections* stay workspace-owned: minted from
//! repository config, dead with the workspace.
//! - **`Workspace::open(path)` is unchanged sugar** that builds a private
//! default runtime bound to that path. The one-repository host never sees
//! this module; only the N-repository host reaches for it.
//!
//! ```no_run
//! # async fn example() -> Result<(), basis::RunError> {
//! use std::sync::Arc;
//! use basis::{Runtime, Workspace};
//!
//! let runtime = Arc::new(Runtime::builder().build()?);
//! let one = Workspace::builder("/repo/one").with_runtime(Arc::clone(&runtime)).open().await?;
//! let two = Workspace::builder("/repo/two").with_runtime(runtime).open().await?;
//! # let _ = (one, two);
//! # Ok(())
//! # }
//! ```
//!
//! # What is where
//!
//! This file is the noun: the [`Runtime`] itself, what a builder settled on it,
//! and the readers a workspace asks. The three questions sharing one costs
//! answers to live beside it, because each is a subject of its own and this
//! file was carrying all four:
//!
//! - `scope` — what a workspace's sessions run *as*. The policy, the tool
//! audience and the persisted identity mentra keeps in no agent, restated on
//! every mint and every resume.
//! - `claims` — who holds what on the single tool and skill registries a
//! shared runtime carries, and what a collision means for each.
//! - `interception` — who judges a call: the host's global guards, and each
//! workspace's own chain, holder-counted per audience.
//! - `agents` — which workspace each live agent answers for. The one question
//! an audience cannot answer, because two opens of one directory share one.
pub
pub
pub
use HashMap;
use ;
use ;
use ModelSelector;
pub use ;
pub use ToolResultPolicy;
pub use DeclaredToolOrigin;
use McpClaim;
pub use ToolClaims;
use HookChainClaim;
pub use HookChainHold;
pub use SessionScope;
/// The types a **command target's executor** is written against.
///
/// Re-exported for the reason [`CancellationToken`](crate::CancellationToken)
/// is, and under the same rule: every mentra type basis's surface makes a
/// caller *name*, basis re-exports — so a host implementing
/// [`RuntimeExecutor`] never adds mentra to its own manifest and pins the
/// same version, a skew that would otherwise fail to compile with no hint
/// two crates disagree about one trait. There is currently no public way to
/// register an executor a command routes to (`docs/targets.md` has the
/// dateline note); the trait and the types below it are unaffected. The
/// sibling of [`crate::tools`]'s tool-authoring re-exports, in the module
/// that owns this seam.
///
/// The set is what an executor's `run` signature and body actually touch:
/// [`RuntimeExecutor`] to implement, [`CommandRequest`] to read,
/// [`CommandSpec`] to match the command out of it, [`CommandOutput`] to answer
/// with, and [`LocalRuntimeExecutor`] for a wrapper that delegates the ordinary
/// case rather than reimplementing it. Writing the `async fn` also needs
/// [`async_trait`](crate::async_trait), which the crate root already re-exports.
/// See `docs/targets.md` for a worked example.
pub use ;
/// How patiently a run waits out a provider that is failing transiently, as
/// [`RuntimeBuilder::with_provider_retry`] takes it.
///
/// Mentra's own type, re-exported under the rule on
/// [`CancellationToken`](crate::CancellationToken): the builder makes a host
/// *name* this to call the method, so basis re-exports it rather than sending
/// the host to its own `mentra` dependency and a version pin that can skew.
/// basis defines no schedule of its own — a parallel type here would be two
/// spellings of one policy, and mentra is the half that does the sleeping.
pub use ProviderRetry;
/// One statement about how a provider connection is retried: the waits, and
/// how many of them.
///
/// mentra keeps the two apart on `RunOptions` — a typed schedule beside a bare
/// count — and basis's hosts set them apart too, since the commonest adjustment
/// is the count alone. But nothing downstream of a builder ever wants one
/// without the other: a runtime's fallback, the copy every
/// [`PreparedRun`](crate::PreparedRun) carries from it, and the value a turn's
/// options fall back to are each *both* halves. So they travel as one value
/// from the builder to the run rather than as a pair that every hop has to
/// remember to keep together.
///
/// Internal: the halves are set and overridden separately on the public
/// surface — [`RuntimeBuilder::with_provider_retry`] and
/// [`RuntimeBuilder::with_provider_retry_budget`], and their
/// [`TurnOptions`](crate::TurnOptions) counterparts — which is the shape a host
/// asked for and mentra's own.
pub
/// Which wire transport mentra streams the Responses format over, as
/// [`RuntimeBuilder::with_responses_transport`] takes it.
///
/// Re-exported for the same reason and beside the executor types above, in the
/// module that owns the builder asking for it. Mind the feature: selecting
/// [`ResponsesTransport::WebSocket`] needs basis's `responses-websocket`
/// feature, which forwards to mentra's — see the method for what happens
/// without it.
pub use ResponsesTransport;
/// Which builtin file tools the model is offered, as
/// [`RuntimeBuilder::with_file_tools`] takes it.
///
/// Mentra's own enum, re-exported beside the two above and for their reason:
/// the method makes a host *name* it, and a parallel type here would be a
/// second spelling of a set mentra is the one registering. basis's default is
/// [`FileToolProfile::Split`] rather than mentra's `Batched` — see the method
/// for why, and for who would want the other.
pub use FileToolProfile;
/// The types a **host-supplied provider** is written with.
///
/// [`RuntimeBuilder::with_provider_instance`] takes an `impl Provider` — the
/// trait itself is re-exported at the crate root, beside the other types
/// basis's surface makes a caller name — and implementing it touches exactly
/// this set: [`ProviderDescriptor`] (naming itself by [`ProviderId`]) and
/// [`ProviderCapabilities`] to say who and what, [`ModelInfo`] to list
/// models, [`Request`] to receive, mentra's [`ProviderError`] to fail with,
/// and a [`ProviderEventStream`] to answer with — assembled whole from a
/// [`Response`] (content in [`ContentBlock`]s, spoken in a [`Role`], costed
/// in [`TokenUsage`]) via [`provider_event_stream_from_response`], or event
/// by event from [`ProviderEvent`] ([`ContentBlockStart`],
/// [`ContentBlockDelta`]). Re-exported beside the executor types above and
/// under their rule: the builder makes a host *name* these, so basis
/// re-exports them rather than costing the host a mentra dependency and a
/// version pin that can skew. Mind the name: this `ProviderError` is
/// mentra's — the one a `Provider` implementation answers with — not
/// [`crate::provider::ProviderError`], which is how basis's own *resolution*
/// refuses.
pub use ;
/// What [`RuntimeBuilder::with_gateway_ring`] and its two companions take
/// and report, under the same rule as the provider-authoring types above: the
/// builder makes a host name these, so basis re-exports them. The ring itself
/// stays in mentra (ADR-0027); [`GatewayMember`] is basis's own, because it
/// carries a URL the way [`RuntimeBuilder::with_base_url`] takes one.
pub use ;
/// Which request format a custom endpoint is spoken to in, as
/// [`RuntimeBuilder::with_wire`] takes it.
///
/// Two wires answer to the name "OpenAI-compatible" and they agree on almost
/// nothing: a flat `messages` array against typed input items, tool arguments
/// as a JSON string against a value, `max_tokens` against `max_output_tokens`
/// — and, the part an operator meets first, `v1/chat/completions` against
/// `v1/responses`. Speaking the wrong one is a 404 on the very first turn,
/// worded like a mistyped URL.
///
/// basis's own enum rather than mentra's `WireApi`, which is where the rule
/// above gives way. `WireApi` also names Anthropic's and Gemini's formats, and
/// neither is something a base URL can be spoken to in — re-exporting it would
/// let a host write a call basis could only refuse. Two wires are what basis
/// can honor here, so two variants is what it takes.
use crateRunError;
use PolicyShaping;
/// One process's substrate: mentra's runtime plus the resolution policy and
/// host guards that were fixed when it was built.
///
/// Shared through an `Arc` by every [`Workspace`](crate::Workspace) opened on
/// it, so N repositories cost one provider resolution and one store handle.
/// `Send` and `Sync`; sessions are minted from `&self`.
/// Hand-written because mentra's runtime is not `Debug`. No credential lives
/// here — the key was consumed building the provider — so nothing is redacted.