@hashgraphonline/conversational-agent 0.1.217 → 0.1.219
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/cli/readme.md +181 -0
- package/dist/cjs/constants/entity-references.d.ts +18 -0
- package/dist/cjs/constants/form-priorities.d.ts +24 -0
- package/dist/cjs/constants/index.d.ts +4 -0
- package/dist/cjs/constants/messages.d.ts +19 -0
- package/dist/cjs/constants/test-constants.d.ts +42 -0
- package/dist/cjs/conversational-agent.d.ts +3 -8
- package/dist/{types/core/ToolRegistry.d.ts → cjs/core/tool-registry.d.ts} +11 -1
- package/dist/{types/execution/ExecutionPipeline.d.ts → cjs/execution/execution-pipeline.d.ts} +3 -3
- package/dist/cjs/forms/field-guidance-registry.d.ts +108 -0
- package/dist/cjs/forms/form-generator.d.ts +2 -7
- package/dist/cjs/forms/index.d.ts +3 -0
- package/dist/cjs/forms/types.d.ts +9 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +7 -12
- package/dist/cjs/langchain/external-tool-wrapper.d.ts +101 -0
- package/dist/{types/langchain/FormAwareAgentExecutor.d.ts → cjs/langchain/form-aware-agent-executor.d.ts} +19 -4
- package/dist/cjs/langchain/index.d.ts +3 -0
- package/dist/{types → cjs/langchain}/langchain-agent.d.ts +15 -7
- package/dist/cjs/mcp/adapters/index.d.ts +1 -0
- package/dist/cjs/mcp/adapters/langchain.d.ts +1 -1
- package/dist/{types/mcp/ContentProcessor.d.ts → cjs/mcp/content-processor.d.ts} +1 -1
- package/dist/cjs/mcp/index.d.ts +5 -0
- package/dist/{types/mcp/MCPClientManager.d.ts → cjs/mcp/mcp-client-manager.d.ts} +1 -1
- package/dist/cjs/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
- package/dist/cjs/memory/index.d.ts +5 -7
- package/dist/{types/memory/MemoryWindow.d.ts → cjs/memory/memory-window.d.ts} +1 -1
- package/dist/{types/memory/SmartMemoryManager.d.ts → cjs/memory/smart-memory-manager.d.ts} +1 -1
- package/dist/cjs/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
- package/dist/cjs/services/context/resolution-context.d.ts +49 -0
- package/dist/cjs/services/entity-resolver.d.ts +58 -0
- package/dist/cjs/services/formatters/converters/index.d.ts +2 -0
- package/dist/cjs/services/formatters/converters/string-normalization-converter.d.ts +13 -0
- package/dist/cjs/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
- package/dist/cjs/services/formatters/format-converter-registry.d.ts +66 -0
- package/dist/cjs/services/formatters/index.d.ts +3 -0
- package/dist/cjs/services/formatters/types.d.ts +29 -0
- package/dist/cjs/services/index.d.ts +3 -0
- package/dist/cjs/services/resolution/resolution-pipeline.d.ts +44 -0
- package/dist/cjs/tools/index.d.ts +1 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/esm/index.js +40 -13
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index10.js +669 -13
- package/dist/esm/index10.js.map +1 -1
- package/dist/esm/index11.js +310 -95
- package/dist/esm/index11.js.map +1 -1
- package/dist/esm/index12.js +130 -95
- package/dist/esm/index12.js.map +1 -1
- package/dist/esm/index13.js +262 -153
- package/dist/esm/index13.js.map +1 -1
- package/dist/esm/index14.js +100 -664
- package/dist/esm/index14.js.map +1 -1
- package/dist/esm/index15.js +135 -408
- package/dist/esm/index15.js.map +1 -1
- package/dist/esm/index16.js +240 -122
- package/dist/esm/index16.js.map +1 -1
- package/dist/esm/index17.js +147 -135
- package/dist/esm/index17.js.map +1 -1
- package/dist/esm/index18.js +376 -533
- package/dist/esm/index18.js.map +1 -1
- package/dist/esm/index19.js +87 -214
- package/dist/esm/index19.js.map +1 -1
- package/dist/esm/index2.js +21 -4
- package/dist/esm/index2.js.map +1 -1
- package/dist/esm/index20.js +158 -92
- package/dist/esm/index20.js.map +1 -1
- package/dist/esm/index21.js +717 -44
- package/dist/esm/index21.js.map +1 -1
- package/dist/esm/index22.js +58 -96
- package/dist/esm/index22.js.map +1 -1
- package/dist/esm/index23.js +324 -34
- package/dist/esm/index23.js.map +1 -1
- package/dist/esm/index24.js +125 -712
- package/dist/esm/index24.js.map +1 -1
- package/dist/esm/index25.js +113 -133
- package/dist/esm/index25.js.map +1 -1
- package/dist/esm/index26.js +18 -152
- package/dist/esm/index26.js.map +1 -1
- package/dist/esm/index27.js +14 -210
- package/dist/esm/index27.js.map +1 -1
- package/dist/esm/index28.js +70 -173
- package/dist/esm/index28.js.map +1 -1
- package/dist/esm/index29.js +882 -220
- package/dist/esm/index29.js.map +1 -1
- package/dist/esm/index30.js +218 -126
- package/dist/esm/index30.js.map +1 -1
- package/dist/esm/index31.js +1258 -44
- package/dist/esm/index31.js.map +1 -1
- package/dist/esm/index32.js +132 -24
- package/dist/esm/index32.js.map +1 -1
- package/dist/esm/index33.js +104 -82
- package/dist/esm/index33.js.map +1 -1
- package/dist/esm/index34.js +43 -239
- package/dist/esm/index34.js.map +1 -1
- package/dist/esm/index35.js +106 -0
- package/dist/esm/index35.js.map +1 -0
- package/dist/esm/index36.js +24 -0
- package/dist/esm/index36.js.map +1 -0
- package/dist/esm/index37.js +8 -0
- package/dist/esm/index37.js.map +1 -0
- package/dist/esm/index38.js +15 -0
- package/dist/esm/index38.js.map +1 -0
- package/dist/esm/index39.js +258 -0
- package/dist/esm/index39.js.map +1 -0
- package/dist/esm/index40.js +187 -0
- package/dist/esm/index40.js.map +1 -0
- package/dist/esm/index41.js +30 -0
- package/dist/esm/index41.js.map +1 -0
- package/dist/esm/index42.js +10 -0
- package/dist/esm/index42.js.map +1 -0
- package/dist/esm/index43.js +95 -0
- package/dist/esm/index43.js.map +1 -0
- package/dist/esm/index5.js +2 -2
- package/dist/esm/index5.js.map +1 -1
- package/dist/esm/index6.js +44 -67
- package/dist/esm/index6.js.map +1 -1
- package/dist/esm/index7.js +9 -0
- package/dist/esm/index7.js.map +1 -1
- package/dist/esm/index8.js +13 -1095
- package/dist/esm/index8.js.map +1 -1
- package/dist/esm/index9.js +17 -13
- package/dist/esm/index9.js.map +1 -1
- package/dist/types/constants/entity-references.d.ts +18 -0
- package/dist/types/constants/form-priorities.d.ts +24 -0
- package/dist/types/constants/index.d.ts +4 -0
- package/dist/types/constants/messages.d.ts +19 -0
- package/dist/types/constants/test-constants.d.ts +42 -0
- package/dist/types/conversational-agent.d.ts +3 -8
- package/dist/{cjs/core/ToolRegistry.d.ts → types/core/tool-registry.d.ts} +11 -1
- package/dist/{cjs/execution/ExecutionPipeline.d.ts → types/execution/execution-pipeline.d.ts} +3 -3
- package/dist/types/forms/field-guidance-registry.d.ts +108 -0
- package/dist/types/forms/form-generator.d.ts +2 -7
- package/dist/types/forms/index.d.ts +3 -0
- package/dist/types/forms/types.d.ts +9 -1
- package/dist/types/index.d.ts +7 -12
- package/dist/types/langchain/external-tool-wrapper.d.ts +101 -0
- package/dist/{cjs/langchain/FormAwareAgentExecutor.d.ts → types/langchain/form-aware-agent-executor.d.ts} +19 -4
- package/dist/types/langchain/index.d.ts +3 -0
- package/dist/{cjs → types/langchain}/langchain-agent.d.ts +15 -7
- package/dist/types/mcp/adapters/index.d.ts +1 -0
- package/dist/types/mcp/adapters/langchain.d.ts +1 -1
- package/dist/{cjs/mcp/ContentProcessor.d.ts → types/mcp/content-processor.d.ts} +1 -1
- package/dist/types/mcp/index.d.ts +5 -0
- package/dist/{cjs/mcp/MCPClientManager.d.ts → types/mcp/mcp-client-manager.d.ts} +1 -1
- package/dist/types/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
- package/dist/types/memory/index.d.ts +5 -7
- package/dist/{cjs/memory/MemoryWindow.d.ts → types/memory/memory-window.d.ts} +1 -1
- package/dist/{cjs/memory/SmartMemoryManager.d.ts → types/memory/smart-memory-manager.d.ts} +1 -1
- package/dist/types/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
- package/dist/types/services/context/resolution-context.d.ts +49 -0
- package/dist/types/services/entity-resolver.d.ts +58 -0
- package/dist/types/services/formatters/converters/index.d.ts +2 -0
- package/dist/types/services/formatters/converters/string-normalization-converter.d.ts +13 -0
- package/dist/types/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
- package/dist/types/services/formatters/format-converter-registry.d.ts +66 -0
- package/dist/types/services/formatters/index.d.ts +3 -0
- package/dist/types/services/formatters/types.d.ts +29 -0
- package/dist/types/services/index.d.ts +3 -0
- package/dist/types/services/resolution/resolution-pipeline.d.ts +44 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +30 -27
- package/src/agent-factory.ts +1 -1
- package/src/base-agent.ts +9 -0
- package/src/config/system-message.ts +2 -15
- package/src/constants/entity-references.ts +23 -0
- package/src/constants/form-priorities.ts +25 -0
- package/src/constants/index.ts +4 -0
- package/src/constants/messages.ts +20 -0
- package/src/constants/test-constants.ts +49 -0
- package/src/conversational-agent.ts +42 -69
- package/src/core/{ToolRegistry.ts → tool-registry.ts} +71 -1
- package/src/examples/external-tool-wrapper-example.ts +56 -0
- package/src/execution/{ExecutionPipeline.ts → execution-pipeline.ts} +3 -3
- package/src/forms/field-guidance-registry.ts +415 -0
- package/src/forms/field-type-registry.ts +49 -48
- package/src/forms/{FormEngine.ts → form-engine.ts} +66 -43
- package/src/forms/form-generator.ts +91 -17
- package/src/forms/index.ts +4 -1
- package/src/forms/types.ts +9 -1
- package/src/index.ts +7 -37
- package/src/langchain/external-tool-wrapper.ts +90 -0
- package/src/langchain/{FormAwareAgentExecutor.ts → form-aware-agent-executor.ts} +615 -231
- package/src/langchain/{FormValidatingToolWrapper.ts → form-validating-tool-wrapper.ts} +2 -1
- package/src/langchain/index.ts +3 -0
- package/src/{langchain-agent.ts → langchain/langchain-agent.ts} +389 -113
- package/src/mcp/adapters/index.ts +1 -0
- package/src/mcp/adapters/langchain.ts +27 -18
- package/src/mcp/{ContentProcessor.ts → content-processor.ts} +71 -47
- package/src/mcp/index.ts +5 -0
- package/src/mcp/{MCPClientManager.ts → mcp-client-manager.ts} +2 -2
- package/src/memory/{ContentStorage.ts → content-storage.ts} +263 -167
- package/src/memory/index.ts +5 -8
- package/src/memory/{MemoryWindow.ts → memory-window.ts} +47 -24
- package/src/memory/{SmartMemoryManager.ts → smart-memory-manager.ts} +49 -22
- package/src/plugins/hbar/HbarPlugin.ts +1 -1
- package/src/plugins/hcs-10/HCS10Plugin.ts +46 -28
- package/src/scripts/test-external-tool-wrapper.ts +6 -6
- package/src/scripts/test-inscribe-form-generation.ts +22 -21
- package/src/scripts/test-inscribe-wrapper-verification.ts +5 -4
- package/src/services/{ContentStoreManager.ts → content-store-manager.ts} +75 -33
- package/src/services/context/resolution-context.ts +80 -0
- package/src/services/entity-resolver.ts +425 -0
- package/src/services/formatters/converters/index.ts +2 -0
- package/src/services/formatters/converters/string-normalization-converter.ts +106 -0
- package/src/services/formatters/converters/topic-id-to-hrl-converter.ts +25 -0
- package/src/services/formatters/format-converter-registry.ts +229 -0
- package/src/services/formatters/index.ts +3 -0
- package/src/services/formatters/types.ts +31 -0
- package/src/services/index.ts +3 -0
- package/src/services/resolution/resolution-pipeline.ts +106 -0
- package/src/tools/index.ts +1 -0
- package/src/types/content-reference.ts +87 -60
- package/src/utils/index.ts +1 -0
- package/cli/dist/CLIApp.d.ts +0 -9
- package/cli/dist/CLIApp.js +0 -127
- package/cli/dist/LocalConversationalAgent.d.ts +0 -37
- package/cli/dist/LocalConversationalAgent.js +0 -58
- package/cli/dist/app.d.ts +0 -16
- package/cli/dist/app.js +0 -13
- package/cli/dist/cli.d.ts +0 -2
- package/cli/dist/cli.js +0 -51
- package/cli/dist/components/AppContainer.d.ts +0 -16
- package/cli/dist/components/AppContainer.js +0 -24
- package/cli/dist/components/AppScreens.d.ts +0 -2
- package/cli/dist/components/AppScreens.js +0 -259
- package/cli/dist/components/ChatScreen.d.ts +0 -15
- package/cli/dist/components/ChatScreen.js +0 -39
- package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
- package/cli/dist/components/DebugLoadingScreen.js +0 -31
- package/cli/dist/components/LoadingScreen.d.ts +0 -2
- package/cli/dist/components/LoadingScreen.js +0 -16
- package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
- package/cli/dist/components/LoadingScreenDebug.js +0 -27
- package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
- package/cli/dist/components/MCPConfigScreen.js +0 -168
- package/cli/dist/components/ScreenRouter.d.ts +0 -12
- package/cli/dist/components/ScreenRouter.js +0 -22
- package/cli/dist/components/SetupScreen.d.ts +0 -15
- package/cli/dist/components/SetupScreen.js +0 -65
- package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
- package/cli/dist/components/SingleLoadingScreen.js +0 -27
- package/cli/dist/components/StatusBadge.d.ts +0 -7
- package/cli/dist/components/StatusBadge.js +0 -28
- package/cli/dist/components/TerminalWindow.d.ts +0 -8
- package/cli/dist/components/TerminalWindow.js +0 -24
- package/cli/dist/components/WelcomeScreen.d.ts +0 -11
- package/cli/dist/components/WelcomeScreen.js +0 -47
- package/cli/dist/context/AppContext.d.ts +0 -68
- package/cli/dist/context/AppContext.js +0 -363
- package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
- package/cli/dist/hooks/useInitializeAgent.js +0 -28
- package/cli/dist/hooks/useStableState.d.ts +0 -38
- package/cli/dist/hooks/useStableState.js +0 -68
- package/cli/dist/managers/AgentManager.d.ts +0 -57
- package/cli/dist/managers/AgentManager.js +0 -119
- package/cli/dist/managers/ConfigManager.d.ts +0 -53
- package/cli/dist/managers/ConfigManager.js +0 -173
- package/cli/dist/types.d.ts +0 -31
- package/cli/dist/types.js +0 -19
- package/dist/cjs/context/ReferenceContextManager.d.ts +0 -84
- package/dist/cjs/context/ReferenceResponseProcessor.d.ts +0 -76
- package/dist/cjs/services/EntityResolver.d.ts +0 -26
- package/dist/types/context/ReferenceContextManager.d.ts +0 -84
- package/dist/types/context/ReferenceResponseProcessor.d.ts +0 -76
- package/dist/types/services/EntityResolver.d.ts +0 -26
- package/src/context/ReferenceContextManager.ts +0 -350
- package/src/context/ReferenceResponseProcessor.ts +0 -295
- package/src/scripts/test-hedera-kit-wrapper.ts +0 -265
- package/src/services/EntityResolver.ts +0 -128
- /package/dist/cjs/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
- /package/dist/cjs/langchain/{FormValidatingToolWrapper.d.ts → form-validating-tool-wrapper.d.ts} +0 -0
- /package/dist/cjs/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
- /package/dist/cjs/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
- /package/dist/cjs/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
- /package/dist/cjs/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
- /package/dist/types/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
- /package/dist/types/langchain/{FormValidatingToolWrapper.d.ts → form-validating-tool-wrapper.d.ts} +0 -0
- /package/dist/types/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
- /package/dist/types/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
- /package/dist/types/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
- /package/dist/types/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
- /package/src/memory/{ReferenceIdGenerator.ts → reference-id-generator.ts} +0 -0
- /package/src/memory/{TokenCounter.ts → token-counter.ts} +0 -0
- /package/src/tools/{EntityResolverTool.ts → entity-resolver-tool.ts} +0 -0
- /package/src/utils/{ResponseFormatter.ts → response-formatter.ts} +0 -0
|
@@ -2,7 +2,7 @@ import { AgentExecutor } from 'langchain/agents';
|
|
|
2
2
|
import { ZodError, z } from 'zod';
|
|
3
3
|
import { FormGenerator } from '../forms/form-generator';
|
|
4
4
|
import type { FormMessage, FormSubmission } from '../forms/types';
|
|
5
|
-
import { FormEngine } from '../forms/
|
|
5
|
+
import { FormEngine } from '../forms/form-engine';
|
|
6
6
|
import { Logger } from '@hashgraphonline/standards-sdk';
|
|
7
7
|
import type { AgentAction, AgentFinish, AgentStep } from 'langchain/agents';
|
|
8
8
|
import type { ToolInterface } from '@langchain/core/tools';
|
|
@@ -10,7 +10,9 @@ import { isFormValidatable } from '@hashgraphonline/standards-agent-kit';
|
|
|
10
10
|
import type { ChainValues } from '@langchain/core/utils/types';
|
|
11
11
|
import type { CallbackManagerForChainRun } from '@langchain/core/callbacks/manager';
|
|
12
12
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
13
|
-
import { ResponseFormatter } from '../utils/
|
|
13
|
+
import { ResponseFormatter } from '../utils/response-formatter';
|
|
14
|
+
|
|
15
|
+
type BasicFieldType = 'text' | 'number' | 'select' | 'checkbox' | 'textarea';
|
|
14
16
|
|
|
15
17
|
const globalPendingForms: Map<string, PendingFormData> = new Map();
|
|
16
18
|
|
|
@@ -33,7 +35,9 @@ interface PendingFormData {
|
|
|
33
35
|
originalToolInput?: unknown;
|
|
34
36
|
schema: unknown;
|
|
35
37
|
toolRef?: ToolInterface | undefined;
|
|
36
|
-
originalToolRef?:
|
|
38
|
+
originalToolRef?:
|
|
39
|
+
| { call?: (args: Record<string, unknown>) => Promise<string> }
|
|
40
|
+
| undefined;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
interface ToolResponse {
|
|
@@ -57,6 +61,27 @@ interface IntermediateStepData {
|
|
|
57
61
|
observation?: unknown;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
interface HashLinkBlock {
|
|
65
|
+
blockId: string;
|
|
66
|
+
hashLink: string;
|
|
67
|
+
template: string;
|
|
68
|
+
attributes: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ResponseMetadataWithHashLink {
|
|
72
|
+
hashLinkBlock?: HashLinkBlock;
|
|
73
|
+
[key: string]: unknown;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Parameter preprocessing callback interface
|
|
78
|
+
*/
|
|
79
|
+
export interface ParameterPreprocessingCallback {
|
|
80
|
+
(toolName: string, parameters: Record<string, unknown>): Promise<
|
|
81
|
+
Record<string, unknown>
|
|
82
|
+
>;
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
/**
|
|
61
86
|
* Agent executor that intercepts Zod validation errors and generates forms,
|
|
62
87
|
* and processes HashLink block responses for rich UI rendering
|
|
@@ -66,12 +91,51 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
66
91
|
private formEngine: FormEngine;
|
|
67
92
|
private formLogger: Logger;
|
|
68
93
|
private pendingForms: Map<string, PendingFormData> = new Map();
|
|
94
|
+
private parameterPreprocessingCallback:
|
|
95
|
+
| ParameterPreprocessingCallback
|
|
96
|
+
| undefined;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Type guard to check if a Zod type is a ZodObject
|
|
100
|
+
*/
|
|
101
|
+
private isZodObject(schema: unknown): schema is z.ZodObject<z.ZodRawShape> {
|
|
102
|
+
return schema instanceof z.ZodObject;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Type guard to check if metadata has hashLinkBlock
|
|
107
|
+
*/
|
|
108
|
+
private hasHashLinkBlock(
|
|
109
|
+
metadata: unknown
|
|
110
|
+
): metadata is ResponseMetadataWithHashLink & {
|
|
111
|
+
hashLinkBlock: HashLinkBlock;
|
|
112
|
+
} {
|
|
113
|
+
return (
|
|
114
|
+
typeof metadata === 'object' &&
|
|
115
|
+
metadata !== null &&
|
|
116
|
+
'hashLinkBlock' in metadata &&
|
|
117
|
+
typeof (metadata as Record<string, unknown>).hashLinkBlock === 'object' &&
|
|
118
|
+
(metadata as Record<string, unknown>).hashLinkBlock !== null
|
|
119
|
+
);
|
|
120
|
+
}
|
|
69
121
|
|
|
70
122
|
constructor(...args: ConstructorParameters<typeof AgentExecutor>) {
|
|
71
123
|
super(...args);
|
|
72
124
|
this.formGenerator = new FormGenerator();
|
|
73
|
-
this.formEngine = new FormEngine(
|
|
125
|
+
this.formEngine = new FormEngine(
|
|
126
|
+
new Logger({ module: 'FormAwareAgentExecutor.FormEngine' })
|
|
127
|
+
);
|
|
74
128
|
this.formLogger = new Logger({ module: 'FormAwareAgentExecutor' });
|
|
129
|
+
this.parameterPreprocessingCallback = undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Set parameter preprocessing callback
|
|
134
|
+
*/
|
|
135
|
+
setParameterPreprocessingCallback(
|
|
136
|
+
callback: ParameterPreprocessingCallback | undefined
|
|
137
|
+
): void {
|
|
138
|
+
this.parameterPreprocessingCallback = callback;
|
|
75
139
|
}
|
|
76
140
|
|
|
77
141
|
/**
|
|
@@ -87,11 +151,15 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
87
151
|
): Promise<AgentFinish | AgentStep[]> {
|
|
88
152
|
this.formLogger.info('🛡️ BULLETPROOF INTERCEPTION: _takeNextStep called', {
|
|
89
153
|
availableTools: Object.keys(nameToolMap),
|
|
90
|
-
inputKeys: Object.keys(inputs)
|
|
154
|
+
inputKeys: Object.keys(inputs),
|
|
91
155
|
});
|
|
92
156
|
|
|
93
|
-
const result = await this.agent.plan(
|
|
94
|
-
|
|
157
|
+
const result = await this.agent.plan(
|
|
158
|
+
intermediateSteps,
|
|
159
|
+
inputs,
|
|
160
|
+
runManager?.getChild()
|
|
161
|
+
);
|
|
162
|
+
|
|
95
163
|
if ('returnValues' in result) {
|
|
96
164
|
this.formLogger.info('Agent returned finish action, passing through');
|
|
97
165
|
return result;
|
|
@@ -104,89 +172,119 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
104
172
|
this.formLogger.info(`🎯 INTERCEPTING TOOL CALL: ${toolName}`, {
|
|
105
173
|
toolInput,
|
|
106
174
|
hasInNameToolMap: toolName in nameToolMap,
|
|
107
|
-
toolInputKeys: Object.keys(toolInput || {})
|
|
175
|
+
toolInputKeys: Object.keys(toolInput || {}),
|
|
108
176
|
});
|
|
109
177
|
|
|
110
|
-
const tool =
|
|
111
|
-
|
|
178
|
+
const tool =
|
|
179
|
+
nameToolMap[toolName] || this.tools.find((t) => t.name === toolName);
|
|
180
|
+
|
|
112
181
|
if (!tool) {
|
|
113
182
|
this.formLogger.error(`Tool ${toolName} not found in registry`);
|
|
114
183
|
throw new Error(`Tool "${toolName}" not found`);
|
|
115
184
|
}
|
|
116
185
|
|
|
117
186
|
let shouldGenerateForm = false;
|
|
118
|
-
|
|
187
|
+
|
|
119
188
|
if (isFormValidatable(tool)) {
|
|
120
|
-
this.formLogger.info(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
189
|
+
this.formLogger.info(
|
|
190
|
+
`🔍 Tool ${toolName} implements FormValidatable, checking shouldGenerateForm()`,
|
|
191
|
+
{
|
|
192
|
+
toolInput,
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
|
|
124
196
|
try {
|
|
125
197
|
shouldGenerateForm = tool.shouldGenerateForm(toolInput);
|
|
126
|
-
this.formLogger.info(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
198
|
+
this.formLogger.info(
|
|
199
|
+
`FormValidatable.shouldGenerateForm() result: ${shouldGenerateForm}`,
|
|
200
|
+
{
|
|
201
|
+
toolName,
|
|
202
|
+
toolInput,
|
|
203
|
+
}
|
|
204
|
+
);
|
|
130
205
|
} catch (error) {
|
|
131
|
-
this.formLogger.error(
|
|
206
|
+
this.formLogger.error(
|
|
207
|
+
`Error calling shouldGenerateForm() on ${toolName}:`,
|
|
208
|
+
error
|
|
209
|
+
);
|
|
132
210
|
shouldGenerateForm = false;
|
|
133
211
|
}
|
|
134
212
|
}
|
|
135
213
|
|
|
136
214
|
if (shouldGenerateForm) {
|
|
137
215
|
this.formLogger.info(`🚨 FORM GENERATION TRIGGERED for ${toolName}`);
|
|
138
|
-
|
|
216
|
+
|
|
139
217
|
try {
|
|
140
218
|
let schemaToUse: z.ZodSchema;
|
|
141
219
|
let isFocusedSchema = false;
|
|
142
|
-
|
|
220
|
+
|
|
143
221
|
if (isFormValidatable(tool)) {
|
|
144
|
-
this.formLogger.info(
|
|
222
|
+
this.formLogger.info(
|
|
223
|
+
`🎯 Tool ${toolName} is FormValidatable, attempting to get focused schema`
|
|
224
|
+
);
|
|
145
225
|
try {
|
|
146
226
|
const focusedSchema = tool.getFormSchema();
|
|
147
227
|
if (focusedSchema) {
|
|
148
228
|
schemaToUse = focusedSchema;
|
|
149
229
|
isFocusedSchema = true;
|
|
150
|
-
this.formLogger.info(
|
|
230
|
+
this.formLogger.info(
|
|
231
|
+
`✅ Successfully obtained focused schema for ${toolName}`
|
|
232
|
+
);
|
|
151
233
|
} else {
|
|
152
|
-
this.formLogger.warn(
|
|
234
|
+
this.formLogger.warn(
|
|
235
|
+
`getFormSchema() returned null/undefined for ${toolName}, using default schema`
|
|
236
|
+
);
|
|
153
237
|
schemaToUse = tool.schema;
|
|
154
238
|
isFocusedSchema = false;
|
|
155
239
|
}
|
|
156
240
|
} catch (error) {
|
|
157
|
-
this.formLogger.error(
|
|
158
|
-
|
|
241
|
+
this.formLogger.error(
|
|
242
|
+
`Failed to get focused schema from ${toolName}:`,
|
|
243
|
+
error
|
|
244
|
+
);
|
|
245
|
+
this.formLogger.info(
|
|
246
|
+
`Falling back to default schema for ${toolName}`
|
|
247
|
+
);
|
|
159
248
|
schemaToUse = tool.schema;
|
|
160
249
|
isFocusedSchema = false;
|
|
161
250
|
}
|
|
162
251
|
} else {
|
|
163
|
-
this.formLogger.info(
|
|
252
|
+
this.formLogger.info(
|
|
253
|
+
`Tool ${toolName} is not FormValidatable, using default schema`
|
|
254
|
+
);
|
|
164
255
|
schemaToUse = tool.schema;
|
|
165
256
|
isFocusedSchema = false;
|
|
166
257
|
}
|
|
167
258
|
|
|
168
259
|
let schemaFieldCount = 'unknown';
|
|
169
260
|
try {
|
|
170
|
-
if (schemaToUse
|
|
171
|
-
const
|
|
261
|
+
if (this.isZodObject(schemaToUse)) {
|
|
262
|
+
const zodObject = schemaToUse as z.ZodObject<z.ZodRawShape>;
|
|
263
|
+
const shape = zodObject.shape;
|
|
172
264
|
if (shape && typeof shape === 'object') {
|
|
173
265
|
schemaFieldCount = Object.keys(shape).length.toString();
|
|
174
266
|
}
|
|
175
267
|
}
|
|
176
|
-
} catch {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
268
|
+
} catch {}
|
|
269
|
+
|
|
270
|
+
this.formLogger.info(
|
|
271
|
+
`📋 Generating form with ${
|
|
272
|
+
isFocusedSchema ? 'FOCUSED' : 'DEFAULT'
|
|
273
|
+
} schema`,
|
|
274
|
+
{
|
|
275
|
+
toolName,
|
|
276
|
+
schemaType: schemaToUse?.constructor?.name,
|
|
277
|
+
estimatedFieldCount: schemaFieldCount,
|
|
278
|
+
isFocusedSchema,
|
|
279
|
+
}
|
|
280
|
+
);
|
|
185
281
|
|
|
186
282
|
let missingFields: Set<string> | undefined;
|
|
187
|
-
|
|
283
|
+
|
|
188
284
|
if (isFocusedSchema) {
|
|
189
|
-
this.formLogger.info(
|
|
285
|
+
this.formLogger.info(
|
|
286
|
+
`⭐ Using focused schema - letting FormGenerator determine fields from schema`
|
|
287
|
+
);
|
|
190
288
|
missingFields = undefined;
|
|
191
289
|
} else {
|
|
192
290
|
missingFields = new Set<string>();
|
|
@@ -195,38 +293,42 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
195
293
|
const shape = zodObject.shape || {};
|
|
196
294
|
for (const fieldName of Object.keys(shape)) {
|
|
197
295
|
const value = (toolInput || {})[fieldName];
|
|
198
|
-
|
|
199
|
-
const isEmpty =
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
296
|
+
|
|
297
|
+
const isEmpty =
|
|
298
|
+
isFormValidatable(tool) && tool.isFieldEmpty
|
|
299
|
+
? tool.isFieldEmpty(fieldName, value)
|
|
300
|
+
: value === undefined ||
|
|
301
|
+
value === '' ||
|
|
302
|
+
value === null ||
|
|
303
|
+
(Array.isArray(value) && value.length === 0);
|
|
304
|
+
|
|
206
305
|
const isRequired = this.isFieldRequired(schemaToUse, fieldName);
|
|
207
|
-
|
|
208
|
-
const isEssential =
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
306
|
+
|
|
307
|
+
const isEssential =
|
|
308
|
+
isFormValidatable(tool) && tool.getEssentialFields
|
|
309
|
+
? tool.getEssentialFields().includes(fieldName)
|
|
310
|
+
: false;
|
|
311
|
+
|
|
212
312
|
this.formLogger.info(`🔍 Field analysis: ${fieldName}`, {
|
|
213
313
|
value: value,
|
|
214
314
|
isEmpty: isEmpty,
|
|
215
315
|
isRequired: isRequired,
|
|
216
316
|
isEssential: isEssential,
|
|
217
|
-
willAddToMissingFields: isEmpty && (isRequired || isEssential)
|
|
317
|
+
willAddToMissingFields: isEmpty && (isRequired || isEssential),
|
|
218
318
|
});
|
|
219
|
-
|
|
319
|
+
|
|
220
320
|
if (isEmpty && (isRequired || isEssential)) {
|
|
221
321
|
missingFields.add(fieldName);
|
|
222
322
|
}
|
|
223
323
|
}
|
|
224
324
|
}
|
|
225
|
-
|
|
325
|
+
|
|
226
326
|
this.formLogger.info(`📋 Missing fields analysis complete`, {
|
|
227
|
-
totalFields: this.isZodObject(schemaToUse)
|
|
327
|
+
totalFields: this.isZodObject(schemaToUse)
|
|
328
|
+
? Object.keys(schemaToUse.shape).length
|
|
329
|
+
: 0,
|
|
228
330
|
missingFieldsCount: missingFields.size,
|
|
229
|
-
missingFields: Array.from(missingFields)
|
|
331
|
+
missingFields: Array.from(missingFields),
|
|
230
332
|
});
|
|
231
333
|
}
|
|
232
334
|
|
|
@@ -235,34 +337,44 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
235
337
|
toolInput,
|
|
236
338
|
{
|
|
237
339
|
toolName: toolName,
|
|
238
|
-
toolDescription: tool.description
|
|
340
|
+
toolDescription: tool.description,
|
|
239
341
|
},
|
|
240
|
-
missingFields
|
|
342
|
+
missingFields // Pass undefined for focused schemas, Set<string> for others
|
|
241
343
|
);
|
|
242
344
|
|
|
243
345
|
if (this.isZodObject(schemaToUse)) {
|
|
244
346
|
try {
|
|
245
|
-
const { jsonSchema, uiSchema } =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
347
|
+
const { jsonSchema, uiSchema } =
|
|
348
|
+
this.formGenerator.generateJsonSchemaForm(
|
|
349
|
+
schemaToUse,
|
|
350
|
+
toolInput as Record<string, unknown> | undefined,
|
|
351
|
+
missingFields
|
|
352
|
+
);
|
|
250
353
|
formMessage.jsonSchema = jsonSchema;
|
|
251
354
|
formMessage.uiSchema = uiSchema;
|
|
252
355
|
} catch (error) {
|
|
253
|
-
this.formLogger.warn(
|
|
356
|
+
this.formLogger.warn(
|
|
357
|
+
'Failed to generate JSON Schema for RJSF:',
|
|
358
|
+
error
|
|
359
|
+
);
|
|
254
360
|
}
|
|
255
361
|
}
|
|
256
362
|
|
|
257
363
|
formMessage.partialInput = toolInput;
|
|
258
|
-
|
|
364
|
+
|
|
259
365
|
const formData: PendingFormData = {
|
|
260
366
|
toolName: toolName,
|
|
261
367
|
originalInput: inputs,
|
|
262
368
|
originalToolInput: toolInput,
|
|
263
369
|
schema: schemaToUse,
|
|
264
370
|
toolRef: tool as ToolInterface | undefined,
|
|
265
|
-
originalToolRef: (
|
|
371
|
+
originalToolRef: (
|
|
372
|
+
tool as unknown as {
|
|
373
|
+
originalTool?: {
|
|
374
|
+
call?: (args: Record<string, unknown>) => Promise<string>;
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
).originalTool,
|
|
266
378
|
};
|
|
267
379
|
this.pendingForms.set(formMessage.id, formData);
|
|
268
380
|
globalPendingForms.set(formMessage.id, formData);
|
|
@@ -271,33 +383,155 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
271
383
|
|
|
272
384
|
const formResult = {
|
|
273
385
|
requiresForm: true,
|
|
274
|
-
formMessage
|
|
386
|
+
formMessage,
|
|
275
387
|
};
|
|
276
388
|
|
|
277
|
-
return [
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
389
|
+
return [
|
|
390
|
+
{
|
|
391
|
+
action: action,
|
|
392
|
+
observation: JSON.stringify(formResult),
|
|
393
|
+
},
|
|
394
|
+
];
|
|
282
395
|
} catch (error) {
|
|
283
396
|
this.formLogger.error(`Form generation failed for ${toolName}:`, error);
|
|
284
|
-
|
|
285
397
|
}
|
|
286
398
|
}
|
|
287
399
|
|
|
288
|
-
this.formLogger.info(
|
|
289
|
-
|
|
290
|
-
|
|
400
|
+
this.formLogger.info(
|
|
401
|
+
`⚪ Passing through to normal tool execution for ${toolName}`
|
|
402
|
+
);
|
|
291
403
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
404
|
+
if (this.parameterPreprocessingCallback && toolInput) {
|
|
405
|
+
this.formLogger.info(
|
|
406
|
+
`🔄 Applying parameter preprocessing for ${toolName}`
|
|
407
|
+
);
|
|
408
|
+
try {
|
|
409
|
+
const preprocessedInput = await this.parameterPreprocessingCallback(
|
|
410
|
+
toolName,
|
|
411
|
+
toolInput as Record<string, unknown>
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
if (
|
|
415
|
+
preprocessedInput &&
|
|
416
|
+
typeof preprocessedInput === 'object' &&
|
|
417
|
+
'__requestForm' in (preprocessedInput as Record<string, unknown>)
|
|
418
|
+
) {
|
|
419
|
+
const rf = (preprocessedInput as Record<string, unknown>).__requestForm as {
|
|
420
|
+
id?: string;
|
|
421
|
+
title?: string;
|
|
422
|
+
description?: string;
|
|
423
|
+
fields?: Array<{
|
|
424
|
+
name: string;
|
|
425
|
+
label: string;
|
|
426
|
+
type: string;
|
|
427
|
+
required?: boolean;
|
|
428
|
+
options?: Array<{ value: string; label: string }>;
|
|
429
|
+
}>;
|
|
430
|
+
submitLabel?: string;
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const formId = rf.id || `form_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
434
|
+
const formMessage = {
|
|
435
|
+
type: 'form',
|
|
436
|
+
id: formId,
|
|
437
|
+
originalPrompt: 'Parameter validation required',
|
|
438
|
+
toolName,
|
|
439
|
+
formConfig: {
|
|
440
|
+
title: rf.title || 'Complete required parameters',
|
|
441
|
+
description:
|
|
442
|
+
rf.description ||
|
|
443
|
+
'One or more parameters require confirmation. Please review and submit.',
|
|
444
|
+
submitLabel: rf.submitLabel || 'Continue',
|
|
445
|
+
fields: (rf.fields || []).map((f) => {
|
|
446
|
+
const allowedTypes: BasicFieldType[] = [
|
|
447
|
+
'text',
|
|
448
|
+
'number',
|
|
449
|
+
'select',
|
|
450
|
+
'checkbox',
|
|
451
|
+
'textarea',
|
|
452
|
+
];
|
|
453
|
+
const resolvedType: BasicFieldType = allowedTypes.includes(
|
|
454
|
+
f.type as BasicFieldType
|
|
455
|
+
)
|
|
456
|
+
? (f.type as BasicFieldType)
|
|
457
|
+
: 'text';
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
name: f.name,
|
|
461
|
+
label: f.label,
|
|
462
|
+
type: resolvedType,
|
|
463
|
+
required: f.required ?? true,
|
|
464
|
+
options: f.options,
|
|
465
|
+
};
|
|
466
|
+
}),
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const resolvedSchema = isFormValidatable(tool)
|
|
471
|
+
? (() => {
|
|
472
|
+
try {
|
|
473
|
+
const s = tool.getFormSchema();
|
|
474
|
+
return s || tool.schema;
|
|
475
|
+
} catch {
|
|
476
|
+
return tool.schema;
|
|
477
|
+
}
|
|
478
|
+
})()
|
|
479
|
+
: tool.schema;
|
|
480
|
+
|
|
481
|
+
this.pendingForms.set(formId, {
|
|
482
|
+
toolName,
|
|
483
|
+
originalInput: inputs,
|
|
484
|
+
originalToolInput: toolInput,
|
|
485
|
+
schema: resolvedSchema,
|
|
486
|
+
toolRef: tool as ToolInterface | undefined,
|
|
487
|
+
originalToolRef: (
|
|
488
|
+
tool as unknown as { originalTool?: { call?: (a: Record<string, unknown>) => Promise<string> } }
|
|
489
|
+
).originalTool,
|
|
490
|
+
});
|
|
491
|
+
globalPendingForms.set(formId, {
|
|
492
|
+
toolName,
|
|
493
|
+
originalInput: inputs,
|
|
494
|
+
originalToolInput: toolInput,
|
|
495
|
+
schema: resolvedSchema,
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
return [
|
|
499
|
+
{
|
|
500
|
+
action,
|
|
501
|
+
observation: JSON.stringify({ requiresForm: true, formMessage }),
|
|
502
|
+
},
|
|
503
|
+
];
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (JSON.stringify(preprocessedInput) !== JSON.stringify(toolInput)) {
|
|
507
|
+
this.formLogger.info(`📝 Parameters preprocessed for ${toolName}:`, {
|
|
508
|
+
original: Object.keys(toolInput as Record<string, unknown>),
|
|
509
|
+
preprocessed: Object.keys(preprocessedInput),
|
|
510
|
+
hasChanges: true,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
(action as unknown as { toolInput?: Record<string, unknown> }).toolInput =
|
|
515
|
+
preprocessedInput as Record<string, unknown>;
|
|
516
|
+
} catch {}
|
|
517
|
+
} else {
|
|
518
|
+
this.formLogger.debug(`No parameter changes needed for ${toolName}`);
|
|
519
|
+
}
|
|
520
|
+
} catch (preprocessError) {
|
|
521
|
+
this.formLogger.warn(
|
|
522
|
+
`Parameter preprocessing failed for ${toolName}, using original parameters:`,
|
|
523
|
+
preprocessError
|
|
524
|
+
);
|
|
525
|
+
}
|
|
298
526
|
}
|
|
299
|
-
|
|
300
|
-
return
|
|
527
|
+
|
|
528
|
+
return super._takeNextStep(
|
|
529
|
+
nameToolMap,
|
|
530
|
+
inputs,
|
|
531
|
+
intermediateSteps,
|
|
532
|
+
runManager,
|
|
533
|
+
config
|
|
534
|
+
);
|
|
301
535
|
}
|
|
302
536
|
|
|
303
537
|
/**
|
|
@@ -314,9 +548,10 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
314
548
|
if (!def || def.typeName !== 'ZodObject') {
|
|
315
549
|
return false;
|
|
316
550
|
}
|
|
317
|
-
const rawShape: unknown =
|
|
318
|
-
|
|
319
|
-
|
|
551
|
+
const rawShape: unknown =
|
|
552
|
+
typeof (def as { shape?: unknown }).shape === 'function'
|
|
553
|
+
? (def as { shape: () => Record<string, z.ZodTypeAny> }).shape()
|
|
554
|
+
: (def as { shape?: Record<string, z.ZodTypeAny> }).shape;
|
|
320
555
|
if (!rawShape || typeof rawShape !== 'object') {
|
|
321
556
|
return false;
|
|
322
557
|
}
|
|
@@ -326,14 +561,22 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
326
561
|
return false;
|
|
327
562
|
}
|
|
328
563
|
const unwrapOptional = (s: z.ZodTypeAny): z.ZodTypeAny => {
|
|
329
|
-
const inner = (
|
|
564
|
+
const inner = (
|
|
565
|
+
s as unknown as {
|
|
566
|
+
_def?: { typeName?: string; innerType?: z.ZodTypeAny };
|
|
567
|
+
}
|
|
568
|
+
)._def;
|
|
330
569
|
if (inner && inner.typeName === 'ZodOptional' && inner.innerType) {
|
|
331
570
|
return inner.innerType;
|
|
332
571
|
}
|
|
333
572
|
return s;
|
|
334
573
|
};
|
|
335
574
|
const unwrapped = unwrapOptional(fieldSchema);
|
|
336
|
-
const fdef = (
|
|
575
|
+
const fdef = (
|
|
576
|
+
unwrapped as unknown as {
|
|
577
|
+
_def?: { typeName?: string; defaultValue?: unknown };
|
|
578
|
+
}
|
|
579
|
+
)._def;
|
|
337
580
|
if (!fdef) {
|
|
338
581
|
return true;
|
|
339
582
|
}
|
|
@@ -345,7 +588,10 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
345
588
|
}
|
|
346
589
|
return true;
|
|
347
590
|
} catch (error) {
|
|
348
|
-
this.formLogger.debug(
|
|
591
|
+
this.formLogger.debug(
|
|
592
|
+
`Could not determine if field ${fieldPath} is required:`,
|
|
593
|
+
error
|
|
594
|
+
);
|
|
349
595
|
}
|
|
350
596
|
return false;
|
|
351
597
|
}
|
|
@@ -353,69 +599,83 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
353
599
|
/**
|
|
354
600
|
* Override _call to intercept Zod validation errors at the execution level
|
|
355
601
|
*/
|
|
356
|
-
override async _call(
|
|
602
|
+
override async _call(
|
|
603
|
+
inputs: Record<string, unknown>
|
|
604
|
+
): Promise<Record<string, unknown>> {
|
|
357
605
|
try {
|
|
358
606
|
const result = await super._call(inputs);
|
|
359
|
-
|
|
607
|
+
|
|
360
608
|
if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {
|
|
361
609
|
for (const step of result.intermediateSteps) {
|
|
362
610
|
if (step.observation) {
|
|
363
611
|
try {
|
|
364
|
-
const parsed: ToolResponse =
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
612
|
+
const parsed: ToolResponse =
|
|
613
|
+
typeof step.observation === 'string'
|
|
614
|
+
? JSON.parse(step.observation)
|
|
615
|
+
: (step.observation as ToolResponse);
|
|
616
|
+
|
|
368
617
|
if (parsed.requiresForm && parsed.formMessage) {
|
|
369
618
|
this.formLogger.info('Tool requested form generation', {
|
|
370
619
|
toolName: step.action?.tool,
|
|
371
|
-
hasForm: true
|
|
620
|
+
hasForm: true,
|
|
372
621
|
});
|
|
373
|
-
|
|
374
|
-
const actionToolName =
|
|
375
|
-
|
|
376
|
-
const
|
|
622
|
+
|
|
623
|
+
const actionToolName =
|
|
624
|
+
(step as IntermediateStepData).action?.tool || 'unknown';
|
|
625
|
+
const toolInstance = this.tools.find(
|
|
626
|
+
(t) => t.name === actionToolName
|
|
627
|
+
) as ToolInterface | undefined;
|
|
628
|
+
const originalToolCandidate =
|
|
629
|
+
(toolInstance as unknown as {
|
|
630
|
+
originalTool?: {
|
|
631
|
+
call?: (args: Record<string, unknown>) => Promise<string>;
|
|
632
|
+
};
|
|
633
|
+
}) || {};
|
|
377
634
|
const pf: PendingFormData = {
|
|
378
635
|
toolName: actionToolName,
|
|
379
636
|
originalInput: inputs,
|
|
380
|
-
originalToolInput: (step as IntermediateStepData).action
|
|
637
|
+
originalToolInput: (step as IntermediateStepData).action
|
|
638
|
+
?.toolInput as Record<string, unknown> | undefined,
|
|
381
639
|
schema: null,
|
|
382
640
|
toolRef: toolInstance,
|
|
383
|
-
originalToolRef: originalToolCandidate?.originalTool
|
|
641
|
+
originalToolRef: originalToolCandidate?.originalTool,
|
|
384
642
|
};
|
|
385
643
|
this.pendingForms.set(parsed.formMessage.id, pf);
|
|
386
644
|
globalPendingForms.set(parsed.formMessage.id, pf);
|
|
387
|
-
|
|
645
|
+
|
|
388
646
|
return {
|
|
389
647
|
...result,
|
|
390
648
|
requiresForm: true,
|
|
391
649
|
formMessage: parsed.formMessage,
|
|
392
|
-
output:
|
|
650
|
+
output:
|
|
651
|
+
parsed.message || 'Please complete the form to continue.',
|
|
393
652
|
};
|
|
394
653
|
}
|
|
395
|
-
|
|
396
|
-
if (
|
|
654
|
+
|
|
655
|
+
if (
|
|
656
|
+
parsed.hashLinkBlock ||
|
|
657
|
+
(parsed.success && parsed.inscription && parsed.hashLinkBlock)
|
|
658
|
+
) {
|
|
397
659
|
this.formLogger.info('Tool returned HashLink blocks', {
|
|
398
660
|
toolName: (step as IntermediateStepData).action?.tool,
|
|
399
661
|
hasHashLink: true,
|
|
400
|
-
blockId: parsed.hashLinkBlock?.blockId
|
|
662
|
+
blockId: parsed.hashLinkBlock?.blockId,
|
|
401
663
|
});
|
|
402
|
-
|
|
664
|
+
|
|
403
665
|
const hashLinkResponse = this.processHashLinkResponse(parsed);
|
|
404
|
-
|
|
666
|
+
|
|
405
667
|
return {
|
|
406
668
|
...result,
|
|
407
669
|
hasHashLinkBlocks: true,
|
|
408
670
|
hashLinkBlock: hashLinkResponse.hashLinkBlock,
|
|
409
|
-
output: hashLinkResponse.message
|
|
671
|
+
output: hashLinkResponse.message,
|
|
410
672
|
};
|
|
411
673
|
}
|
|
412
|
-
} catch {
|
|
413
|
-
|
|
414
|
-
}
|
|
674
|
+
} catch {}
|
|
415
675
|
}
|
|
416
676
|
}
|
|
417
677
|
}
|
|
418
|
-
|
|
678
|
+
|
|
419
679
|
return result;
|
|
420
680
|
} catch (error) {
|
|
421
681
|
if (error instanceof ZodError) {
|
|
@@ -436,16 +696,24 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
436
696
|
): Promise<Record<string, unknown>> {
|
|
437
697
|
this.formLogger.info('Zod validation error detected, generating form', {
|
|
438
698
|
errorIssues: error.issues.length,
|
|
439
|
-
inputKeys: Object.keys(inputs)
|
|
699
|
+
inputKeys: Object.keys(inputs),
|
|
440
700
|
});
|
|
441
701
|
|
|
442
|
-
let toolInfo = this.extractToolInfoFromError(
|
|
443
|
-
|
|
702
|
+
let toolInfo = this.extractToolInfoFromError(
|
|
703
|
+
error,
|
|
704
|
+
inputs,
|
|
705
|
+
intermediateSteps
|
|
706
|
+
);
|
|
707
|
+
|
|
444
708
|
if (!toolInfo) {
|
|
445
|
-
this.formLogger.warn(
|
|
709
|
+
this.formLogger.warn(
|
|
710
|
+
'Could not extract tool info from validation error, trying fallback detection'
|
|
711
|
+
);
|
|
446
712
|
const fallbackTool = this.detectToolFromErrorContext(error);
|
|
447
713
|
if (!fallbackTool) {
|
|
448
|
-
this.formLogger.error(
|
|
714
|
+
this.formLogger.error(
|
|
715
|
+
'No tool detected for form generation, rethrowing error'
|
|
716
|
+
);
|
|
449
717
|
throw error;
|
|
450
718
|
}
|
|
451
719
|
toolInfo = fallbackTool;
|
|
@@ -453,7 +721,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
453
721
|
|
|
454
722
|
this.formLogger.info('Generating form for tool:', {
|
|
455
723
|
toolName: toolInfo.toolName,
|
|
456
|
-
hasSchema: !!toolInfo.schema
|
|
724
|
+
hasSchema: !!toolInfo.schema,
|
|
457
725
|
});
|
|
458
726
|
|
|
459
727
|
const formMessage = this.formGenerator.generateFormFromError(
|
|
@@ -466,20 +734,20 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
466
734
|
this.pendingForms.set(formMessage.id, {
|
|
467
735
|
toolName: toolInfo.toolName,
|
|
468
736
|
originalInput: inputs,
|
|
469
|
-
schema: toolInfo.schema
|
|
737
|
+
schema: toolInfo.schema,
|
|
470
738
|
});
|
|
471
739
|
|
|
472
740
|
globalPendingForms.set(formMessage.id, {
|
|
473
741
|
toolName: toolInfo.toolName,
|
|
474
742
|
originalInput: inputs,
|
|
475
|
-
schema: toolInfo.schema
|
|
743
|
+
schema: toolInfo.schema,
|
|
476
744
|
});
|
|
477
745
|
|
|
478
746
|
return {
|
|
479
747
|
output: this.formatFormResponse(formMessage),
|
|
480
748
|
formMessage,
|
|
481
749
|
requiresForm: true,
|
|
482
|
-
intermediateSteps: intermediateSteps || []
|
|
750
|
+
intermediateSteps: intermediateSteps || [],
|
|
483
751
|
};
|
|
484
752
|
}
|
|
485
753
|
|
|
@@ -502,11 +770,16 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
502
770
|
/**
|
|
503
771
|
* Processes form submission and continues tool execution
|
|
504
772
|
*/
|
|
505
|
-
async processFormSubmission(
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
773
|
+
async processFormSubmission(
|
|
774
|
+
submission: FormSubmission
|
|
775
|
+
): Promise<Record<string, unknown>> {
|
|
776
|
+
this.formLogger.info(
|
|
777
|
+
'🚀 FormAwareAgentExecutor.processFormSubmission called!',
|
|
778
|
+
{
|
|
779
|
+
submissionFormId: submission.formId,
|
|
780
|
+
submissionToolName: submission.toolName,
|
|
781
|
+
}
|
|
782
|
+
);
|
|
510
783
|
if (!submission) {
|
|
511
784
|
throw new Error('Form submission is null or undefined');
|
|
512
785
|
}
|
|
@@ -515,8 +788,19 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
515
788
|
throw new Error('Form submission missing formId');
|
|
516
789
|
}
|
|
517
790
|
|
|
518
|
-
if (
|
|
519
|
-
|
|
791
|
+
if (
|
|
792
|
+
!submission.parameters ||
|
|
793
|
+
submission.parameters === null ||
|
|
794
|
+
typeof submission.parameters !== 'object' ||
|
|
795
|
+
Array.isArray(submission.parameters)
|
|
796
|
+
) {
|
|
797
|
+
throw new Error(
|
|
798
|
+
`Form submission parameters are invalid: ${typeof submission.parameters}, isNull: ${
|
|
799
|
+
submission.parameters === null
|
|
800
|
+
}, isArray: ${Array.isArray(
|
|
801
|
+
submission.parameters
|
|
802
|
+
)}, parameters: ${JSON.stringify(submission.parameters)}`
|
|
803
|
+
);
|
|
520
804
|
}
|
|
521
805
|
|
|
522
806
|
this.formLogger.info('Processing form submission:', {
|
|
@@ -541,41 +825,58 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
541
825
|
this.pendingForms.delete(submission.formId);
|
|
542
826
|
globalPendingForms.delete(submission.formId);
|
|
543
827
|
|
|
544
|
-
const tool =
|
|
828
|
+
const tool =
|
|
829
|
+
pendingForm.toolRef ||
|
|
830
|
+
this.tools.find((t) => t.name === pendingForm.toolName);
|
|
545
831
|
if (!tool) {
|
|
546
|
-
throw new Error(
|
|
832
|
+
throw new Error(
|
|
833
|
+
`Tool not found for form submission: ${pendingForm.toolName}`
|
|
834
|
+
);
|
|
547
835
|
}
|
|
548
836
|
|
|
549
837
|
let baseToolInput: Record<string, unknown> = {};
|
|
550
838
|
try {
|
|
551
|
-
if (
|
|
552
|
-
|
|
839
|
+
if (
|
|
840
|
+
pendingForm.originalToolInput &&
|
|
841
|
+
typeof pendingForm.originalToolInput === 'object'
|
|
842
|
+
) {
|
|
843
|
+
baseToolInput = {
|
|
844
|
+
...(pendingForm.originalToolInput as Record<string, unknown>),
|
|
845
|
+
};
|
|
553
846
|
}
|
|
554
847
|
} catch (error) {
|
|
555
|
-
this.formLogger.warn(
|
|
848
|
+
this.formLogger.warn(
|
|
849
|
+
'Failed to extract base tool input, using empty object:',
|
|
850
|
+
error
|
|
851
|
+
);
|
|
556
852
|
baseToolInput = {};
|
|
557
853
|
}
|
|
558
854
|
|
|
559
855
|
let submissionData: Record<string, unknown> = {};
|
|
560
856
|
try {
|
|
561
857
|
if (submission.parameters && typeof submission.parameters === 'object') {
|
|
562
|
-
submissionData = {
|
|
858
|
+
submissionData = {
|
|
859
|
+
...(submission.parameters as Record<string, unknown>),
|
|
860
|
+
};
|
|
563
861
|
}
|
|
564
862
|
} catch (error) {
|
|
565
|
-
this.formLogger.warn(
|
|
863
|
+
this.formLogger.warn(
|
|
864
|
+
'Failed to extract submission parameters, using empty object:',
|
|
865
|
+
error
|
|
866
|
+
);
|
|
566
867
|
submissionData = {};
|
|
567
868
|
}
|
|
568
869
|
|
|
569
870
|
const mergedToolInput: Record<string, unknown> = {};
|
|
570
871
|
try {
|
|
571
|
-
Object.keys(baseToolInput).forEach(key => {
|
|
872
|
+
Object.keys(baseToolInput).forEach((key) => {
|
|
572
873
|
const value = baseToolInput[key];
|
|
573
874
|
if (value !== undefined && value !== null) {
|
|
574
875
|
mergedToolInput[key] = value;
|
|
575
876
|
}
|
|
576
877
|
});
|
|
577
878
|
|
|
578
|
-
Object.keys(submissionData).forEach(key => {
|
|
879
|
+
Object.keys(submissionData).forEach((key) => {
|
|
579
880
|
const value = submissionData[key];
|
|
580
881
|
if (value !== undefined && value !== null) {
|
|
581
882
|
mergedToolInput[key] = value;
|
|
@@ -584,7 +885,6 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
584
885
|
|
|
585
886
|
mergedToolInput.renderForm = false;
|
|
586
887
|
mergedToolInput.__fromForm = true;
|
|
587
|
-
|
|
588
888
|
|
|
589
889
|
this.formLogger.info('Successfully merged tool input:', {
|
|
590
890
|
baseKeys: Object.keys(baseToolInput),
|
|
@@ -593,14 +893,24 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
593
893
|
});
|
|
594
894
|
} catch (error) {
|
|
595
895
|
this.formLogger.error('Failed to merge tool input data:', error);
|
|
596
|
-
throw new Error(
|
|
896
|
+
throw new Error(
|
|
897
|
+
`Failed to merge tool input data: ${
|
|
898
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
899
|
+
}`
|
|
900
|
+
);
|
|
597
901
|
}
|
|
598
902
|
|
|
599
903
|
try {
|
|
600
904
|
const maybeWrapper = tool as unknown as {
|
|
601
905
|
executeOriginal?: (args: Record<string, unknown>) => Promise<string>;
|
|
602
|
-
getOriginalTool?: () => {
|
|
603
|
-
|
|
906
|
+
getOriginalTool?: () => {
|
|
907
|
+
_call?: (args: Record<string, unknown>) => Promise<string>;
|
|
908
|
+
call?: (args: Record<string, unknown>) => Promise<string>;
|
|
909
|
+
};
|
|
910
|
+
originalTool?: {
|
|
911
|
+
_call?: (args: Record<string, unknown>) => Promise<string>;
|
|
912
|
+
call?: (args: Record<string, unknown>) => Promise<string>;
|
|
913
|
+
};
|
|
604
914
|
call?: (args: Record<string, unknown>) => Promise<string>;
|
|
605
915
|
};
|
|
606
916
|
let toolOutput: string;
|
|
@@ -617,72 +927,116 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
617
927
|
} else if (ot && typeof otCall.call === 'function') {
|
|
618
928
|
toolOutput = await otCall.call(mergedToolInput);
|
|
619
929
|
} else {
|
|
620
|
-
const tcall = tool as unknown as {
|
|
930
|
+
const tcall = tool as unknown as {
|
|
931
|
+
call?: (a: Record<string, unknown>) => Promise<string>;
|
|
932
|
+
};
|
|
621
933
|
if (typeof tcall.call === 'function') {
|
|
622
934
|
toolOutput = await tcall.call(mergedToolInput);
|
|
623
935
|
} else {
|
|
624
|
-
throw new Error(
|
|
936
|
+
throw new Error(
|
|
937
|
+
'No callable tool implementation found for form submission'
|
|
938
|
+
);
|
|
625
939
|
}
|
|
626
940
|
}
|
|
627
|
-
} else if (
|
|
941
|
+
} else if (
|
|
942
|
+
maybeWrapper.originalTool &&
|
|
943
|
+
typeof maybeWrapper.originalTool._call === 'function'
|
|
944
|
+
) {
|
|
628
945
|
toolOutput = await maybeWrapper.originalTool._call(mergedToolInput);
|
|
629
|
-
} else if (
|
|
946
|
+
} else if (
|
|
947
|
+
maybeWrapper.originalTool &&
|
|
948
|
+
typeof maybeWrapper.originalTool.call === 'function'
|
|
949
|
+
) {
|
|
630
950
|
toolOutput = await maybeWrapper.originalTool.call(mergedToolInput);
|
|
631
|
-
} else if (
|
|
632
|
-
|
|
951
|
+
} else if (
|
|
952
|
+
typeof (
|
|
953
|
+
tool as unknown as {
|
|
954
|
+
call?: (a: Record<string, unknown>) => Promise<string>;
|
|
955
|
+
}
|
|
956
|
+
).call === 'function'
|
|
957
|
+
) {
|
|
958
|
+
toolOutput = await (
|
|
959
|
+
tool as unknown as {
|
|
960
|
+
call: (a: Record<string, unknown>) => Promise<string>;
|
|
961
|
+
}
|
|
962
|
+
).call(mergedToolInput);
|
|
633
963
|
} else {
|
|
634
|
-
throw new Error(
|
|
964
|
+
throw new Error(
|
|
965
|
+
'No callable tool implementation found for form submission'
|
|
966
|
+
);
|
|
635
967
|
}
|
|
636
968
|
|
|
637
969
|
let responseMetadata: Record<string, unknown> = {};
|
|
638
970
|
let formattedOutput: string;
|
|
639
|
-
|
|
971
|
+
|
|
640
972
|
this.formLogger.info('🔍 METADATA EXTRACTION: Analyzing tool output', {
|
|
641
973
|
outputType: typeof toolOutput,
|
|
642
974
|
outputLength: toolOutput?.length || 0,
|
|
643
975
|
isString: typeof toolOutput === 'string',
|
|
644
|
-
firstChars:
|
|
976
|
+
firstChars:
|
|
977
|
+
typeof toolOutput === 'string'
|
|
978
|
+
? toolOutput.substring(0, 100)
|
|
979
|
+
: 'not-string',
|
|
645
980
|
});
|
|
646
|
-
|
|
981
|
+
|
|
647
982
|
try {
|
|
648
983
|
const parsed = JSON.parse(toolOutput);
|
|
649
|
-
this.formLogger.info(
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
984
|
+
this.formLogger.info(
|
|
985
|
+
'✅ METADATA EXTRACTION: Successfully parsed JSON',
|
|
986
|
+
{
|
|
987
|
+
jsonKeys: Object.keys(parsed),
|
|
988
|
+
hasHashLinkBlock: !!(parsed as Record<string, unknown>)
|
|
989
|
+
.hashLinkBlock,
|
|
990
|
+
}
|
|
991
|
+
);
|
|
992
|
+
|
|
654
993
|
if (parsed && typeof parsed === 'object') {
|
|
655
994
|
if (ResponseFormatter.isHashLinkResponse(parsed)) {
|
|
656
|
-
this.formLogger.info(
|
|
657
|
-
|
|
995
|
+
this.formLogger.info(
|
|
996
|
+
'🔗 HASHLINK DETECTED: Processing HashLink response separately to preserve metadata'
|
|
997
|
+
);
|
|
998
|
+
|
|
658
999
|
responseMetadata = {
|
|
659
1000
|
...responseMetadata,
|
|
660
|
-
hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock
|
|
1001
|
+
hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,
|
|
661
1002
|
};
|
|
662
|
-
|
|
1003
|
+
|
|
663
1004
|
formattedOutput = ResponseFormatter.formatHashLinkResponse(parsed);
|
|
664
|
-
|
|
665
|
-
this.formLogger.info(
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
1005
|
+
|
|
1006
|
+
this.formLogger.info(
|
|
1007
|
+
'🔗 METADATA PRESERVED: HashLink metadata extracted for component rendering',
|
|
1008
|
+
{
|
|
1009
|
+
blockId: this.hasHashLinkBlock(responseMetadata)
|
|
1010
|
+
? responseMetadata.hashLinkBlock.blockId
|
|
1011
|
+
: undefined,
|
|
1012
|
+
hasTemplate: this.hasHashLinkBlock(responseMetadata)
|
|
1013
|
+
? !!responseMetadata.hashLinkBlock.template
|
|
1014
|
+
: false,
|
|
1015
|
+
}
|
|
1016
|
+
);
|
|
669
1017
|
} else {
|
|
670
1018
|
formattedOutput = ResponseFormatter.formatResponse(toolOutput);
|
|
671
|
-
|
|
1019
|
+
|
|
672
1020
|
responseMetadata = {
|
|
673
1021
|
...responseMetadata,
|
|
674
|
-
hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock
|
|
1022
|
+
hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,
|
|
675
1023
|
};
|
|
676
1024
|
}
|
|
677
1025
|
} else {
|
|
678
1026
|
formattedOutput = ResponseFormatter.formatResponse(toolOutput);
|
|
679
1027
|
}
|
|
680
1028
|
} catch (error) {
|
|
681
|
-
this.formLogger.warn(
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1029
|
+
this.formLogger.warn(
|
|
1030
|
+
'❌ METADATA EXTRACTION: Tool output is not JSON',
|
|
1031
|
+
{
|
|
1032
|
+
error: error instanceof Error ? error.message : 'unknown error',
|
|
1033
|
+
outputSample:
|
|
1034
|
+
typeof toolOutput === 'string'
|
|
1035
|
+
? toolOutput.substring(0, 200)
|
|
1036
|
+
: 'not-string',
|
|
1037
|
+
}
|
|
1038
|
+
);
|
|
1039
|
+
|
|
686
1040
|
formattedOutput = ResponseFormatter.formatResponse(toolOutput);
|
|
687
1041
|
}
|
|
688
1042
|
|
|
@@ -691,7 +1045,9 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
691
1045
|
formCompleted: true,
|
|
692
1046
|
originalFormId: submission.formId,
|
|
693
1047
|
intermediateSteps: [],
|
|
694
|
-
metadata: responseMetadata
|
|
1048
|
+
metadata: responseMetadata,
|
|
1049
|
+
rawToolOutput: toolOutput,
|
|
1050
|
+
toolName: pendingForm.toolName,
|
|
695
1051
|
};
|
|
696
1052
|
} catch (error) {
|
|
697
1053
|
if (error instanceof ZodError) {
|
|
@@ -713,12 +1069,15 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
713
1069
|
if (intermediateSteps.length > 0) {
|
|
714
1070
|
const lastStep = intermediateSteps[intermediateSteps.length - 1];
|
|
715
1071
|
if (lastStep.action && lastStep.action.tool) {
|
|
716
|
-
const tool = this.tools.find(t => t.name === lastStep.action.tool);
|
|
1072
|
+
const tool = this.tools.find((t) => t.name === lastStep.action.tool);
|
|
717
1073
|
if (tool && 'schema' in tool) {
|
|
718
|
-
this.formLogger.info(
|
|
1074
|
+
this.formLogger.info(
|
|
1075
|
+
'Found tool from intermediate steps:',
|
|
1076
|
+
lastStep.action.tool
|
|
1077
|
+
);
|
|
719
1078
|
return {
|
|
720
1079
|
toolName: lastStep.action.tool,
|
|
721
|
-
schema: (tool as unknown as Record<string, unknown>).schema
|
|
1080
|
+
schema: (tool as unknown as Record<string, unknown>).schema,
|
|
722
1081
|
};
|
|
723
1082
|
}
|
|
724
1083
|
}
|
|
@@ -728,7 +1087,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
728
1087
|
if (inputSteps.length > 0) {
|
|
729
1088
|
const lastStep = inputSteps[inputSteps.length - 1];
|
|
730
1089
|
let action: AgentAction;
|
|
731
|
-
|
|
1090
|
+
|
|
732
1091
|
if (Array.isArray(lastStep) && lastStep.length > 0) {
|
|
733
1092
|
action = lastStep[0] as AgentAction;
|
|
734
1093
|
} else if ((lastStep as Record<string, unknown>).action) {
|
|
@@ -736,14 +1095,14 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
736
1095
|
} else {
|
|
737
1096
|
action = lastStep as AgentAction;
|
|
738
1097
|
}
|
|
739
|
-
|
|
1098
|
+
|
|
740
1099
|
if (action && action.tool) {
|
|
741
|
-
const tool = this.tools.find(t => t.name === action.tool);
|
|
1100
|
+
const tool = this.tools.find((t) => t.name === action.tool);
|
|
742
1101
|
if (tool && 'schema' in tool) {
|
|
743
1102
|
this.formLogger.info('Found tool from input steps:', action.tool);
|
|
744
1103
|
return {
|
|
745
1104
|
toolName: action.tool,
|
|
746
|
-
schema: (tool as unknown as Record<string, unknown>).schema
|
|
1105
|
+
schema: (tool as unknown as Record<string, unknown>).schema,
|
|
747
1106
|
};
|
|
748
1107
|
}
|
|
749
1108
|
}
|
|
@@ -751,7 +1110,10 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
751
1110
|
|
|
752
1111
|
const toolFromContext = this.findToolFromContext(inputs);
|
|
753
1112
|
if (toolFromContext) {
|
|
754
|
-
this.formLogger.info(
|
|
1113
|
+
this.formLogger.info(
|
|
1114
|
+
'Found tool from context:',
|
|
1115
|
+
toolFromContext.toolName
|
|
1116
|
+
);
|
|
755
1117
|
return toolFromContext;
|
|
756
1118
|
}
|
|
757
1119
|
|
|
@@ -765,22 +1127,24 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
765
1127
|
/**
|
|
766
1128
|
* Attempts to find tool from execution context
|
|
767
1129
|
*/
|
|
768
|
-
private findToolFromContext(inputs: Record<string, unknown>): {
|
|
769
|
-
toolName: string;
|
|
770
|
-
schema: unknown
|
|
1130
|
+
private findToolFromContext(inputs: Record<string, unknown>): {
|
|
1131
|
+
toolName: string;
|
|
1132
|
+
schema: unknown;
|
|
771
1133
|
} | null {
|
|
772
1134
|
const inputText = (inputs.input as string) || '';
|
|
773
|
-
|
|
1135
|
+
|
|
774
1136
|
for (const tool of this.tools) {
|
|
775
1137
|
const keywords = this.extractToolKeywords(tool.name);
|
|
776
|
-
|
|
777
|
-
if (
|
|
778
|
-
|
|
779
|
-
|
|
1138
|
+
|
|
1139
|
+
if (
|
|
1140
|
+
keywords.some((keyword) =>
|
|
1141
|
+
inputText.toLowerCase().includes(keyword.toLowerCase())
|
|
1142
|
+
)
|
|
1143
|
+
) {
|
|
780
1144
|
if ('schema' in tool) {
|
|
781
1145
|
return {
|
|
782
1146
|
toolName: tool.name,
|
|
783
|
-
schema: (tool as unknown as Record<string, unknown>).schema
|
|
1147
|
+
schema: (tool as unknown as Record<string, unknown>).schema,
|
|
784
1148
|
};
|
|
785
1149
|
}
|
|
786
1150
|
}
|
|
@@ -795,16 +1159,19 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
795
1159
|
private detectToolFromErrorContext(
|
|
796
1160
|
error: ZodError
|
|
797
1161
|
): { toolName: string; schema: unknown } | null {
|
|
798
|
-
const errorPaths = error.issues.map(issue => issue.path.join('.'));
|
|
799
|
-
|
|
1162
|
+
const errorPaths = error.issues.map((issue) => issue.path.join('.'));
|
|
1163
|
+
|
|
800
1164
|
for (const tool of this.tools) {
|
|
801
1165
|
if ('schema' in tool) {
|
|
802
1166
|
const toolSchema = (tool as unknown as Record<string, unknown>).schema;
|
|
803
1167
|
if (this.schemaMatchesErrorPaths(toolSchema, errorPaths)) {
|
|
804
|
-
this.formLogger.info(
|
|
1168
|
+
this.formLogger.info(
|
|
1169
|
+
'Detected tool from error path analysis:',
|
|
1170
|
+
tool.name
|
|
1171
|
+
);
|
|
805
1172
|
return {
|
|
806
1173
|
toolName: tool.name,
|
|
807
|
-
schema: toolSchema
|
|
1174
|
+
schema: toolSchema,
|
|
808
1175
|
};
|
|
809
1176
|
}
|
|
810
1177
|
}
|
|
@@ -816,16 +1183,19 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
816
1183
|
/**
|
|
817
1184
|
* Checks if a schema structure matches error paths
|
|
818
1185
|
*/
|
|
819
|
-
private schemaMatchesErrorPaths(
|
|
1186
|
+
private schemaMatchesErrorPaths(
|
|
1187
|
+
schema: unknown,
|
|
1188
|
+
errorPaths: string[]
|
|
1189
|
+
): boolean {
|
|
820
1190
|
const schemaRecord = schema as Record<string, unknown>;
|
|
821
1191
|
if (!schemaRecord || !schemaRecord._def) return false;
|
|
822
|
-
|
|
1192
|
+
|
|
823
1193
|
try {
|
|
824
1194
|
const def = schemaRecord._def as Record<string, unknown>;
|
|
825
1195
|
if (def.typeName === 'ZodObject') {
|
|
826
1196
|
const shape = def.shape as Record<string, unknown>;
|
|
827
1197
|
const schemaKeys = Object.keys(shape || {});
|
|
828
|
-
return errorPaths.some(path => {
|
|
1198
|
+
return errorPaths.some((path) => {
|
|
829
1199
|
const topLevelKey = path.split('.')[0];
|
|
830
1200
|
return schemaKeys.includes(topLevelKey);
|
|
831
1201
|
});
|
|
@@ -833,7 +1203,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
833
1203
|
} catch (err) {
|
|
834
1204
|
this.formLogger.debug('Error analyzing schema structure:', err);
|
|
835
1205
|
}
|
|
836
|
-
|
|
1206
|
+
|
|
837
1207
|
return false;
|
|
838
1208
|
}
|
|
839
1209
|
|
|
@@ -845,8 +1215,8 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
845
1215
|
.replace(/([A-Z])/g, ' $1')
|
|
846
1216
|
.toLowerCase()
|
|
847
1217
|
.split(/[\s_-]+/)
|
|
848
|
-
.filter(w => w.length > 2);
|
|
849
|
-
|
|
1218
|
+
.filter((w) => w.length > 2);
|
|
1219
|
+
|
|
850
1220
|
return [...words, toolName.toLowerCase()];
|
|
851
1221
|
}
|
|
852
1222
|
|
|
@@ -857,7 +1227,7 @@ export class FormAwareAgentExecutor extends AgentExecutor {
|
|
|
857
1227
|
const fieldCount = formMessage.formConfig.fields.length;
|
|
858
1228
|
const fieldList = formMessage.formConfig.fields
|
|
859
1229
|
.slice(0, 3)
|
|
860
|
-
.map(f => `• ${f.label}`)
|
|
1230
|
+
.map((f) => `• ${f.label}`)
|
|
861
1231
|
.join('\n');
|
|
862
1232
|
|
|
863
1233
|
return `I need some additional information to complete your request.
|
|
@@ -883,78 +1253,89 @@ Please fill out the form below to continue.`;
|
|
|
883
1253
|
getPendingFormsInfo(): Array<{ formId: string; toolName: string }> {
|
|
884
1254
|
return Array.from(this.pendingForms.entries()).map(([formId, info]) => ({
|
|
885
1255
|
formId,
|
|
886
|
-
toolName: info.toolName
|
|
1256
|
+
toolName: info.toolName,
|
|
887
1257
|
}));
|
|
888
1258
|
}
|
|
889
1259
|
|
|
890
1260
|
/**
|
|
891
1261
|
* Processes HashLink block responses from tools
|
|
892
1262
|
*/
|
|
893
|
-
private processHashLinkResponse(
|
|
1263
|
+
private processHashLinkResponse(
|
|
1264
|
+
toolResponse: ToolResponse
|
|
1265
|
+
): HashLinkResponse {
|
|
894
1266
|
try {
|
|
895
|
-
|
|
896
1267
|
let hashLinkBlock: HashLinkBlock | undefined;
|
|
897
|
-
|
|
1268
|
+
|
|
898
1269
|
if (toolResponse.hashLinkBlock) {
|
|
899
1270
|
hashLinkBlock = toolResponse.hashLinkBlock;
|
|
900
|
-
} else if (
|
|
1271
|
+
} else if (
|
|
1272
|
+
toolResponse.success &&
|
|
1273
|
+
toolResponse.inscription &&
|
|
1274
|
+
toolResponse.hashLinkBlock
|
|
1275
|
+
) {
|
|
901
1276
|
hashLinkBlock = toolResponse.hashLinkBlock;
|
|
902
1277
|
}
|
|
903
|
-
|
|
1278
|
+
|
|
904
1279
|
if (!hashLinkBlock) {
|
|
905
1280
|
throw new Error('HashLink block data not found in response');
|
|
906
1281
|
}
|
|
907
|
-
|
|
908
|
-
if (
|
|
909
|
-
|
|
1282
|
+
|
|
1283
|
+
if (
|
|
1284
|
+
!hashLinkBlock.blockId ||
|
|
1285
|
+
!hashLinkBlock.hashLink ||
|
|
1286
|
+
!hashLinkBlock.attributes
|
|
1287
|
+
) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
'Invalid HashLink block structure - missing required fields'
|
|
1290
|
+
);
|
|
910
1291
|
}
|
|
911
|
-
|
|
1292
|
+
|
|
912
1293
|
let message = 'Content processed successfully!';
|
|
913
|
-
|
|
1294
|
+
|
|
914
1295
|
if (toolResponse.success && toolResponse.inscription) {
|
|
915
1296
|
const inscription = toolResponse.inscription;
|
|
916
1297
|
const metadata = toolResponse.metadata || {};
|
|
917
|
-
|
|
1298
|
+
|
|
918
1299
|
message = `✅ ${inscription.standard} Hashinal inscription completed!\n\n`;
|
|
919
|
-
|
|
1300
|
+
|
|
920
1301
|
if (metadata.name) {
|
|
921
1302
|
message += `**${metadata.name}**\n`;
|
|
922
1303
|
}
|
|
923
|
-
|
|
1304
|
+
|
|
924
1305
|
if (metadata.description) {
|
|
925
1306
|
message += `${metadata.description}\n\n`;
|
|
926
1307
|
}
|
|
927
|
-
|
|
1308
|
+
|
|
928
1309
|
message += `📍 **Topic ID:** ${inscription.topicId}\n`;
|
|
929
1310
|
message += `🔗 **HRL:** ${inscription.hrl}\n`;
|
|
930
|
-
|
|
1311
|
+
|
|
931
1312
|
if (inscription.cdnUrl) {
|
|
932
1313
|
message += `🌐 **CDN URL:** ${inscription.cdnUrl}\n`;
|
|
933
1314
|
}
|
|
934
|
-
|
|
1315
|
+
|
|
935
1316
|
if (metadata.creator) {
|
|
936
1317
|
message += `👤 **Creator:** ${metadata.creator}\n`;
|
|
937
1318
|
}
|
|
938
1319
|
}
|
|
939
|
-
|
|
1320
|
+
|
|
940
1321
|
this.formLogger.info('Processed HashLink response', {
|
|
941
1322
|
blockId: hashLinkBlock.blockId,
|
|
942
1323
|
hashLink: hashLinkBlock.hashLink,
|
|
943
1324
|
hasTemplate: !!hashLinkBlock.template,
|
|
944
|
-
attributeCount: Object.keys(hashLinkBlock.attributes || {}).length
|
|
1325
|
+
attributeCount: Object.keys(hashLinkBlock.attributes || {}).length,
|
|
945
1326
|
});
|
|
946
|
-
|
|
1327
|
+
|
|
947
1328
|
return {
|
|
948
1329
|
hasHashLinkBlocks: true,
|
|
949
1330
|
hashLinkBlock,
|
|
950
|
-
message
|
|
1331
|
+
message,
|
|
951
1332
|
};
|
|
952
1333
|
} catch (error) {
|
|
953
1334
|
this.formLogger.error('Error processing HashLink response:', error);
|
|
954
|
-
|
|
1335
|
+
|
|
955
1336
|
return {
|
|
956
1337
|
hasHashLinkBlocks: false,
|
|
957
|
-
message: 'Content processed, but interactive display is not available.'
|
|
1338
|
+
message: 'Content processed, but interactive display is not available.',
|
|
958
1339
|
};
|
|
959
1340
|
}
|
|
960
1341
|
}
|
|
@@ -962,7 +1343,10 @@ Please fill out the form below to continue.`;
|
|
|
962
1343
|
/**
|
|
963
1344
|
* Get FormEngine statistics for debugging
|
|
964
1345
|
*/
|
|
965
|
-
getFormEngineStatistics() {
|
|
1346
|
+
getFormEngineStatistics(): {
|
|
1347
|
+
strategies: string[];
|
|
1348
|
+
middleware: string[];
|
|
1349
|
+
} {
|
|
966
1350
|
return {
|
|
967
1351
|
strategies: this.formEngine.getRegisteredStrategies(),
|
|
968
1352
|
middleware: this.formEngine.getRegisteredMiddleware(),
|