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
//! **The operator's document** (yog's `docs/REMOTE.md` §5.2, §5.4; DESIGN
//! §3.4): what this box offers, and — by dropping half of it — what it says it
//! offers.
//!
//! ```json
//! [{"name": "Bash",
//! "description": "run a command in a shell",
//! "input_schema": {"type": "object",
//! "properties": {"command": {"type": "string"}},
//! "required": ["command"]},
//! "command": ["/usr/local/libexec/thrall-tools/bash-tool"],
//! "cwd": "/srv/work"}]
//! ```
//!
//! **One document, two readings.** The first three keys *are* REMOTE §5.1's
//! advertised element, verbatim, and [`advertisement`] is the whole of the
//! derivation: drop `command` and `cwd`. So what this box offers and what it
//! can actually run cannot drift, which is the entire reason the config is not
//! a pair of lists an operator has to keep in step.
//!
//! **Local config gates what is enabled, and this document is the gate.** A
//! tool absent from it is a tool this box does not have. Server-side
//! adjudication is unchanged, stacks on top, and fails closed — but it stacks
//! on *this*, so removing a capability from this machine is deleting an entry
//! here rather than editing anything, on the box whose operator is the one
//! entitled to decide (DESIGN §3.4).
//!
//! **`command` is an argv, spawned directly.** There is no shell and no
//! interpolation of the invocation's input into it. A shell would make the
//! declared `input_schema` advisory and turn an operator's config file into a
//! command-injection surface for anything a model can type; the input reaches
//! the command the way a local tool contract already delivers one — the JSON on
//! stdin, bytes on stdout, the exit code the verdict (bl-4cda).
//!
//! **It sits beside the channel material, not inside anything generated**
//! (`<thrall-data-root>/tools.json`, the sibling of `wire/`), for the material's
//! reason exactly: it describes *this machine*, it is written by the operator's
//! hand, and nothing thrall generates may sit where a rebuild would take it.
use ;
use Value;
use crate;
use crate;
/// The document's leaf under the data root.
pub const TOOLS: &str = "tools.json";
/// One tool this box offers: the advertised half, and the local half that is
/// never presented to anyone.
/// This box's document, under a data root.
/// Read it, or say why it is not one.
///
/// **An absent document is a refusal rather than the empty set.** A foot with
/// nothing to offer has nothing to do, and starting one is an explicit act that
/// deserves an explicit answer — the same posture absent channel material takes
/// (`channel::material`), and the opposite of the *presented* set, where an
/// empty array is a legitimate thing to say.
/// One element: the advertised three read by the **same** decoder the wire
/// spends, then the local two.
/// **The advertisement, derived** (REMOTE §5.2): the same document with the
/// local half dropped. The one derivation, so this box cannot offer what it
/// cannot run.
/// Which element an invocation names, by position — an index rather than a
/// borrow, so the caller resolves it against the very list it passed in.