@gaunt-sloth/core 2.0.0-alpha.2 → 2.0.0-alpha.4

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.
Files changed (53) hide show
  1. package/.gsloth.code.md +10 -0
  2. package/README.md +3 -4
  3. package/dist/config/defaults.d.ts +84 -0
  4. package/dist/config/defaults.js +97 -0
  5. package/dist/config/defaults.js.map +1 -0
  6. package/dist/config/loader.d.ts +88 -0
  7. package/dist/config/loader.js +604 -0
  8. package/dist/config/loader.js.map +1 -0
  9. package/dist/config/schema.d.ts +471 -0
  10. package/dist/config/schema.js +301 -0
  11. package/dist/config/schema.js.map +1 -0
  12. package/dist/config/shell-policy.d.ts +212 -0
  13. package/dist/config/shell-policy.js +142 -0
  14. package/dist/config/shell-policy.js.map +1 -0
  15. package/dist/config/types.d.ts +453 -0
  16. package/dist/config/types.js +12 -0
  17. package/dist/config/types.js.map +1 -0
  18. package/dist/config.d.ts +18 -647
  19. package/dist/config.js +15 -516
  20. package/dist/config.js.map +1 -1
  21. package/dist/constants.d.ts +6 -0
  22. package/dist/constants.js +6 -0
  23. package/dist/constants.js.map +1 -1
  24. package/dist/core/GthAbstractAgent.d.ts +24 -1
  25. package/dist/core/GthAbstractAgent.js +86 -4
  26. package/dist/core/GthAbstractAgent.js.map +1 -1
  27. package/dist/core/GthAgentRunner.d.ts +127 -1
  28. package/dist/core/GthAgentRunner.js +298 -4
  29. package/dist/core/GthAgentRunner.js.map +1 -1
  30. package/dist/core/shell/allowlist.d.ts +75 -0
  31. package/dist/core/shell/allowlist.js +187 -0
  32. package/dist/core/shell/allowlist.js.map +1 -0
  33. package/dist/core/shell/arity.d.ts +75 -0
  34. package/dist/core/shell/arity.js +313 -0
  35. package/dist/core/shell/arity.js.map +1 -0
  36. package/dist/core/shell/judge.d.ts +161 -0
  37. package/dist/core/shell/judge.js +261 -0
  38. package/dist/core/shell/judge.js.map +1 -0
  39. package/dist/core/shell/normalize.d.ts +27 -0
  40. package/dist/core/shell/normalize.js +53 -0
  41. package/dist/core/shell/normalize.js.map +1 -0
  42. package/dist/core/types.d.ts +75 -0
  43. package/dist/core/types.js.map +1 -1
  44. package/dist/providers/openrouter.js +2 -2
  45. package/dist/providers/openrouter.js.map +1 -1
  46. package/dist/utils/fileUtils.d.ts +4 -1
  47. package/dist/utils/fileUtils.js +19 -10
  48. package/dist/utils/fileUtils.js.map +1 -1
  49. package/dist/utils/systemUtils.d.ts +31 -0
  50. package/dist/utils/systemUtils.js +38 -0
  51. package/dist/utils/systemUtils.js.map +1 -1
  52. package/package.json +12 -8
  53. package/schema/gsloth-config.schema.json +1548 -0
@@ -0,0 +1,301 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Zod schema for the on-disk raw Gaunt Sloth config (`RawGthConfig`).
4
+ *
5
+ * This is the single source of truth for config validation and for the generated
6
+ * JSON Schema (`packages/core/schema/gsloth-config.schema.json`). It models the
7
+ * canonical config shape only — the deprecated aliases (`contentProvider`,
8
+ * `requirementsProvider`, `contentProviderConfig`, `requirementsProviderConfig`)
9
+ * are intentionally NOT part of the schema. The loader maps those one-way to the
10
+ * canonical names ({@link preMapDeprecatedConfigNames}) BEFORE validating, so by
11
+ * the time a config reaches the schema it only uses canonical names.
12
+ *
13
+ * Design notes:
14
+ * - The top-level object is a {@link z.looseObject} so unknown keys PASS THROUGH
15
+ * (they are neither stripped nor a hard failure). The loader separately diffs
16
+ * present-vs-known top-level keys ({@link findUnknownTopLevelKeys}) to warn about
17
+ * likely typos without failing.
18
+ * - Every field is optional. The schema validates the *shape/type of what is
19
+ * present*, not requiredness. In particular `llm` is optional so the loader's
20
+ * existing "must at least define llm.type" checks remain the authority on llm
21
+ * validity (and keep emitting their established messages).
22
+ * - Runtime-object-bearing fields (`tools`, `middleware`, `mcpServers`,
23
+ * `a2aAgents`, `builtInToolsConfig`) are modelled permissively because JS/MJS
24
+ * `configure()` returns live instances/objects there.
25
+ *
26
+ * The exported {@link RawGthConfig}/{@link GthConfig} interfaces in `config.ts`
27
+ * remain the public type surface; the `z.infer` here ({@link RawGthConfigInput})
28
+ * is additive and legitimately differs (no deprecated fields).
29
+ */
30
+ import { z } from 'zod';
31
+ const filesystemSchema = z.union([z.array(z.string()), z.enum(['all', 'read', 'none'])]);
32
+ const llmConfigSchema = z.looseObject({
33
+ type: z.string().optional(),
34
+ model: z.string().optional(),
35
+ configuration: z.record(z.string(), z.unknown()).optional(),
36
+ apiKeyEnvironmentVariable: z.string().optional(),
37
+ });
38
+ const ratingConfigSchema = z.object({
39
+ enabled: z.boolean().optional(),
40
+ passThreshold: z.number().optional(),
41
+ maxRating: z.number().optional(),
42
+ minRating: z.number().optional(),
43
+ errorOnReviewFail: z.boolean().optional(),
44
+ });
45
+ const customCommandParameterSchema = z.object({
46
+ description: z.string(),
47
+ allow: z
48
+ .array(z.enum(['absolute-paths', 'directory-traversal', 'shell-injection', 'null-bytes']))
49
+ .optional(),
50
+ });
51
+ const customCommandConfigSchema = z.object({
52
+ command: z.string(),
53
+ description: z.string(),
54
+ parameters: z.record(z.string(), customCommandParameterSchema).optional(),
55
+ timeout: z.number().optional(),
56
+ });
57
+ const customToolsConfigSchema = z.record(z.string(), customCommandConfigSchema);
58
+ const customToolsOrFalseSchema = z.union([z.literal(false), customToolsConfigSchema]);
59
+ const binaryFormatConfigSchema = z.object({
60
+ type: z.enum(['image', 'file', 'audio', 'video', 'binary']),
61
+ extensions: z.array(z.string()),
62
+ maxSize: z.number().optional(),
63
+ mimeTypes: z.record(z.string(), z.string()).optional(),
64
+ });
65
+ const binaryFormatsSchema = z.union([z.literal(false), z.array(binaryFormatConfigSchema)]);
66
+ const shellJudgeSchema = z.union([
67
+ z.boolean(),
68
+ z.object({
69
+ enabled: z.boolean().optional(),
70
+ autoApproveLow: z.boolean().optional(),
71
+ blockHigh: z.boolean().optional(),
72
+ model: llmConfigSchema.optional(),
73
+ }),
74
+ ]);
75
+ const shellConfigSchema = z.union([
76
+ z.boolean(),
77
+ z.object({
78
+ enabled: z.boolean().optional(),
79
+ timeout: z.number().optional(),
80
+ maxOutputBytes: z.number().optional(),
81
+ allowlist: z.boolean().optional(),
82
+ persistAllowlist: z.boolean().optional(),
83
+ judge: shellJudgeSchema.optional(),
84
+ }),
85
+ ]);
86
+ const devToolsConfigSchema = z.object({
87
+ run_tests: z.string().optional(),
88
+ run_lint: z.string().optional(),
89
+ run_build: z.string().optional(),
90
+ run_single_test: z.string().optional(),
91
+ shell: shellConfigSchema.optional(),
92
+ shellYolo: z.boolean().optional(),
93
+ });
94
+ const prCommandSchema = z.object({
95
+ contentSource: z.string().optional(),
96
+ requirementSource: z.string().optional(),
97
+ filesystem: filesystemSchema.optional(),
98
+ builtInTools: z.array(z.string()).optional(),
99
+ customTools: customToolsOrFalseSchema.optional(),
100
+ allowedTools: z.array(z.string()).optional(),
101
+ logWorkForReviewInSeconds: z.number().optional(),
102
+ rating: ratingConfigSchema.optional(),
103
+ binaryFormats: binaryFormatsSchema.optional(),
104
+ });
105
+ const reviewCommandSchema = z.object({
106
+ contentSource: z.string().optional(),
107
+ requirementSource: z.string().optional(),
108
+ filesystem: filesystemSchema.optional(),
109
+ builtInTools: z.array(z.string()).optional(),
110
+ customTools: customToolsOrFalseSchema.optional(),
111
+ allowedTools: z.array(z.string()).optional(),
112
+ rating: ratingConfigSchema.optional(),
113
+ binaryFormats: binaryFormatsSchema.optional(),
114
+ });
115
+ const askCommandSchema = z.object({
116
+ filesystem: filesystemSchema.optional(),
117
+ builtInTools: z.array(z.string()).optional(),
118
+ customTools: customToolsOrFalseSchema.optional(),
119
+ allowedTools: z.array(z.string()).optional(),
120
+ devTools: devToolsConfigSchema.optional(),
121
+ binaryFormats: binaryFormatsSchema.optional(),
122
+ });
123
+ const chatCommandSchema = z.object({
124
+ filesystem: filesystemSchema.optional(),
125
+ builtInTools: z.array(z.string()).optional(),
126
+ customTools: customToolsOrFalseSchema.optional(),
127
+ allowedTools: z.array(z.string()).optional(),
128
+ binaryFormats: binaryFormatsSchema.optional(),
129
+ });
130
+ const codeCommandSchema = z.object({
131
+ filesystem: filesystemSchema.optional(),
132
+ builtInTools: z.array(z.string()).optional(),
133
+ customTools: customToolsOrFalseSchema.optional(),
134
+ allowedTools: z.array(z.string()).optional(),
135
+ devTools: devToolsConfigSchema.optional(),
136
+ binaryFormats: binaryFormatsSchema.optional(),
137
+ });
138
+ const execCommandSchema = z.object({
139
+ filesystem: filesystemSchema.optional(),
140
+ builtInTools: z.array(z.string()).optional(),
141
+ customTools: customToolsOrFalseSchema.optional(),
142
+ allowedTools: z.array(z.string()).optional(),
143
+ devTools: devToolsConfigSchema.optional(),
144
+ binaryFormats: binaryFormatsSchema.optional(),
145
+ });
146
+ const apiCommandSchema = z.object({
147
+ filesystem: filesystemSchema.optional(),
148
+ builtInTools: z.array(z.string()).optional(),
149
+ port: z.number().optional(),
150
+ cors: z
151
+ .object({
152
+ allowOrigin: z.string().optional(),
153
+ allowMethods: z.string().optional(),
154
+ allowHeaders: z.string().optional(),
155
+ })
156
+ .optional(),
157
+ });
158
+ const commandsSchema = z.object({
159
+ pr: prCommandSchema.optional(),
160
+ review: reviewCommandSchema.optional(),
161
+ ask: askCommandSchema.optional(),
162
+ chat: chatCommandSchema.optional(),
163
+ code: codeCommandSchema.optional(),
164
+ exec: execCommandSchema.optional(),
165
+ api: apiCommandSchema.optional(),
166
+ });
167
+ /**
168
+ * Zod schema for the raw, on-disk Gaunt Sloth config. Loose at the top level so
169
+ * unknown keys are preserved (warn-only via {@link findUnknownTopLevelKeys}).
170
+ */
171
+ export const rawGthConfigSchema = z.looseObject({
172
+ // Allow a JSON Schema reference for editor support; never read at runtime.
173
+ $schema: z.string().optional(),
174
+ llm: llmConfigSchema.optional(),
175
+ binaryFormats: binaryFormatsSchema.optional(),
176
+ contentSource: z.string().optional(),
177
+ requirementSource: z.string().optional(),
178
+ contentSourceConfig: z.record(z.string(), z.unknown()).optional(),
179
+ requirementSourceConfig: z.record(z.string(), z.unknown()).optional(),
180
+ projectGuidelines: z.string().optional(),
181
+ identityProfile: z.string().optional(),
182
+ includeCurrentDateAfterGuidelines: z.boolean().optional(),
183
+ organization: z
184
+ .object({
185
+ name: z.string().optional(),
186
+ locale: z.string().optional(),
187
+ timezone: z.string().optional(),
188
+ })
189
+ .optional(),
190
+ projectReviewInstructions: z.string().optional(),
191
+ noDefaultPrompts: z.boolean().optional(),
192
+ filesystem: filesystemSchema.optional(),
193
+ builtInTools: z.array(z.string()).optional(),
194
+ // Live tool instances / toolkits in JS configs — kept permissive.
195
+ tools: z.array(z.unknown()).optional(),
196
+ allowedTools: z.array(z.string()).optional(),
197
+ // Predefined (string/object) or custom (object) middleware — permissive.
198
+ middleware: z.array(z.unknown()).optional(),
199
+ streamOutput: z.boolean().optional(),
200
+ writeOutputToFile: z.union([z.boolean(), z.string()]).optional(),
201
+ writeBinaryOutputsToFile: z.boolean().optional(),
202
+ useColour: z.boolean().optional(),
203
+ streamSessionInferenceLog: z.boolean().optional(),
204
+ canInterruptInferenceWithEsc: z.boolean().optional(),
205
+ debugLog: z.boolean().optional(),
206
+ recursionLimit: z.number().optional(),
207
+ consoleLevel: z.union([z.string(), z.number()]).optional(),
208
+ customTools: customToolsConfigSchema.optional(),
209
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
210
+ a2aAgents: z.record(z.string(), z.unknown()).optional(),
211
+ builtInToolsConfig: z.record(z.string(), z.unknown()).optional(),
212
+ aiignore: z
213
+ .object({
214
+ enabled: z.boolean().optional(),
215
+ patterns: z.array(z.string()).optional(),
216
+ })
217
+ .optional(),
218
+ commands: commandsSchema.optional(),
219
+ modelDisplayName: z.string().optional(),
220
+ allowDirs: z.array(z.string()).optional(),
221
+ askWriteMode: z.boolean().optional(),
222
+ });
223
+ /**
224
+ * The set of known top-level config keys, derived from the schema shape so it can
225
+ * never drift from {@link rawGthConfigSchema}. Includes `$schema`.
226
+ */
227
+ export const KNOWN_TOP_LEVEL_KEYS = new Set(Object.keys(rawGthConfigSchema.shape));
228
+ /**
229
+ * Return the top-level keys present in `raw` that are not part of the known config
230
+ * surface. Deprecated aliases should be pre-mapped away first (see
231
+ * {@link preMapDeprecatedConfigNames}) so they do not show up here.
232
+ */
233
+ export function findUnknownTopLevelKeys(raw) {
234
+ return Object.keys(raw).filter((key) => !KNOWN_TOP_LEVEL_KEYS.has(key));
235
+ }
236
+ /**
237
+ * Render a friendly, path-scoped validation message from a Zod error. Each issue
238
+ * becomes a line ` - <path>: <message>`, with `(root)` for top-level issues.
239
+ */
240
+ export function formatConfigValidationError(error) {
241
+ return error.issues
242
+ .map((issue) => {
243
+ const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
244
+ return ` - ${path}: ${issue.message}`;
245
+ })
246
+ .join('\n');
247
+ }
248
+ /** Deprecated → canonical key pairs at the config root. */
249
+ const DEPRECATED_ROOT_PAIRS = [
250
+ ['contentProvider', 'contentSource'],
251
+ ['requirementsProvider', 'requirementSource'],
252
+ ['contentProviderConfig', 'contentSourceConfig'],
253
+ ['requirementsProviderConfig', 'requirementSourceConfig'],
254
+ ];
255
+ /** Deprecated → canonical key pairs inside a `commands.<name>` block. */
256
+ const DEPRECATED_COMMAND_PAIRS = [
257
+ ['contentProvider', 'contentSource'],
258
+ ['requirementsProvider', 'requirementSource'],
259
+ ];
260
+ function remapDeprecated(obj, pairs, scope, warnings) {
261
+ for (const [deprecated, canonical] of pairs) {
262
+ if (Object.prototype.hasOwnProperty.call(obj, deprecated)) {
263
+ warnings.push(`Config property "${deprecated}"${scope} is deprecated. Use "${canonical}" instead.`);
264
+ // Canonical wins when both are present; otherwise adopt the deprecated value.
265
+ if (obj[canonical] === undefined) {
266
+ obj[canonical] = obj[deprecated];
267
+ }
268
+ delete obj[deprecated];
269
+ }
270
+ }
271
+ }
272
+ /**
273
+ * B3 — one-way pre-map of deprecated config key names to their canonical names, at
274
+ * the config root AND per-command. Mutates `raw` in place (it is always a freshly
275
+ * loaded config layer) and returns it alongside a list of deprecation warnings the
276
+ * caller should emit via `displayWarning`. Canonical names win when both are
277
+ * present; the deprecated key is always removed so it does not later surface as an
278
+ * "unknown top-level key".
279
+ */
280
+ export function preMapDeprecatedConfigNames(raw) {
281
+ const warnings = [];
282
+ remapDeprecated(raw, DEPRECATED_ROOT_PAIRS, '', warnings);
283
+ const commands = raw.commands;
284
+ if (commands && typeof commands === 'object') {
285
+ for (const [name, cmd] of Object.entries(commands)) {
286
+ if (cmd && typeof cmd === 'object') {
287
+ remapDeprecated(cmd, DEPRECATED_COMMAND_PAIRS, ` in commands.${name}`, warnings);
288
+ }
289
+ }
290
+ }
291
+ return { config: raw, warnings };
292
+ }
293
+ /**
294
+ * Generate the JSON Schema for the raw config from {@link rawGthConfigSchema} using
295
+ * zod 4's native `z.toJSONSchema`. The output is committed to
296
+ * `packages/core/schema/gsloth-config.schema.json` and asserted by a golden test.
297
+ */
298
+ export function generateConfigJsonSchema() {
299
+ return z.toJSONSchema(rawGthConfigSchema, { io: 'input' });
300
+ }
301
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Shell / dev-tools policy: the {@link GthDevToolsConfig} type plus all the resolvers
4
+ * that interpret it (shell enablement, timeouts, output budget, allow-list, the EXT-10
5
+ * LLM-as-judge gate, and per-command dev-tools selection). Extracted verbatim from the
6
+ * former `config.ts` god-file; behaviour is unchanged.
7
+ */
8
+ import type { GthCommand } from '#src/core/types.js';
9
+ import type { GthConfig, LLMConfig } from '#src/config/types.js';
10
+ /**
11
+ * Config for {@link GthDevToolkit}.
12
+ * Tools are not applied when config is not provided.
13
+ * Only available in `code`/`exec` mode (and `ask --write`).
14
+ */
15
+ export interface GthDevToolsConfig {
16
+ /**
17
+ * Optional shell command to run tests.
18
+ * Not applied when config is not provided.
19
+ */
20
+ run_tests?: string;
21
+ /**
22
+ * Optional shell command to run static analysis (lint).
23
+ * Not applied when config is not provided.
24
+ */
25
+ run_lint?: string;
26
+ /**
27
+ * Optional shell command to run the build.
28
+ * Not applied when config is not provided.
29
+ */
30
+ run_build?: string;
31
+ /**
32
+ * Optional shell command to run a single test file.
33
+ * Supports command interpolation with the `${testPath}` placeholder.
34
+ * Example: "npm test -- ${testPath}" or "jest ${testPath}"
35
+ * Example: "npm test" - the test will simply be appended
36
+ * Not applied when config is not provided.
37
+ */
38
+ run_single_test?: string;
39
+ /**
40
+ * Opt-in general-purpose shell tool (`run_shell_command`). Unlike the fixed
41
+ * `run_*` commands above, this lets the agent run ARBITRARY shell commands it
42
+ * composes itself — the agentic-coding escape hatch the deep agent otherwise
43
+ * lacks (it can read/write files but not run commands).
44
+ *
45
+ * EXT-12 — default: ON in `code` mode, OFF elsewhere. When this is ABSENT/undefined,
46
+ * `code` mode emits the tool (still GATED behind the per-command approval prompt — the
47
+ * absent-config default NEVER implies yolo); `exec` / `ask --write` keep it OFF. An
48
+ * EXPLICIT value always wins: `shell: false` (or `{ enabled: false }`) is a hard escape
49
+ * hatch that fully disables it even in `code`. Accepts a bare boolean or an
50
+ * `{ enabled }` object for symmetry with future per-tool options.
51
+ *
52
+ * Because the model chooses the command, every invocation is gated behind a
53
+ * per-command human confirmation dialog (LangChain `humanInTheLoopMiddleware`,
54
+ * wired via deepagents' `interruptOn`) UNLESS {@link shellYolo} bypasses it.
55
+ * The confirmation — not string-filtering — is the guardrail, so the command
56
+ * is passed through verbatim (pipes / `$` / `;` are all legitimate).
57
+ *
58
+ * The object form also tunes the EXT-9 Tier-1 hardening applied to every run
59
+ * (these have safe defaults so bare `shell: true` is already hardened):
60
+ * - `timeout`: per-command wall-clock limit in MILLISECONDS before the child
61
+ * (and its process group) is killed. Default {@link SHELL_DEFAULT_TIMEOUT_MS}.
62
+ * - `maxOutputBytes`: byte budget for the captured output returned to the model
63
+ * (head + tail window; the middle is dropped and the full output spilled to a
64
+ * temp file). Default {@link SHELL_DEFAULT_MAX_OUTPUT_BYTES}. Live terminal
65
+ * streaming is never capped.
66
+ *
67
+ * A hardcoded hardline blocklist of catastrophic commands (rm -rf /, mkfs, dd
68
+ * to a block device, fork bomb, shutdown/reboot, …) is refused even under
69
+ * {@link shellYolo}; that floor is not configurable.
70
+ *
71
+ * Example: `{ "shell": true }`,
72
+ * `{ "shell": { "enabled": true, "timeout": 300000, "maxOutputBytes": 200000 } }`.
73
+ *
74
+ * The object form additionally accepts EXT-9 Tier-2 allow-list knobs:
75
+ * - `allowlist`: master switch for the scoped approval allow-list (session +
76
+ * persisted `always`). Default `true` — once a command is approved at `session`/
77
+ * `always` scope, flag-variants of the same classified operation auto-approve
78
+ * without re-prompting. Set `false` to require fresh approval for every command.
79
+ * - `persistAllowlist`: whether `always`-scoped approvals are written to the project
80
+ * allow-list file (`.gsloth/.gsloth-settings/shell-allowlist.json`). Default `true`.
81
+ * When `false`, an `always` decision behaves like `session` (in-memory only).
82
+ *
83
+ * The object form also accepts the EXT-10 LLM-as-judge safety gate (default OFF):
84
+ * - `judge`: an opt-in, tiered auto-approve pre-filter that vets each `run_shell_command`
85
+ * with a lightweight judge model BEFORE the human prompt. It auto-approves clearly-safe
86
+ * commands (fatigue reducer), escalates the rest to the existing human prompt, and may
87
+ * reject clearly-catastrophic ones. Default OFF because it costs one LLM call per command.
88
+ * Accepts a bare boolean (`judge: true` → defaults: auto-approve low, escalate medium/high,
89
+ * judge model = `config.llm`) or an object:
90
+ * - `enabled`: turn the gate on.
91
+ * - `autoApproveLow`: auto-approve `low`-risk, statically-resolvable commands. Default true.
92
+ * - `blockHigh`: reject clearly-catastrophic (`high` + destructive) verdicts WITHOUT
93
+ * prompting. Default false (conservative; EXT-9's hardline floor already refuses truly
94
+ * catastrophic commands at exec time).
95
+ * - `model`: an optional separate (e.g. cheaper) judge model config. Defaults to `config.llm`.
96
+ * Hardening (always on when the judge runs): the command is normalized + XML-tagged as
97
+ * UNTRUSTED input in the judge prompt; a judge throw/timeout/parse-failure fails CLOSED
98
+ * (escalate, never auto-approve); commands whose target can't be statically resolved
99
+ * (shell composition / substitution / redirection) and interpreter+script invocations that
100
+ * leak ALL_CAPS env vars are NEVER auto-approved.
101
+ */
102
+ shell?: boolean | {
103
+ enabled?: boolean;
104
+ timeout?: number;
105
+ maxOutputBytes?: number;
106
+ allowlist?: boolean;
107
+ persistAllowlist?: boolean;
108
+ judge?: boolean | {
109
+ enabled?: boolean;
110
+ autoApproveLow?: boolean;
111
+ blockHigh?: boolean;
112
+ model?: LLMConfig;
113
+ };
114
+ };
115
+ /**
116
+ * Opt-out of the per-command confirmation dialog for {@link shell}
117
+ * (`run_shell_command`) — the explicit "yolo" bypass. When `true` AND `shell`
118
+ * is enabled, the shell tool runs without any approval interrupt: the model's
119
+ * commands execute immediately. Dangerous by design; off by default.
120
+ *
121
+ * Example: `{ "shell": true, "shellYolo": true }`.
122
+ */
123
+ shellYolo?: boolean;
124
+ }
125
+ /**
126
+ * Default per-command shell timeout (ms) when {@link GthDevToolsConfig.shell}
127
+ * does not specify one. ~120s suits typical build/test/git steps without
128
+ * hanging the agent forever on a stuck command.
129
+ */
130
+ export declare const SHELL_DEFAULT_TIMEOUT_MS = 120000;
131
+ /**
132
+ * Default byte budget for shell output captured into the ToolMessage returned to
133
+ * the model (head + tail window). ~100KB keeps a noisy log from blowing the
134
+ * context window; the full output is spilled to a temp file when this is exceeded.
135
+ */
136
+ export declare const SHELL_DEFAULT_MAX_OUTPUT_BYTES = 100000;
137
+ /**
138
+ * Normalize the {@link GthDevToolsConfig.shell} opt-in (bare boolean or
139
+ * `{ enabled }`) to a plain boolean. Centralized so the toolkit (tool emission)
140
+ * and the deep agent (interrupt wiring) agree on what "shell enabled" means.
141
+ *
142
+ * EXT-12 — default-resolution: an EXPLICIT value always wins (a bare boolean, or the
143
+ * object form's `enabled`), so `shell: false` / `{ enabled: false }` remains a hard
144
+ * escape hatch that fully disables the tool. Only when `shell` is ABSENT/undefined does
145
+ * the per-mode default apply: in `code` mode the shell tool is ON by default (still
146
+ * gated — the per-command approval interrupt is wired separately and is NOT bypassed by
147
+ * this), and OFF everywhere else (`exec`, `ask --write`, …) to preserve prior behaviour.
148
+ * The default is `code`-mode only because `code` is the interactive agentic-coding surface
149
+ * where a TTY can answer the approval prompt; the absent-config default never implies yolo.
150
+ *
151
+ * @param command The active command, so the absent-config default can be scoped to `code`.
152
+ * Omit (or pass a non-`code` command) to keep the historical OFF-by-default behaviour.
153
+ */
154
+ export declare function isShellToolEnabled(devTools: GthDevToolsConfig | undefined, command?: GthCommand | undefined): boolean;
155
+ /**
156
+ * Resolve the per-command shell timeout (ms) from config, falling back to
157
+ * {@link SHELL_DEFAULT_TIMEOUT_MS}. Only the object form can override it; a bare
158
+ * `shell: true` uses the default. Non-positive / non-finite values are ignored.
159
+ */
160
+ export declare function getShellTimeoutMs(devTools: GthDevToolsConfig | undefined): number;
161
+ /**
162
+ * Resolve the captured-output byte budget from config, falling back to
163
+ * {@link SHELL_DEFAULT_MAX_OUTPUT_BYTES}. Only the object form can override it.
164
+ * Non-positive / non-finite values are ignored.
165
+ */
166
+ export declare function getShellMaxOutputBytes(devTools: GthDevToolsConfig | undefined): number;
167
+ /**
168
+ * Whether the EXT-9 Tier-2 scoped allow-list is active. Default `true`; only the object
169
+ * form's `allowlist: false` disables it (a bare `shell: true` keeps it on). When off, the
170
+ * runner prompts for every `run_shell_command` regardless of prior approvals.
171
+ */
172
+ export declare function isShellAllowlistEnabled(devTools: GthDevToolsConfig | undefined): boolean;
173
+ /**
174
+ * Whether `always`-scoped approvals are persisted to the project allow-list file. Default
175
+ * `true`; only the object form's `persistAllowlist: false` disables persistence (an
176
+ * `always` decision then behaves as `session`).
177
+ */
178
+ export declare function isShellAllowlistPersisted(devTools: GthDevToolsConfig | undefined): boolean;
179
+ /**
180
+ * Resolved settings for the EXT-10 LLM-as-judge safety gate.
181
+ */
182
+ export interface ShellJudgeSettings {
183
+ /** Whether the judge gate runs at all. */
184
+ enabled: boolean;
185
+ /** Auto-approve `low`-risk, statically-resolvable commands (the fatigue reducer). */
186
+ autoApproveLow: boolean;
187
+ /** Reject clearly-catastrophic (`high` + destructive) verdicts without prompting. */
188
+ blockHigh: boolean;
189
+ /** Optional separate judge model config; when absent the runner uses `config.llm`. */
190
+ model?: LLMConfig;
191
+ }
192
+ /**
193
+ * Whether the EXT-10 LLM-as-judge safety gate is enabled for the given dev-tools config.
194
+ * Default OFF (only the object form's `judge` truthy enables it), mirroring
195
+ * {@link isShellToolEnabled}. A bare `shell: true` keeps the judge OFF — it costs an LLM call
196
+ * per command and must be opted into explicitly.
197
+ */
198
+ export declare function isShellJudgeEnabled(devTools: GthDevToolsConfig | undefined): boolean;
199
+ /**
200
+ * Resolve the EXT-10 judge gate settings from a dev-tools config, applying safe defaults
201
+ * (auto-approve low, do NOT block high). `enabled` reflects {@link isShellJudgeEnabled}.
202
+ */
203
+ export declare function getShellJudgeSettings(devTools: GthDevToolsConfig | undefined): ShellJudgeSettings;
204
+ /**
205
+ * Resolve the {@link GthDevToolsConfig} that applies to the active command, mirroring the
206
+ * per-command selection in `builtInToolsConfig.getDefaultTools` (which is what actually emits
207
+ * the dev tools) and `GthDeepAgent.getEffectiveDevToolsConfig`: `exec` → `commands.exec`,
208
+ * `ask --write` → `commands.ask`, `code` → `commands.code`; `undefined` elsewhere (the
209
+ * toolkit is inert there). Shared in core so the runner's allow-list gate stays in lockstep
210
+ * with where the shell tool is actually emitted.
211
+ */
212
+ export declare function getEffectiveDevToolsConfig(config: Pick<GthConfig, 'commands' | 'askWriteMode'> | undefined, command: GthCommand | undefined): GthDevToolsConfig | undefined;