@gaunt-sloth/agent 0.1.8 → 2.0.0-alpha.1

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 (80) hide show
  1. package/README.md +14 -5
  2. package/cli-acp.js +35 -0
  3. package/cli.js +35 -0
  4. package/dist/builtInToolsConfig.d.ts +26 -0
  5. package/dist/builtInToolsConfig.js +148 -0
  6. package/dist/builtInToolsConfig.js.map +1 -0
  7. package/dist/core/GthDeepAgent.d.ts +76 -0
  8. package/dist/core/GthDeepAgent.js +368 -0
  9. package/dist/core/GthDeepAgent.js.map +1 -0
  10. package/dist/core/debugCapture.d.ts +51 -0
  11. package/dist/core/debugCapture.js +2 -0
  12. package/dist/core/debugCapture.js.map +1 -0
  13. package/dist/core/deepAgentPermissions.d.ts +55 -0
  14. package/dist/core/deepAgentPermissions.js +120 -0
  15. package/dist/core/deepAgentPermissions.js.map +1 -0
  16. package/dist/core/gthAcpServer.d.ts +27 -0
  17. package/dist/core/gthAcpServer.js +71 -0
  18. package/dist/core/gthAcpServer.js.map +1 -0
  19. package/dist/core/gthDeepAgentFactory.d.ts +8 -0
  20. package/dist/core/gthDeepAgentFactory.js +9 -0
  21. package/dist/core/gthDeepAgentFactory.js.map +1 -0
  22. package/dist/index.d.ts +13 -0
  23. package/dist/index.js +16 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/mcp/OAuthClientProviderImpl.d.ts +37 -0
  26. package/dist/mcp/OAuthClientProviderImpl.js +223 -0
  27. package/dist/mcp/OAuthClientProviderImpl.js.map +1 -0
  28. package/dist/middleware/binaryContentInjectionMiddleware.d.ts +22 -0
  29. package/dist/middleware/binaryContentInjectionMiddleware.js +125 -0
  30. package/dist/middleware/binaryContentInjectionMiddleware.js.map +1 -0
  31. package/dist/middleware/registry.d.ts +34 -0
  32. package/dist/middleware/registry.js +124 -0
  33. package/dist/middleware/registry.js.map +1 -0
  34. package/dist/middleware/types.d.ts +89 -0
  35. package/dist/middleware/types.js +9 -0
  36. package/dist/middleware/types.js.map +1 -0
  37. package/dist/modules/a2a/A2AClientWrapper.d.ts +22 -0
  38. package/dist/modules/a2a/A2AClientWrapper.js +63 -0
  39. package/dist/modules/a2a/A2AClientWrapper.js.map +1 -0
  40. package/dist/modules/acpModule.d.ts +37 -0
  41. package/dist/modules/acpModule.js +67 -0
  42. package/dist/modules/acpModule.js.map +1 -0
  43. package/dist/modules/apiAgUiModule.d.ts +2 -0
  44. package/dist/modules/apiAgUiModule.js +417 -0
  45. package/dist/modules/apiAgUiModule.js.map +1 -0
  46. package/dist/modules/interactiveSessionModule.d.ts +9 -0
  47. package/dist/modules/interactiveSessionModule.js +99 -0
  48. package/dist/modules/interactiveSessionModule.js.map +1 -0
  49. package/dist/resolvers.d.ts +18 -0
  50. package/dist/resolvers.js +140 -0
  51. package/dist/resolvers.js.map +1 -0
  52. package/dist/tools/A2AAgentTool.d.ts +24 -0
  53. package/dist/tools/A2AAgentTool.js +37 -0
  54. package/dist/tools/A2AAgentTool.js.map +1 -0
  55. package/dist/tools/GthCustomToolkit.d.ts +41 -0
  56. package/dist/tools/GthCustomToolkit.js +289 -0
  57. package/dist/tools/GthCustomToolkit.js.map +1 -0
  58. package/dist/tools/GthDevToolkit.d.ts +24 -0
  59. package/dist/tools/GthDevToolkit.js +189 -0
  60. package/dist/tools/GthDevToolkit.js.map +1 -0
  61. package/dist/tools/GthFileSystemToolkit.d.ts +36 -0
  62. package/dist/tools/GthFileSystemToolkit.js +775 -0
  63. package/dist/tools/GthFileSystemToolkit.js.map +1 -0
  64. package/dist/tools/binaryUtils.d.ts +13 -0
  65. package/dist/tools/binaryUtils.js +55 -0
  66. package/dist/tools/binaryUtils.js.map +1 -0
  67. package/dist/tools/gthStatusUpdateTool.d.ts +2 -0
  68. package/dist/tools/gthStatusUpdateTool.js +15 -0
  69. package/dist/tools/gthStatusUpdateTool.js.map +1 -0
  70. package/dist/tools/gthWebFetchTool.d.ts +2 -0
  71. package/dist/tools/gthWebFetchTool.js +47 -0
  72. package/dist/tools/gthWebFetchTool.js.map +1 -0
  73. package/dist/tools/showA2UISurfaceTool.d.ts +9 -0
  74. package/dist/tools/showA2UISurfaceTool.js +25 -0
  75. package/dist/tools/showA2UISurfaceTool.js.map +1 -0
  76. package/dist/utils/mcpUtils.d.ts +13 -0
  77. package/dist/utils/mcpUtils.js +225 -0
  78. package/dist/utils/mcpUtils.js.map +1 -0
  79. package/package.json +49 -10
  80. package/index.js +0 -6
@@ -0,0 +1,368 @@
1
+ import { GthAbstractAgent } from '@gaunt-sloth/core/core/GthAbstractAgent.js';
2
+ import { StatusLevel } from '@gaunt-sloth/core/core/types.js';
3
+ import { debugLog, debugLogObject } from '@gaunt-sloth/core/utils/debugUtils.js';
4
+ import { buildSystemMessages, formatToolCalls, readChatPrompt, readCodePrompt, readExecPrompt, } from '@gaunt-sloth/core/utils/llmUtils.js';
5
+ import { getCurrentWorkDir } from '@gaunt-sloth/core/utils/systemUtils.js';
6
+ import { AIMessage, ToolMessage } from '@langchain/core/messages';
7
+ import { createMiddleware } from 'langchain';
8
+ import { createDeepAgent, FilesystemBackend } from 'deepagents';
9
+ import { buildPermissions, FILESYSTEM_TOOL_NAMES, } from '#src/core/deepAgentPermissions.js';
10
+ /**
11
+ * Deep agent: builds a `createDeepAgent` graph (deepagents). All run/stream/event
12
+ * plumbing lives in {@link GthAbstractAgent}; this class only knows how to construct
13
+ * the graph in {@link init}.
14
+ *
15
+ * Differences from the lean {@link GthLangChainAgent}:
16
+ * - deepagents provides the filesystem tools (`read_file`/`write_file`/`edit_file`/
17
+ * `ls`/`glob`/`grep`/`execute`) via its own middleware, backed by a
18
+ * {@link FilesystemBackend}. gsloth's `.aiignore` + `filesystem` config are mapped
19
+ * onto deepagents `permissions` (see {@link buildPermissions}). Any resolved tool
20
+ * that reuses a deepagents filesystem-tool name is therefore superseded and dropped
21
+ * (`createDeepAgent` would otherwise throw on the collision).
22
+ * - todos / subagents / summarization come from deepagents' standard middleware.
23
+ *
24
+ * The transport-agnostic param assembly lives in {@link buildDeepAgentParams} so the ACP
25
+ * entry (`deepagents-acp`) can reuse the exact same tool resolution, permission mapping and
26
+ * middleware hardening without re-running `createDeepAgent` locally.
27
+ */
28
+ export class GthDeepAgent extends GthAbstractAgent {
29
+ /**
30
+ * Opt-in debug sink for the TUI `/debug` panel. Set AFTER {@link init} via
31
+ * `runner.getAgent()`; read lazily inside the `wrapModelCall` middleware so that when it
32
+ * is `undefined` (the normal path) the middleware is a transparent pass-through. Never
33
+ * touched by the lean agent or the AG-UI server, so those contracts are unchanged.
34
+ */
35
+ debugCapture;
36
+ async init(command, configIn, checkpointer) {
37
+ const params = await this.buildDeepAgentParams(command, configIn);
38
+ // Runner-path only: surface requested tool calls to the console. This is intentionally
39
+ // NOT part of buildDeepAgentParams — it writes via statusUpdate (stdout) and the ACP
40
+ // server renders tool calls itself over its own protocol channel.
41
+ const statusUpdate = this.statusUpdate;
42
+ const toolCallStatusMiddleware = createMiddleware({
43
+ name: 'GthMiddlewareToolCallStatusUpdate',
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ afterModel: (state) => {
46
+ debugLogObject('postModel state', state);
47
+ const lastMessage = state.messages[state.messages.length - 1];
48
+ if (AIMessage.isInstance(lastMessage) &&
49
+ lastMessage.tool_calls &&
50
+ lastMessage.tool_calls?.length > 0) {
51
+ statusUpdate(StatusLevel.INFO, `\nRequested tools: ${formatToolCalls(lastMessage.tool_calls)}\n`);
52
+ }
53
+ return state;
54
+ },
55
+ });
56
+ // Debug-capture middleware (TUI `/debug` panel). Always installed but lazy: it reads
57
+ // `this.debugCapture` per call, so until the TUI attaches a sink it is a transparent
58
+ // pass-through (one extra await around the handler — the normal path pays nothing).
59
+ // `request.messages` is the real history at call time (post-summarization/middleware),
60
+ // and `handler(request)` resolves to the AIMessage response (decision (a): whole
61
+ // resolved message, not per-chunk — the streaming core stays untouched).
62
+ const getDebugCapture = () => this.debugCapture;
63
+ const debugCaptureMiddleware = createMiddleware({
64
+ name: 'GthMiddlewareDebugCapture',
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ wrapModelCall: async (request, handler) => {
67
+ const capture = getDebugCapture();
68
+ if (!capture)
69
+ return handler(request);
70
+ try {
71
+ capture.onRequest?.(request.messages, extractDebugRequestExtras(request));
72
+ }
73
+ catch {
74
+ /* a debug sink must never break the run */
75
+ }
76
+ const response = await handler(request);
77
+ try {
78
+ capture.onResponse?.(response);
79
+ }
80
+ catch {
81
+ /* a debug sink must never break the run */
82
+ }
83
+ return response;
84
+ },
85
+ });
86
+ const middleware = [...params.middleware, toolCallStatusMiddleware, debugCaptureMiddleware];
87
+ this.statusUpdate(StatusLevel.INFO, `Loaded middleware: ${middleware.map((m) => m.name).join(', ')}`);
88
+ // Default: a virtual-root sandbox anchored at cwd (absolute paths / `..` cannot escape).
89
+ // `--allow-dir` (config.allowDirs) opts into widening: drop virtualMode so the listed real
90
+ // directories are reachable, and rely on the permission allow-rules (built in
91
+ // buildDeepAgentParams) to constrain access to cwd + those dirs. This removes a guardrail,
92
+ // so it is announced loudly by the exec command and surfaced here in the status log.
93
+ const allowDirs = this.config?.allowDirs;
94
+ const widenFs = Array.isArray(allowDirs) && allowDirs.length > 0;
95
+ if (widenFs) {
96
+ this.statusUpdate(StatusLevel.WARNING, `Filesystem sandbox widened beyond cwd (--allow-dir): ${allowDirs.join(', ')}`);
97
+ }
98
+ const backend = new FilesystemBackend({
99
+ rootDir: getCurrentWorkDir(),
100
+ virtualMode: !widenFs,
101
+ });
102
+ this.agent = createDeepAgent({
103
+ model: params.model,
104
+ tools: params.tools,
105
+ // gsloth's composed prompt, combined ADDITIVELY by deepagents with its base + fs prompts
106
+ // into a single system message (avoids the two-system-message Anthropic rejection).
107
+ systemPrompt: params.systemPrompt,
108
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
+ middleware: middleware,
110
+ backend,
111
+ permissions: params.permissions,
112
+ checkpointer,
113
+ });
114
+ debugLog('Deep agent created successfully');
115
+ }
116
+ /**
117
+ * Assemble the transport-agnostic {@link GthDeepAgentParams}: resolve tools (with the
118
+ * filesystem disabled so deepagents owns fs access), apply the allowedTools allow-list and
119
+ * the deepagents fs-name supersession safety-net, map `.aiignore` + filesystem mode onto
120
+ * deepagents permissions, and build the fs-denial-softening middleware. Shared by the local
121
+ * runner ({@link init}) and the `deepagents-acp` ACP entry.
122
+ */
123
+ async buildDeepAgentParams(command, configIn) {
124
+ this.command = command;
125
+ debugLog(`GthDeepAgent.buildDeepAgentParams called with command: ${command || 'default'}`);
126
+ // Merge command-specific filesystem config if provided
127
+ this.config = this.getEffectiveConfig(configIn, command);
128
+ debugLogObject('Effective Config', {
129
+ filesystem: this.config.filesystem,
130
+ builtInTools: this.config.builtInTools,
131
+ streamOutput: this.config.streamOutput,
132
+ debugLog: this.config.debugLog,
133
+ });
134
+ this.statusUpdate(StatusLevel.INFO, `Workdir: ${getCurrentWorkDir()}`);
135
+ if (this.config.modelDisplayName) {
136
+ this.statusUpdate(StatusLevel.INFO, `Model: ${this.config.modelDisplayName}`);
137
+ }
138
+ // An empty allowedTools allow-list disables every tool. Skip resolution entirely so we
139
+ // don't contact MCP servers (and trigger OAuth) just to discard the result.
140
+ const allowedTools = this.config.allowedTools;
141
+ const toolsDisabled = Array.isArray(allowedTools) && allowedTools.length === 0;
142
+ if (toolsDisabled) {
143
+ this.statusUpdate(StatusLevel.INFO, 'Tool loading disabled by allowedTools: []; MCP/A2A servers will not be contacted. Omit allowedTools for no filtering.');
144
+ }
145
+ // Resolve tools with filesystem access disabled. deepagents OWNS the filesystem
146
+ // (its fs middleware + the `permissions` built below); gsloth's filesystem toolkit
147
+ // must NOT be loaded here, because its non-colliding tools (read_multiple_files,
148
+ // delete_file, search_files, …) would otherwise bypass deepagents' permission
149
+ // enforcement entirely — a model could read an .aiignore-protected file through them.
150
+ debugLog('Resolving tools (filesystem disabled; deepagents provides fs)...');
151
+ const toolResolutionConfig = { ...this.config, filesystem: 'none' };
152
+ const resolvedTools = !toolsDisabled && this.resolvers?.resolveTools
153
+ ? await this.resolvers.resolveTools(toolResolutionConfig, command)
154
+ : [];
155
+ debugLog(`Resolved tools loaded: ${resolvedTools.length}`);
156
+ // Get user config tools (toolkit-flattened; client tools get interrupt() stubs)
157
+ const flattenedConfigTools = toolsDisabled
158
+ ? []
159
+ : this.extractAndFlattenTools(this.config.tools || []);
160
+ debugLog(`User config tools loaded: ${flattenedConfigTools.length}`);
161
+ // Combine all tools, then apply the allowedTools name allow-list when configured.
162
+ let tools = [...resolvedTools, ...flattenedConfigTools];
163
+ if (Array.isArray(allowedTools)) {
164
+ const allowed = new Set(allowedTools);
165
+ tools = tools.filter((tool) => !tool.name || allowed.has(tool.name));
166
+ }
167
+ // Safety net: a custom/dev/MCP tool may still reuse a deepagents filesystem-tool
168
+ // name (createDeepAgent throws on such a collision). Drop the colliding tool — the
169
+ // deep agent's built-in fs tool wins. With filesystem disabled above this is normally
170
+ // empty; it only fires for a genuine user/MCP name clash.
171
+ const reserved = new Set(FILESYSTEM_TOOL_NAMES);
172
+ const superseded = tools.filter((tool) => tool.name && reserved.has(tool.name));
173
+ const passThroughTools = tools.filter((tool) => !tool.name || !reserved.has(tool.name));
174
+ if (superseded.length > 0) {
175
+ const names = superseded.map((tool) => tool.name).join(', ');
176
+ this.statusUpdate(StatusLevel.WARNING, `Dropping tool(s) that collide with deepagents built-in filesystem tools: ${names}`);
177
+ }
178
+ if (passThroughTools.length > 0) {
179
+ const toolNames = passThroughTools
180
+ .map((tool) => tool.name)
181
+ .filter((name) => name)
182
+ .join(', ');
183
+ this.statusUpdate(StatusLevel.INFO, `Loaded tools: ${toolNames}`);
184
+ debugLog(`Total tools available: ${passThroughTools.length}`);
185
+ debugLogObject('All Tools', toolNames.split(', '));
186
+ }
187
+ debugLog('Creating deep agent...');
188
+ // Resolve middleware via resolver or fall back to empty. These are applied AFTER
189
+ // deepagents' standard middleware (todos, subagents, summarization, filesystem).
190
+ const resolvedMiddleware = this.resolvers?.resolveMiddleware
191
+ ? await this.resolvers.resolveMiddleware(
192
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
193
+ this.config.middleware, this.config)
194
+ : [];
195
+ // deepagents' standard middleware already summarizes long conversations; drop any
196
+ // gsloth-configured summarization middleware so the deep agent doesn't summarize twice.
197
+ const configuredMiddleware = resolvedMiddleware.filter((m) => {
198
+ const name = m.name ?? '';
199
+ if (/summar/i.test(name)) {
200
+ debugLog(`Dropping duplicate summarization middleware '${name}' (deepagents provides it)`);
201
+ return false;
202
+ }
203
+ return true;
204
+ });
205
+ // Soften deepagents' fail-hard filesystem permission denials. By default a denied
206
+ // read/write THROWS, which aborts the whole run; wrap tool calls so a denial becomes
207
+ // a recoverable ToolMessage instead, letting the model continue and report it. This
208
+ // preserves gsloth's recoverable-denial UX (the old GthFileSystemToolkit returned a
209
+ // message rather than throwing).
210
+ const fsDenialSoftening = createMiddleware({
211
+ name: 'GthDeepFsDenialSoftening',
212
+ wrapToolCall: async (request, handler) => {
213
+ try {
214
+ return await handler(request);
215
+ }
216
+ catch (e) {
217
+ const message = e instanceof Error ? e.message : String(e);
218
+ if (/permission denied for (read|write)/i.test(message)) {
219
+ debugLog(`Softened fs permission denial into a ToolMessage: ${message}`);
220
+ return new ToolMessage({
221
+ content: message,
222
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
223
+ tool_call_id: request.toolCall?.id ?? '',
224
+ status: 'error',
225
+ });
226
+ }
227
+ throw e;
228
+ }
229
+ },
230
+ });
231
+ // fsDenialSoftening first so it is the outermost wrapToolCall — it must see the throw
232
+ // from deepagents' permission-enforcing fs tools. The console-bound tool-call-status
233
+ // middleware is NOT added here (see GthDeepAgentParams.middleware); the runner appends it.
234
+ const middleware = [fsDenialSoftening, ...configuredMiddleware];
235
+ // Map gsloth's .aiignore + filesystem mode onto deepagents permission rules. When
236
+ // `--allow-dir` widens the sandbox, the backend runs without virtualMode, so paths are REAL
237
+ // absolute paths: constrain read+write to cwd + the allowed dirs (everything else denied),
238
+ // layered under the .aiignore deny rules.
239
+ const permissions = buildPermissions({
240
+ filesystem: this.config.filesystem,
241
+ aiignore: this.config.aiignore,
242
+ allowDirs: Array.isArray(this.config.allowDirs) && this.config.allowDirs.length > 0
243
+ ? this.config.allowDirs
244
+ : undefined,
245
+ });
246
+ debugLogObject('Filesystem permissions', permissions);
247
+ // Compose gsloth's system prompt (backstory + guidelines + per-command mode prompt +
248
+ // system prompt) so identity profiles (Gaunt Sloth, sorcerer, fisher-alt, …) and
249
+ // `.gsloth.*.md` are honored. This is passed to createDeepAgent as `systemPrompt` — combined
250
+ // additively with deepagents' base + fs prompts into ONE system message — rather than injected
251
+ // as a separate SystemMessage per turn (which produced a non-first system message that
252
+ // Anthropic rejects). 'code' uses the code-mode prompt; 'exec' uses the prompt-as-script
253
+ // exec-mode prompt; chat/api/others use the chat prompt.
254
+ const modePrompt = this.command === 'code'
255
+ ? readCodePrompt(this.config)
256
+ : this.command === 'exec'
257
+ ? readExecPrompt(this.config)
258
+ : readChatPrompt(this.config);
259
+ const systemMessages = buildSystemMessages(this.config, modePrompt);
260
+ const systemPrompt = typeof systemMessages[0]?.content === 'string' ? systemMessages[0].content : undefined;
261
+ return {
262
+ model: this.config.llm,
263
+ tools: passThroughTools,
264
+ permissions,
265
+ middleware,
266
+ systemPrompt,
267
+ };
268
+ }
269
+ }
270
+ /**
271
+ * Scalar model-param fields worth surfacing in the `/debug` panel. Deliberately an
272
+ * allowlist (NOT a whole-object dump) so no credential field (`apiKey`, `accessToken`, …)
273
+ * can ever leak into the rendered debug view.
274
+ *
275
+ * `streaming` is intentionally NOT here: it is the model instance's static flag, which is
276
+ * usually `false` even when the turn streams — the GthAgentRunner decides streaming by calling
277
+ * `.stream()` vs `.invoke()`, not by this property — so surfacing it just misleads.
278
+ */
279
+ const DEBUG_MODEL_PARAM_KEYS = [
280
+ 'model',
281
+ 'modelName',
282
+ 'modelId',
283
+ 'deploymentName',
284
+ 'temperature',
285
+ 'topP',
286
+ 'topK',
287
+ 'maxTokens',
288
+ 'maxOutputTokens',
289
+ 'maxReasoningTokens',
290
+ 'reasoningEffort',
291
+ 'thinkingBudget',
292
+ 'stop',
293
+ 'provider',
294
+ ];
295
+ /** Pull the key-free scalar model params from the (provider-specific) model instance. */
296
+ function extractModelParams(model) {
297
+ if (!model || typeof model !== 'object')
298
+ return undefined;
299
+ const src = model;
300
+ const out = {};
301
+ for (const key of DEBUG_MODEL_PARAM_KEYS) {
302
+ const value = src[key];
303
+ if (value === undefined || value === null)
304
+ continue;
305
+ // Only scalars / scalar arrays — never nested objects that could carry credentials.
306
+ if (typeof value === 'object' && !Array.isArray(value))
307
+ continue;
308
+ out[key] = value;
309
+ }
310
+ // `model` / `modelName` / `modelId` are langchain aliases for the same value; collapse the
311
+ // duplicates so the panel shows the model id once instead of two identical lines.
312
+ if (typeof out.model !== 'string' && typeof out.modelName === 'string') {
313
+ out.model = out.modelName;
314
+ }
315
+ if (out.modelName === out.model)
316
+ delete out.modelName;
317
+ if (out.modelId === out.model)
318
+ delete out.modelId;
319
+ return Object.keys(out).length > 0 ? out : undefined;
320
+ }
321
+ /** Best-effort tool definition (name + description + schema) for the debug view. */
322
+ function extractToolDefs(tools) {
323
+ if (!Array.isArray(tools) || tools.length === 0)
324
+ return undefined;
325
+ const defs = [];
326
+ for (const tool of tools) {
327
+ if (!tool || typeof tool !== 'object')
328
+ continue;
329
+ const t = tool;
330
+ const name = typeof t.name === 'string' ? t.name : undefined;
331
+ if (!name)
332
+ continue;
333
+ const description = typeof t.description === 'string' ? t.description : undefined;
334
+ // LangChain StructuredTools expose a Zod/JSON `schema`; some carry it on `lc_kwargs`.
335
+ const schema = t.schema ?? undefined;
336
+ defs.push({ name, description, schema });
337
+ }
338
+ return defs.length > 0 ? defs : undefined;
339
+ }
340
+ /**
341
+ * Assemble the non-message request parts ({@link DebugRequestExtras}) for the `/debug`
342
+ * panel from a `wrapModelCall` request, defensively and key-free. Never throws (the caller
343
+ * already guards, but a debug sink must never break a run) and never dumps the raw model.
344
+ */
345
+ export function extractDebugRequestExtras(request) {
346
+ if (!request || typeof request !== 'object')
347
+ return undefined;
348
+ const req = request;
349
+ const systemMessage = req.systemMessage;
350
+ const systemPrompt = typeof req.systemPrompt === 'string' && req.systemPrompt
351
+ ? req.systemPrompt
352
+ : typeof systemMessage?.content === 'string'
353
+ ? systemMessage.content
354
+ : undefined;
355
+ const extras = {
356
+ systemPrompt,
357
+ tools: extractToolDefs(req.tools),
358
+ modelParams: extractModelParams(req.model),
359
+ toolChoice: req.toolChoice,
360
+ };
361
+ // Return undefined when nothing useful was captured so the renderer can show a clear empty state.
362
+ const hasAny = extras.systemPrompt !== undefined ||
363
+ extras.tools !== undefined ||
364
+ extras.modelParams !== undefined ||
365
+ extras.toolChoice !== undefined;
366
+ return hasAny ? extras : undefined;
367
+ }
368
+ //# sourceMappingURL=GthDeepAgent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GthDeepAgent.js","sourceRoot":"","sources":["../../src/core/GthDeepAgent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { BaseMessage } from '@langchain/core/messages';
2
+ /**
3
+ * The non-message parts of a `wrapModelCall` request that also shape a turn: the tool
4
+ * definitions, the system prompt, and the model params. Captured alongside the message
5
+ * history so the `/debug` panel can show the full picture of what was sent to the model.
6
+ *
7
+ * SECURITY: these are assembled from an explicit allowlist at the capture site
8
+ * (see `GthDeepAgent`); the raw model instance (which can carry an `apiKey`) is never
9
+ * passed through here.
10
+ */
11
+ export interface DebugRequestExtras {
12
+ /** The composed system prompt string sent to the model for this call. */
13
+ systemPrompt?: string;
14
+ /** The tool definitions made available for this call (name + description + JSON schema). */
15
+ tools?: DebugToolDef[];
16
+ /** Scalar model params (model id, temperature, …) — a key-free allowlist. */
17
+ modelParams?: Record<string, unknown>;
18
+ /** The tool-choice configuration for this call, if any. */
19
+ toolChoice?: unknown;
20
+ }
21
+ /** A single tool's debug-renderable definition. */
22
+ export interface DebugToolDef {
23
+ name: string;
24
+ description?: string;
25
+ /** The tool's JSON-schema parameters, when resolvable. */
26
+ schema?: unknown;
27
+ }
28
+ /**
29
+ * Debug-capture sink for the TUI's `/debug` panel.
30
+ *
31
+ * A {@link DebugCapture} is an OPT-IN callback the TUI sets on a live
32
+ * {@link import('#src/core/GthDeepAgent.js').GthDeepAgent} after `init`. When present,
33
+ * the deep agent's `wrapModelCall` middleware reports, per model call:
34
+ *
35
+ * - `request` — `request.messages: BaseMessage[]`, the real history sent to the model at
36
+ * call time (post-summarization / post-middleware), plus the {@link DebugRequestExtras}
37
+ * (tools, system prompt, model params) that also shape the turn. This supersedes any
38
+ * `getState`/`getMessageHistory` snapshot idea: it is exactly what the model saw.
39
+ * - `response` — the resolved `AIMessage` returned by the handler, captured as a whole
40
+ * (decision (a): resolved message, not per-chunk frames; keeps the streaming core
41
+ * untouched).
42
+ *
43
+ * The sink is read lazily inside the middleware (per call), so when no TUI debug panel is
44
+ * attached the middleware is a transparent pass-through and the normal path pays nothing.
45
+ */
46
+ export interface DebugCapture {
47
+ /** The full message history sent to the model for this call, plus the request extras. */
48
+ onRequest?(messages: BaseMessage[], extras?: DebugRequestExtras): void;
49
+ /** The resolved model response for this call (an `AIMessage`). */
50
+ onResponse?(response: unknown): void;
51
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debugCapture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugCapture.js","sourceRoot":"","sources":["../../src/core/debugCapture.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import type { FilesystemPermission } from 'deepagents';
2
+ export type { FilesystemPermission };
3
+ /**
4
+ * Tool names deepagents' filesystem middleware registers. This mirrors deepagents'
5
+ * internal `FILESYSTEM_TOOL_NAMES` (which is declared in its types but not exported
6
+ * at runtime). `createDeepAgent` throws on a name collision with any of these, so a
7
+ * gsloth-supplied tool sharing one of these names is superseded by the deep agent's
8
+ * built-in filesystem tool. Kept here as the single place the deep path references it.
9
+ */
10
+ export declare const FILESYSTEM_TOOL_NAMES: readonly ["ls", "read_file", "write_file", "edit_file", "glob", "grep", "execute"];
11
+ /** The slice of GthConfig the permission mapping consumes. */
12
+ export interface PermissionConfigSlice {
13
+ filesystem: string[] | 'all' | 'read' | 'none';
14
+ aiignore?: {
15
+ enabled?: boolean;
16
+ patterns?: string[];
17
+ };
18
+ /**
19
+ * Extra real filesystem roots to allow (`gth exec --allow-dir`). When present, the backend runs
20
+ * WITHOUT virtualMode, so permission paths are real absolute paths: access is allow-listed to
21
+ * cwd + these dirs and everything else is denied. Undefined/empty keeps the cwd-only sandbox.
22
+ */
23
+ allowDirs?: string[];
24
+ }
25
+ /**
26
+ * Build allow+deny rules for the widened (`--allow-dir`) sandbox. Because the backend runs
27
+ * without virtualMode, paths are REAL absolute paths, so we anchor allow rules at the resolved
28
+ * absolute cwd and each allowed dir, then deny everything else. First-match-wins, so the allow
29
+ * rules must come before the catch-all deny.
30
+ */
31
+ export declare function allowDirsToPermissions(allowDirs: string[]): FilesystemPermission[];
32
+ /**
33
+ * Convert `.aiignore` patterns (relative, .gitignore-ish) into deepagents deny rules.
34
+ *
35
+ * deepagents matches the path argument the model passes to a fs tool — resolved by the
36
+ * backend — against ABSOLUTE globs. With `virtualMode` the backend treats paths as
37
+ * virtual-absolute under `rootDir`, so we anchor at "/".
38
+ *
39
+ * A bare pattern (`*.env`, `secret.txt`) should match at any depth, so we emit both a
40
+ * top-level (`/secret.txt`) and a recursive (`/&#42;&#42;/secret.txt`) rule. A pattern already
41
+ * containing "/" (`config/secrets.json`) is anchored as-is (plus a `/**` subtree rule).
42
+ *
43
+ * `base` defaults to "" so paths are anchored at the virtual root "/". When the sandbox is
44
+ * widened (`--allow-dir`, no virtualMode) the backend uses REAL absolute paths, so the caller
45
+ * passes the absolute cwd as `base` to anchor these deny rules there.
46
+ */
47
+ export declare function aiignoreToPermissions(patterns: string[], base?: string): FilesystemPermission[];
48
+ /** Map gsloth's filesystem mode onto deepagents permission rules. */
49
+ export declare function filesystemModeToPermissions(fs: string[] | 'all' | 'read' | 'none'): FilesystemPermission[];
50
+ /**
51
+ * Compose the full permission list. `.aiignore` deny rules go FIRST so they win over
52
+ * any allow rule (first-match-wins). Then the filesystem-mode rules. `.aiignore` is
53
+ * skipped when explicitly disabled (`aiignore.enabled === false`) or has no patterns.
54
+ */
55
+ export declare function buildPermissions(config: PermissionConfigSlice): FilesystemPermission[];
@@ -0,0 +1,120 @@
1
+ import path from 'node:path';
2
+ import { getCurrentWorkDir } from '@gaunt-sloth/core/utils/systemUtils.js';
3
+ /**
4
+ * Tool names deepagents' filesystem middleware registers. This mirrors deepagents'
5
+ * internal `FILESYSTEM_TOOL_NAMES` (which is declared in its types but not exported
6
+ * at runtime). `createDeepAgent` throws on a name collision with any of these, so a
7
+ * gsloth-supplied tool sharing one of these names is superseded by the deep agent's
8
+ * built-in filesystem tool. Kept here as the single place the deep path references it.
9
+ */
10
+ export const FILESYSTEM_TOOL_NAMES = [
11
+ 'ls',
12
+ 'read_file',
13
+ 'write_file',
14
+ 'edit_file',
15
+ 'glob',
16
+ 'grep',
17
+ 'execute',
18
+ ];
19
+ /**
20
+ * Build allow+deny rules for the widened (`--allow-dir`) sandbox. Because the backend runs
21
+ * without virtualMode, paths are REAL absolute paths, so we anchor allow rules at the resolved
22
+ * absolute cwd and each allowed dir, then deny everything else. First-match-wins, so the allow
23
+ * rules must come before the catch-all deny.
24
+ */
25
+ export function allowDirsToPermissions(allowDirs) {
26
+ const cwd = getCurrentWorkDir();
27
+ const roots = [cwd, ...allowDirs.map((d) => path.resolve(cwd, d))];
28
+ // De-dupe resolved roots (e.g. an --allow-dir pointing back at cwd).
29
+ const uniqueRoots = Array.from(new Set(roots));
30
+ const allow = uniqueRoots.map((root) => ({
31
+ operations: ['read', 'write'],
32
+ paths: [`${root}/**`, root],
33
+ mode: 'allow',
34
+ }));
35
+ return [...allow, { operations: ['read', 'write'], paths: ['/**'], mode: 'deny' }];
36
+ }
37
+ /**
38
+ * Strip a single leading "./" or "/" and any trailing slashes, using linear string
39
+ * ops rather than regex. The previous `/\/+$/` trailing-slash regex was flagged by
40
+ * CodeQL as a polynomial ReDoS (the `$` anchor makes the greedy `\/+` retry from every
41
+ * start position → quadratic on a long run of slashes); plain slicing is O(n) and safe.
42
+ */
43
+ function normalizePathFragment(p) {
44
+ let start = 0;
45
+ if (p.startsWith('./'))
46
+ start = 2;
47
+ else if (p.startsWith('/'))
48
+ start = 1;
49
+ let end = p.length;
50
+ while (end > start && p[end - 1] === '/')
51
+ end--;
52
+ return p.slice(start, end);
53
+ }
54
+ /**
55
+ * Convert `.aiignore` patterns (relative, .gitignore-ish) into deepagents deny rules.
56
+ *
57
+ * deepagents matches the path argument the model passes to a fs tool — resolved by the
58
+ * backend — against ABSOLUTE globs. With `virtualMode` the backend treats paths as
59
+ * virtual-absolute under `rootDir`, so we anchor at "/".
60
+ *
61
+ * A bare pattern (`*.env`, `secret.txt`) should match at any depth, so we emit both a
62
+ * top-level (`/secret.txt`) and a recursive (`/&#42;&#42;/secret.txt`) rule. A pattern already
63
+ * containing "/" (`config/secrets.json`) is anchored as-is (plus a `/**` subtree rule).
64
+ *
65
+ * `base` defaults to "" so paths are anchored at the virtual root "/". When the sandbox is
66
+ * widened (`--allow-dir`, no virtualMode) the backend uses REAL absolute paths, so the caller
67
+ * passes the absolute cwd as `base` to anchor these deny rules there.
68
+ */
69
+ export function aiignoreToPermissions(patterns, base = '') {
70
+ const rules = [];
71
+ for (const raw of patterns) {
72
+ const clean = normalizePathFragment(raw);
73
+ if (clean.length === 0)
74
+ continue;
75
+ const paths = clean.includes('/')
76
+ ? [`${base}/${clean}`, `${base}/${clean}/**`]
77
+ : [`${base}/${clean}`, `${base}/**/${clean}`];
78
+ rules.push({ operations: ['read', 'write'], paths, mode: 'deny' });
79
+ }
80
+ return rules;
81
+ }
82
+ /** Map gsloth's filesystem mode onto deepagents permission rules. */
83
+ export function filesystemModeToPermissions(fs) {
84
+ if (fs === 'all')
85
+ return [];
86
+ if (fs === 'read')
87
+ return [{ operations: ['write'], paths: ['/**'], mode: 'deny' }];
88
+ if (fs === 'none')
89
+ return [{ operations: ['read', 'write'], paths: ['/**'], mode: 'deny' }];
90
+ // string[] — explicit allow-list of directories. Allow read+write within each,
91
+ // deny everything else. Allow rules first (first-match-wins), deny catch-all last.
92
+ const allow = fs
93
+ .filter((d) => d !== 'all' && d !== 'read')
94
+ .map((d) => {
95
+ const dir = `/${normalizePathFragment(d)}`;
96
+ return { operations: ['read', 'write'], paths: [`${dir}/**`, dir], mode: 'allow' };
97
+ });
98
+ return [...allow, { operations: ['read', 'write'], paths: ['/**'], mode: 'deny' }];
99
+ }
100
+ /**
101
+ * Compose the full permission list. `.aiignore` deny rules go FIRST so they win over
102
+ * any allow rule (first-match-wins). Then the filesystem-mode rules. `.aiignore` is
103
+ * skipped when explicitly disabled (`aiignore.enabled === false`) or has no patterns.
104
+ */
105
+ export function buildPermissions(config) {
106
+ const widen = Array.isArray(config.allowDirs) && config.allowDirs.length > 0;
107
+ const aiignoreEnabled = config.aiignore?.enabled !== false && !!config.aiignore?.patterns?.length;
108
+ // When widening, the backend uses real absolute paths — anchor aiignore deny rules at the
109
+ // absolute cwd so they keep matching project-relative ignore patterns.
110
+ const aiignore = aiignoreEnabled
111
+ ? aiignoreToPermissions(config.aiignore.patterns, widen ? getCurrentWorkDir() : '')
112
+ : [];
113
+ // `--allow-dir` replaces the filesystem-mode rules with the cwd + allowed-dirs allow-list,
114
+ // since the model now sees real absolute paths rather than virtual ones.
115
+ const modeRules = widen
116
+ ? allowDirsToPermissions(config.allowDirs)
117
+ : filesystemModeToPermissions(config.filesystem);
118
+ return [...aiignore, ...modeRules];
119
+ }
120
+ //# sourceMappingURL=deepAgentPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deepAgentPermissions.js","sourceRoot":"","sources":["../../src/core/deepAgentPermissions.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAI3E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI;IACJ,WAAW;IACX,YAAY;IACZ,WAAW;IACX,MAAM;IACN,MAAM;IACN,SAAS;CACD,CAAC;AAcX;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAmB;IACxD,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,qEAAqE;IACrE,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAA2B,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC/D,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAC7B,KAAK,EAAE,CAAC,GAAG,IAAI,KAAK,EAAE,IAAI,CAAC;QAC3B,IAAI,EAAE,OAAO;KACd,CAAC,CAAC,CAAC;IACJ,OAAO,CAAC,GAAG,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACrF,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,CAAS;IACtC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,KAAK,GAAG,CAAC,CAAC;SAC7B,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,KAAK,GAAG,CAAC,CAAC;IACtC,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IACnB,OAAO,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG;QAAE,GAAG,EAAE,CAAC;IAChD,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAkB,EAAE,IAAI,GAAG,EAAE;IACjE,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/B,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC;YAC7C,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,EAAE,GAAG,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,2BAA2B,CACzC,EAAsC;IAEtC,IAAI,EAAE,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,EAAE,KAAK,MAAM;QAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,IAAI,EAAE,KAAK,MAAM;QAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,+EAA+E;IAC/E,mFAAmF;IACnF,MAAM,KAAK,GAA2B,EAAE;SACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM,CAAC;SAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACrF,CAAC,CAAC,CAAC;IACL,OAAO,CAAC,GAAG,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA6B;IAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;IAClG,0FAA0F;IAC1F,uEAAuE;IACvE,MAAM,QAAQ,GAAG,eAAe;QAC9B,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,QAAS,CAAC,QAAS,EAAE,KAAK,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,CAAC,CAAC,EAAE,CAAC;IACP,2FAA2F;IAC3F,yEAAyE;IACzE,MAAM,SAAS,GAAG,KAAK;QACrB,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,SAAU,CAAC;QAC3C,CAAC,CAAC,2BAA2B,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAC;AACrC,CAAC"}