@gaunt-sloth/core 2.0.0-alpha.24 → 2.0.0-alpha.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/defaults.d.ts +1 -0
- package/dist/config/defaults.js +1 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/loader.d.ts +13 -6
- package/dist/config/loader.js +171 -28
- package/dist/config/loader.js.map +1 -1
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/schema.d.ts +2372 -114
- package/dist/config/schema.js +845 -16
- package/dist/config/schema.js.map +1 -1
- package/dist/config/shell-policy.d.ts +466 -116
- package/dist/config/shell-policy.js +273 -62
- package/dist/config/shell-policy.js.map +1 -1
- package/dist/config/tool-descriptions.d.ts +165 -0
- package/dist/config/tool-descriptions.js +229 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +36 -1
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +59 -1
- package/dist/core/GthAbstractAgent.js +72 -0
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +341 -58
- package/dist/core/GthAgentRunner.js +817 -149
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +16 -0
- package/dist/core/GthLangChainAgent.js +72 -2
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/launchBanner.d.ts +120 -0
- package/dist/core/launchBanner.js +399 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/plainToolIndication.js +13 -7
- package/dist/core/plainToolIndication.js.map +1 -1
- package/dist/core/shell/approvalStop.d.ts +75 -0
- package/dist/core/shell/approvalStop.js +108 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +41 -1
- package/dist/core/shell/normalize.js +58 -4
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +138 -0
- package/dist/core/shell/openWorld.js +523 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +560 -0
- package/dist/core/shell/rater.js +895 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +66 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/types.d.ts +71 -9
- package/dist/core/types.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +8 -7
- package/dist/runtime/askStructured.js +8 -7
- package/dist/runtime/askStructured.js.map +1 -1
- package/dist/runtime/conversation.js +89 -76
- package/dist/runtime/conversation.js.map +1 -1
- package/dist/runtime/singleShot.js +71 -60
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +30 -0
- package/dist/utils/consoleUtils.js +27 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/systemUtils.d.ts +17 -0
- package/dist/utils/systemUtils.js +17 -0
- package/dist/utils/systemUtils.js.map +1 -1
- package/package.json +5 -2
- package/schema/gsloth-config.schema.json +1216 -417
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §4.5's table, **verbatim**. The wordings are normative copy the model reads; do not paraphrase,
|
|
3
|
+
* re-punctuate or "improve" them.
|
|
4
|
+
*
|
|
5
|
+
* - `read-only` and `write` share one sentence: at both rungs a non-granted call goes to the human,
|
|
6
|
+
* so the user's approval is a certainty, not a possibility.
|
|
7
|
+
* - `auto-safe` softens `will` to `MAY`: the rater approves what it rates safe, so only some calls
|
|
8
|
+
* reach the user.
|
|
9
|
+
* - `full-auto` gets its **own** wording because the consequence differs — the user is not asked
|
|
10
|
+
* there, so promising the user's approval would be false. What can happen is a refusal by the
|
|
11
|
+
* rater.
|
|
12
|
+
* - `bypass` appends nothing to anything: no gate, so no sentence could be true.
|
|
13
|
+
*/
|
|
14
|
+
export const RUNG_TOOL_DESCRIPTION_SUFFIXES = {
|
|
15
|
+
'read-only': "Calling this tool will require the user's approval. Only use it when the result cannot be " +
|
|
16
|
+
'achieved with the other provided tools.',
|
|
17
|
+
write: "Calling this tool will require the user's approval. Only use it when the result cannot be " +
|
|
18
|
+
'achieved with the other provided tools.',
|
|
19
|
+
'auto-safe': "Calling this tool MAY require the user's approval if it does not look safe. Only use it when " +
|
|
20
|
+
'it is impossible to achieve the result with the other provided tools.',
|
|
21
|
+
'full-auto': 'Calling this tool MAY be refused by the auto-rater if it does not look safe. Only use it ' +
|
|
22
|
+
'when it is impossible to achieve the result with the other provided tools.',
|
|
23
|
+
bypass: null,
|
|
24
|
+
};
|
|
25
|
+
/** The distinct suffix strings, for {@link stripRungToolDescriptionSuffix}'s idempotency check. */
|
|
26
|
+
const ALL_SUFFIXES = Array.from(new Set(Object.values(RUNG_TOOL_DESCRIPTION_SUFFIXES).filter((s) => s !== null)));
|
|
27
|
+
/**
|
|
28
|
+
* Access class per built-in tool name. Covers BOTH backends' names: gsloth's own
|
|
29
|
+
* `GthFileSystemToolkit` (lean) and deepagents' filesystem tools (`ls`/`glob`/`grep`, deep) — the
|
|
30
|
+
* two sets overlap on `read_file`/`write_file`/`edit_file`, which is exactly why one flat table
|
|
31
|
+
* keyed by name serves both.
|
|
32
|
+
*
|
|
33
|
+
* Deliberately absent: `run_shell_command`, the fixed dev-command tools, `gth_web_fetch`,
|
|
34
|
+
* `gth_checklist`, `gth_status_update`, `show_a2ui_surface`, MCP/custom/A2A tools. None of them is
|
|
35
|
+
* "reading or writing files in the working folder", so none is granted by a rung's access class.
|
|
36
|
+
* (They are still *granted today* — the gate does not gate them — which {@link isGrantedAtRung}
|
|
37
|
+
* decides on the gated set, not on this table.)
|
|
38
|
+
*/
|
|
39
|
+
export const BUILT_IN_TOOL_ACCESS = {
|
|
40
|
+
// gsloth GthFileSystemToolkit (lean backend)
|
|
41
|
+
read_file: 'read',
|
|
42
|
+
read_multiple_files: 'read',
|
|
43
|
+
gth_read_binary: 'read',
|
|
44
|
+
list_directory: 'read',
|
|
45
|
+
list_directory_with_sizes: 'read',
|
|
46
|
+
directory_tree: 'read',
|
|
47
|
+
search_files: 'read',
|
|
48
|
+
get_file_info: 'read',
|
|
49
|
+
list_allowed_directories: 'read',
|
|
50
|
+
write_file: 'write',
|
|
51
|
+
edit_file: 'write',
|
|
52
|
+
create_directory: 'write',
|
|
53
|
+
move_file: 'write',
|
|
54
|
+
delete_file: 'write',
|
|
55
|
+
delete_directory: 'write',
|
|
56
|
+
// deepagents filesystem tools (deep backend) not already named above
|
|
57
|
+
ls: 'read',
|
|
58
|
+
glob: 'read',
|
|
59
|
+
grep: 'read',
|
|
60
|
+
// gsloth built-ins that read file contents in the working folder
|
|
61
|
+
gth_grep: 'read',
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* §4.3/§4.4 — the one-line descriptions handed to the rater with the granted tools' names.
|
|
65
|
+
*
|
|
66
|
+
* **Authored here on purpose.** §4.3 admits this list as *"trusted, locally-generated text, not
|
|
67
|
+
* part of the fenced block"*, so it may not be assembled from tool `description` fields at large:
|
|
68
|
+
* an MCP server's tool description is attacker-influenceable text, and placing it outside the
|
|
69
|
+
* fenced block would open an injection channel straight past the rater's untrusted-input preamble.
|
|
70
|
+
* Only tools named in THIS table are ever offered, so an MCP, custom or A2A tool can never
|
|
71
|
+
* contribute text to the rater prompt.
|
|
72
|
+
*
|
|
73
|
+
* Restricted to tools that could plausibly stand in for a shell command — the file tools, content
|
|
74
|
+
* search, and the fixed dev-command tools (whose command is human-authored config, so suggesting
|
|
75
|
+
* `run_tests` over `npm test` is exactly the trade this section exists to make). `gth_checklist`,
|
|
76
|
+
* `gth_status_update` and `show_a2ui_surface` are omitted: they substitute for nothing a model
|
|
77
|
+
* would otherwise shell out for, and a suggestion list is only useful while it is short.
|
|
78
|
+
*
|
|
79
|
+
* **`gth_web_fetch` is deliberately NOT here**, though it is ungated at every rung. §4.5's
|
|
80
|
+
* justification for disclosing the posture at all is that the granted tools are "by construction,
|
|
81
|
+
* the constrained ones confined to the working folder" — a network fetch is not. Offering it would
|
|
82
|
+
* let a refused `curl`/`wget` come back as a suggestion whose §7 clause tells the model, verbatim,
|
|
83
|
+
* that the alternative "will not interrupt the user": a refused egress turned into a free one,
|
|
84
|
+
* through the rater rather than through the gate. An `attack` halts before any message reaches the
|
|
85
|
+
* model, but a merely `destructive` fetch would not. Same reasoning excludes MCP and custom tools,
|
|
86
|
+
* which additionally supply text we did not author.
|
|
87
|
+
*/
|
|
88
|
+
export const BUILT_IN_TOOL_SUMMARIES = {
|
|
89
|
+
read_file: 'Read one file in the working folder.',
|
|
90
|
+
read_multiple_files: 'Read several files in the working folder in one call.',
|
|
91
|
+
gth_read_binary: 'Read an image or other binary file in the working folder.',
|
|
92
|
+
list_directory: 'List the entries of a directory in the working folder.',
|
|
93
|
+
list_directory_with_sizes: 'List a directory in the working folder with entry sizes.',
|
|
94
|
+
directory_tree: 'Show a recursive tree of a directory in the working folder.',
|
|
95
|
+
search_files: 'Find files in the working folder by name pattern.',
|
|
96
|
+
get_file_info: 'Show size, timestamps and type of a file in the working folder.',
|
|
97
|
+
list_allowed_directories: 'List the directories the file tools are allowed to touch.',
|
|
98
|
+
write_file: 'Create or overwrite a file in the working folder.',
|
|
99
|
+
edit_file: 'Apply a targeted edit to a file in the working folder.',
|
|
100
|
+
create_directory: 'Create a directory in the working folder.',
|
|
101
|
+
move_file: 'Move or rename a file in the working folder.',
|
|
102
|
+
delete_file: 'Delete a file in the working folder.',
|
|
103
|
+
delete_directory: 'Delete a directory in the working folder.',
|
|
104
|
+
ls: 'List the entries of a directory in the working folder.',
|
|
105
|
+
glob: 'Find files in the working folder by glob pattern.',
|
|
106
|
+
grep: 'Search file contents in the working folder by regular expression.',
|
|
107
|
+
gth_grep: 'Search file contents in the working folder by regular expression.',
|
|
108
|
+
run_tests: "Run the project's configured test command.",
|
|
109
|
+
run_single_test: "Run one test file with the project's configured test command.",
|
|
110
|
+
run_lint: "Run the project's configured lint command.",
|
|
111
|
+
run_build: "Run the project's configured build command.",
|
|
112
|
+
};
|
|
113
|
+
/** The sentence §4.5 appends at this rung, or `null` when the rung appends nothing (`bypass`). */
|
|
114
|
+
export function getRungToolDescriptionSuffix(rung) {
|
|
115
|
+
return RUNG_TOOL_DESCRIPTION_SUFFIXES[rung] ?? null;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Is `toolName` auto-approved (granted, free, no prompt and no rating) at `rung`?
|
|
119
|
+
*
|
|
120
|
+
* @param toolName The registered tool name.
|
|
121
|
+
* @param rung The rung in force for the session.
|
|
122
|
+
* @param gatedTools The names the gate actually wires into the approval interrupt. **This is the
|
|
123
|
+
* parameter that keeps the descriptions honest**: a tool the gate does not gate cannot require
|
|
124
|
+
* approval, whatever a rung's table row says about tool classes, so it is granted. Both backends
|
|
125
|
+
* pass the same set they hand to `interruptOn` / `humanInTheLoopMiddleware`.
|
|
126
|
+
*
|
|
127
|
+
* Order:
|
|
128
|
+
* 1. `bypass` grants everything (§2.5) — the gate is off.
|
|
129
|
+
* 2. A tool the gate does not gate is granted at every rung (§4.3's scope boundary).
|
|
130
|
+
* 3. A gated tool is granted only where the rung's own grant covers its access class: read tools
|
|
131
|
+
* from `read-only` up (§2.1), write tools from `write` up (§2.2, and §2.3/§2.4 which grant
|
|
132
|
+
* "everything `write` grants"). A gated tool with no access class — the shell, a network call,
|
|
133
|
+
* an MCP tool — is granted at no rung but `bypass`.
|
|
134
|
+
*/
|
|
135
|
+
export function isGrantedAtRung(toolName, rung, gatedTools) {
|
|
136
|
+
if (rung === 'bypass')
|
|
137
|
+
return true;
|
|
138
|
+
if (!gatedTools.includes(toolName))
|
|
139
|
+
return true;
|
|
140
|
+
const access = BUILT_IN_TOOL_ACCESS[toolName];
|
|
141
|
+
if (access === 'read')
|
|
142
|
+
return true;
|
|
143
|
+
if (access === 'write')
|
|
144
|
+
return rung !== 'read-only';
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Remove a previously-appended §4.5 suffix (any rung's), returning the tool's own description.
|
|
149
|
+
*
|
|
150
|
+
* Makes {@link applyRungAwareToolDescriptions} idempotent and re-appliable at a different rung —
|
|
151
|
+
* which matters because a resolver may hand back the SAME tool instance on a re-init (an MCP
|
|
152
|
+
* client caches its tool objects), and a second pass would otherwise stack sentences.
|
|
153
|
+
*/
|
|
154
|
+
export function stripRungToolDescriptionSuffix(description) {
|
|
155
|
+
let result = description;
|
|
156
|
+
// Loop: a description that was appended to twice by an older build still ends up clean.
|
|
157
|
+
let changed = true;
|
|
158
|
+
while (changed) {
|
|
159
|
+
changed = false;
|
|
160
|
+
for (const suffix of ALL_SUFFIXES) {
|
|
161
|
+
if (result.endsWith(suffix)) {
|
|
162
|
+
result = result.slice(0, -suffix.length).replace(/\s+$/, '');
|
|
163
|
+
changed = true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* §4.5 — at tool-registration time, append the rung's sentence to the description of every tool
|
|
171
|
+
* that is NOT auto-approved at that rung, and leave every granted tool's description untouched.
|
|
172
|
+
*
|
|
173
|
+
* Mutates in place (and returns the same array): the tools are about to be handed to
|
|
174
|
+
* `createAgent`/`createDeepAgent`, and the array is freshly resolved per init. Idempotent — any
|
|
175
|
+
* previously-appended suffix is stripped first, so re-registration at a different rung replaces
|
|
176
|
+
* the sentence rather than stacking one.
|
|
177
|
+
*
|
|
178
|
+
* A tool with no name is left alone (provider-native "magic object" tools carry no name and cannot
|
|
179
|
+
* be classified); a tool with an empty description gets the suffix as its whole description rather
|
|
180
|
+
* than a leading space.
|
|
181
|
+
*/
|
|
182
|
+
export function applyRungAwareToolDescriptions(tools, options) {
|
|
183
|
+
const suffix = getRungToolDescriptionSuffix(options.rung);
|
|
184
|
+
for (const tool of tools) {
|
|
185
|
+
if (!tool || typeof tool.name !== 'string' || tool.name.length === 0)
|
|
186
|
+
continue;
|
|
187
|
+
if (typeof tool.description !== 'string')
|
|
188
|
+
continue;
|
|
189
|
+
const base = stripRungToolDescriptionSuffix(tool.description);
|
|
190
|
+
// A granted tool carries NO sentence — its absence is what marks it free (§4.5).
|
|
191
|
+
if (suffix === null || isGrantedAtRung(tool.name, options.rung, options.gatedTools)) {
|
|
192
|
+
tool.description = base;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
tool.description = base.length > 0 ? `${base} ${suffix}` : suffix;
|
|
196
|
+
}
|
|
197
|
+
return tools;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* §4.3/§4.4 — the names and one-line descriptions of the built-in tools already granted at `rung`,
|
|
201
|
+
* for the rater prompt.
|
|
202
|
+
*
|
|
203
|
+
* Filtered three ways, each of which matters:
|
|
204
|
+
* - to tools **actually registered** in this session (a suggestion naming a tool the model does not
|
|
205
|
+
* have is worse than no suggestion);
|
|
206
|
+
* - to tools in {@link BUILT_IN_TOOL_SUMMARIES}, so only locally-authored text ever reaches the
|
|
207
|
+
* rater prompt (never an MCP/custom tool's own description);
|
|
208
|
+
* - to tools **granted at the rung** — suggesting a tool that would itself need approval defeats
|
|
209
|
+
* the point.
|
|
210
|
+
*
|
|
211
|
+
* Order follows the registration order so the prompt is stable across runs.
|
|
212
|
+
*/
|
|
213
|
+
export function describeGrantedBuiltInTools(registeredToolNames, rung, gatedTools) {
|
|
214
|
+
const seen = new Set();
|
|
215
|
+
const summaries = [];
|
|
216
|
+
for (const name of registeredToolNames) {
|
|
217
|
+
if (seen.has(name))
|
|
218
|
+
continue;
|
|
219
|
+
seen.add(name);
|
|
220
|
+
const description = BUILT_IN_TOOL_SUMMARIES[name];
|
|
221
|
+
if (!description)
|
|
222
|
+
continue;
|
|
223
|
+
if (!isGrantedAtRung(name, rung, gatedTools))
|
|
224
|
+
continue;
|
|
225
|
+
summaries.push({ name, description });
|
|
226
|
+
}
|
|
227
|
+
return summaries;
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=tool-descriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-descriptions.js","sourceRoot":"","sources":["../../src/config/tool-descriptions.ts"],"names":[],"mappings":"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"}
|
package/dist/config/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
8
8
|
import type { BaseToolkit, StructuredToolInterface } from '@langchain/core/tools';
|
|
9
9
|
import type { StatusLevel } from '#src/core/types.js';
|
|
10
|
-
import type { BuiltInToolsSetting } from '#src/config/shell-policy.js';
|
|
10
|
+
import type { ApprovalsConfig, BuiltInToolsSetting } from '#src/config/shell-policy.js';
|
|
11
11
|
/**
|
|
12
12
|
* GS2-43 — the seven configurable prompt segments. Each maps to a prompt file with a
|
|
13
13
|
* well-known default name (`.gsloth.backstory.md`, `.gsloth.guidelines.md`,
|
|
@@ -59,6 +59,12 @@ export type PromptsConfig = Partial<Record<PromptSegmentName, PromptSegmentSetti
|
|
|
59
59
|
export interface CommandToolingConfig {
|
|
60
60
|
filesystem?: string[] | 'all' | 'read' | 'none';
|
|
61
61
|
builtInTools?: BuiltInToolsSetting;
|
|
62
|
+
/**
|
|
63
|
+
* §9.1 — per-command approvals posture. It overrides only the fields it NAMES: `mode`,
|
|
64
|
+
* `rater`, `raterTimeoutMs` and `allow` replace the root's, while `deny` and `escalate`
|
|
65
|
+
* concatenate with it. See {@link GthConfig.approvals}.
|
|
66
|
+
*/
|
|
67
|
+
approvals?: ApprovalsConfig;
|
|
62
68
|
customTools?: CustomToolsConfig | false;
|
|
63
69
|
/** See {@link GthConfig.allowedTools}. */
|
|
64
70
|
allowedTools?: string[];
|
|
@@ -187,6 +193,22 @@ export interface GthConfig {
|
|
|
187
193
|
* a per-command value replaces the top-level one.
|
|
188
194
|
*/
|
|
189
195
|
builtInTools?: BuiltInToolsSetting;
|
|
196
|
+
/**
|
|
197
|
+
* CFG-27 — the tool-approval **ladder**: one of the five rungs (`read-only` · `write` ·
|
|
198
|
+
* `auto-safe` · `full-auto` · `bypass`), written either as the bare rung name or as an object
|
|
199
|
+
* carrying the rater's identity profile and the declared allow/deny lists. Each rung fully
|
|
200
|
+
* determines behaviour — there are no severity thresholds, no strictness levels and no
|
|
201
|
+
* independent rater switch.
|
|
202
|
+
*
|
|
203
|
+
* Settable at the root or per command (`commands.<command>.approvals`). §9.1 — a per-command
|
|
204
|
+
* value overrides only the fields it NAMES. `mode`, `rater` and `raterTimeoutMs` replace the
|
|
205
|
+
* root's; `deny` and `escalate` CONCATENATE across every scope, so a per-command rung can never
|
|
206
|
+
* discard the root's prohibitions; `allow` is REPLACED when the command states its own and
|
|
207
|
+
* inherited when it does not, so a scope may narrow what runs unprompted and may never widen
|
|
208
|
+
* what is prohibited (§3.1: a too-broad allow entry runs unrated, a missed deny entry does not).
|
|
209
|
+
* Absent = `auto-safe`, resolved by `resolveApprovals`.
|
|
210
|
+
*/
|
|
211
|
+
approvals?: ApprovalsConfig;
|
|
190
212
|
tools?: StructuredToolInterface[] | BaseToolkit[] | ServerTool[];
|
|
191
213
|
/**
|
|
192
214
|
* Restrict the agent to this allow-list of tool names, applied after every tool source
|
|
@@ -262,6 +284,13 @@ export interface GthConfig {
|
|
|
262
284
|
* Use colour in output
|
|
263
285
|
*/
|
|
264
286
|
useColour: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Enable terminal mouse reporting in the Ink TUI, making its affordances clickable.
|
|
289
|
+
* On by default in an interactive terminal. While it is on the terminal's own text selection
|
|
290
|
+
* needs a modifier (Shift, or Option in some macOS terminals) — set this to `false`, or set
|
|
291
|
+
* `GTH_NO_MOUSE`, to get unmodified selection back.
|
|
292
|
+
*/
|
|
293
|
+
useMouse: boolean;
|
|
265
294
|
/**
|
|
266
295
|
* Stream session log instead of writing it when inference streaming is complete.
|
|
267
296
|
* (only works when {@link streamOutput} is true)
|
|
@@ -351,6 +380,12 @@ export interface GthConfig {
|
|
|
351
380
|
api?: {
|
|
352
381
|
filesystem?: string[] | 'all' | 'read' | 'none';
|
|
353
382
|
builtInTools?: BuiltInToolsSetting;
|
|
383
|
+
/**
|
|
384
|
+
* §9.1 — per-command approvals posture. It overrides only the fields it NAMES: `mode`,
|
|
385
|
+
* `rater`, `raterTimeoutMs` and `allow` replace the root's, while `deny` and `escalate`
|
|
386
|
+
* concatenate with it. See {@link GthConfig.approvals}.
|
|
387
|
+
*/
|
|
388
|
+
approvals?: ApprovalsConfig;
|
|
354
389
|
port?: number;
|
|
355
390
|
cors?: {
|
|
356
391
|
allowOrigin?: string;
|
package/dist/config/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAwqBA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,UAAU;IACV,WAAW;IACX,MAAM;IACN,UAAU;IACV,QAAQ;IACR,cAAc;IACd,KAAK;IACL,YAAY;IACZ,aAAa;IACb,QAAQ;CACA,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -15,12 +15,15 @@
|
|
|
15
15
|
* - `config/defaults.ts` — {@link DEFAULT_CONFIG}.
|
|
16
16
|
* - `config/loader.ts` — discovery + the layered load/merge pipeline.
|
|
17
17
|
* - `config/schema.ts` — the Zod schema (single source of truth) + JSON-Schema generator.
|
|
18
|
+
* - `config/tool-descriptions.ts` — EXT-58: the rung-aware tool-description suffixes (§4.5) and
|
|
19
|
+
* the granted-built-in table the rater's alternative suggestion draws on (§4.4).
|
|
18
20
|
*
|
|
19
21
|
* Every name that was previously exported from `config.ts` is re-exported here, so the
|
|
20
22
|
* public import path `@gaunt-sloth/core/config.js` (and `#src/config.js`) is unchanged.
|
|
21
23
|
*/
|
|
22
24
|
export * from '#src/config/types.js';
|
|
23
25
|
export * from '#src/config/shell-policy.js';
|
|
26
|
+
export * from '#src/config/tool-descriptions.js';
|
|
24
27
|
export * from '#src/config/defaults.js';
|
|
25
28
|
export * from '#src/config/loader.js';
|
|
26
29
|
export * from '#src/config/profiles.js';
|
package/dist/config.js
CHANGED
|
@@ -15,12 +15,15 @@
|
|
|
15
15
|
* - `config/defaults.ts` — {@link DEFAULT_CONFIG}.
|
|
16
16
|
* - `config/loader.ts` — discovery + the layered load/merge pipeline.
|
|
17
17
|
* - `config/schema.ts` — the Zod schema (single source of truth) + JSON-Schema generator.
|
|
18
|
+
* - `config/tool-descriptions.ts` — EXT-58: the rung-aware tool-description suffixes (§4.5) and
|
|
19
|
+
* the granted-built-in table the rater's alternative suggestion draws on (§4.4).
|
|
18
20
|
*
|
|
19
21
|
* Every name that was previously exported from `config.ts` is re-exported here, so the
|
|
20
22
|
* public import path `@gaunt-sloth/core/config.js` (and `#src/config.js`) is unchanged.
|
|
21
23
|
*/
|
|
22
24
|
export * from '#src/config/types.js';
|
|
23
25
|
export * from '#src/config/shell-policy.js';
|
|
26
|
+
export * from '#src/config/tool-descriptions.js';
|
|
24
27
|
export * from '#src/config/defaults.js';
|
|
25
28
|
export * from '#src/config/loader.js';
|
|
26
29
|
export * from '#src/config/profiles.js';
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { GthConfig, ServerTool } from '#src/config.js';
|
|
1
|
+
import { GthConfig, ServerTool, type ApprovalRung, type DescribableTool } from '#src/config.js';
|
|
2
2
|
import { AgentResolvers, AgentStreamEvent, GthAgentInterface, GthCommand, GthCompiledGraph, GthRunStats, Message, PendingToolInterrupt, StatusUpdateCallback } from '#src/core/types.js';
|
|
3
|
+
import type { DeclaredToolAnnotations } from '#src/core/approvals/annotations.js';
|
|
3
4
|
import type { DebugCapture, DebugRequestExtras, LastModelRequest } from '#src/core/debugCapture.js';
|
|
4
5
|
import { AIMessageChunk, BaseMessage } from '@langchain/core/messages';
|
|
5
6
|
import { RunnableConfig } from '@langchain/core/runnables';
|
|
@@ -75,6 +76,22 @@ export declare abstract class GthAbstractAgent implements GthAgentInterface {
|
|
|
75
76
|
* fully fail-soft (accumulation is guarded and never throws into a run).
|
|
76
77
|
*/
|
|
77
78
|
private runStatsAcc;
|
|
79
|
+
/**
|
|
80
|
+
* EXT-58 — the names of the tools registered with the graph at the last {@link init}, recorded by
|
|
81
|
+
* {@link registerApprovalsAwareTools}. Read by `GthAgentRunner` to build the rater's
|
|
82
|
+
* granted-built-in list (§4.4), so a suggestion can only ever name a tool the model actually has.
|
|
83
|
+
*/
|
|
84
|
+
private registeredToolNames;
|
|
85
|
+
/**
|
|
86
|
+
* EXT-70 §4.7.1 — what the connected MCP servers DECLARED about their own tools, captured from
|
|
87
|
+
* the same registration hook as {@link registeredToolNames} and keyed by the registered tool
|
|
88
|
+
* name. Read by `GthAgentRunner` as the `mcp` half of a `DeclaredToolAnnotationLookup`.
|
|
89
|
+
*
|
|
90
|
+
* It is a record of claims, never of decisions: no trust is applied here (that is
|
|
91
|
+
* `createEffectiveToolAnnotationSource`'s only job), and an absent tool yields the fail-closed
|
|
92
|
+
* defaults rather than "declared nothing".
|
|
93
|
+
*/
|
|
94
|
+
private declaredMcpToolAnnotations;
|
|
78
95
|
constructor(statusUpdate: StatusUpdateCallback, resolvers?: AgentResolvers);
|
|
79
96
|
/**
|
|
80
97
|
* GS2-63 — emit one line of the technical run-header preamble (the Workdir/Model/Tools/Middleware
|
|
@@ -85,6 +102,47 @@ export declare abstract class GthAbstractAgent implements GthAgentInterface {
|
|
|
85
102
|
* output, warnings and errors keep using {@link statusUpdate} directly.
|
|
86
103
|
*/
|
|
87
104
|
protected headerStatus(message: string): void;
|
|
105
|
+
/**
|
|
106
|
+
* EXT-58 (spec §4.5) — the ONE tool-registration hook both backends call with their final tool
|
|
107
|
+
* array, just before handing it to the graph builder. It does two things:
|
|
108
|
+
*
|
|
109
|
+
* 1. Appends the rung's approval sentence to every tool that is **not** auto-approved at that
|
|
110
|
+
* rung, and leaves every granted tool's description untouched (the absence of the sentence is
|
|
111
|
+
* what marks a tool free). See {@link applyRungAwareToolDescriptions}.
|
|
112
|
+
* 2. Records the registered tool names for {@link getRegisteredToolNames}, which feeds the
|
|
113
|
+
* rater's granted-alternative list (§4.4).
|
|
114
|
+
* 3. EXT-70 §4.7.1 — records what the MCP servers declared about their own tools, for
|
|
115
|
+
* {@link getDeclaredMcpToolAnnotations}. This is the ONE place a `tools/list` annotation
|
|
116
|
+
* enters the approvals stack, and it enters as a claim: nothing here decides whether it is
|
|
117
|
+
* believed.
|
|
118
|
+
*
|
|
119
|
+
* `gatedTools` MUST be the same set the caller wires into the approval interrupt
|
|
120
|
+
* (`humanInTheLoopMiddleware`'s `interruptOn` on lean, deepagents' `interruptOn` on deep). That
|
|
121
|
+
* shared parameter is what makes it impossible for a description to promise an approval the gate
|
|
122
|
+
* will not ask for — §4.5's "a description that disagrees with what the gate will actually do is
|
|
123
|
+
* worse than no description at all".
|
|
124
|
+
*
|
|
125
|
+
* `additionalToolNames` covers tools the graph builder registers itself and that therefore never
|
|
126
|
+
* appear in `tools` — deepagents' own filesystem tools on the deep backend. Their descriptions
|
|
127
|
+
* are deepagents', not ours, so they cannot be suffixed here; they are recorded only so the
|
|
128
|
+
* rater's suggestion list reflects what the deep model actually has.
|
|
129
|
+
*/
|
|
130
|
+
protected registerApprovalsAwareTools<T extends DescribableTool>(tools: T[], options: {
|
|
131
|
+
rung: ApprovalRung;
|
|
132
|
+
gatedTools: readonly string[];
|
|
133
|
+
additionalToolNames?: readonly string[];
|
|
134
|
+
}): T[];
|
|
135
|
+
/**
|
|
136
|
+
* EXT-58 — the tool names registered with the graph at the last {@link init} (empty before it).
|
|
137
|
+
* The runner intersects these with the built-in summaries table to build the rater's
|
|
138
|
+
* granted-alternative list, so the rater can never name a tool this session does not have.
|
|
139
|
+
*/
|
|
140
|
+
getRegisteredToolNames(): string[];
|
|
141
|
+
/**
|
|
142
|
+
* EXT-70 §4.7.1 — what the MCP servers declared for their tools at the last {@link init}, keyed
|
|
143
|
+
* by registered tool name (empty before it, and on a session with no MCP servers).
|
|
144
|
+
*/
|
|
145
|
+
getDeclaredMcpToolAnnotations(): ReadonlyMap<string, DeclaredToolAnnotations>;
|
|
88
146
|
/**
|
|
89
147
|
* GS2-16 — clear the per-run analytics tally so the next turn starts from zero. The runner
|
|
90
148
|
* calls this at each turn boundary because it (and this agent) are reused across turns in an
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { applyRungAwareToolDescriptions, } from '#src/config.js';
|
|
1
2
|
import { StatusLevel, } from '#src/core/types.js';
|
|
2
3
|
import { accumulateMessage, createRunStatsAccumulator, finalizeRunStats, } from '#src/core/runStats.js';
|
|
4
|
+
import { collectDeclaredMcpToolAnnotations } from '#src/core/approvals/toolAnnotationSources.js';
|
|
3
5
|
import { createPlainToolIndication } from '#src/core/plainToolIndication.js';
|
|
4
6
|
import { debugLog, debugLogError, debugLogObject } from '#src/utils/debugUtils.js';
|
|
5
7
|
import { ProgressIndicator } from '#src/utils/ProgressIndicator.js';
|
|
@@ -205,6 +207,22 @@ export class GthAbstractAgent {
|
|
|
205
207
|
* fully fail-soft (accumulation is guarded and never throws into a run).
|
|
206
208
|
*/
|
|
207
209
|
runStatsAcc = createRunStatsAccumulator();
|
|
210
|
+
/**
|
|
211
|
+
* EXT-58 — the names of the tools registered with the graph at the last {@link init}, recorded by
|
|
212
|
+
* {@link registerApprovalsAwareTools}. Read by `GthAgentRunner` to build the rater's
|
|
213
|
+
* granted-built-in list (§4.4), so a suggestion can only ever name a tool the model actually has.
|
|
214
|
+
*/
|
|
215
|
+
registeredToolNames = [];
|
|
216
|
+
/**
|
|
217
|
+
* EXT-70 §4.7.1 — what the connected MCP servers DECLARED about their own tools, captured from
|
|
218
|
+
* the same registration hook as {@link registeredToolNames} and keyed by the registered tool
|
|
219
|
+
* name. Read by `GthAgentRunner` as the `mcp` half of a `DeclaredToolAnnotationLookup`.
|
|
220
|
+
*
|
|
221
|
+
* It is a record of claims, never of decisions: no trust is applied here (that is
|
|
222
|
+
* `createEffectiveToolAnnotationSource`'s only job), and an absent tool yields the fail-closed
|
|
223
|
+
* defaults rather than "declared nothing".
|
|
224
|
+
*/
|
|
225
|
+
declaredMcpToolAnnotations = new Map();
|
|
208
226
|
constructor(statusUpdate, resolvers) {
|
|
209
227
|
this.statusUpdate = (level, message) => {
|
|
210
228
|
statusUpdate(level, message);
|
|
@@ -224,6 +242,60 @@ export class GthAbstractAgent {
|
|
|
224
242
|
return;
|
|
225
243
|
this.statusUpdate(StatusLevel.INFO, message);
|
|
226
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* EXT-58 (spec §4.5) — the ONE tool-registration hook both backends call with their final tool
|
|
247
|
+
* array, just before handing it to the graph builder. It does two things:
|
|
248
|
+
*
|
|
249
|
+
* 1. Appends the rung's approval sentence to every tool that is **not** auto-approved at that
|
|
250
|
+
* rung, and leaves every granted tool's description untouched (the absence of the sentence is
|
|
251
|
+
* what marks a tool free). See {@link applyRungAwareToolDescriptions}.
|
|
252
|
+
* 2. Records the registered tool names for {@link getRegisteredToolNames}, which feeds the
|
|
253
|
+
* rater's granted-alternative list (§4.4).
|
|
254
|
+
* 3. EXT-70 §4.7.1 — records what the MCP servers declared about their own tools, for
|
|
255
|
+
* {@link getDeclaredMcpToolAnnotations}. This is the ONE place a `tools/list` annotation
|
|
256
|
+
* enters the approvals stack, and it enters as a claim: nothing here decides whether it is
|
|
257
|
+
* believed.
|
|
258
|
+
*
|
|
259
|
+
* `gatedTools` MUST be the same set the caller wires into the approval interrupt
|
|
260
|
+
* (`humanInTheLoopMiddleware`'s `interruptOn` on lean, deepagents' `interruptOn` on deep). That
|
|
261
|
+
* shared parameter is what makes it impossible for a description to promise an approval the gate
|
|
262
|
+
* will not ask for — §4.5's "a description that disagrees with what the gate will actually do is
|
|
263
|
+
* worse than no description at all".
|
|
264
|
+
*
|
|
265
|
+
* `additionalToolNames` covers tools the graph builder registers itself and that therefore never
|
|
266
|
+
* appear in `tools` — deepagents' own filesystem tools on the deep backend. Their descriptions
|
|
267
|
+
* are deepagents', not ours, so they cannot be suffixed here; they are recorded only so the
|
|
268
|
+
* rater's suggestion list reflects what the deep model actually has.
|
|
269
|
+
*/
|
|
270
|
+
registerApprovalsAwareTools(tools, options) {
|
|
271
|
+
applyRungAwareToolDescriptions(tools, {
|
|
272
|
+
rung: options.rung,
|
|
273
|
+
gatedTools: options.gatedTools,
|
|
274
|
+
});
|
|
275
|
+
const names = tools
|
|
276
|
+
.map((tool) => tool?.name)
|
|
277
|
+
.filter((name) => typeof name === 'string' && name.length > 0);
|
|
278
|
+
this.registeredToolNames = [...names, ...(options.additionalToolNames ?? [])];
|
|
279
|
+
// `additionalToolNames` are deliberately NOT consulted: they are names the graph builder
|
|
280
|
+
// registers itself, with no tool object and therefore no declaration to read.
|
|
281
|
+
this.declaredMcpToolAnnotations = collectDeclaredMcpToolAnnotations(tools);
|
|
282
|
+
return tools;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* EXT-58 — the tool names registered with the graph at the last {@link init} (empty before it).
|
|
286
|
+
* The runner intersects these with the built-in summaries table to build the rater's
|
|
287
|
+
* granted-alternative list, so the rater can never name a tool this session does not have.
|
|
288
|
+
*/
|
|
289
|
+
getRegisteredToolNames() {
|
|
290
|
+
return [...this.registeredToolNames];
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* EXT-70 §4.7.1 — what the MCP servers declared for their tools at the last {@link init}, keyed
|
|
294
|
+
* by registered tool name (empty before it, and on a session with no MCP servers).
|
|
295
|
+
*/
|
|
296
|
+
getDeclaredMcpToolAnnotations() {
|
|
297
|
+
return this.declaredMcpToolAnnotations;
|
|
298
|
+
}
|
|
227
299
|
/**
|
|
228
300
|
* GS2-16 — clear the per-run analytics tally so the next turn starts from zero. The runner
|
|
229
301
|
* calls this at each turn boundary because it (and this agent) are reused across turns in an
|