@adminforth/agent 2.0.10 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +333 -10
- package/dist/application/ports.d.ts +66 -0
- package/dist/application/runTurnUseCase.d.ts +68 -0
- package/dist/application/runTurnUseCase.js +358 -0
- package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
- package/dist/{agent → domain}/systemPrompt.js +1 -1
- package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
- package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +40 -35
- package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
- package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
- package/dist/llm/agentModels.js +65 -0
- package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
- package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
- package/dist/llm/langGraphLlm.d.ts +25 -0
- package/dist/llm/langGraphLlm.js +54 -0
- package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
- package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
- package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
- package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
- package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
- package/dist/llm/streamAdapter.d.ts +18 -0
- package/dist/llm/streamAdapter.js +117 -0
- package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
- package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
- package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
- package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
- package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
- package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
- package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
- package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
- package/dist/{agent/tools → tools}/index.d.ts +1 -1
- package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
- package/dist/{endpoints → transport/http}/context.d.ts +2 -2
- package/dist/transport/http/context.js +1 -0
- package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
- package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
- package/dist/transport/sse/sseWriter.d.ts +29 -0
- package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
- package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
- package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
- package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
- package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
- package/dist/types.d.ts +10 -4
- package/package.json +11 -2
- package/.woodpecker/buildRelease.sh +0 -13
- package/.woodpecker/buildSlackNotify.sh +0 -46
- package/.woodpecker/release.yml +0 -57
- package/agent/checkpointer.ts +0 -329
- package/agent/languageDetect.ts +0 -92
- package/agent/middleware/apiBasedTools.ts +0 -174
- package/agent/middleware/openAiResponsesContinuation.ts +0 -92
- package/agent/middleware/sequenceDebug.ts +0 -429
- package/agent/models/AgentModeResolver.ts +0 -9
- package/agent/models/AgentModelFactory.ts +0 -28
- package/agent/runtime/AgentContext.ts +0 -30
- package/agent/runtime/AgentRuntime.ts +0 -89
- package/agent/simpleAgent.ts +0 -199
- package/agent/skills/registry.ts +0 -162
- package/agent/speech/SpeechTurnService.ts +0 -179
- package/agent/systemPrompt.ts +0 -133
- package/agent/toolCallEvents.ts +0 -135
- package/agent/tools/AgentToolProvider.ts +0 -28
- package/agent/tools/apiTool.ts +0 -66
- package/agent/tools/fetchSkill.ts +0 -68
- package/agent/tools/fetchToolSchema.ts +0 -47
- package/agent/tools/getUserLocation.ts +0 -45
- package/agent/tools/index.ts +0 -31
- package/agent/tools/navigateUser.ts +0 -210
- package/agent/turn/TurnContextBuilder.ts +0 -36
- package/agent/turn/TurnLifecycleService.ts +0 -47
- package/agent/turn/TurnPersistenceService.ts +0 -33
- package/agent/turn/TurnPromptBuilder.ts +0 -51
- package/agent/turn/TurnStreamConsumer.ts +0 -69
- package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
- package/agent/turn/turnTypes.ts +0 -100
- package/agentEvents.ts +0 -75
- package/agentTurnService.ts +0 -314
- package/apiBasedTools.ts +0 -712
- package/build.log +0 -67
- package/chatSurfaceService.ts +0 -319
- package/custom/ChatFooter.vue +0 -173
- package/custom/ChatHeader.vue +0 -78
- package/custom/ChatSurface.vue +0 -160
- package/custom/CustomAutoScrollContainer.vue +0 -164
- package/custom/SessionsHistory.vue +0 -88
- package/custom/chat.ts +0 -82
- package/custom/composables/agentAudio/utils.ts +0 -220
- package/custom/composables/agentStore/constants.ts +0 -19
- package/custom/composables/agentStore/pageContext.ts +0 -8
- package/custom/composables/agentStore/useAgentChat.ts +0 -241
- package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
- package/custom/composables/agentStore/useAgentSessions.ts +0 -350
- package/custom/composables/useAgentAudio.ts +0 -272
- package/custom/composables/useAgentStore.ts +0 -510
- package/custom/composables/useAgentTransitions.ts +0 -58
- package/custom/conversation_area/ConversationArea.vue +0 -301
- package/custom/conversation_area/MessageRenderer.vue +0 -49
- package/custom/conversation_area/ProcessingTimeline.vue +0 -286
- package/custom/conversation_area/ReasoningRenderer.vue +0 -79
- package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
- package/custom/conversation_area/TextRenderer.vue +0 -182
- package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
- package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
- package/custom/conversation_area/ToolRenderer.vue +0 -178
- package/custom/conversation_area/ToolsGroup.vue +0 -59
- package/custom/env.d.ts +0 -7
- package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
- package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
- package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
- package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
- package/custom/package.json +0 -30
- package/custom/pnpm-lock.yaml +0 -2394
- package/custom/public/agentAudio/agent-processing.mp3 +0 -0
- package/custom/skills/analyze_data/SKILL.md +0 -25
- package/custom/skills/charts/SKILL.md +0 -193
- package/custom/skills/fetch_data/SKILL.md +0 -31
- package/custom/skills/mutate_data/SKILL.md +0 -121
- package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
- package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
- package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
- package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
- package/custom/tsconfig.json +0 -15
- package/custom/types.ts +0 -108
- package/custom/utils.ts +0 -38
- package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
- package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
- package/dist/agent/models/AgentModeResolver.d.ts +0 -9
- package/dist/agent/models/AgentModeResolver.js +0 -9
- package/dist/agent/simpleAgent.js +0 -118
- package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
- package/dist/agent/turn/TurnContextBuilder.js +0 -31
- package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
- package/dist/agent/turn/TurnLifecycleService.js +0 -47
- package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
- package/dist/agent/turn/TurnPersistenceService.js +0 -35
- package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
- package/dist/agent/turn/TurnPromptBuilder.js +0 -43
- package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
- package/dist/agent/turn/TurnStreamConsumer.js +0 -84
- package/dist/agentTurnService.d.ts +0 -24
- package/dist/agentTurnService.js +0 -269
- package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
- package/endpoints/chatSurfaces.ts +0 -66
- package/endpoints/context.ts +0 -52
- package/endpoints/core.ts +0 -181
- package/endpoints/sessions.ts +0 -183
- package/errors.ts +0 -10
- package/index.ts +0 -192
- package/pnpm-workspace.yaml +0 -4
- package/sanitizeSpeechText.ts +0 -32
- package/sessionStore.ts +0 -105
- package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
- package/tsconfig.json +0 -14
- package/types.ts +0 -127
- /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
- /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
- /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
- /package/dist/{agent → domain}/languageDetect.js +0 -0
- /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
- /package/dist/{agent → domain}/toolCallEvents.js +0 -0
- /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
- /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
- /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
- /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
- /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
- /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
- /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
- /package/dist/{errors.js → shared/errors.js} +0 -0
- /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
- /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
- /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
- /package/dist/{agent/tools → tools}/apiTool.js +0 -0
- /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
- /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
- /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
- /package/dist/{agent/tools → tools}/index.js +0 -0
- /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
- /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
- /package/dist/{agent → tools}/skills/registry.js +0 -0
- /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
- /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
- /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
- /package/dist/{endpoints/sessions.d.ts → transport/http/sessionEndpoints.d.ts} +0 -0
package/apiBasedTools.ts
DELETED
|
@@ -1,712 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AdminForthDataTypes,
|
|
3
|
-
logger,
|
|
4
|
-
type AdminUser,
|
|
5
|
-
type IAdminForth,
|
|
6
|
-
type IAdminForthHttpResponse,
|
|
7
|
-
type IRegisteredApiSchema,
|
|
8
|
-
} from 'adminforth';
|
|
9
|
-
import dayjs from 'dayjs';
|
|
10
|
-
import timezone from 'dayjs/plugin/timezone.js';
|
|
11
|
-
import utc from 'dayjs/plugin/utc.js';
|
|
12
|
-
import YAML from 'yaml';
|
|
13
|
-
|
|
14
|
-
dayjs.extend(utc);
|
|
15
|
-
dayjs.extend(timezone);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type ToolOverrideContext = {
|
|
19
|
-
adminforth: IAdminForth;
|
|
20
|
-
output?: unknown;
|
|
21
|
-
adminUser?: AdminUser;
|
|
22
|
-
inputs?: Record<string, unknown>;
|
|
23
|
-
resourceLabel?: string;
|
|
24
|
-
userTimeZone?: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type ToolOverride = {
|
|
28
|
-
wipe_frontend_specific_data?: readonly string[];
|
|
29
|
-
format_tool?: (params: ToolOverrideContext) => Promise<string> | string;
|
|
30
|
-
post_process_response?: (params: ToolOverrideContext) => Promise<unknown> | unknown;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
type GetResourceDataToolResponse = {
|
|
34
|
-
data: Array<Record<string, unknown>>;
|
|
35
|
-
total?: number;
|
|
36
|
-
options?: Record<string, unknown>;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
type DateTimeColumnType = AdminForthDataTypes.DATETIME | AdminForthDataTypes.TIME;
|
|
40
|
-
type RegisteredApiToolSchema = IRegisteredApiSchema & {
|
|
41
|
-
handler: (input: unknown) => void | Promise<unknown>;
|
|
42
|
-
agent?: AgentToolMeta;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const DEFAULT_USER_TIME_ZONE = 'UTC';
|
|
46
|
-
|
|
47
|
-
type AgentToolMeta = {
|
|
48
|
-
isDangerous?: boolean;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
function hasRegisteredApiToolHandler(schema: IRegisteredApiSchema): schema is RegisteredApiToolSchema {
|
|
52
|
-
return typeof (schema as { handler?: unknown }).handler === 'function';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function getInputString(inputs: Record<string, unknown> | undefined, key: string) {
|
|
56
|
-
const value = inputs?.[key];
|
|
57
|
-
|
|
58
|
-
return typeof value === 'string' && value ? value : undefined;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function isHiddenResourceCall(
|
|
62
|
-
hiddenResourceIds: ReadonlySet<string>,
|
|
63
|
-
inputs: Record<string, unknown> | undefined,
|
|
64
|
-
) {
|
|
65
|
-
const resourceId = getInputString(inputs, 'resourceId');
|
|
66
|
-
|
|
67
|
-
return resourceId ? hiddenResourceIds.has(resourceId) : false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getInputArrayLength(inputs: Record<string, unknown> | undefined, key: string) {
|
|
71
|
-
const value = inputs?.[key];
|
|
72
|
-
|
|
73
|
-
return Array.isArray(value) ? value.length : undefined;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function resourceLabel(adminforth: IAdminForth, inputs: Record<string, unknown> | undefined) {
|
|
77
|
-
const resourceId = getInputString(inputs, 'resourceId');
|
|
78
|
-
const resource = adminforth.config.resources.find((res) => res.resourceId === resourceId);
|
|
79
|
-
|
|
80
|
-
return resource?.label ?? resourceId ?? 'resource';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function getDataPrefix(inputs: Record<string, unknown> | undefined) {
|
|
84
|
-
const offset = typeof inputs?.offset === 'number' ? inputs.offset : undefined;
|
|
85
|
-
const limit = typeof inputs?.limit === 'number' ? inputs.limit : undefined;
|
|
86
|
-
|
|
87
|
-
if (offset !== undefined && limit !== undefined) {
|
|
88
|
-
return `${offset}-${offset + limit} `;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return limit === undefined ? '' : `${limit} `;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function actionText(inputs: Record<string, unknown> | undefined) {
|
|
95
|
-
const actionId = getInputString(inputs, 'actionId');
|
|
96
|
-
|
|
97
|
-
return actionId ? ` action ${actionId}` : ' action';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const TOOL_OVERRIDES: Record<string, ToolOverride> = {
|
|
101
|
-
get_resource: {
|
|
102
|
-
wipe_frontend_specific_data: [
|
|
103
|
-
'resource.columns[].filterOptions',
|
|
104
|
-
'resource.columns[].components',
|
|
105
|
-
'resource.options.actions[].customComponent',
|
|
106
|
-
'resource.options.pageInjections',
|
|
107
|
-
],
|
|
108
|
-
format_tool: ({ resourceLabel }) => `Get ${resourceLabel} resource`,
|
|
109
|
-
},
|
|
110
|
-
get_resource_data: {
|
|
111
|
-
format_tool: ({ inputs, resourceLabel }) => (
|
|
112
|
-
`Get ${getDataPrefix(inputs)}${resourceLabel}`
|
|
113
|
-
),
|
|
114
|
-
post_process_response: async ({ adminforth, output, inputs, userTimeZone }) => {
|
|
115
|
-
if (hasToolError(output)) {
|
|
116
|
-
return output;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const dateTimeColumnNames = getDateTimeColumnNames(adminforth, inputs);
|
|
120
|
-
|
|
121
|
-
if (dateTimeColumnNames.length === 0) {
|
|
122
|
-
return output;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!hasGetResourceDataRows(output)) {
|
|
126
|
-
logger.warn(
|
|
127
|
-
`Skipping datetime formatting for get_resource_data because response.data is not an array for resource ${getInputString(inputs, 'resourceId') ?? 'unknown'}`,
|
|
128
|
-
);
|
|
129
|
-
return output;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const localizedTimeZone = userTimeZone ?? DEFAULT_USER_TIME_ZONE;
|
|
133
|
-
formatDateTimeColumns(output.data, dateTimeColumnNames, localizedTimeZone);
|
|
134
|
-
|
|
135
|
-
return output;
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
aggregate: {
|
|
139
|
-
format_tool: ({ resourceLabel }) => `Aggregate ${resourceLabel}`,
|
|
140
|
-
},
|
|
141
|
-
start_custom_action: {
|
|
142
|
-
format_tool: ({ inputs, resourceLabel }) => `Run ${resourceLabel}${actionText(inputs)}`,
|
|
143
|
-
},
|
|
144
|
-
start_custom_bulk_action: {
|
|
145
|
-
format_tool: ({ inputs, resourceLabel }) => {
|
|
146
|
-
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
147
|
-
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
148
|
-
|
|
149
|
-
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
start_bulk_action: {
|
|
153
|
-
format_tool: ({ inputs, resourceLabel }) => {
|
|
154
|
-
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
155
|
-
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
156
|
-
|
|
157
|
-
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
create_record: {
|
|
161
|
-
format_tool: ({ resourceLabel }) => `Create ${resourceLabel}`,
|
|
162
|
-
},
|
|
163
|
-
update_record: {
|
|
164
|
-
format_tool: ({ resourceLabel }) => `Update ${resourceLabel}`,
|
|
165
|
-
},
|
|
166
|
-
delete_record: {
|
|
167
|
-
format_tool: ({ resourceLabel }) => `Delete ${resourceLabel}`,
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
export type ApiBasedToolCallParams = {
|
|
172
|
-
adminUser?: AdminUser;
|
|
173
|
-
adminuser?: AdminUser;
|
|
174
|
-
abortSignal?: AbortSignal;
|
|
175
|
-
inputs?: Record<string, unknown>;
|
|
176
|
-
userTimeZone?: string;
|
|
177
|
-
acceptLanguage?: string;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
export type ApiBasedTool = {
|
|
181
|
-
description?: string;
|
|
182
|
-
input_schema?: unknown;
|
|
183
|
-
agent?: AgentToolMeta;
|
|
184
|
-
call: (params?: ApiBasedToolCallParams) => Promise<string>;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
function sanitizeForYaml(
|
|
188
|
-
value: unknown,
|
|
189
|
-
): unknown {
|
|
190
|
-
const traversalStack: object[] = [];
|
|
191
|
-
const serialized = JSON.stringify(value, function (this: unknown, _key: string, nestedValue: unknown) {
|
|
192
|
-
if (typeof nestedValue === 'function' || typeof nestedValue === 'symbol' || nestedValue === undefined) {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (typeof nestedValue === 'bigint') {
|
|
197
|
-
return nestedValue.toString();
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (typeof nestedValue !== 'object' || nestedValue === null) {
|
|
201
|
-
return nestedValue;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (nestedValue instanceof Map) {
|
|
205
|
-
return Object.fromEntries(nestedValue);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (nestedValue instanceof Set) {
|
|
209
|
-
return Array.from(nestedValue.values());
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
while (traversalStack.length > 0 && traversalStack[traversalStack.length - 1] !== this) {
|
|
213
|
-
traversalStack.pop();
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (traversalStack.includes(nestedValue)) {
|
|
217
|
-
return undefined;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
traversalStack.push(nestedValue);
|
|
221
|
-
return nestedValue;
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (serialized === undefined) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return JSON.parse(serialized);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function wipePath(target: unknown, pathParts: string[]): void {
|
|
232
|
-
if (!target || typeof target !== 'object' || pathParts.length === 0) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const [currentPart, ...rest] = pathParts;
|
|
237
|
-
const isArrayTraversal = currentPart.endsWith('[]');
|
|
238
|
-
const key = isArrayTraversal ? currentPart.slice(0, -2) : currentPart;
|
|
239
|
-
const targetRecord = target as Record<string, unknown>;
|
|
240
|
-
|
|
241
|
-
if (!(key in targetRecord)) {
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (rest.length === 0) {
|
|
246
|
-
delete targetRecord[key];
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const nextValue = targetRecord[key];
|
|
251
|
-
|
|
252
|
-
if (isArrayTraversal) {
|
|
253
|
-
if (!Array.isArray(nextValue)) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
for (const item of nextValue) {
|
|
258
|
-
wipePath(item, rest);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
wipePath(nextValue, rest);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function hasToolError(output: unknown): output is { error: unknown } {
|
|
268
|
-
return typeof output === 'object' && output !== null && 'error' in output;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function hasGetResourceDataRows(output: unknown): output is GetResourceDataToolResponse {
|
|
272
|
-
if (typeof output !== 'object' || output === null || !('data' in output)) {
|
|
273
|
-
return false;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return Array.isArray((output as { data?: unknown }).data);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function getDateTimeColumnNames(
|
|
280
|
-
adminforth: IAdminForth,
|
|
281
|
-
inputs: Record<string, unknown> | undefined,
|
|
282
|
-
): string[] {
|
|
283
|
-
const resourceId = getInputString(inputs, 'resourceId');
|
|
284
|
-
const resource = adminforth.config.resources.find((res) => res.resourceId === resourceId);
|
|
285
|
-
|
|
286
|
-
if (!resource) {
|
|
287
|
-
return [];
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return resource.dataSourceColumns
|
|
291
|
-
.filter((column) => column.type === AdminForthDataTypes.DATETIME)
|
|
292
|
-
.map((column) => column.name);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function formatGmtOffset(offsetMinutes: number): string {
|
|
296
|
-
const sign = offsetMinutes >= 0 ? '+' : '-';
|
|
297
|
-
const absoluteOffsetMinutes = Math.abs(offsetMinutes);
|
|
298
|
-
const hours = Math.floor(absoluteOffsetMinutes / 60);
|
|
299
|
-
const minutes = absoluteOffsetMinutes % 60;
|
|
300
|
-
|
|
301
|
-
if (minutes === 0) {
|
|
302
|
-
return `GMT${sign}${hours}`;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return `GMT${sign}${hours}:${String(minutes).padStart(2, '0')}`;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function formatDateTimeValue(value: string, userTimeZone: string): string {
|
|
309
|
-
const localizedValue = dayjs.utc(value).tz(userTimeZone);
|
|
310
|
-
return `${localizedValue.format('DD MMM YYYY, HH:mm:ss.SSS')} (${formatGmtOffset(localizedValue.utcOffset())})`;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function formatDateTimeColumns(
|
|
314
|
-
rows: Array<Record<string, unknown>>,
|
|
315
|
-
dateTimeColumnNames: string[],
|
|
316
|
-
userTimeZone: string,
|
|
317
|
-
): void {
|
|
318
|
-
for (const row of rows) {
|
|
319
|
-
for (const columnName of dateTimeColumnNames) {
|
|
320
|
-
const value = row[columnName];
|
|
321
|
-
|
|
322
|
-
if (typeof value === 'string' && value) {
|
|
323
|
-
row[columnName] = formatDateTimeValue(value, userTimeZone);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
async function applyToolOverride(params: {
|
|
330
|
-
adminforth: IAdminForth;
|
|
331
|
-
adminUser?: AdminUser;
|
|
332
|
-
inputs?: Record<string, unknown>;
|
|
333
|
-
output: unknown;
|
|
334
|
-
toolName: string;
|
|
335
|
-
userTimeZone?: string;
|
|
336
|
-
}): Promise<unknown> {
|
|
337
|
-
const { adminforth, adminUser, inputs, output, toolName, userTimeZone } = params;
|
|
338
|
-
const sanitizedOutput = sanitizeForYaml(output);
|
|
339
|
-
const override = TOOL_OVERRIDES[toolName];
|
|
340
|
-
|
|
341
|
-
if (!override) {
|
|
342
|
-
return sanitizedOutput;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
for (const path of override.wipe_frontend_specific_data ?? []) {
|
|
346
|
-
wipePath(sanitizedOutput, path.split('.'));
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return override.post_process_response
|
|
350
|
-
? sanitizeForYaml(await override.post_process_response({
|
|
351
|
-
adminforth,
|
|
352
|
-
adminUser,
|
|
353
|
-
output: sanitizedOutput,
|
|
354
|
-
inputs,
|
|
355
|
-
userTimeZone,
|
|
356
|
-
}))
|
|
357
|
-
: sanitizedOutput;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function endpointPathToToolName(path: string) {
|
|
361
|
-
return path
|
|
362
|
-
.replace(/^\/+/, '')
|
|
363
|
-
.replace(/[^a-zA-Z0-9_]+/g, '_')
|
|
364
|
-
.replace(/^_+|_+$/g, '');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function stripAdminApiPrefix(path: string, adminforth: IAdminForth) {
|
|
368
|
-
const configuredBaseUrl = adminforth.config.baseUrl || '';
|
|
369
|
-
const normalizedBaseUrl = configuredBaseUrl.endsWith('/')
|
|
370
|
-
? configuredBaseUrl.slice(0, -1)
|
|
371
|
-
: configuredBaseUrl;
|
|
372
|
-
const apiPrefix = `${normalizedBaseUrl}/adminapi/v1`;
|
|
373
|
-
|
|
374
|
-
if (path.startsWith(apiPrefix)) {
|
|
375
|
-
const strippedPath = path.slice(apiPrefix.length);
|
|
376
|
-
return strippedPath.startsWith('/') ? strippedPath : `/${strippedPath}`;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
return path;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
function openApiSchemaPathToToolName(path: string, adminforth: IAdminForth) {
|
|
383
|
-
return endpointPathToToolName(stripAdminApiPrefix(path, adminforth));
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
function formatLogNameList(names: string[]) {
|
|
387
|
-
return names.length ? names.join(', ') : '(none)';
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
export async function formatApiBasedToolCall(params: {
|
|
391
|
-
adminforth: IAdminForth;
|
|
392
|
-
adminUser?: AdminUser;
|
|
393
|
-
inputs?: Record<string, unknown>;
|
|
394
|
-
toolName: string;
|
|
395
|
-
userTimeZone?: string;
|
|
396
|
-
}) {
|
|
397
|
-
return await TOOL_OVERRIDES[params.toolName]?.format_tool?.({
|
|
398
|
-
adminforth: params.adminforth,
|
|
399
|
-
adminUser: params.adminUser,
|
|
400
|
-
inputs: params.inputs,
|
|
401
|
-
resourceLabel: resourceLabel(params.adminforth, params.inputs),
|
|
402
|
-
userTimeZone: params.userTimeZone,
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function normalizeDateTimeInputsToUtc(
|
|
407
|
-
body: Record<string, unknown>,
|
|
408
|
-
adminforth: IAdminForth,
|
|
409
|
-
userTimeZone?: string,
|
|
410
|
-
): Record<string, unknown> {
|
|
411
|
-
if (!userTimeZone || typeof body.resourceId !== 'string') {
|
|
412
|
-
return body;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const resource = adminforth.config.resources.find((res) => res.resourceId === body.resourceId);
|
|
416
|
-
|
|
417
|
-
if (!resource) {
|
|
418
|
-
return body;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const columnsByName = new Map(resource.dataSourceColumns.map((column) => [column.name, column]));
|
|
422
|
-
|
|
423
|
-
const normalizeColumnValue = (
|
|
424
|
-
value: unknown,
|
|
425
|
-
columnType: DateTimeColumnType,
|
|
426
|
-
): unknown => {
|
|
427
|
-
if (Array.isArray(value)) {
|
|
428
|
-
return value.map((item) => normalizeColumnValue(item, columnType));
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (typeof value !== 'string' || value === '') {
|
|
432
|
-
return value;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (columnType === AdminForthDataTypes.DATETIME) {
|
|
436
|
-
return dayjs.tz(value, userTimeZone).utc().toISOString();
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const userDate = dayjs().tz(userTimeZone).format('YYYY-MM-DD');
|
|
440
|
-
return dayjs.tz(`${userDate}T${value}`, userTimeZone).utc().format('HH:mm:ss');
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
const normalizeValue = (value: unknown, key?: string): unknown => {
|
|
444
|
-
const column = key ? columnsByName.get(key) : undefined;
|
|
445
|
-
|
|
446
|
-
if (column?.type === AdminForthDataTypes.DATETIME || column?.type === AdminForthDataTypes.TIME) {
|
|
447
|
-
return normalizeColumnValue(value, column.type);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
if (Array.isArray(value)) {
|
|
451
|
-
return value.map((item) => normalizeValue(item));
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (!value || typeof value !== 'object') {
|
|
455
|
-
return value;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const record = value as Record<string, unknown>;
|
|
459
|
-
const filterColumn = typeof record.field === 'string' ? columnsByName.get(record.field) : undefined;
|
|
460
|
-
|
|
461
|
-
if (
|
|
462
|
-
'value' in record &&
|
|
463
|
-
(filterColumn?.type === AdminForthDataTypes.DATETIME || filterColumn?.type === AdminForthDataTypes.TIME)
|
|
464
|
-
) {
|
|
465
|
-
return {
|
|
466
|
-
...record,
|
|
467
|
-
value: normalizeColumnValue(record.value, filterColumn.type),
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return Object.fromEntries(
|
|
472
|
-
Object.entries(record).map(([nestedKey, nestedValue]) => [
|
|
473
|
-
nestedKey,
|
|
474
|
-
normalizeValue(nestedValue, nestedKey),
|
|
475
|
-
]),
|
|
476
|
-
);
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
return normalizeValue(body) as Record<string, unknown>;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
const METHODS_WITHOUT_REQUEST_BODY = new Set<string>(['GET', 'HEAD']);
|
|
483
|
-
const TOOL_HANDLER_TIMEOUT_MS = 15_000;
|
|
484
|
-
const EMPTY_HANDLER_RESPONSE_ERROR = {
|
|
485
|
-
error: 'EMPTY_HANDLER_RESPONSE',
|
|
486
|
-
message: 'Tool handler completed without returning a response.',
|
|
487
|
-
};
|
|
488
|
-
const TOOL_HANDLER_TIMEOUT_ERROR = {
|
|
489
|
-
error: 'TOOL_HANDLER_TIMEOUT',
|
|
490
|
-
message: `Tool handler timed out after ${TOOL_HANDLER_TIMEOUT_MS / 1000} seconds.`,
|
|
491
|
-
};
|
|
492
|
-
|
|
493
|
-
function createDirectToolResponse(): IAdminForthHttpResponse & {
|
|
494
|
-
headers: Array<[string, string]>;
|
|
495
|
-
status: number;
|
|
496
|
-
message?: string;
|
|
497
|
-
} {
|
|
498
|
-
const headers: Array<[string, string]> = [];
|
|
499
|
-
|
|
500
|
-
return {
|
|
501
|
-
headers,
|
|
502
|
-
status: 200,
|
|
503
|
-
setHeader(name, value) {
|
|
504
|
-
headers.push([name, value]);
|
|
505
|
-
},
|
|
506
|
-
setStatus(code, message) {
|
|
507
|
-
this.status = code;
|
|
508
|
-
this.message = message;
|
|
509
|
-
},
|
|
510
|
-
blobStream() {
|
|
511
|
-
throw new Error('blobStream is not available for API-based agent tools');
|
|
512
|
-
},
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function validationErrorResponse(
|
|
517
|
-
error: 'REQUEST_VALIDATION_FAILED' | 'RESPONSE_VALIDATION_FAILED',
|
|
518
|
-
details: unknown,
|
|
519
|
-
) {
|
|
520
|
-
return {
|
|
521
|
-
error,
|
|
522
|
-
details,
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
async function withToolHandlerTimeout<T>(callback: (abortSignal: AbortSignal) => T | Promise<T>, abortSignal?: AbortSignal) {
|
|
527
|
-
const controller = new AbortController();
|
|
528
|
-
const abortHandler = () => controller.abort();
|
|
529
|
-
let timeout: ReturnType<typeof setTimeout>;
|
|
530
|
-
const timeoutPromise = new Promise<typeof TOOL_HANDLER_TIMEOUT_ERROR>((resolve) => {
|
|
531
|
-
timeout = setTimeout(() => {
|
|
532
|
-
controller.abort();
|
|
533
|
-
resolve(TOOL_HANDLER_TIMEOUT_ERROR);
|
|
534
|
-
}, TOOL_HANDLER_TIMEOUT_MS);
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
abortSignal?.addEventListener('abort', abortHandler, { once: true });
|
|
538
|
-
|
|
539
|
-
try {
|
|
540
|
-
return await Promise.race([
|
|
541
|
-
callback(controller.signal),
|
|
542
|
-
timeoutPromise,
|
|
543
|
-
]);
|
|
544
|
-
} finally {
|
|
545
|
-
clearTimeout(timeout!);
|
|
546
|
-
abortSignal?.removeEventListener('abort', abortHandler);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
async function callOpenApiSchema(params: {
|
|
551
|
-
adminforth: IAdminForth;
|
|
552
|
-
adminUser?: AdminUser;
|
|
553
|
-
abortSignal?: AbortSignal;
|
|
554
|
-
inputs?: Record<string, unknown>;
|
|
555
|
-
schema: RegisteredApiToolSchema;
|
|
556
|
-
toolName: string;
|
|
557
|
-
userTimeZone?: string;
|
|
558
|
-
acceptLanguage?: string;
|
|
559
|
-
}) {
|
|
560
|
-
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone, acceptLanguage } = params;
|
|
561
|
-
const method = schema.method.toUpperCase();
|
|
562
|
-
const normalizedInputs = normalizeDateTimeInputsToUtc(
|
|
563
|
-
(inputs ?? {}) as Record<string, unknown>,
|
|
564
|
-
adminforth,
|
|
565
|
-
userTimeZone,
|
|
566
|
-
);
|
|
567
|
-
const hasRequestBody = !METHODS_WITHOUT_REQUEST_BODY.has(method);
|
|
568
|
-
const body = hasRequestBody ? normalizedInputs : {};
|
|
569
|
-
const query = hasRequestBody ? {} : normalizedInputs;
|
|
570
|
-
const requestValidation = adminforth.openApi.validateRequestSchema(schema, body);
|
|
571
|
-
|
|
572
|
-
if (!requestValidation.valid) {
|
|
573
|
-
return validationErrorResponse('REQUEST_VALIDATION_FAILED', requestValidation.errors);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
const response = createDirectToolResponse();
|
|
577
|
-
logger.info(`Calling OpenAPI tool "${toolName}" with direct handler`);
|
|
578
|
-
const lang = acceptLanguage ?? "en";
|
|
579
|
-
const tr = (
|
|
580
|
-
msg: string,
|
|
581
|
-
category: string,
|
|
582
|
-
trParams: unknown,
|
|
583
|
-
pluralizationNumber?: number,
|
|
584
|
-
) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
|
|
585
|
-
const output = await withToolHandlerTimeout((handlerAbortSignal) => schema.handler({
|
|
586
|
-
body,
|
|
587
|
-
query,
|
|
588
|
-
headers: {},
|
|
589
|
-
cookies: [],
|
|
590
|
-
adminUser,
|
|
591
|
-
response,
|
|
592
|
-
requestUrl: schema.path,
|
|
593
|
-
abortSignal: handlerAbortSignal,
|
|
594
|
-
_raw_express_req: undefined as never,
|
|
595
|
-
_raw_express_res: undefined as never,
|
|
596
|
-
tr,
|
|
597
|
-
}),
|
|
598
|
-
abortSignal,
|
|
599
|
-
);
|
|
600
|
-
|
|
601
|
-
if (response.message) {
|
|
602
|
-
return response.status >= 400
|
|
603
|
-
? {
|
|
604
|
-
error: 'HANDLER_ERROR',
|
|
605
|
-
status: response.status,
|
|
606
|
-
response: response.message,
|
|
607
|
-
}
|
|
608
|
-
: response.message;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
if (output === undefined) {
|
|
612
|
-
return EMPTY_HANDLER_RESPONSE_ERROR;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
if (output === null) {
|
|
616
|
-
return { status: response.status };
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
const responseValidation = adminforth.openApi.validateResponseSchema(schema, output);
|
|
620
|
-
|
|
621
|
-
if (!responseValidation.valid) {
|
|
622
|
-
return validationErrorResponse('RESPONSE_VALIDATION_FAILED', responseValidation.errors);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
return response.status >= 400
|
|
626
|
-
? {
|
|
627
|
-
error: 'HANDLER_ERROR',
|
|
628
|
-
status: response.status,
|
|
629
|
-
response: output,
|
|
630
|
-
}
|
|
631
|
-
: output;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
function stringifyToolOutput(output: unknown): string {
|
|
635
|
-
return YAML.stringify(output === undefined ? EMPTY_HANDLER_RESPONSE_ERROR : output);
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
function attachDurationMs(output: unknown, durationMs: number): unknown {
|
|
639
|
-
if (output !== null && typeof output === 'object' && !Array.isArray(output)) {
|
|
640
|
-
return { ...output, durationMs };
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
return { result: output, durationMs };
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
export function prepareApiBasedTools(
|
|
647
|
-
adminforth: IAdminForth,
|
|
648
|
-
hiddenResourceIds: Iterable<string> = [],
|
|
649
|
-
): Record<string, ApiBasedTool> {
|
|
650
|
-
const apiBasedTools: Record<string, ApiBasedTool> = {};
|
|
651
|
-
const openApiSchemas = adminforth.openApi.registeredSchemas;
|
|
652
|
-
const openApiSchemasByToolName = new Map<string, RegisteredApiToolSchema>();
|
|
653
|
-
const hiddenResourceIdSet = new Set(hiddenResourceIds);
|
|
654
|
-
|
|
655
|
-
for (const schema of openApiSchemas) {
|
|
656
|
-
const toolName = openApiSchemaPathToToolName(schema.path, adminforth);
|
|
657
|
-
if (hasRegisteredApiToolHandler(schema)) {
|
|
658
|
-
openApiSchemasByToolName.set(toolName, schema);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
logger.info(
|
|
663
|
-
`AdminForth Agent OpenAPI APIs: ${formatLogNameList(
|
|
664
|
-
adminforth.openApi.registeredSchemas.map((schema) => openApiSchemaPathToToolName(schema.path, adminforth)),
|
|
665
|
-
)}`,
|
|
666
|
-
);
|
|
667
|
-
logger.info(
|
|
668
|
-
`AdminForth Agent OpenAPI tools connected: ${formatLogNameList([...openApiSchemasByToolName.keys()])}`,
|
|
669
|
-
);
|
|
670
|
-
|
|
671
|
-
for (const [toolName, schema] of openApiSchemasByToolName.entries()) {
|
|
672
|
-
apiBasedTools[toolName] = {
|
|
673
|
-
description: schema.description,
|
|
674
|
-
input_schema: schema.request_schema,
|
|
675
|
-
agent: schema.agent,
|
|
676
|
-
call: async ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) => {
|
|
677
|
-
const startedAt = Date.now();
|
|
678
|
-
|
|
679
|
-
if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
|
|
680
|
-
return stringifyToolOutput(attachDurationMs({
|
|
681
|
-
error: 'RESOURCE_NOT_AVAILABLE',
|
|
682
|
-
message: 'This resource is not available to the agent.',
|
|
683
|
-
}, Date.now() - startedAt));
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
const output = await callOpenApiSchema({
|
|
687
|
-
adminforth,
|
|
688
|
-
adminUser: adminUser ?? adminuser,
|
|
689
|
-
abortSignal,
|
|
690
|
-
schema,
|
|
691
|
-
toolName,
|
|
692
|
-
inputs,
|
|
693
|
-
userTimeZone,
|
|
694
|
-
acceptLanguage,
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
const processedOutput = await applyToolOverride({
|
|
698
|
-
adminforth,
|
|
699
|
-
adminUser: adminUser ?? adminuser,
|
|
700
|
-
inputs,
|
|
701
|
-
output,
|
|
702
|
-
toolName,
|
|
703
|
-
userTimeZone,
|
|
704
|
-
});
|
|
705
|
-
|
|
706
|
-
return stringifyToolOutput(attachDurationMs(processedOutput, Date.now() - startedAt));
|
|
707
|
-
},
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
return apiBasedTools;
|
|
712
|
-
}
|