@gaunt-sloth/agent 2.0.0-alpha.3 → 2.0.0-alpha.30
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/dist/builtInToolsConfig.d.ts +17 -3
- package/dist/builtInToolsConfig.js +40 -41
- package/dist/builtInToolsConfig.js.map +1 -1
- package/dist/core/GthDeepAgent.d.ts +52 -32
- package/dist/core/GthDeepAgent.js +438 -198
- package/dist/core/GthDeepAgent.js.map +1 -1
- package/dist/core/debugCapture.d.ts +8 -49
- package/dist/core/debugCapture.js +1 -1
- package/dist/core/debugCapture.js.map +1 -1
- package/dist/core/deepAgentPermissions.d.ts +67 -2
- package/dist/core/deepAgentPermissions.js +151 -3
- package/dist/core/deepAgentPermissions.js.map +1 -1
- package/dist/core/gthAcpServer.js +11 -0
- package/dist/core/gthAcpServer.js.map +1 -1
- package/dist/core/gthDeepAgentFactory.d.ts +3 -0
- package/dist/core/gthDeepAgentFactory.js +9 -1
- package/dist/core/gthDeepAgentFactory.js.map +1 -1
- package/dist/core/resolveAgentFactory.d.ts +14 -0
- package/dist/core/resolveAgentFactory.js +18 -0
- package/dist/core/resolveAgentFactory.js.map +1 -0
- package/dist/core/subagentProfiles.d.ts +50 -0
- package/dist/core/subagentProfiles.js +76 -0
- package/dist/core/subagentProfiles.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- 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 +106 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js +166 -0
- package/dist/middleware/frontendImageInjectionMiddleware.js.map +1 -0
- package/dist/middleware/registry.js +36 -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/acpModule.js +17 -1
- package/dist/modules/acpModule.js.map +1 -1
- package/dist/modules/apiAgUiModule.d.ts +87 -0
- package/dist/modules/apiAgUiModule.js +229 -28
- package/dist/modules/apiAgUiModule.js.map +1 -1
- package/dist/modules/interactiveSessionModule.js +501 -41
- package/dist/modules/interactiveSessionModule.js.map +1 -1
- package/dist/modules/slashCommands.d.ts +576 -0
- package/dist/modules/slashCommands.js +995 -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 +11 -3
- package/dist/tools/GthDevToolkit.js +120 -34
- 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 +81 -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 +11 -0
- package/dist/tools/shell/workDir.js +45 -0
- package/dist/tools/shell/workDir.js.map +1 -0
- package/dist/utils/mcpAuthError.d.ts +36 -0
- package/dist/utils/mcpAuthError.js +89 -0
- package/dist/utils/mcpAuthError.js.map +1 -0
- package/dist/utils/mcpUtils.js +16 -0
- package/dist/utils/mcpUtils.js.map +1 -1
- package/package.json +12 -11
- 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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Opt-in middleware that turns a frontend "capture image" tool result into a vision message the
|
|
4
|
+
* model can actually see.
|
|
5
|
+
*
|
|
6
|
+
* A browser/frontend tool such as CopilotKit's `capture_image` fulfils client-side and posts its
|
|
7
|
+
* result back to gth's AG-UI server as a trailing `tool`-role message whose content is a JSON
|
|
8
|
+
* string `{"mimeType":"image/...","data":"<base64>"}`. gth hands that to the model as a plain-string
|
|
9
|
+
* ToolMessage — no vision block — so the model literally cannot see the photo. This middleware
|
|
10
|
+
* detects that ToolMessage in `beforeModel`, parses the envelope, and injects a `HumanMessage`
|
|
11
|
+
* carrying a provider-appropriate vision block before the next model call.
|
|
12
|
+
*
|
|
13
|
+
* Strictly opt-in: it fires ONLY when referenced by name in `config.middleware`
|
|
14
|
+
* (`"middleware": ["frontend-image-injection"]`), never auto-injected. Promoted from
|
|
15
|
+
* pukeko-robot-controller's proven middleware (RC-21), minus the robot-specific motion-tool coupling.
|
|
16
|
+
*/
|
|
17
|
+
import { createMiddleware } from 'langchain';
|
|
18
|
+
import { HumanMessage, isToolMessage } from '@langchain/core/messages';
|
|
19
|
+
/** Default frontend capture tool name. Overridable via the `toolName` middleware setting. */
|
|
20
|
+
export const DEFAULT_CAPTURE_TOOL_NAME = 'capture_image';
|
|
21
|
+
/**
|
|
22
|
+
* A vision content block the target provider's `@langchain` converter actually decodes. Verified
|
|
23
|
+
* against the installed converters (RC-21):
|
|
24
|
+
* - **ollama** → `{ type:'image_url', image_url:'<data-URL string>' }`. ChatOllama's
|
|
25
|
+
* `convertToOllamaMessages` only handles `image_url` blocks (extractBase64FromDataUrl); the
|
|
26
|
+
* LangChain standard `source_type` block throws "Unsupported content type: image".
|
|
27
|
+
* - **OpenAI-compatible** (`openai`, `openrouter`, `deepseek`, `xai`, `groq` — all extend
|
|
28
|
+
* `ChatOpenAI` / report `_llmType()==='openai'`) → `{ type:'image_url', image_url:{ url:'<data-URL>' } }`.
|
|
29
|
+
* This native OpenAI shape is correct on BOTH the Completions API AND the Responses API (GS2-74
|
|
30
|
+
* flips reasoning-capable openai models to Responses). A raw `source_type` standard block
|
|
31
|
+
* serialises to an *invalid* image part on the Responses path, so we emit the provider-native
|
|
32
|
+
* shape rather than lean on `@langchain/core`'s (deprecated, internal) auto-conversion.
|
|
33
|
+
* - **anthropic** → the provider-native block `{ type:'image', source:{ type:'base64',
|
|
34
|
+
* media_type, data } }`. The LangChain standard block is NOT usable here (RC-32): in
|
|
35
|
+
* `@langchain/anthropic`'s `_formatContentBlocks`, the `isDataContentBlock` branch yields its
|
|
36
|
+
* conversion and then FALLS THROUGH — no `continue` — into the chain below, where
|
|
37
|
+
* `type === 'image'` matches the very same block and yields a SECOND one whose `media_type` is
|
|
38
|
+
* read from camelCase `mimeType` (a key the snake_case standard block never has) and so
|
|
39
|
+
* defaults to the literal `image/jpeg`. Every frame is therefore sent twice, and a non-JPEG
|
|
40
|
+
* capture 400s outright on the mislabelled copy. The native block is recognised earlier by
|
|
41
|
+
* `_isAnthropicImageBlockParam` and passed through untouched, exactly once.
|
|
42
|
+
* - **google-genai / vertexai** (and any unknown/default) → the LangChain standard base64 data
|
|
43
|
+
* content block `{ type:'image', source_type:'base64', mime_type, data }`, which those native
|
|
44
|
+
* converters decode directly and which is the most broadly decodable fallback.
|
|
45
|
+
*
|
|
46
|
+
* The through-line: emit what the target provider's converter consumes natively rather than lean on
|
|
47
|
+
* a generic auto-conversion — the same lesson as GS2-75 on the OpenAI Responses path.
|
|
48
|
+
*
|
|
49
|
+
* Pure and exported so each provider branch can be unit-tested directly.
|
|
50
|
+
*/
|
|
51
|
+
export function imageBlockFor(provider, mimeType, data) {
|
|
52
|
+
const dataUrl = `data:${mimeType};base64,${data}`;
|
|
53
|
+
switch (provider) {
|
|
54
|
+
case 'ollama':
|
|
55
|
+
return { type: 'image_url', image_url: dataUrl };
|
|
56
|
+
case 'openai':
|
|
57
|
+
case 'openrouter':
|
|
58
|
+
case 'deepseek':
|
|
59
|
+
case 'xai':
|
|
60
|
+
case 'groq':
|
|
61
|
+
return { type: 'image_url', image_url: { url: dataUrl } };
|
|
62
|
+
case 'anthropic':
|
|
63
|
+
return {
|
|
64
|
+
type: 'image',
|
|
65
|
+
source: { type: 'base64', media_type: mimeType, data },
|
|
66
|
+
};
|
|
67
|
+
case 'google-genai':
|
|
68
|
+
case 'vertexai':
|
|
69
|
+
default:
|
|
70
|
+
return {
|
|
71
|
+
type: 'image',
|
|
72
|
+
source_type: 'base64',
|
|
73
|
+
mime_type: mimeType,
|
|
74
|
+
data,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create the frontend-image-injection middleware.
|
|
80
|
+
*
|
|
81
|
+
* @param opts.provider - provider string selecting the vision-block shape (see {@link imageBlockFor}).
|
|
82
|
+
* @param opts.toolName - capture tool name (default {@link DEFAULT_CAPTURE_TOOL_NAME}).
|
|
83
|
+
*/
|
|
84
|
+
export function createFrontendImageInjectionMiddleware(opts) {
|
|
85
|
+
const toolName = opts.toolName ?? DEFAULT_CAPTURE_TOOL_NAME;
|
|
86
|
+
// thread_id → set of tool_call_ids whose image (or error note) has already been injected. It
|
|
87
|
+
// scopes injection to ONE frame per capture per graph thread: `beforeModel` runs before every
|
|
88
|
+
// model call, so a multi-step turn would otherwise stack a copy of the same frame at each step,
|
|
89
|
+
// each one appended after the newest content and mispairing the assistant message with a stale
|
|
90
|
+
// frame (the RC-21 idempotency guard). It is deliberately keyed on the GRAPH thread rather than
|
|
91
|
+
// the client session — the AG-UI server gives each fresh run its own checkpoint thread (RC-31),
|
|
92
|
+
// and that run replays the whole history into an empty graph, so it must re-inject the frame or
|
|
93
|
+
// the model would lose the photo the moment the capture turn ended.
|
|
94
|
+
//
|
|
95
|
+
// Closure-scoped (one Map per middleware instance), NOT a module global as the robot had it. The
|
|
96
|
+
// AG-UI server caches one agent per client-toolset signature (getAgentForTools), so a thread's
|
|
97
|
+
// turns share this instance and idempotency-across-turns is preserved — while unrelated agents (and
|
|
98
|
+
// tests) get independent state instead of a process-lifetime Map that accumulates every thread_id.
|
|
99
|
+
const injectedByThread = new Map();
|
|
100
|
+
return createMiddleware({
|
|
101
|
+
name: 'frontend-image-injection',
|
|
102
|
+
beforeModel: async (state, runtime) => {
|
|
103
|
+
const messages = state.messages || [];
|
|
104
|
+
// The AG-UI server sets runConfig.configurable.thread_id (= the run's threadId) and threads it
|
|
105
|
+
// to the graph, so per-session idempotency keys correctly. '__default__' is only reached off
|
|
106
|
+
// that path (e.g. a bare invoke with no thread_id), which still behaves correctly per-instance.
|
|
107
|
+
const threadId = runtime?.configurable?.thread_id ?? '__default__';
|
|
108
|
+
let injectedIds = injectedByThread.get(threadId);
|
|
109
|
+
if (!injectedIds) {
|
|
110
|
+
injectedIds = new Set();
|
|
111
|
+
injectedByThread.set(threadId, injectedIds);
|
|
112
|
+
}
|
|
113
|
+
// Scan forward so injected frames stay in chronological order; skip any tool_call_id already
|
|
114
|
+
// injected on this thread (idempotent across a retained/replayed tail).
|
|
115
|
+
const injected = [];
|
|
116
|
+
for (let i = 0; i < messages.length; i++) {
|
|
117
|
+
const msg = messages[i];
|
|
118
|
+
if (
|
|
119
|
+
// RC-21 (golden fix): use the duck-typed `isToolMessage`, NEVER `msg instanceof
|
|
120
|
+
// ToolMessage`. A consumer (galvanized/robot) importing this middleware across a `file:`-dep
|
|
121
|
+
// boundary resolves a SECOND @langchain/core copy, and a capture ToolMessage constructed by
|
|
122
|
+
// the AG-UI pipeline's core copy is not an instance of the `ToolMessage` class we import —
|
|
123
|
+
// `instanceof` silently returns false across copies and no frame is ever injected.
|
|
124
|
+
isToolMessage(msg) &&
|
|
125
|
+
typeof msg.content === 'string' &&
|
|
126
|
+
msg.name === toolName) {
|
|
127
|
+
const id = msg.tool_call_id;
|
|
128
|
+
if (!id || injectedIds.has(id))
|
|
129
|
+
continue;
|
|
130
|
+
try {
|
|
131
|
+
injected.push({ payload: JSON.parse(msg.content), id });
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Non-JSON tool result — skip injection (leave the guard clean).
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (injected.length === 0)
|
|
139
|
+
return undefined;
|
|
140
|
+
const newMessages = [...messages];
|
|
141
|
+
for (const { payload, id } of injected) {
|
|
142
|
+
if (payload.error) {
|
|
143
|
+
// Mark injected so the error note isn't re-emitted on a later turn.
|
|
144
|
+
injectedIds.add(id);
|
|
145
|
+
newMessages.push(new HumanMessage({ content: `Camera unavailable: ${payload.error}` }));
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (payload.mimeType && payload.data) {
|
|
149
|
+
// RC-21: mark injected ONLY on a successful frame emission. A capture result that arrived
|
|
150
|
+
// WITHOUT its base64 `data` (dropped upstream) injects nothing and must NOT poison the
|
|
151
|
+
// guard — a later data-bearing result for the same tool_call_id can still recover.
|
|
152
|
+
injectedIds.add(id);
|
|
153
|
+
const block = imageBlockFor(opts.provider, payload.mimeType, payload.data);
|
|
154
|
+
newMessages.push(new HumanMessage({
|
|
155
|
+
content: [{ type: 'text', text: 'Camera frame captured:' }, block],
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
// else: a capture result whose `data` is absent — inject nothing, leave the guard clean.
|
|
159
|
+
}
|
|
160
|
+
// If every candidate was data-less (nothing appended), return no state update rather than an
|
|
161
|
+
// identical copy — keeps beforeModel a true no-op and leaves the guard clean for recovery.
|
|
162
|
+
return newMessages.length > messages.length ? { messages: newMessages } : undefined;
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=frontendImageInjectionMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontendImageInjectionMiddleware.js","sourceRoot":"","sources":["../../src/middleware/frontendImageInjectionMiddleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,28 @@ import { displayWarning } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
|
9
9
|
import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
10
10
|
import { anthropicPromptCachingMiddleware, summarizationMiddleware, } from 'langchain';
|
|
11
11
|
import { createBinaryContentInjectionMiddleware, } from '#src/middleware/binaryContentInjectionMiddleware.js';
|
|
12
|
+
import { createFrontendImageInjectionMiddleware } from '#src/middleware/frontendImageInjectionMiddleware.js';
|
|
13
|
+
/**
|
|
14
|
+
* Derive the provider string the vision middleware maps to a per-provider block shape. Prefers the
|
|
15
|
+
* loader-stashed raw `llm.type` ({@link GthConfig.modelProviderType}) — the exact gth provider
|
|
16
|
+
* namespace (`anthropic`/`openrouter`/`deepseek`/`xai`/`groq`/`ollama`/`google-genai`/`vertexai`/…)
|
|
17
|
+
* — and falls back to the live model's `_llmType()` only when it is absent (module configs). The
|
|
18
|
+
* OpenAI-compatible shims (openrouter/deepseek/xai/groq) all report `_llmType() === 'openai'`, which
|
|
19
|
+
* maps to the same `image_url:{url}` block, so the fallback stays shape-correct.
|
|
20
|
+
*/
|
|
21
|
+
function resolveVisionProvider(gthConfig) {
|
|
22
|
+
if (gthConfig.modelProviderType)
|
|
23
|
+
return gthConfig.modelProviderType;
|
|
24
|
+
const llm = gthConfig.llm;
|
|
25
|
+
try {
|
|
26
|
+
if (typeof llm?._llmType === 'function')
|
|
27
|
+
return llm._llmType();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// A misbehaving _llmType must not break middleware resolution.
|
|
31
|
+
}
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
12
34
|
const predefinedMiddlewareFactories = {
|
|
13
35
|
/**
|
|
14
36
|
* Anthropic prompt caching middleware. see https://docs.langchain.com/oss/javascript/langchain/middleware#anthropic-prompt-caching
|
|
@@ -24,7 +46,20 @@ const predefinedMiddlewareFactories = {
|
|
|
24
46
|
* as HumanMessage content blocks before the next model call.
|
|
25
47
|
* This works around LangChain's limitation where ToolMessage doesn't support binary content.
|
|
26
48
|
*/
|
|
27
|
-
'binary-content-injection': (settings, gthConfig) => createBinaryContentInjectionMiddleware(
|
|
49
|
+
'binary-content-injection': (settings, gthConfig) => createBinaryContentInjectionMiddleware({
|
|
50
|
+
...settings,
|
|
51
|
+
provider: resolveVisionProvider(gthConfig),
|
|
52
|
+
}, gthConfig),
|
|
53
|
+
/**
|
|
54
|
+
* Frontend image injection middleware (RC-22). Converts a frontend capture tool's
|
|
55
|
+
* `{mimeType,data}` ToolMessage (default tool name `capture_image`) into a provider-appropriate
|
|
56
|
+
* vision HumanMessage the model can see. Strictly opt-in — resolved ONLY when named in
|
|
57
|
+
* `config.middleware` (no auto-inject branch). Optional `toolName` setting overrides the tool name.
|
|
58
|
+
*/
|
|
59
|
+
'frontend-image-injection': (settings, gthConfig) => Promise.resolve(createFrontendImageInjectionMiddleware({
|
|
60
|
+
provider: resolveVisionProvider(gthConfig),
|
|
61
|
+
toolName: typeof settings.toolName === 'string' ? settings.toolName : undefined,
|
|
62
|
+
})),
|
|
28
63
|
};
|
|
29
64
|
function isPredefinedMiddlewareName(name) {
|
|
30
65
|
return name in predefinedMiddlewareFactories;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/middleware/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EACL,gCAAgC,EAChC,uBAAuB,GAExB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,sCAAsC,GAEvC,MAAM,qDAAqD,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/middleware/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ import { AgentMiddleware } from 'langchain';
|
|
|
10
10
|
/**
|
|
11
11
|
* Predefined middleware types that can be configured via JSON config.
|
|
12
12
|
*/
|
|
13
|
-
export type PredefinedMiddlewareName = 'anthropic-prompt-caching' | 'summarization' | 'binary-content-injection';
|
|
13
|
+
export type PredefinedMiddlewareName = 'anthropic-prompt-caching' | 'summarization' | 'binary-content-injection' | 'frontend-image-injection';
|
|
14
14
|
/**
|
|
15
15
|
* Configuration for Anthropic prompt caching middleware.
|
|
16
16
|
*/
|
|
@@ -70,6 +70,18 @@ export interface ImageFormatTransformConfig {
|
|
|
70
70
|
*/
|
|
71
71
|
export interface BinaryContentInjectionConfig {
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Configuration for frontend image injection middleware (RC-22).
|
|
75
|
+
* Converts a frontend capture tool's `{mimeType,data}` tool result into a vision HumanMessage the
|
|
76
|
+
* model can see. Opt-in — resolved only when named in `config.middleware`.
|
|
77
|
+
*/
|
|
78
|
+
export interface FrontendImageInjectionConfig {
|
|
79
|
+
/**
|
|
80
|
+
* Name of the frontend capture tool whose result is converted into a vision message.
|
|
81
|
+
* Defaults to `capture_image`.
|
|
82
|
+
*/
|
|
83
|
+
toolName?: string;
|
|
84
|
+
}
|
|
73
85
|
/**
|
|
74
86
|
* Union type of all predefined middleware configurations.
|
|
75
87
|
*/
|
|
@@ -79,7 +91,9 @@ export type PredefinedMiddlewareConfig = ({
|
|
|
79
91
|
name: 'summarization';
|
|
80
92
|
} & SummarizationConfig) | ({
|
|
81
93
|
name: 'binary-content-injection';
|
|
82
|
-
} & BinaryContentInjectionConfig)
|
|
94
|
+
} & BinaryContentInjectionConfig) | ({
|
|
95
|
+
name: 'frontend-image-injection';
|
|
96
|
+
} & FrontendImageInjectionConfig);
|
|
83
97
|
/**
|
|
84
98
|
* Middleware configuration that can be specified in JSON or JS config.
|
|
85
99
|
* - String: Name of predefined middleware with default settings
|
|
@@ -5,12 +5,33 @@ export interface A2AClientConfig {
|
|
|
5
5
|
/** URL endpoint for the A2A agent */
|
|
6
6
|
agentUrl: string;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* A single A2A turn's result with its conversation-continuity handles (BATCH-14). Unlike the
|
|
10
|
+
* text-only {@link A2AClientWrapper.sendMessage}, this carries the `contextId`/`taskId` the server
|
|
11
|
+
* returned so a caller can thread them into follow-up turns (an ADK agent keeps conversational
|
|
12
|
+
* context by `contextId`). Both are optional because a response may be a bare `Message` (which
|
|
13
|
+
* carries them only optionally) or a `Task` (which always carries `contextId`, and `id` as the
|
|
14
|
+
* taskId).
|
|
15
|
+
*/
|
|
16
|
+
export interface A2AMessageResult {
|
|
17
|
+
/** The agent's answer text, extracted from the response's text parts. */
|
|
18
|
+
text: string;
|
|
19
|
+
/** The A2A context id to thread into subsequent turns for conversational continuity. */
|
|
20
|
+
contextId?: string;
|
|
21
|
+
/** The A2A task id, when the response was a Task (`Task.id`) or a task-scoped Message. */
|
|
22
|
+
taskId?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Optional conversation-continuity handles to attach to an outgoing A2A message (BATCH-14). */
|
|
25
|
+
export interface A2ASendContext {
|
|
26
|
+
contextId?: string;
|
|
27
|
+
taskId?: string;
|
|
28
|
+
}
|
|
8
29
|
/**
|
|
9
30
|
* Wrapper around the A2A SDK client for communicating with external agents.
|
|
10
31
|
* @experimental
|
|
11
32
|
*/
|
|
12
33
|
export declare class A2AClientWrapper {
|
|
13
|
-
private
|
|
34
|
+
private clientPromise;
|
|
14
35
|
private config;
|
|
15
36
|
constructor(config: A2AClientConfig);
|
|
16
37
|
/**
|
|
@@ -19,4 +40,38 @@ export declare class A2AClientWrapper {
|
|
|
19
40
|
* @returns The agent's response as a string
|
|
20
41
|
*/
|
|
21
42
|
sendMessage(messageText: string): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* BATCH-14 — send one message and return its text ALONG WITH the A2A `contextId`/`taskId` needed to
|
|
45
|
+
* thread a multi-turn conversation. Reads the real `@a2a-js/sdk` result shapes rather than a
|
|
46
|
+
* loose envelope:
|
|
47
|
+
*
|
|
48
|
+
* - A **Message** result carries its text in `parts` and `contextId`/`taskId` directly (both
|
|
49
|
+
* optional, and empty-string when absent in the v1.0 proto model).
|
|
50
|
+
* - A **Task** result — what Google ADK agents commonly return — carries text in
|
|
51
|
+
* `status.message.parts` (falling back to the last artifact's parts), `contextId` (required), and
|
|
52
|
+
* the taskId as `Task.id`.
|
|
53
|
+
*
|
|
54
|
+
* `context.contextId`/`taskId` are attached to the OUTGOING message only when defined, so a
|
|
55
|
+
* first-turn send stays byte-identical to a contextless one.
|
|
56
|
+
*
|
|
57
|
+
* @param messageText - The message to send to the agent.
|
|
58
|
+
* @param context - Optional context/task ids to continue an existing conversation.
|
|
59
|
+
* @returns The agent's text answer plus the context/task ids from its response.
|
|
60
|
+
*/
|
|
61
|
+
sendMessageWithContext(messageText: string, context?: A2ASendContext): Promise<A2AMessageResult>;
|
|
62
|
+
/** Build the outgoing `SendMessageRequest`. The v1.0 data model is generated from the A2A
|
|
63
|
+
* protobufs, so every field is required rather than optional: `role` is the numeric {@link Role}
|
|
64
|
+
* enum (not `'user'`), a text part is `{ content: { $case: 'text', value } }` (not
|
|
65
|
+
* `{ kind: 'text', text }`), and the continuity handles are empty strings rather than absent
|
|
66
|
+
* when there is no conversation to continue. */
|
|
67
|
+
private static buildSendRequest;
|
|
68
|
+
/** Normalize a `Message | Task` A2A result into text + continuity handles (BATCH-14). Static +
|
|
69
|
+
* tolerant of missing optional fields so it can be reused and unit-tested directly. */
|
|
70
|
+
private static extractResult;
|
|
71
|
+
/** v1.0 dropped the `kind` discriminator that told a Message from a Task, so discriminate
|
|
72
|
+
* structurally: `messageId` is required on every Message and never present on a Task. */
|
|
73
|
+
private static isTask;
|
|
74
|
+
/** Concatenate the text of every {@link https://github.com/a2aproject/A2A TextPart} in `parts`
|
|
75
|
+
* (ignoring file/data parts), or `''` when there is no text part. */
|
|
76
|
+
private static extractText;
|
|
22
77
|
}
|
|
@@ -3,20 +3,48 @@
|
|
|
3
3
|
* Wrapper for A2A (Agent-to-Agent) protocol client.
|
|
4
4
|
* @experimental A2A support is experimental and may change.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { ClientFactory, ClientFactoryOptions, DefaultAgentCardResolver, JsonRpcTransportFactory, RestTransportFactory, } from '@a2a-js/sdk/client';
|
|
7
|
+
import { Role } from '@a2a-js/sdk';
|
|
7
8
|
import { debugLog, debugLogError } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
8
9
|
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
+
/** The A2A spec's well-known agent-card path. The SDK's resolver needs the full CARD url, whereas
|
|
11
|
+
* {@link A2AClientConfig.agentUrl} is the agent's BASE url — so we append this ourselves and hand
|
|
12
|
+
* the resolver an empty relative path, keeping the fetched card URL byte-identical to what the
|
|
13
|
+
* pre-1.0 `A2AClient` string constructor produced. (Letting the resolver append its own default
|
|
14
|
+
* would resolve the path RELATIVE to the base url, silently dropping a base path segment: for
|
|
15
|
+
* `http://host/a2a` it would fetch `http://host/.well-known/agent-card.json`.) */
|
|
16
|
+
const AGENT_CARD_PATH = '.well-known/agent-card.json';
|
|
9
17
|
/**
|
|
10
18
|
* Wrapper around the A2A SDK client for communicating with external agents.
|
|
11
19
|
* @experimental
|
|
12
20
|
*/
|
|
13
21
|
export class A2AClientWrapper {
|
|
14
|
-
|
|
22
|
+
clientPromise;
|
|
15
23
|
config;
|
|
16
24
|
constructor(config) {
|
|
17
25
|
this.config = config;
|
|
18
|
-
//
|
|
19
|
-
|
|
26
|
+
// `@a2a-js/sdk` 1.0 removed the `A2AClient` class outright; a client is now built by a
|
|
27
|
+
// `ClientFactory` from the agent card. `legacyCompat` is enabled on the card resolver AND on
|
|
28
|
+
// every transport factory so we keep talking to agents still on protocol v0.3 — which is what
|
|
29
|
+
// Google ADK agents (our only real A2A peer today, see adk-eval-it/) currently speak. With it
|
|
30
|
+
// on, the resolver detects a v0.3-shaped card, translates it to the v1.0 model and stamps each
|
|
31
|
+
// synthesized interface `protocolVersion: '0.3'`, and the matching factory then instantiates
|
|
32
|
+
// the v0.3 wire transport. A v1.0 agent is served by the native transports unchanged, so this
|
|
33
|
+
// wrapper speaks to both.
|
|
34
|
+
const factory = new ClientFactory(ClientFactoryOptions.createFrom(ClientFactoryOptions.default, {
|
|
35
|
+
cardResolver: new DefaultAgentCardResolver({ legacyCompat: { enabled: true } }),
|
|
36
|
+
transports: [
|
|
37
|
+
new JsonRpcTransportFactory({ legacyCompat: { enabled: true } }),
|
|
38
|
+
new RestTransportFactory({ legacyCompat: { enabled: true } }),
|
|
39
|
+
],
|
|
40
|
+
}));
|
|
41
|
+
// Client construction is async (it fetches the card), so we hold the promise and await it per
|
|
42
|
+
// send. Empty path = "the base url IS the card url" — see AGENT_CARD_PATH.
|
|
43
|
+
const cardUrl = `${config.agentUrl.replace(/\/+$/, '')}/${AGENT_CARD_PATH}`;
|
|
44
|
+
this.clientPromise = factory.createFromUrl(cardUrl, '');
|
|
45
|
+
// Guard against an unhandled rejection if the wrapper is constructed but never used; real
|
|
46
|
+
// callers still observe the rejection when they await `clientPromise` inside a send method.
|
|
47
|
+
void this.clientPromise.catch(() => undefined);
|
|
20
48
|
}
|
|
21
49
|
/**
|
|
22
50
|
* Sends a message to the A2A agent and returns the response.
|
|
@@ -26,38 +54,110 @@ export class A2AClientWrapper {
|
|
|
26
54
|
async sendMessage(messageText) {
|
|
27
55
|
debugLog(`Sending message to A2A agent ${this.config.agentId} at ${this.config.agentUrl}: ${messageText}`);
|
|
28
56
|
try {
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
messageId: messageId,
|
|
34
|
-
role: 'user',
|
|
35
|
-
parts: [{ kind: 'text', text: messageText }],
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
debugLog(`Received response from A2A agent: ${JSON.stringify(response)}`);
|
|
39
|
-
// Check for error response
|
|
40
|
-
if ('error' in response) {
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
-
throw new Error(`A2A Error: ${JSON.stringify(response.error)}`);
|
|
43
|
-
}
|
|
44
|
-
// Extract text from response
|
|
45
|
-
// The result is likely a TaskStatus which contains a message
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
-
const result = response.result;
|
|
48
|
-
if (result.message && result.message.parts && result.message.parts.length > 0) {
|
|
49
|
-
// Assuming the first part is text for now
|
|
50
|
-
return result.message.parts[0].text || JSON.stringify(result.message.parts);
|
|
51
|
-
}
|
|
52
|
-
else if (result.state) {
|
|
53
|
-
return `Task state: ${result.state}`;
|
|
54
|
-
}
|
|
55
|
-
return JSON.stringify(result);
|
|
57
|
+
const client = await this.clientPromise;
|
|
58
|
+
const result = await client.sendMessage(A2AClientWrapper.buildSendRequest(messageText, uuidv4()));
|
|
59
|
+
debugLog(`Received response from A2A agent: ${JSON.stringify(result)}`);
|
|
60
|
+
return A2AClientWrapper.extractResult(result).text;
|
|
56
61
|
}
|
|
57
62
|
catch (error) {
|
|
58
63
|
debugLogError('Error sending message to A2A agent', error);
|
|
59
64
|
throw error;
|
|
60
65
|
}
|
|
61
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* BATCH-14 — send one message and return its text ALONG WITH the A2A `contextId`/`taskId` needed to
|
|
69
|
+
* thread a multi-turn conversation. Reads the real `@a2a-js/sdk` result shapes rather than a
|
|
70
|
+
* loose envelope:
|
|
71
|
+
*
|
|
72
|
+
* - A **Message** result carries its text in `parts` and `contextId`/`taskId` directly (both
|
|
73
|
+
* optional, and empty-string when absent in the v1.0 proto model).
|
|
74
|
+
* - A **Task** result — what Google ADK agents commonly return — carries text in
|
|
75
|
+
* `status.message.parts` (falling back to the last artifact's parts), `contextId` (required), and
|
|
76
|
+
* the taskId as `Task.id`.
|
|
77
|
+
*
|
|
78
|
+
* `context.contextId`/`taskId` are attached to the OUTGOING message only when defined, so a
|
|
79
|
+
* first-turn send stays byte-identical to a contextless one.
|
|
80
|
+
*
|
|
81
|
+
* @param messageText - The message to send to the agent.
|
|
82
|
+
* @param context - Optional context/task ids to continue an existing conversation.
|
|
83
|
+
* @returns The agent's text answer plus the context/task ids from its response.
|
|
84
|
+
*/
|
|
85
|
+
async sendMessageWithContext(messageText, context) {
|
|
86
|
+
debugLog(`Sending message (with context) to A2A agent ${this.config.agentId} at ` +
|
|
87
|
+
`${this.config.agentUrl}: ${messageText}` +
|
|
88
|
+
(context?.contextId ? ` [contextId=${context.contextId}]` : ''));
|
|
89
|
+
try {
|
|
90
|
+
const client = await this.clientPromise;
|
|
91
|
+
const result = await client.sendMessage(A2AClientWrapper.buildSendRequest(messageText, uuidv4(), context));
|
|
92
|
+
debugLog(`Received response from A2A agent: ${JSON.stringify(result)}`);
|
|
93
|
+
return A2AClientWrapper.extractResult(result);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
debugLogError('Error sending message (with context) to A2A agent', error);
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** Build the outgoing `SendMessageRequest`. The v1.0 data model is generated from the A2A
|
|
101
|
+
* protobufs, so every field is required rather than optional: `role` is the numeric {@link Role}
|
|
102
|
+
* enum (not `'user'`), a text part is `{ content: { $case: 'text', value } }` (not
|
|
103
|
+
* `{ kind: 'text', text }`), and the continuity handles are empty strings rather than absent
|
|
104
|
+
* when there is no conversation to continue. */
|
|
105
|
+
static buildSendRequest(messageText, messageId, context) {
|
|
106
|
+
const message = {
|
|
107
|
+
messageId,
|
|
108
|
+
contextId: context?.contextId ?? '',
|
|
109
|
+
taskId: context?.taskId ?? '',
|
|
110
|
+
role: Role.ROLE_USER,
|
|
111
|
+
parts: [
|
|
112
|
+
{
|
|
113
|
+
content: { $case: 'text', value: messageText },
|
|
114
|
+
metadata: undefined,
|
|
115
|
+
filename: '',
|
|
116
|
+
mediaType: 'text/plain',
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
metadata: undefined,
|
|
120
|
+
extensions: [],
|
|
121
|
+
referenceTaskIds: [],
|
|
122
|
+
};
|
|
123
|
+
return { tenant: '', message, configuration: undefined, metadata: undefined };
|
|
124
|
+
}
|
|
125
|
+
/** Normalize a `Message | Task` A2A result into text + continuity handles (BATCH-14). Static +
|
|
126
|
+
* tolerant of missing optional fields so it can be reused and unit-tested directly. */
|
|
127
|
+
static extractResult(result) {
|
|
128
|
+
if (A2AClientWrapper.isTask(result)) {
|
|
129
|
+
const statusParts = result.status?.message?.parts;
|
|
130
|
+
const artifactParts = result.artifacts?.[result.artifacts.length - 1]?.parts;
|
|
131
|
+
const text = A2AClientWrapper.extractText(statusParts ?? artifactParts) || JSON.stringify(result);
|
|
132
|
+
return {
|
|
133
|
+
text,
|
|
134
|
+
contextId: result.contextId || undefined,
|
|
135
|
+
taskId: result.id || undefined,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const text = A2AClientWrapper.extractText(result?.parts) || JSON.stringify(result);
|
|
139
|
+
// The proto model uses '' (not undefined) for an absent id; normalize back to undefined so a
|
|
140
|
+
// caller can't thread an empty handle into the next turn.
|
|
141
|
+
return {
|
|
142
|
+
text,
|
|
143
|
+
contextId: result?.contextId || undefined,
|
|
144
|
+
taskId: result?.taskId || undefined,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** v1.0 dropped the `kind` discriminator that told a Message from a Task, so discriminate
|
|
148
|
+
* structurally: `messageId` is required on every Message and never present on a Task. */
|
|
149
|
+
static isTask(result) {
|
|
150
|
+
return typeof result?.messageId !== 'string';
|
|
151
|
+
}
|
|
152
|
+
/** Concatenate the text of every {@link https://github.com/a2aproject/A2A TextPart} in `parts`
|
|
153
|
+
* (ignoring file/data parts), or `''` when there is no text part. */
|
|
154
|
+
static extractText(parts) {
|
|
155
|
+
if (!parts || parts.length === 0)
|
|
156
|
+
return '';
|
|
157
|
+
return parts
|
|
158
|
+
.filter((part) => part?.content?.$case === 'text')
|
|
159
|
+
.map((part) => part.content?.value)
|
|
160
|
+
.join('\n');
|
|
161
|
+
}
|
|
62
162
|
}
|
|
63
163
|
//# sourceMappingURL=A2AClientWrapper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"A2AClientWrapper.js","sourceRoot":"","sources":["../../../src/modules/a2a/A2AClientWrapper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"A2AClientWrapper.js","sourceRoot":"","sources":["../../../src/modules/a2a/A2AClientWrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { getProcessCwd, stderr } from '@gaunt-sloth/core/utils/systemUtils.js';
|
|
17
17
|
import { debugLog } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
18
|
+
import { disableGeminiThoughtSummaries } from '@gaunt-sloth/core/providers/geminiThinking.js';
|
|
18
19
|
import { GthDeepAgent } from '#src/core/GthDeepAgent.js';
|
|
19
20
|
import { startGthAcpServer } from '#src/core/gthAcpServer.js';
|
|
20
21
|
import { createResolvers } from '#src/resolvers.js';
|
|
@@ -41,6 +42,14 @@ const acpStatusUpdate = (_level, message) => {
|
|
|
41
42
|
*/
|
|
42
43
|
export async function startAcpServer(config, options = {}) {
|
|
43
44
|
const command = options.command ?? 'code';
|
|
45
|
+
// ACP is structurally deep-only: it calls GthDeepAgent.buildDeepAgentParams and hands the
|
|
46
|
+
// extracted params to the deepagents-acp server. There is no lean analog, so an explicit
|
|
47
|
+
// `agent.backend: 'lean'` cannot be honored here — reject it loudly rather than silently
|
|
48
|
+
// running deep despite the request (B5 selector, kept honest at the ACP entry).
|
|
49
|
+
if (config.agent?.backend === 'lean') {
|
|
50
|
+
throw new Error("agent.backend: 'lean' is not supported by the ACP server — ACP relies on the deep " +
|
|
51
|
+
'(deepagents) backend. Remove the lean setting, or use the AG-UI/api server for a lean agent.');
|
|
52
|
+
}
|
|
44
53
|
const agent = new GthDeepAgent(acpStatusUpdate, createResolvers());
|
|
45
54
|
const params = await agent.buildDeepAgentParams(command, config);
|
|
46
55
|
// gsloth's composed system prompt (backstory + guidelines + per-command mode prompt + system
|
|
@@ -52,11 +61,18 @@ export async function startAcpServer(config, options = {}) {
|
|
|
52
61
|
// getCurrentWorkDir() — its INIT_CWD preference leaks stale paths into this long-lived subprocess.
|
|
53
62
|
const workspaceRoot = getProcessCwd();
|
|
54
63
|
debugLog(`Starting ACP server (command: ${command}, startup workspace: ${workspaceRoot})`);
|
|
64
|
+
// deepagents-acp renders assistant content itself: it sends a `thinking`-typed block to the ACP
|
|
65
|
+
// client's thought channel and EVERY `text`-typed block to the message channel. Gemini's thought
|
|
66
|
+
// summary is typed `text` (marked only by `thought: true`), so on this path the model's reasoning
|
|
67
|
+
// would arrive in the IDE as the assistant's answer. Nothing here goes through GthAbstractAgent,
|
|
68
|
+
// so gsloth's reasoning bridge cannot separate them — the only reliable fix is not to ask for the
|
|
69
|
+
// summary on this surface. Thinking itself stays on, and the budget is untouched.
|
|
70
|
+
const model = disableGeminiThoughtSummaries(params.model);
|
|
55
71
|
await startGthAcpServer({
|
|
56
72
|
agents: {
|
|
57
73
|
name: options.name ?? 'gaunt-sloth',
|
|
58
74
|
description: options.description ?? 'Gaunt Sloth deep coding agent',
|
|
59
|
-
model
|
|
75
|
+
model,
|
|
60
76
|
tools: params.tools,
|
|
61
77
|
systemPrompt,
|
|
62
78
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acpModule.js","sourceRoot":"","sources":["../../src/modules/acpModule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAWpD;;;GAGG;AACH,MAAM,eAAe,GAAyB,CAAC,MAAmB,EAAE,OAAe,EAAQ,EAAE;IAC3F,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"acpModule.js","sourceRoot":"","sources":["../../src/modules/acpModule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+CAA+C,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAWpD;;;GAGG;AACH,MAAM,eAAe,GAAyB,CAAC,MAAmB,EAAE,OAAe,EAAQ,EAAE;IAC3F,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,OAAO,GAA0B,EAAE;IAEnC,MAAM,OAAO,GAAe,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAEtD,0FAA0F;IAC1F,yFAAyF;IACzF,yFAAyF;IACzF,gFAAgF;IAChF,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,oFAAoF;YAClF,8FAA8F,CACjG,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,eAAe,EAAE,eAAe,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAEjE,6FAA6F;IAC7F,2FAA2F;IAC3F,yFAAyF;IACzF,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;IAEzC,+FAA+F;IAC/F,qFAAqF;IACrF,mGAAmG;IACnG,MAAM,aAAa,GAAG,aAAa,EAAE,CAAC;IACtC,QAAQ,CAAC,iCAAiC,OAAO,wBAAwB,aAAa,GAAG,CAAC,CAAC;IAE3F,gGAAgG;IAChG,iGAAiG;IACjG,kGAAkG;IAClG,iGAAiG;IACjG,kGAAkG;IAClG,kFAAkF;IAClF,MAAM,KAAK,GAAG,6BAA6B,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1D,MAAM,iBAAiB,CAAC;QACtB,MAAM,EAAE;YACN,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,aAAa;YACnC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,+BAA+B;YACnE,KAAK;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,YAAY;YACZ,8DAA8D;YAC9D,UAAU,EAAE,MAAM,CAAC,UAAiB;YACpC,sFAAsF;YACtF,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC;QACD,aAAa;KACd,CAAC,CAAC;AACL,CAAC"}
|