@adminforth/agent 1.23.0 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/agent/middleware/apiBasedTools.ts +27 -4
- package/agent/middleware/sequenceDebug.ts +39 -2
- package/agent/simpleAgent.ts +283 -52
- package/agent/toolCallEvents.ts +3 -0
- package/apiBasedTools.ts +98 -8
- package/build.log +2 -2
- package/custom/composables/useAgentStore.ts +3 -0
- package/custom/package.json +1 -1
- package/dist/agent/middleware/apiBasedTools.js +22 -3
- package/dist/agent/middleware/sequenceDebug.js +18 -2
- package/dist/agent/simpleAgent.js +167 -27
- package/dist/agent/toolCallEvents.js +1 -0
- package/dist/apiBasedTools.js +73 -6
- package/dist/custom/composables/useAgentStore.ts +3 -0
- package/dist/custom/package.json +1 -1
- package/dist/index.js +32 -18
- package/index.ts +33 -15
- package/package.json +16 -5
package/apiBasedTools.ts
CHANGED
|
@@ -65,10 +65,11 @@ type ToolHttpResponse = IAdminForthHttpResponse & {
|
|
|
65
65
|
type ToolOverrideCallParams = Pick<ApiBasedToolCallParams, 'httpExtra' | 'inputs' | 'userTimeZone'>;
|
|
66
66
|
|
|
67
67
|
type ToolOverrideContext = {
|
|
68
|
-
output
|
|
68
|
+
output?: unknown;
|
|
69
69
|
adminUser?: AdminUser;
|
|
70
70
|
httpExtra?: Partial<HttpExtra>;
|
|
71
71
|
inputs?: Record<string, unknown>;
|
|
72
|
+
resourceLabel?: string;
|
|
72
73
|
userTimeZone?: string;
|
|
73
74
|
invokeTool: (toolName: string, params?: ToolOverrideCallParams) => Promise<unknown>;
|
|
74
75
|
};
|
|
@@ -98,6 +99,42 @@ type DateTimeColumnType = AdminForthDataTypes.DATETIME | AdminForthDataTypes.TIM
|
|
|
98
99
|
|
|
99
100
|
const DEFAULT_USER_TIME_ZONE = 'UTC';
|
|
100
101
|
|
|
102
|
+
function getInputString(inputs: Record<string, unknown> | undefined, key: string) {
|
|
103
|
+
const value = inputs?.[key];
|
|
104
|
+
|
|
105
|
+
return typeof value === 'string' && value ? value : undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getInputArrayLength(inputs: Record<string, unknown> | undefined, key: string) {
|
|
109
|
+
const value = inputs?.[key];
|
|
110
|
+
|
|
111
|
+
return Array.isArray(value) ? value.length : undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function resourceLabel(adminforth: IAdminForth, inputs: Record<string, unknown> | undefined) {
|
|
115
|
+
const resourceId = getInputString(inputs, 'resourceId');
|
|
116
|
+
const resource = adminforth.config.resources.find((res) => res.resourceId === resourceId);
|
|
117
|
+
|
|
118
|
+
return resource?.label ?? resourceId ?? 'resource';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function getDataPrefix(inputs: Record<string, unknown> | undefined) {
|
|
122
|
+
const offset = typeof inputs?.offset === 'number' ? inputs.offset : undefined;
|
|
123
|
+
const limit = typeof inputs?.limit === 'number' ? inputs.limit : undefined;
|
|
124
|
+
|
|
125
|
+
if (offset !== undefined && limit !== undefined) {
|
|
126
|
+
return `${offset}-${offset + limit} `;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return limit === undefined ? '' : `${limit} `;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function actionText(inputs: Record<string, unknown> | undefined) {
|
|
133
|
+
const actionId = getInputString(inputs, 'actionId');
|
|
134
|
+
|
|
135
|
+
return actionId ? ` action ${actionId}` : ' action';
|
|
136
|
+
}
|
|
137
|
+
|
|
101
138
|
const TOOL_OVERRIDES: Record<string, ToolOverride> = {
|
|
102
139
|
get_resource: {
|
|
103
140
|
wipe_frontend_specific_data: [
|
|
@@ -106,11 +143,12 @@ const TOOL_OVERRIDES: Record<string, ToolOverride> = {
|
|
|
106
143
|
'resource.options.actions[].customComponent',
|
|
107
144
|
'resource.options.pageInjections',
|
|
108
145
|
],
|
|
109
|
-
format_tool:
|
|
110
|
-
return "get resource Apartments"
|
|
111
|
-
}
|
|
146
|
+
format_tool: ({ resourceLabel }) => `Get ${resourceLabel} resource`,
|
|
112
147
|
},
|
|
113
148
|
get_resource_data: {
|
|
149
|
+
format_tool: ({ inputs, resourceLabel }) => (
|
|
150
|
+
`Get ${getDataPrefix(inputs)}${resourceLabel}`
|
|
151
|
+
),
|
|
114
152
|
post_process_response: async ({ output, inputs, invokeTool, userTimeZone }) => {
|
|
115
153
|
if (hasToolError(output)) {
|
|
116
154
|
return output;
|
|
@@ -132,9 +170,37 @@ const TOOL_OVERRIDES: Record<string, ToolOverride> = {
|
|
|
132
170
|
|
|
133
171
|
return response;
|
|
134
172
|
},
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
173
|
+
},
|
|
174
|
+
aggregate: {
|
|
175
|
+
format_tool: ({ resourceLabel }) => `Aggregate ${resourceLabel}`,
|
|
176
|
+
},
|
|
177
|
+
start_custom_action: {
|
|
178
|
+
format_tool: ({ inputs, resourceLabel }) => `Run ${resourceLabel}${actionText(inputs)}`,
|
|
179
|
+
},
|
|
180
|
+
start_custom_bulk_action: {
|
|
181
|
+
format_tool: ({ inputs, resourceLabel }) => {
|
|
182
|
+
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
183
|
+
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
184
|
+
|
|
185
|
+
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
start_bulk_action: {
|
|
189
|
+
format_tool: ({ inputs, resourceLabel }) => {
|
|
190
|
+
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
191
|
+
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
192
|
+
|
|
193
|
+
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
create_record: {
|
|
197
|
+
format_tool: ({ resourceLabel }) => `Create ${resourceLabel}`,
|
|
198
|
+
},
|
|
199
|
+
update_record: {
|
|
200
|
+
format_tool: ({ resourceLabel }) => `Update ${resourceLabel}`,
|
|
201
|
+
},
|
|
202
|
+
delete_record: {
|
|
203
|
+
format_tool: ({ resourceLabel }) => `Delete ${resourceLabel}`,
|
|
138
204
|
},
|
|
139
205
|
};
|
|
140
206
|
|
|
@@ -401,7 +467,31 @@ function endpointPathToToolName(path: string) {
|
|
|
401
467
|
.replace(/^_+|_+$/g, '');
|
|
402
468
|
}
|
|
403
469
|
|
|
404
|
-
function
|
|
470
|
+
export async function formatApiBasedToolCall(params: {
|
|
471
|
+
adminforth: IAdminForth;
|
|
472
|
+
adminUser?: AdminUser;
|
|
473
|
+
httpExtra?: Partial<HttpExtra>;
|
|
474
|
+
inputs?: Record<string, unknown>;
|
|
475
|
+
toolName: string;
|
|
476
|
+
userTimeZone?: string;
|
|
477
|
+
}) {
|
|
478
|
+
const formatTool = TOOL_OVERRIDES[params.toolName]?.format_tool;
|
|
479
|
+
|
|
480
|
+
return await formatTool?.({
|
|
481
|
+
adminUser: params.adminUser,
|
|
482
|
+
httpExtra: params.httpExtra,
|
|
483
|
+
inputs: params.inputs,
|
|
484
|
+
resourceLabel: resourceLabel(params.adminforth, params.inputs),
|
|
485
|
+
userTimeZone: params.userTimeZone,
|
|
486
|
+
invokeTool: async () => {
|
|
487
|
+
throw new Error('Tool info formatting cannot invoke tools');
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function normalizeCookies(
|
|
493
|
+
cookies?: Partial<HttpExtra>['cookies'] | Record<string, string>,
|
|
494
|
+
): CookieItem[] {
|
|
405
495
|
if (!cookies) {
|
|
406
496
|
return [];
|
|
407
497
|
}
|
package/build.log
CHANGED
|
@@ -38,5 +38,5 @@ custom/skills/fetch_data/SKILL.md
|
|
|
38
38
|
custom/skills/mutate_data/
|
|
39
39
|
custom/skills/mutate_data/SKILL.md
|
|
40
40
|
|
|
41
|
-
sent
|
|
42
|
-
total size is 197,
|
|
41
|
+
sent 200,052 bytes received 562 bytes 401,228.00 bytes/sec
|
|
42
|
+
total size is 197,748 speedup is 0.99
|
|
@@ -541,6 +541,9 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
541
541
|
const res = await callAdminForthApi({
|
|
542
542
|
method: 'POST',
|
|
543
543
|
path: '/agent/get-sessions',
|
|
544
|
+
body: {
|
|
545
|
+
limit: 100,
|
|
546
|
+
},
|
|
544
547
|
});
|
|
545
548
|
if (res.error) {
|
|
546
549
|
console.error('Error fetching sessions list:', res.error);
|
package/custom/package.json
CHANGED
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { ToolMessage } from "@langchain/core/messages";
|
|
11
11
|
import { createMiddleware } from "langchain";
|
|
12
12
|
import { logger } from "adminforth";
|
|
13
|
+
import { formatApiBasedToolCall, } from "../../apiBasedTools.js";
|
|
13
14
|
import { createToolCallTracker, } from "../toolCallEvents.js";
|
|
14
15
|
import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "../tools/index.js";
|
|
15
16
|
import { createApiTool } from "../tools/apiTool.js";
|
|
@@ -40,7 +41,7 @@ function getEnabledApiToolNames(messages) {
|
|
|
40
41
|
}
|
|
41
42
|
return enabledToolNames;
|
|
42
43
|
}
|
|
43
|
-
export function createApiBasedToolsMiddleware(apiBasedTools) {
|
|
44
|
+
export function createApiBasedToolsMiddleware(apiBasedTools, adminforth) {
|
|
44
45
|
const alwaysAvailableApiToolNames = new Set(ALWAYS_AVAILABLE_API_TOOL_NAMES);
|
|
45
46
|
const dynamicTools = Object.fromEntries(Object.entries(apiBasedTools).map(([toolName, apiBasedTool]) => [
|
|
46
47
|
toolName,
|
|
@@ -62,12 +63,30 @@ export function createApiBasedToolsMiddleware(apiBasedTools) {
|
|
|
62
63
|
var _a, _b, _c, _d;
|
|
63
64
|
const startedAt = Date.now();
|
|
64
65
|
const toolInput = JSON.stringify((_a = request.toolCall.args) !== null && _a !== void 0 ? _a : {});
|
|
65
|
-
const { emitToolCallEvent } = request.runtime.context;
|
|
66
|
+
const { adminUser, emitToolCallEvent, userTimeZone } = request.runtime.context;
|
|
67
|
+
const toolArgs = ((_b = request.toolCall.args) !== null && _b !== void 0 ? _b : {});
|
|
68
|
+
let toolInfo;
|
|
69
|
+
if (request.toolCall.name === "fetch_skill") {
|
|
70
|
+
toolInfo = `Load ${toolArgs.skillName.split("_").join(" ")} skill`;
|
|
71
|
+
}
|
|
72
|
+
else if (request.toolCall.name === "fetch_tool_schema") {
|
|
73
|
+
toolInfo = `Load ${toolArgs.toolName.split("_").join(" ")} tool `;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
toolInfo = yield formatApiBasedToolCall({
|
|
77
|
+
adminforth,
|
|
78
|
+
adminUser,
|
|
79
|
+
inputs: toolArgs,
|
|
80
|
+
toolName: request.toolCall.name,
|
|
81
|
+
userTimeZone,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
66
84
|
const toolCallTracker = createToolCallTracker({
|
|
67
85
|
emit: emitToolCallEvent,
|
|
68
86
|
toolCallId: request.toolCall.id,
|
|
69
87
|
toolName: request.toolCall.name,
|
|
70
|
-
|
|
88
|
+
toolInfo,
|
|
89
|
+
input: toolArgs,
|
|
71
90
|
startedAt,
|
|
72
91
|
});
|
|
73
92
|
toolCallTracker.start();
|
|
@@ -66,15 +66,31 @@ function finalizeSequenceDebug(sequence) {
|
|
|
66
66
|
resultType: (_a = sequence.resultType) !== null && _a !== void 0 ? _a : "final_text",
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
+
function getDebugModelName(model) {
|
|
70
|
+
return typeof model.getName === "function" ? model.getName() : undefined;
|
|
71
|
+
}
|
|
72
|
+
function supportsOpenAiResponseDebug(model) {
|
|
73
|
+
return (getDebugModelName(model) === "ChatOpenAI" &&
|
|
74
|
+
typeof model.model === "string" &&
|
|
75
|
+
typeof model.invocationParams === "function");
|
|
76
|
+
}
|
|
69
77
|
function stringifyPromptForDebug(params) {
|
|
70
|
-
var _a;
|
|
78
|
+
var _a, _b, _c, _d;
|
|
71
79
|
const { model, systemMessage, messages, tools, toolChoice, modelSettings } = params;
|
|
80
|
+
if (!supportsOpenAiResponseDebug(model)) {
|
|
81
|
+
return YAML.stringify(Object.assign(Object.assign(Object.assign({ model: {
|
|
82
|
+
name: (_a = getDebugModelName(model)) !== null && _a !== void 0 ? _a : null,
|
|
83
|
+
provider: (_c = (_b = model._defaultConfig) === null || _b === void 0 ? void 0 : _b.modelProvider) !== null && _c !== void 0 ? _c : null,
|
|
84
|
+
configuredModel: typeof model.model === "string" ? model.model : null,
|
|
85
|
+
}, systemMessage,
|
|
86
|
+
messages }, (tools.length > 0 ? { tools } : {})), (toolChoice !== undefined ? { toolChoice } : {})), (modelSettings ? { modelSettings } : {})));
|
|
87
|
+
}
|
|
72
88
|
return YAML.stringify(Object.assign({ input: convertMessagesToResponsesInput({
|
|
73
89
|
messages: [
|
|
74
90
|
...(systemMessage.text === "" ? [] : [systemMessage]),
|
|
75
91
|
...messages,
|
|
76
92
|
],
|
|
77
|
-
zdrEnabled: (
|
|
93
|
+
zdrEnabled: (_d = model.zdrEnabled) !== null && _d !== void 0 ? _d : false,
|
|
78
94
|
model: model.model,
|
|
79
95
|
}) }, model.invocationParams(Object.assign(Object.assign(Object.assign({}, (modelSettings !== null && modelSettings !== void 0 ? modelSettings : {})), (tools.length > 0 ? { tools } : {})), (toolChoice !== undefined ? { tool_choice: toolChoice } : {})))));
|
|
80
96
|
}
|
|
@@ -8,10 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { createAgent, summarizationMiddleware } from "langchain";
|
|
11
|
-
import {
|
|
11
|
+
import { MODEL_PROVIDER_CONFIG, getChatModelByClassName, } from "langchain/chat_models/universal";
|
|
12
|
+
import { logger, } from "adminforth";
|
|
12
13
|
import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
|
|
13
14
|
import { z } from "zod";
|
|
14
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
15
15
|
import { createAgentTools } from "./tools/index.js";
|
|
16
16
|
import { createApiBasedToolsMiddleware } from "./middleware/apiBasedTools.js";
|
|
17
17
|
import { createSequenceDebugMiddleware, } from "./middleware/sequenceDebug.js";
|
|
@@ -23,6 +23,149 @@ export const contextSchema = z.object({
|
|
|
23
23
|
turnId: z.string(),
|
|
24
24
|
emitToolCallEvent: z.custom(),
|
|
25
25
|
});
|
|
26
|
+
function isRecord(value) {
|
|
27
|
+
return typeof value === "object" && value !== null;
|
|
28
|
+
}
|
|
29
|
+
function normalizeProvider(value) {
|
|
30
|
+
if (typeof value !== "string") {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const normalized = value.toLowerCase().replace(/[_\s]+/g, "-");
|
|
34
|
+
if (["openai", "open-ai"].includes(normalized)) {
|
|
35
|
+
return "openai";
|
|
36
|
+
}
|
|
37
|
+
if (["anthropic", "claude"].includes(normalized)) {
|
|
38
|
+
return "anthropic";
|
|
39
|
+
}
|
|
40
|
+
if ([
|
|
41
|
+
"google",
|
|
42
|
+
"gemini",
|
|
43
|
+
"google-genai",
|
|
44
|
+
"google-gemini",
|
|
45
|
+
"google-generative-ai",
|
|
46
|
+
"google-generativeai",
|
|
47
|
+
].includes(normalized)) {
|
|
48
|
+
return "google-genai";
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
function detectProviderFromConstructorName(constructorName) {
|
|
53
|
+
const normalized = constructorName === null || constructorName === void 0 ? void 0 : constructorName.toLowerCase();
|
|
54
|
+
if (!normalized) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
if (normalized.includes("openai")) {
|
|
58
|
+
return "openai";
|
|
59
|
+
}
|
|
60
|
+
if (normalized.includes("anthropic") || normalized.includes("claude")) {
|
|
61
|
+
return "anthropic";
|
|
62
|
+
}
|
|
63
|
+
if (normalized.includes("gemini") || normalized.includes("google")) {
|
|
64
|
+
return "google-genai";
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
function detectProviderFromModelName(model) {
|
|
69
|
+
const normalized = model === null || model === void 0 ? void 0 : model.toLowerCase();
|
|
70
|
+
if (!normalized) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
if (normalized.startsWith("claude")) {
|
|
74
|
+
return "anthropic";
|
|
75
|
+
}
|
|
76
|
+
if (normalized.startsWith("gemini")) {
|
|
77
|
+
return "google-genai";
|
|
78
|
+
}
|
|
79
|
+
if (/^(gpt|o[1-9]|chatgpt)/.test(normalized)) {
|
|
80
|
+
return "openai";
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
function detectAgentModelProvider(adapter) {
|
|
85
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
86
|
+
const options = (_a = adapter.options) !== null && _a !== void 0 ? _a : {};
|
|
87
|
+
return ((_j = (_h = (_g = (_f = (_e = (_c = (_b = normalizeProvider(options.modelProvider)) !== null && _b !== void 0 ? _b : normalizeProvider(options.provider)) !== null && _c !== void 0 ? _c : detectProviderFromConstructorName((_d = adapter.constructor) === null || _d === void 0 ? void 0 : _d.name)) !== null && _e !== void 0 ? _e : (options.openAiApiKey || options.openAIApiKey
|
|
88
|
+
? "openai"
|
|
89
|
+
: undefined)) !== null && _f !== void 0 ? _f : (options.anthropicApiKey ? "anthropic" : undefined)) !== null && _g !== void 0 ? _g : (options.geminiApiKey ||
|
|
90
|
+
options.googleApiKey ||
|
|
91
|
+
options.googleGenAiApiKey ||
|
|
92
|
+
options.googleGenerativeAiApiKey
|
|
93
|
+
? "google-genai"
|
|
94
|
+
: undefined)) !== null && _h !== void 0 ? _h : detectProviderFromModelName(options.model)) !== null && _j !== void 0 ? _j : (() => {
|
|
95
|
+
throw new Error("Could not infer completion adapter provider. Set options.modelProvider to openai, anthropic, or google-genai.");
|
|
96
|
+
})());
|
|
97
|
+
}
|
|
98
|
+
function getProviderApiKey(provider, options) {
|
|
99
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
100
|
+
switch (provider) {
|
|
101
|
+
case "openai":
|
|
102
|
+
return (_b = (_a = options === null || options === void 0 ? void 0 : options.openAiApiKey) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.openAIApiKey) !== null && _b !== void 0 ? _b : options === null || options === void 0 ? void 0 : options.apiKey;
|
|
103
|
+
case "anthropic":
|
|
104
|
+
return (_c = options === null || options === void 0 ? void 0 : options.anthropicApiKey) !== null && _c !== void 0 ? _c : options === null || options === void 0 ? void 0 : options.apiKey;
|
|
105
|
+
case "google-genai":
|
|
106
|
+
return ((_g = (_f = (_e = (_d = options === null || options === void 0 ? void 0 : options.geminiApiKey) !== null && _d !== void 0 ? _d : options === null || options === void 0 ? void 0 : options.googleApiKey) !== null && _e !== void 0 ? _e : options === null || options === void 0 ? void 0 : options.googleGenAiApiKey) !== null && _f !== void 0 ? _f : options === null || options === void 0 ? void 0 : options.googleGenerativeAiApiKey) !== null && _g !== void 0 ? _g : options === null || options === void 0 ? void 0 : options.apiKey);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function getProviderModel(provider, options) {
|
|
110
|
+
if (options === null || options === void 0 ? void 0 : options.model) {
|
|
111
|
+
return options.model;
|
|
112
|
+
}
|
|
113
|
+
if (provider === "openai") {
|
|
114
|
+
return "gpt-5-nano";
|
|
115
|
+
}
|
|
116
|
+
if (provider === "google-genai") {
|
|
117
|
+
return "gemini-3-flash-preview";
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`CompletionAdapter for provider ${provider} must expose options.model`);
|
|
120
|
+
}
|
|
121
|
+
function buildChatModelConfig(params) {
|
|
122
|
+
var _a, _b;
|
|
123
|
+
const { provider, options, maxTokens } = params;
|
|
124
|
+
const apiKey = getProviderApiKey(provider, options);
|
|
125
|
+
if (!apiKey) {
|
|
126
|
+
const optionName = provider === "openai"
|
|
127
|
+
? "options.openAiApiKey"
|
|
128
|
+
: provider === "anthropic"
|
|
129
|
+
? "options.anthropicApiKey"
|
|
130
|
+
: "options.geminiApiKey";
|
|
131
|
+
throw new Error(`CompletionAdapter must expose ${optionName} for ${provider} agent mode`);
|
|
132
|
+
}
|
|
133
|
+
const model = getProviderModel(provider, options);
|
|
134
|
+
const baseURL = (_a = options === null || options === void 0 ? void 0 : options.baseURL) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.baseUrl;
|
|
135
|
+
const extraRequestBodyParameters = Object.assign({}, ((_b = options === null || options === void 0 ? void 0 : options.extraRequestBodyParameters) !== null && _b !== void 0 ? _b : {}));
|
|
136
|
+
if (provider === "openai" && isRecord(extraRequestBodyParameters.reasoning)) {
|
|
137
|
+
extraRequestBodyParameters.reasoning = Object.assign(Object.assign({}, extraRequestBodyParameters.reasoning), { summary: "auto" });
|
|
138
|
+
}
|
|
139
|
+
const config = Object.assign({ model,
|
|
140
|
+
apiKey,
|
|
141
|
+
maxTokens, streaming: true }, extraRequestBodyParameters);
|
|
142
|
+
if (typeof (options === null || options === void 0 ? void 0 : options.timeoutMs) === "number") {
|
|
143
|
+
config.timeout = options.timeoutMs;
|
|
144
|
+
}
|
|
145
|
+
if (baseURL) {
|
|
146
|
+
config.baseURL = baseURL;
|
|
147
|
+
config.baseUrl = baseURL;
|
|
148
|
+
config.configuration = {
|
|
149
|
+
baseURL,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (provider === "openai") {
|
|
153
|
+
config.openAIApiKey = apiKey;
|
|
154
|
+
config.useResponsesApi = true;
|
|
155
|
+
config.outputVersion = "v1";
|
|
156
|
+
config.promptCacheKey = `adminforth-agent:${model}:system-v1:tools-v1`;
|
|
157
|
+
config.promptCacheRetention = "in_memory";
|
|
158
|
+
}
|
|
159
|
+
if (provider === "anthropic") {
|
|
160
|
+
config.anthropicApiKey = apiKey;
|
|
161
|
+
}
|
|
162
|
+
if (provider === "google-genai") {
|
|
163
|
+
config.geminiApiKey = apiKey;
|
|
164
|
+
config.googleApiKey = apiKey;
|
|
165
|
+
config.maxOutputTokens = maxTokens;
|
|
166
|
+
}
|
|
167
|
+
return { model, config };
|
|
168
|
+
}
|
|
26
169
|
function getFiniteNumber(value) {
|
|
27
170
|
return typeof value === "number" && Number.isFinite(value)
|
|
28
171
|
? value
|
|
@@ -102,38 +245,35 @@ function createAgentLlmMetricsLogger() {
|
|
|
102
245
|
return new AgentLlmMetricsLogger();
|
|
103
246
|
}
|
|
104
247
|
export function createAgentChatModel(params) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
baseURL,
|
|
123
|
-
},
|
|
124
|
-
}
|
|
125
|
-
: {})));
|
|
248
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
249
|
+
var _a;
|
|
250
|
+
const adapter = params.adapter;
|
|
251
|
+
const options = (_a = adapter.options) !== null && _a !== void 0 ? _a : {};
|
|
252
|
+
const provider = detectAgentModelProvider(adapter);
|
|
253
|
+
const { config } = buildChatModelConfig({
|
|
254
|
+
provider,
|
|
255
|
+
options,
|
|
256
|
+
maxTokens: params.maxTokens,
|
|
257
|
+
});
|
|
258
|
+
const className = MODEL_PROVIDER_CONFIG[provider].className;
|
|
259
|
+
const ChatModelClass = yield getChatModelByClassName(className, provider);
|
|
260
|
+
return {
|
|
261
|
+
model: new ChatModelClass(config),
|
|
262
|
+
provider,
|
|
263
|
+
};
|
|
264
|
+
});
|
|
126
265
|
}
|
|
127
266
|
export function callAgent(params) {
|
|
128
267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
-
const { name, model, summaryModel, checkpointer, messages, adminUser, apiBasedTools, customComponentsDir, sessionId, turnId, userTimeZone, emitToolCallEvent, sequenceDebugSink, } = params;
|
|
268
|
+
const { name, model, summaryModel, modelProvider, checkpointer, messages, adminUser, adminforth, apiBasedTools, customComponentsDir, sessionId, turnId, userTimeZone, emitToolCallEvent, sequenceDebugSink, } = params;
|
|
130
269
|
const tools = yield createAgentTools(customComponentsDir, apiBasedTools);
|
|
131
|
-
const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools);
|
|
132
|
-
const openAiResponsesContinuationMiddleware = createOpenAiResponsesContinuationMiddleware();
|
|
270
|
+
const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools, adminforth);
|
|
133
271
|
const sequenceDebugMiddleware = createSequenceDebugMiddleware(sequenceDebugSink);
|
|
134
272
|
const middleware = [
|
|
135
273
|
apiBasedToolsMiddleware,
|
|
136
|
-
|
|
274
|
+
...(modelProvider === "openai"
|
|
275
|
+
? [createOpenAiResponsesContinuationMiddleware()]
|
|
276
|
+
: []),
|
|
137
277
|
sequenceDebugMiddleware,
|
|
138
278
|
summarizationMiddleware({
|
|
139
279
|
model: summaryModel,
|
package/dist/apiBasedTools.js
CHANGED
|
@@ -17,6 +17,32 @@ import YAML from 'yaml';
|
|
|
17
17
|
dayjs.extend(utc);
|
|
18
18
|
dayjs.extend(timezone);
|
|
19
19
|
const DEFAULT_USER_TIME_ZONE = 'UTC';
|
|
20
|
+
function getInputString(inputs, key) {
|
|
21
|
+
const value = inputs === null || inputs === void 0 ? void 0 : inputs[key];
|
|
22
|
+
return typeof value === 'string' && value ? value : undefined;
|
|
23
|
+
}
|
|
24
|
+
function getInputArrayLength(inputs, key) {
|
|
25
|
+
const value = inputs === null || inputs === void 0 ? void 0 : inputs[key];
|
|
26
|
+
return Array.isArray(value) ? value.length : undefined;
|
|
27
|
+
}
|
|
28
|
+
function resourceLabel(adminforth, inputs) {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
const resourceId = getInputString(inputs, 'resourceId');
|
|
31
|
+
const resource = adminforth.config.resources.find((res) => res.resourceId === resourceId);
|
|
32
|
+
return (_b = (_a = resource === null || resource === void 0 ? void 0 : resource.label) !== null && _a !== void 0 ? _a : resourceId) !== null && _b !== void 0 ? _b : 'resource';
|
|
33
|
+
}
|
|
34
|
+
function getDataPrefix(inputs) {
|
|
35
|
+
const offset = typeof (inputs === null || inputs === void 0 ? void 0 : inputs.offset) === 'number' ? inputs.offset : undefined;
|
|
36
|
+
const limit = typeof (inputs === null || inputs === void 0 ? void 0 : inputs.limit) === 'number' ? inputs.limit : undefined;
|
|
37
|
+
if (offset !== undefined && limit !== undefined) {
|
|
38
|
+
return `${offset}-${offset + limit} `;
|
|
39
|
+
}
|
|
40
|
+
return limit === undefined ? '' : `${limit} `;
|
|
41
|
+
}
|
|
42
|
+
function actionText(inputs) {
|
|
43
|
+
const actionId = getInputString(inputs, 'actionId');
|
|
44
|
+
return actionId ? ` action ${actionId}` : ' action';
|
|
45
|
+
}
|
|
20
46
|
const TOOL_OVERRIDES = {
|
|
21
47
|
get_resource: {
|
|
22
48
|
wipe_frontend_specific_data: [
|
|
@@ -25,11 +51,10 @@ const TOOL_OVERRIDES = {
|
|
|
25
51
|
'resource.options.actions[].customComponent',
|
|
26
52
|
'resource.options.pageInjections',
|
|
27
53
|
],
|
|
28
|
-
format_tool: (
|
|
29
|
-
return "get resource Apartments";
|
|
30
|
-
})
|
|
54
|
+
format_tool: ({ resourceLabel }) => `Get ${resourceLabel} resource`,
|
|
31
55
|
},
|
|
32
56
|
get_resource_data: {
|
|
57
|
+
format_tool: ({ inputs, resourceLabel }) => (`Get ${getDataPrefix(inputs)}${resourceLabel}`),
|
|
33
58
|
post_process_response: (_a) => __awaiter(void 0, [_a], void 0, function* ({ output, inputs, invokeTool, userTimeZone }) {
|
|
34
59
|
if (hasToolError(output)) {
|
|
35
60
|
return output;
|
|
@@ -47,9 +72,35 @@ const TOOL_OVERRIDES = {
|
|
|
47
72
|
formatDateTimeColumns(response.data, dateTimeColumnNames, localizedTimeZone);
|
|
48
73
|
return response;
|
|
49
74
|
}),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})
|
|
75
|
+
},
|
|
76
|
+
aggregate: {
|
|
77
|
+
format_tool: ({ resourceLabel }) => `Aggregate ${resourceLabel}`,
|
|
78
|
+
},
|
|
79
|
+
start_custom_action: {
|
|
80
|
+
format_tool: ({ inputs, resourceLabel }) => `Run ${resourceLabel}${actionText(inputs)}`,
|
|
81
|
+
},
|
|
82
|
+
start_custom_bulk_action: {
|
|
83
|
+
format_tool: ({ inputs, resourceLabel }) => {
|
|
84
|
+
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
85
|
+
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
86
|
+
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
start_bulk_action: {
|
|
90
|
+
format_tool: ({ inputs, resourceLabel }) => {
|
|
91
|
+
const recordCount = getInputArrayLength(inputs, 'recordIds');
|
|
92
|
+
const recordsText = recordCount === undefined ? '' : ` for ${recordCount} records`;
|
|
93
|
+
return `Run ${resourceLabel}${actionText(inputs)}${recordsText}`;
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
create_record: {
|
|
97
|
+
format_tool: ({ resourceLabel }) => `Create ${resourceLabel}`,
|
|
98
|
+
},
|
|
99
|
+
update_record: {
|
|
100
|
+
format_tool: ({ resourceLabel }) => `Update ${resourceLabel}`,
|
|
101
|
+
},
|
|
102
|
+
delete_record: {
|
|
103
|
+
format_tool: ({ resourceLabel }) => `Delete ${resourceLabel}`,
|
|
53
104
|
},
|
|
54
105
|
};
|
|
55
106
|
function sanitizeForYaml(value) {
|
|
@@ -235,6 +286,22 @@ function endpointPathToToolName(path) {
|
|
|
235
286
|
.replace(/[^a-zA-Z0-9_]+/g, '_')
|
|
236
287
|
.replace(/^_+|_+$/g, '');
|
|
237
288
|
}
|
|
289
|
+
export function formatApiBasedToolCall(params) {
|
|
290
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
var _a;
|
|
292
|
+
const formatTool = (_a = TOOL_OVERRIDES[params.toolName]) === null || _a === void 0 ? void 0 : _a.format_tool;
|
|
293
|
+
return yield (formatTool === null || formatTool === void 0 ? void 0 : formatTool({
|
|
294
|
+
adminUser: params.adminUser,
|
|
295
|
+
httpExtra: params.httpExtra,
|
|
296
|
+
inputs: params.inputs,
|
|
297
|
+
resourceLabel: resourceLabel(params.adminforth, params.inputs),
|
|
298
|
+
userTimeZone: params.userTimeZone,
|
|
299
|
+
invokeTool: () => __awaiter(this, void 0, void 0, function* () {
|
|
300
|
+
throw new Error('Tool info formatting cannot invoke tools');
|
|
301
|
+
}),
|
|
302
|
+
}));
|
|
303
|
+
});
|
|
304
|
+
}
|
|
238
305
|
function normalizeCookies(cookies) {
|
|
239
306
|
if (!cookies) {
|
|
240
307
|
return [];
|
|
@@ -541,6 +541,9 @@ export const useAgentStore = defineStore('agent', () => {
|
|
|
541
541
|
const res = await callAdminForthApi({
|
|
542
542
|
method: 'POST',
|
|
543
543
|
path: '/agent/get-sessions',
|
|
544
|
+
body: {
|
|
545
|
+
limit: 100,
|
|
546
|
+
},
|
|
544
547
|
});
|
|
545
548
|
if (res.error) {
|
|
546
549
|
console.error('Error fetching sessions list:', res.error);
|