@gaunt-sloth/agent 2.0.0-alpha.9 → 2.0.0-beta.0
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 +73 -23
- package/cli-acp.js +21 -24
- package/dist/builtInToolsConfig.d.ts +17 -3
- package/dist/builtInToolsConfig.js +43 -41
- package/dist/builtInToolsConfig.js.map +1 -1
- package/dist/core/debugCapture.d.ts +7 -49
- package/dist/core/debugCapture.js +1 -1
- package/dist/core/debugCapture.js.map +1 -1
- package/dist/core/resolveAgentFactory.d.ts +10 -9
- package/dist/core/resolveAgentFactory.js +11 -12
- package/dist/core/resolveAgentFactory.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/OAuthClientProviderImpl.js.map +1 -1
- package/dist/mcp/tlsTrust.d.ts +61 -0
- package/dist/mcp/tlsTrust.js +109 -0
- package/dist/mcp/tlsTrust.js.map +1 -0
- package/dist/middleware/binaryContentInjectionMiddleware.d.ts +8 -1
- package/dist/middleware/binaryContentInjectionMiddleware.js +11 -2
- package/dist/middleware/binaryContentInjectionMiddleware.js.map +1 -1
- package/dist/middleware/frontendImageInjectionMiddleware.d.ts +107 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js +167 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js.map +1 -0
- package/dist/middleware/registry.js +49 -1
- package/dist/middleware/registry.js.map +1 -1
- package/dist/middleware/types.d.ts +16 -2
- package/dist/modules/a2a/A2AClientWrapper.d.ts +56 -1
- package/dist/modules/a2a/A2AClientWrapper.js +131 -31
- package/dist/modules/a2a/A2AClientWrapper.js.map +1 -1
- package/dist/modules/acp/acpAgentApp.d.ts +57 -0
- package/dist/modules/acp/acpAgentApp.js +378 -0
- package/dist/modules/acp/acpAgentApp.js.map +1 -0
- package/dist/modules/acp/acpAgentAppV1.d.ts +52 -0
- package/dist/modules/acp/acpAgentAppV1.js +307 -0
- package/dist/modules/acp/acpAgentAppV1.js.map +1 -0
- package/dist/modules/acp/acpCommon.d.ts +167 -0
- package/dist/modules/acp/acpCommon.js +282 -0
- package/dist/modules/acp/acpCommon.js.map +1 -0
- package/dist/modules/acp/acpPermissions.d.ts +65 -0
- package/dist/modules/acp/acpPermissions.js +162 -0
- package/dist/modules/acp/acpPermissions.js.map +1 -0
- package/dist/modules/acp/acpPermissionsV1.d.ts +45 -0
- package/dist/modules/acp/acpPermissionsV1.js +110 -0
- package/dist/modules/acp/acpPermissionsV1.js.map +1 -0
- package/dist/modules/acp/acpRouter.d.ts +41 -0
- package/dist/modules/acp/acpRouter.js +48 -0
- package/dist/modules/acp/acpRouter.js.map +1 -0
- package/dist/modules/acp/acpStdio.d.ts +47 -0
- package/dist/modules/acp/acpStdio.js +71 -0
- package/dist/modules/acp/acpStdio.js.map +1 -0
- package/dist/modules/acp/acpToolCalls.d.ts +93 -0
- package/dist/modules/acp/acpToolCalls.js +193 -0
- package/dist/modules/acp/acpToolCalls.js.map +1 -0
- package/dist/modules/acp/acpUpdates.d.ts +48 -0
- package/dist/modules/acp/acpUpdates.js +142 -0
- package/dist/modules/acp/acpUpdates.js.map +1 -0
- package/dist/modules/acp/acpUpdatesV1.d.ts +61 -0
- package/dist/modules/acp/acpUpdatesV1.js +162 -0
- package/dist/modules/acp/acpUpdatesV1.js.map +1 -0
- package/dist/modules/apiAgUiModule.d.ts +87 -0
- package/dist/modules/apiAgUiModule.js +193 -28
- package/dist/modules/apiAgUiModule.js.map +1 -1
- package/dist/modules/interactiveSessionModule.js +497 -51
- package/dist/modules/interactiveSessionModule.js.map +1 -1
- package/dist/modules/slashCommands.d.ts +582 -0
- package/dist/modules/slashCommands.js +1001 -0
- package/dist/modules/slashCommands.js.map +1 -0
- package/dist/resolvers.js +119 -9
- package/dist/resolvers.js.map +1 -1
- package/dist/tools/GthCustomToolkit.js +95 -11
- package/dist/tools/GthCustomToolkit.js.map +1 -1
- package/dist/tools/GthDevToolkit.d.ts +8 -5
- package/dist/tools/GthDevToolkit.js +89 -43
- package/dist/tools/GthDevToolkit.js.map +1 -1
- package/dist/tools/GthFileSystemToolkit.d.ts +63 -0
- package/dist/tools/GthFileSystemToolkit.js +506 -105
- package/dist/tools/GthFileSystemToolkit.js.map +1 -1
- package/dist/tools/McpResourceTool.d.ts +31 -0
- package/dist/tools/McpResourceTool.js +106 -0
- package/dist/tools/McpResourceTool.js.map +1 -0
- package/dist/tools/gthChecklistTool.d.ts +30 -0
- package/dist/tools/gthChecklistTool.js +80 -0
- package/dist/tools/gthChecklistTool.js.map +1 -0
- package/dist/tools/gthGrepTool.d.ts +54 -0
- package/dist/tools/gthGrepTool.js +482 -0
- package/dist/tools/gthGrepTool.js.map +1 -0
- package/dist/tools/shell/env.js +1 -1
- package/dist/tools/shell/env.js.map +1 -1
- package/dist/tools/shell/outputBuffer.js.map +1 -1
- package/dist/tools/shell/workDir.d.ts +1 -10
- package/dist/tools/shell/workDir.js +10 -36
- package/dist/tools/shell/workDir.js.map +1 -1
- package/dist/utils/mcpAuthError.d.ts +36 -0
- package/dist/utils/mcpAuthError.js +89 -0
- package/dist/utils/mcpAuthError.js.map +1 -0
- package/package.json +13 -13
- package/dist/core/GthDeepAgent.d.ts +0 -181
- package/dist/core/GthDeepAgent.js +0 -682
- package/dist/core/GthDeepAgent.js.map +0 -1
- package/dist/core/deepAgentPermissions.d.ts +0 -115
- package/dist/core/deepAgentPermissions.js +0 -282
- package/dist/core/deepAgentPermissions.js.map +0 -1
- package/dist/core/gthAcpServer.d.ts +0 -27
- package/dist/core/gthAcpServer.js +0 -82
- package/dist/core/gthAcpServer.js.map +0 -1
- package/dist/core/gthDeepAgentFactory.d.ts +0 -8
- package/dist/core/gthDeepAgentFactory.js +0 -9
- package/dist/core/gthDeepAgentFactory.js.map +0 -1
- package/dist/modules/acpModule.d.ts +0 -40
- package/dist/modules/acpModule.js +0 -78
- package/dist/modules/acpModule.js.map +0 -1
- package/dist/tools/shell/allowlist.d.ts +0 -11
- package/dist/tools/shell/allowlist.js +0 -12
- package/dist/tools/shell/allowlist.js.map +0 -1
- package/dist/tools/shell/arity.d.ts +0 -11
- package/dist/tools/shell/arity.js +0 -12
- package/dist/tools/shell/arity.js.map +0 -1
- package/dist/tools/shell/hardline.d.ts +0 -15
- package/dist/tools/shell/hardline.js +0 -88
- package/dist/tools/shell/hardline.js.map +0 -1
- package/dist/tools/shell/normalize.d.ts +0 -10
- package/dist/tools/shell/normalize.js +0 -11
- package/dist/tools/shell/normalize.js.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* EXT-31 — classify and format MCP integration connect/tool-load failures so an expired or invalid
|
|
4
|
+
* credential is SURFACED (named + actionable) instead of silently dropping the integration's tools.
|
|
5
|
+
*
|
|
6
|
+
* The `@langchain/mcp-adapters` client only tags a bare HTTP 401 as an authentication error; a 403
|
|
7
|
+
* (forbidden / expired scope) otherwise falls through as a generic "Failed to connect". This module
|
|
8
|
+
* classifies auth failures independently (401/403 + credential keywords) so a stale token is not
|
|
9
|
+
* mistaken for "this integration was never configured" or an unrelated transient error.
|
|
10
|
+
*
|
|
11
|
+
* Pure + side-effect free: callers do the surfacing (`displayWarning`) with the returned message.
|
|
12
|
+
*/
|
|
13
|
+
/** Coarse classification of an MCP connect/tool-load failure. */
|
|
14
|
+
export type McpConnectErrorKind = 'auth' | 'other';
|
|
15
|
+
/** Options that tune the suggested fix path in the surfaced message. */
|
|
16
|
+
export interface McpConnectFailureOptions {
|
|
17
|
+
/** The server uses OAuth (`authProvider: 'OAuth'`) — suggest re-running the OAuth login. */
|
|
18
|
+
oauth?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Classify an MCP connect/tool-load failure as a credential problem (`auth`) or anything else
|
|
22
|
+
* (`other`). Detection is independent of the adapter (which only tags 401), so a 403 or an
|
|
23
|
+
* "expired token" surfaced by the upstream server is still recognised as auth.
|
|
24
|
+
*/
|
|
25
|
+
export declare function classifyMcpConnectError(error: unknown): McpConnectErrorKind;
|
|
26
|
+
/**
|
|
27
|
+
* Build the user-facing message for a failed MCP integration. For `auth` failures it names the
|
|
28
|
+
* integration, states the credential is expired/invalid, and points at the concrete fix path
|
|
29
|
+
* (OAuth login or the API token / authorization header, plus the `mcpServers` entry in gth config).
|
|
30
|
+
* For `other` failures it surfaces the failure plainly and explicitly says it is NOT an auth error,
|
|
31
|
+
* so an unrelated transient never triggers a spurious "re-authenticate" nudge.
|
|
32
|
+
*
|
|
33
|
+
* Either way the caller degrades gracefully AFTER surfacing this — the integration's tools are
|
|
34
|
+
* dropped for the session, but the user (and the log) now knows why.
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatMcpConnectFailureMessage(serverName: string | undefined, error: unknown, options?: McpConnectFailureOptions): string;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* EXT-31 — classify and format MCP integration connect/tool-load failures so an expired or invalid
|
|
4
|
+
* credential is SURFACED (named + actionable) instead of silently dropping the integration's tools.
|
|
5
|
+
*
|
|
6
|
+
* The `@langchain/mcp-adapters` client only tags a bare HTTP 401 as an authentication error; a 403
|
|
7
|
+
* (forbidden / expired scope) otherwise falls through as a generic "Failed to connect". This module
|
|
8
|
+
* classifies auth failures independently (401/403 + credential keywords) so a stale token is not
|
|
9
|
+
* mistaken for "this integration was never configured" or an unrelated transient error.
|
|
10
|
+
*
|
|
11
|
+
* Pure + side-effect free: callers do the surfacing (`displayWarning`) with the returned message.
|
|
12
|
+
*/
|
|
13
|
+
/** Extract a readable message from an unknown thrown value. */
|
|
14
|
+
function errorMessage(error) {
|
|
15
|
+
if (error instanceof Error)
|
|
16
|
+
return error.message;
|
|
17
|
+
if (typeof error === 'string')
|
|
18
|
+
return error;
|
|
19
|
+
try {
|
|
20
|
+
return String(error?.message ?? error);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return String(error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Read a numeric HTTP status from an error object or a `(HTTP NNN)` / `HTTP NNN` / `status NNN` message. */
|
|
27
|
+
function httpStatusOf(error, message) {
|
|
28
|
+
const code = error?.code;
|
|
29
|
+
if (typeof code === 'number')
|
|
30
|
+
return code;
|
|
31
|
+
if (typeof code === 'string' && /^\d{3}$/.test(code))
|
|
32
|
+
return parseInt(code, 10);
|
|
33
|
+
// Only treat 4xx/5xx numbers as a status when they carry HTTP/status context — never a bare "401"
|
|
34
|
+
// substring (which could be a port, a byte count, an id, …) to avoid misclassifying transient errors.
|
|
35
|
+
const m = message.match(/\b(?:HTTP|status(?:\s*code)?)[\s:]*\(?(\d{3})\)?/i);
|
|
36
|
+
return m ? parseInt(m[1], 10) : undefined;
|
|
37
|
+
}
|
|
38
|
+
// Credential-failure phrasing across MCP adapter wrapping, transports, and common upstream servers.
|
|
39
|
+
// Includes the canonical OAuth error codes (`invalid_grant` = expired/revoked refresh token,
|
|
40
|
+
// `invalid_token`, `unauthorized_client`) and generic `oauth …` credential phrasing, so a keyword-
|
|
41
|
+
// bearing OAuth failure is classified as auth even when it does NOT arrive via the OAuth catch site.
|
|
42
|
+
const AUTH_KEYWORDS = /\b(unauthorized|forbidden|authentication failed|authenti[sc]ation (?:error|required)|authorization (?:error|failed|required)|invalid (?:token|credentials?|api[\s-]?key|authorization)|invalid_grant|invalid_token|unauthorized_client|oauth[\s_-]?(?:error|failed|failure|denied|token|authorization|handshake|login)|(?:token|credentials?|session|api[\s-]?key)s? (?:has |have )?(?:expired|is expired|are expired)|expired (?:token|credentials?|session)|access denied|401 unauthorized|403 forbidden)\b/i;
|
|
43
|
+
/**
|
|
44
|
+
* Classify an MCP connect/tool-load failure as a credential problem (`auth`) or anything else
|
|
45
|
+
* (`other`). Detection is independent of the adapter (which only tags 401), so a 403 or an
|
|
46
|
+
* "expired token" surfaced by the upstream server is still recognised as auth.
|
|
47
|
+
*/
|
|
48
|
+
export function classifyMcpConnectError(error) {
|
|
49
|
+
const message = errorMessage(error);
|
|
50
|
+
const status = httpStatusOf(error, message);
|
|
51
|
+
if (status === 401 || status === 403)
|
|
52
|
+
return 'auth';
|
|
53
|
+
if (AUTH_KEYWORDS.test(message))
|
|
54
|
+
return 'auth';
|
|
55
|
+
return 'other';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build the user-facing message for a failed MCP integration. For `auth` failures it names the
|
|
59
|
+
* integration, states the credential is expired/invalid, and points at the concrete fix path
|
|
60
|
+
* (OAuth login or the API token / authorization header, plus the `mcpServers` entry in gth config).
|
|
61
|
+
* For `other` failures it surfaces the failure plainly and explicitly says it is NOT an auth error,
|
|
62
|
+
* so an unrelated transient never triggers a spurious "re-authenticate" nudge.
|
|
63
|
+
*
|
|
64
|
+
* Either way the caller degrades gracefully AFTER surfacing this — the integration's tools are
|
|
65
|
+
* dropped for the session, but the user (and the log) now knows why.
|
|
66
|
+
*/
|
|
67
|
+
export function formatMcpConnectFailureMessage(serverName, error, options = {}) {
|
|
68
|
+
// Reaching the OAuth surfacing site means createAuthProviderAndAuthenticate() threw, i.e. the
|
|
69
|
+
// OAuth handshake/refresh itself failed — that is inherently an auth failure regardless of the
|
|
70
|
+
// message text (e.g. a keyword-less `invalid_grant`). Force `auth` here rather than inferring it
|
|
71
|
+
// from keywords, so an OAuth credential failure never mis-surfaces as "not an authentication error".
|
|
72
|
+
const kind = options.oauth ? 'auth' : classifyMcpConnectError(error);
|
|
73
|
+
const name = serverName ? `"${serverName}"` : 'an MCP server';
|
|
74
|
+
const configHint = serverName
|
|
75
|
+
? `check the ${name} entry under mcpServers in your gth config`
|
|
76
|
+
: 'check the mcpServers entries in your gth config';
|
|
77
|
+
if (kind === 'auth') {
|
|
78
|
+
const reAuth = options.oauth
|
|
79
|
+
? 'complete the OAuth login flow again (clear the stored token first if needed)'
|
|
80
|
+
: 'refresh its API token or key (the apiKeyEnvironmentVariable or authorization header it uses)';
|
|
81
|
+
return (`Integration ${name} authentication failed: its credentials appear expired or invalid ` +
|
|
82
|
+
`(the MCP server rejected the connection with an authorization error). Its tools are ` +
|
|
83
|
+
`unavailable for this session. To restore them, re-authenticate this integration: ` +
|
|
84
|
+
`${reAuth} and ${configHint}, then restart.`);
|
|
85
|
+
}
|
|
86
|
+
return (`Integration ${name} could not connect to its MCP server (this is not an authentication ` +
|
|
87
|
+
`error). Its tools are unavailable for this session. Underlying error: ${errorMessage(error)}`);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=mcpAuthError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpAuthError.js","sourceRoot":"","sources":["../../src/utils/mcpAuthError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,+DAA+D;AAC/D,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,MAAM,CAAE,KAA+B,EAAE,OAAO,IAAI,KAAK,CAAC,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,6GAA6G;AAC7G,SAAS,YAAY,CAAC,KAAc,EAAE,OAAe;IACnD,MAAM,IAAI,GAAI,KAA4B,EAAE,IAAI,CAAC;IACjD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChF,kGAAkG;IAClG,sGAAsG;IACtG,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAC7E,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAED,oGAAoG;AACpG,6FAA6F;AAC7F,mGAAmG;AACnG,qGAAqG;AACrG,MAAM,aAAa,GACjB,gfAAgf,CAAC;AAEnf;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC;IACpD,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,8BAA8B,CAC5C,UAA8B,EAC9B,KAAc,EACd,OAAO,GAA6B,EAAE;IAEtC,8FAA8F;IAC9F,+FAA+F;IAC/F,iGAAiG;IACjG,qGAAqG;IACrG,MAAM,IAAI,GAAwB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC1F,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC;IAC9D,MAAM,UAAU,GAAG,UAAU;QAC3B,CAAC,CAAC,aAAa,IAAI,4CAA4C;QAC/D,CAAC,CAAC,iDAAiD,CAAC;IAEtD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK;YAC1B,CAAC,CAAC,8EAA8E;YAChF,CAAC,CAAC,8FAA8F,CAAC;QACnG,OAAO,CACL,eAAe,IAAI,oEAAoE;YACvF,sFAAsF;YACtF,mFAAmF;YACnF,GAAG,MAAM,QAAQ,UAAU,iBAAiB,CAC7C,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eAAe,IAAI,sEAAsE;QACzF,yEAAyE,YAAY,CAAC,KAAK,CAAC,EAAE,CAC/F,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaunt-sloth/agent",
|
|
3
|
-
"version": "2.0.0-
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
|
+
"description": "Agent runtime for Gaunt Sloth: tools, middleware, MCP/A2A clients and the AG-UI server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andrew Kondratev",
|
|
7
7
|
"repository": {
|
|
@@ -38,21 +38,21 @@
|
|
|
38
38
|
"#src/*.js": "./dist/*.js"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@a2a-js/sdk": "^0.
|
|
41
|
+
"@a2a-js/sdk": "^1.0.1",
|
|
42
42
|
"@ag-ui/core": "^0.0.57",
|
|
43
43
|
"@ag-ui/encoder": "^0.0.57",
|
|
44
|
-
"@
|
|
45
|
-
"@langchain/
|
|
44
|
+
"@agentclientprotocol/sdk": "1.3.0",
|
|
45
|
+
"@langchain/core": "^1.2.5",
|
|
46
|
+
"@langchain/langgraph": "^1.4.9",
|
|
46
47
|
"@langchain/mcp-adapters": "^1.1.3",
|
|
47
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
48
|
-
"deepagents": "^1.10.5",
|
|
49
|
-
"deepagents-acp": "^0.1.15",
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
50
49
|
"diff": "^9.0.0",
|
|
51
50
|
"express": "^5.2.1",
|
|
52
|
-
"langchain": "^1.5.
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
51
|
+
"langchain": "^1.5.5",
|
|
52
|
+
"undici": "^8.10.0",
|
|
53
|
+
"uuid": "^14.0.1",
|
|
54
|
+
"zod": "^4.4.3",
|
|
55
|
+
"@gaunt-sloth/core": "2.0.0-beta.0"
|
|
56
56
|
},
|
|
57
57
|
"files": [
|
|
58
58
|
"./dist/*",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"cli-acp.js"
|
|
61
61
|
],
|
|
62
62
|
"publishConfig": {
|
|
63
|
-
"tag": "
|
|
63
|
+
"tag": "beta"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"build": "tsc"
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
2
|
-
import { GthAbstractAgent } from '@gaunt-sloth/core/core/GthAbstractAgent.js';
|
|
3
|
-
import { type GthCommand } from '@gaunt-sloth/core/core/types.js';
|
|
4
|
-
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
5
|
-
import type { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
6
|
-
import { type InterruptOnConfig } from 'langchain';
|
|
7
|
-
import { type FilesystemPermission } from '#src/core/deepAgentPermissions.js';
|
|
8
|
-
import type { DebugCapture, DebugRequestExtras } from '#src/core/debugCapture.js';
|
|
9
|
-
/**
|
|
10
|
-
* The subset of `createDeepAgent` params that are independent of the transport
|
|
11
|
-
* (the local runner vs. the ACP server). Both {@link GthDeepAgent.init} (which adds the
|
|
12
|
-
* console-bound tool-call-status middleware + a virtual {@link FilesystemBackend} +
|
|
13
|
-
* checkpointer and calls `createDeepAgent`) and the ACP entry (deepagents-acp
|
|
14
|
-
* `startServer`, which supplies its own ACP-proxying backend, checkpointer and tool-call
|
|
15
|
-
* reporting) consume these.
|
|
16
|
-
*
|
|
17
|
-
* `middleware` here deliberately EXCLUDES the tool-call-status middleware: that one writes
|
|
18
|
-
* to stdout, which on the ACP path is the JSON-RPC channel and must stay clean. The runner
|
|
19
|
-
* path appends it in {@link GthDeepAgent.init}.
|
|
20
|
-
*/
|
|
21
|
-
export interface GthDeepAgentParams {
|
|
22
|
-
model: any;
|
|
23
|
-
tools: StructuredToolInterface[];
|
|
24
|
-
permissions: FilesystemPermission[];
|
|
25
|
-
middleware: any[];
|
|
26
|
-
/**
|
|
27
|
-
* gsloth's composed system prompt (backstory + guidelines + per-command mode prompt +
|
|
28
|
-
* system prompt). Passed to `createDeepAgent({ systemPrompt })`, where deepagents combines
|
|
29
|
-
* it ADDITIVELY with its own base + filesystem prompts into ONE system message. This replaces
|
|
30
|
-
* the previous per-turn `SystemMessage` injection by the runner/AG-UI callers — two system
|
|
31
|
-
* messages (deepagents' own + gsloth's, not first) are rejected by Anthropic. `undefined` when
|
|
32
|
-
* no prompt content is composed (lets deepagents use only its base prompt).
|
|
33
|
-
*/
|
|
34
|
-
systemPrompt: string | undefined;
|
|
35
|
-
/**
|
|
36
|
-
* Per-tool human-in-the-loop configuration passed straight to
|
|
37
|
-
* `createDeepAgent({ interruptOn })` (deepagents installs LangChain's
|
|
38
|
-
* `humanInTheLoopMiddleware` for it). A matching tool call suspends the graph with a
|
|
39
|
-
* `__interrupt__` (a `HITLRequest`) so a consumer can approve/reject before the tool runs;
|
|
40
|
-
* resume with `new Command({ resume: { decisions: [...] } })` on the same `thread_id`.
|
|
41
|
-
*
|
|
42
|
-
* gsloth currently sets this only for the opt-in `run_shell_command` tool (when its
|
|
43
|
-
* `devTools.shell` is enabled and `devTools.shellYolo` is NOT). Left `undefined` otherwise —
|
|
44
|
-
* including under yolo — so no tool is gated and runs never suspend for approval.
|
|
45
|
-
*/
|
|
46
|
-
interruptOn?: Record<string, boolean | InterruptOnConfig>;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Deep agent: builds a `createDeepAgent` graph (deepagents). All run/stream/event
|
|
50
|
-
* plumbing lives in {@link GthAbstractAgent}; this class only knows how to construct
|
|
51
|
-
* the graph in {@link init}.
|
|
52
|
-
*
|
|
53
|
-
* Differences from the lean {@link GthLangChainAgent}:
|
|
54
|
-
* - deepagents provides the filesystem tools (`read_file`/`write_file`/`edit_file`/
|
|
55
|
-
* `ls`/`glob`/`grep`/`execute`) via its own middleware, backed by a
|
|
56
|
-
* {@link FilesystemBackend}. gsloth's `.aiignore` + `filesystem` config are mapped
|
|
57
|
-
* onto deepagents `permissions` (see {@link buildPermissions}). Any resolved tool
|
|
58
|
-
* that reuses a deepagents filesystem-tool name is therefore superseded and dropped
|
|
59
|
-
* (`createDeepAgent` would otherwise throw on the collision). EXT-14: the
|
|
60
|
-
* `FilesystemBackend` itself is wrapped with {@link guardFilesystemBackend} before it
|
|
61
|
-
* reaches `createDeepAgent`, adding a realpath (symlink-resolved) containment check the
|
|
62
|
-
* permission globs alone can't provide.
|
|
63
|
-
* - todos / subagents / summarization come from deepagents' standard middleware.
|
|
64
|
-
*
|
|
65
|
-
* The transport-agnostic param assembly lives in {@link buildDeepAgentParams} so the ACP
|
|
66
|
-
* entry (`deepagents-acp`) can reuse the exact same tool resolution, permission mapping and
|
|
67
|
-
* middleware hardening without re-running `createDeepAgent` locally.
|
|
68
|
-
*/
|
|
69
|
-
export declare class GthDeepAgent extends GthAbstractAgent {
|
|
70
|
-
/**
|
|
71
|
-
* Opt-in debug sink for the TUI `/debug` panel. Set AFTER {@link init} via
|
|
72
|
-
* `runner.getAgent()`; read lazily inside the `wrapModelCall` middleware so that when it
|
|
73
|
-
* is `undefined` (the normal path) the middleware is a transparent pass-through. Never
|
|
74
|
-
* touched by the lean agent or the AG-UI server, so those contracts are unchanged.
|
|
75
|
-
*/
|
|
76
|
-
debugCapture: DebugCapture | undefined;
|
|
77
|
-
init(command: GthCommand | undefined, configIn: GthConfig, checkpointer?: BaseCheckpointSaver | undefined): Promise<void>;
|
|
78
|
-
/**
|
|
79
|
-
* Assemble the transport-agnostic {@link GthDeepAgentParams}: resolve tools (with the
|
|
80
|
-
* filesystem disabled so deepagents owns fs access), apply the allowedTools allow-list and
|
|
81
|
-
* the deepagents fs-name supersession safety-net, map `.aiignore` + filesystem mode onto
|
|
82
|
-
* deepagents permissions, and build the fs-denial-softening middleware. Shared by the local
|
|
83
|
-
* runner ({@link init}) and the `deepagents-acp` ACP entry.
|
|
84
|
-
*/
|
|
85
|
-
buildDeepAgentParams(command: GthCommand | undefined, configIn: GthConfig): Promise<GthDeepAgentParams>;
|
|
86
|
-
/**
|
|
87
|
-
* Resolve the {@link GthDevToolsConfig} that applies to the active command, mirroring the
|
|
88
|
-
* per-command selection in `builtInToolsConfig.getDefaultTools` (which is what actually emits
|
|
89
|
-
* the dev tools): `exec` → `commands.exec.devTools`, `ask --write` → `commands.ask.devTools`,
|
|
90
|
-
* otherwise (`code`) → `commands.code.devTools`. Returns `undefined` for any other command,
|
|
91
|
-
* matching the toolkit being inert there. Kept private and side-effect-free so the interrupt
|
|
92
|
-
* wiring above and the tool emission stay in lockstep.
|
|
93
|
-
*/
|
|
94
|
-
private getEffectiveDevToolsConfig;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* EXT-22: shared virtualMode path-namespace guidance — ONE source of truth used by BOTH the S2
|
|
98
|
-
* early-framing note ({@link appendVirtualCwdNote}, injected into gsloth's composed systemPrompt =
|
|
99
|
-
* block 0) and the S1 last-word correction middleware
|
|
100
|
-
* ({@link createPathNamespaceCorrectionMiddleware}, appended after deepagents' `/`-rooted line).
|
|
101
|
-
*
|
|
102
|
-
* In a virtualMode `code` session (EXT-16, e.g. Windows) the deepagents filesystem tools use a
|
|
103
|
-
* VIRTUAL `/` root (= the working dir) while `run_shell_command` uses REAL native OS paths; the
|
|
104
|
-
* model conflates the two forms. This text draws the distinction and steers toward cwd-relative
|
|
105
|
-
* paths (the one form both tool families read alike).
|
|
106
|
-
*
|
|
107
|
-
* It deliberately does NOT equate the virtual root with a specific real path (no "`/` = D:\\work"):
|
|
108
|
-
* virtualMode withholds the real cwd on purpose (see the systemPrompt gate in {@link
|
|
109
|
-
* GthDeepAgent.init}), so the guidance is about the DISTINCTION between the two namespaces and the
|
|
110
|
-
* safety of relative paths, not a mapping between them.
|
|
111
|
-
*/
|
|
112
|
-
export declare const PATH_NAMESPACE_GUIDANCE: string;
|
|
113
|
-
/**
|
|
114
|
-
* EXT-22 (S2): virtualMode variant of {@link appendCwdNote}. On the `code` path when the fs
|
|
115
|
-
* backend runs in virtualMode (EXT-16), inject the shared path-namespace guidance EARLY in
|
|
116
|
-
* gsloth's composed systemPrompt (block 0) so the model is framed before deepagents' own prompt.
|
|
117
|
-
*
|
|
118
|
-
* This is early framing only: deepagents' hardcoded `/`-rooted line lands in a LATER block and can
|
|
119
|
-
* partially override block 0, so the authoritative last word is delivered by the S1 middleware
|
|
120
|
-
* ({@link createPathNamespaceCorrectionMiddleware}); see handoff/spike-systemmessage-ordering.md.
|
|
121
|
-
* Returns the note alone when there is no base prompt.
|
|
122
|
-
*/
|
|
123
|
-
export declare function appendVirtualCwdNote(systemPrompt: string | undefined): string;
|
|
124
|
-
/**
|
|
125
|
-
* EXT-22 (S1): the load-bearing path-namespace correction. A gsloth `wrapModelCall` middleware
|
|
126
|
-
* runs INNERMOST (inside deepagents' filesystem middleware), so appending a trailing block to
|
|
127
|
-
* `request.systemMessage` lands AFTER deepagents' hardcoded "All file paths must start with a /."
|
|
128
|
-
* line — giving gsloth the last word on path semantics (empirically verified; see
|
|
129
|
-
* handoff/spike-systemmessage-ordering.md). It APPENDS via `request.systemMessage.concat(...)`
|
|
130
|
-
* (mirroring how deepagents appends its own fs prompt), never string-splices, and returns a NEW
|
|
131
|
-
* request so it never mutates persisted state (no compounding across turns).
|
|
132
|
-
*
|
|
133
|
-
* `appendCorrection` gates it to `code` + virtualMode: only there do the fs virtual `/` root and
|
|
134
|
-
* the shell's real-OS paths diverge. On POSIX real-path mode deepagents' "start with /" is
|
|
135
|
-
* literally true, so the middleware is a transparent pass-through (like the debug-capture
|
|
136
|
-
* middleware when no sink is attached).
|
|
137
|
-
*/
|
|
138
|
-
export declare function createPathNamespaceCorrectionMiddleware(appendCorrection: boolean): import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[], readonly []>;
|
|
139
|
-
/**
|
|
140
|
-
* EXT-13 (part b): append a real-cwd / path-model note to the composed code-mode system prompt.
|
|
141
|
-
*
|
|
142
|
-
* The default code-mode backend runs in REAL-path mode (no virtualMode), so the deepagents fs
|
|
143
|
-
* tools and `run_shell_command` share one real-absolute-path namespace rooted at `cwd`. Neither
|
|
144
|
-
* deepagents' base prompt nor `.gsloth.code.md` states the actual cwd, so without this the model
|
|
145
|
-
* assumes `/` is cwd and hands `/`-rooted paths to the real-fs shell. The cwd is injected
|
|
146
|
-
* dynamically (never baked into the .md). Returns the note alone when there is no base prompt.
|
|
147
|
-
*/
|
|
148
|
-
export declare function appendCwdNote(systemPrompt: string | undefined, cwd: string): string;
|
|
149
|
-
/**
|
|
150
|
-
* EXT-26: the platform-agnostic tail shared by both {@link appendOsShellNote} branches.
|
|
151
|
-
*
|
|
152
|
-
* The recurring failure mode on non-POSIX hosts is not just wrong command NAMES but shell
|
|
153
|
-
* REDIRECTION quoting: a grouped/multi-line `echo` redirect on cmd.exe reported success yet wrote
|
|
154
|
-
* a 0-byte file. So on every platform we steer file creation/mutation to the deepagents built-in
|
|
155
|
-
* `write_file`/`edit_file` tools (which never touch the shell's quoting) and keep each shell
|
|
156
|
-
* command a single line. Kept short — this is prompt text an LLM reads, not documentation.
|
|
157
|
-
*/
|
|
158
|
-
export declare const OS_SHELL_GUIDANCE: string;
|
|
159
|
-
/**
|
|
160
|
-
* EXT-26: append an OS + shell-dialect note to the composed code-mode system prompt.
|
|
161
|
-
*
|
|
162
|
-
* The deep-agent model was never told its host OS or which shell `run_shell_command` uses, so on
|
|
163
|
-
* non-POSIX hosts it defaulted to POSIX idioms that fail (ran `ls` where cmd.exe has `dir`, a
|
|
164
|
-
* multi-line echo-redirect that wrote 0 bytes, a PowerShell here-string, `python -c` multi-line).
|
|
165
|
-
* This is ORTHOGONAL to the EXT-13/16/22 path-namespace notes: those say WHERE the model is (path
|
|
166
|
-
* form); this says WHAT shell it speaks (dialect).
|
|
167
|
-
*
|
|
168
|
-
* The shell is derived from the SAME rule Node's `spawn(command, { shell: true })` uses — exactly
|
|
169
|
-
* how `run_shell_command` spawns (GthDevToolkit spawn) — so on `win32` it is cmd.exe (via
|
|
170
|
-
* `%ComSpec%`) and on POSIX it is `/bin/sh` (POSIX sh, NOT guaranteed bash). Computed from
|
|
171
|
-
* `process.platform` at call time so the text is correct per host. Returns the note alone when
|
|
172
|
-
* there is no base prompt. A single injection is authoritative (nothing in deepagents' base prompt
|
|
173
|
-
* contradicts shell dialect), so unlike EXT-22 no correction middleware is needed.
|
|
174
|
-
*/
|
|
175
|
-
export declare function appendOsShellNote(systemPrompt: string | undefined): string;
|
|
176
|
-
/**
|
|
177
|
-
* Assemble the non-message request parts ({@link DebugRequestExtras}) for the `/debug`
|
|
178
|
-
* panel from a `wrapModelCall` request, defensively and key-free. Never throws (the caller
|
|
179
|
-
* already guards, but a debug sink must never break a run) and never dumps the raw model.
|
|
180
|
-
*/
|
|
181
|
-
export declare function extractDebugRequestExtras(request: unknown): DebugRequestExtras | undefined;
|