@adminforth/agent 1.0.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/.woodpecker/buildRelease.sh +13 -0
- package/.woodpecker/buildSlackNotify.sh +46 -0
- package/.woodpecker/release.yml +57 -0
- package/agent/middleware/apiBasedTools.ts +109 -0
- package/agent/middleware/sequenceDebug.ts +302 -0
- package/agent/simpleAgent.ts +291 -0
- package/agent/skills/registry.ts +135 -0
- package/agent/systemPrompt.ts +69 -0
- package/agent/toolCallEvents.ts +17 -0
- package/agent/tools/apiTool.ts +99 -0
- package/agent/tools/fetchSkill.ts +58 -0
- package/agent/tools/fetchToolSchema.ts +50 -0
- package/agent/tools/index.ts +26 -0
- package/apiBasedTools.ts +625 -0
- package/build.log +30 -0
- package/custom/ChatSurface.vue +184 -0
- package/custom/ConversationArea.vue +175 -0
- package/custom/Message.vue +206 -0
- package/custom/SessionsHistory.vue +93 -0
- package/custom/ToolRenderer.vue +131 -0
- package/custom/ToolsGroup.vue +67 -0
- package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +301 -0
- package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +285 -0
- package/custom/incremark_code_renderers/incremarkRenderer.ts +653 -0
- package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +118 -0
- package/custom/package.json +26 -0
- package/custom/pnpm-lock.yaml +1467 -0
- package/custom/skills/fetch_data/SKILL.md +15 -0
- package/custom/skills/mutate_data/SKILL.md +108 -0
- package/custom/tsconfig.json +16 -0
- package/custom/types.ts +34 -0
- package/custom/useAgentStore.ts +349 -0
- package/dist/agent/middleware/apiBasedTools.js +91 -0
- package/dist/agent/middleware/sequenceDebug.js +210 -0
- package/dist/agent/simpleAgent.js +173 -0
- package/dist/agent/skills/registry.js +108 -0
- package/dist/agent/systemPrompt.js +64 -0
- package/dist/agent/toolCallEvents.js +1 -0
- package/dist/agent/tools/apiTool.js +93 -0
- package/dist/agent/tools/fetchSkill.js +51 -0
- package/dist/agent/tools/fetchToolSchema.js +36 -0
- package/dist/agent/tools/index.js +28 -0
- package/dist/apiBasedTools.js +412 -0
- package/dist/custom/ChatSurface.vue +184 -0
- package/dist/custom/ConversationArea.vue +175 -0
- package/dist/custom/Message.vue +206 -0
- package/dist/custom/SessionsHistory.vue +93 -0
- package/dist/custom/ToolRenderer.vue +131 -0
- package/dist/custom/ToolsGroup.vue +67 -0
- package/dist/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +301 -0
- package/dist/custom/incremark_code_renderers/incremarkCodeHighlight.ts +285 -0
- package/dist/custom/incremark_code_renderers/incremarkRenderer.ts +653 -0
- package/dist/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +118 -0
- package/dist/custom/package.json +26 -0
- package/dist/custom/pnpm-lock.yaml +1467 -0
- package/dist/custom/skills/fetch_data/SKILL.md +15 -0
- package/dist/custom/skills/mutate_data/SKILL.md +108 -0
- package/dist/custom/tsconfig.json +16 -0
- package/dist/custom/types.ts +34 -0
- package/dist/custom/useAgentStore.ts +349 -0
- package/dist/index.js +415 -0
- package/dist/types.js +1 -0
- package/index.ts +457 -0
- package/package.json +58 -0
- package/tsconfig.json +13 -0
- package/types.ts +45 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { tool } from "langchain";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { listSkillManifests, loadSkillMarkdown, } from "../skills/registry.js";
|
|
13
|
+
const fetchSkillSchema = z.object({
|
|
14
|
+
skillName: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe("Name of the custom AdminForth skill to load, for example fetch_data or mutate_data."),
|
|
17
|
+
});
|
|
18
|
+
function serializeSkillManifests(skillManifests) {
|
|
19
|
+
return skillManifests.map((skill) => ({
|
|
20
|
+
name: skill.name,
|
|
21
|
+
description: skill.description,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
export function createFetchSkillTool(customComponentsDir) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const availableSkills = yield listSkillManifests(customComponentsDir);
|
|
27
|
+
const availableSkillNames = availableSkills.map((skill) => skill.name);
|
|
28
|
+
return tool((_a) => __awaiter(this, [_a], void 0, function* ({ skillName }) {
|
|
29
|
+
try {
|
|
30
|
+
const skillMarkdown = yield loadSkillMarkdown(skillName, customComponentsDir);
|
|
31
|
+
if (!skillMarkdown) {
|
|
32
|
+
return [
|
|
33
|
+
`Skill "${skillName}" not found.`,
|
|
34
|
+
"Available skills:",
|
|
35
|
+
JSON.stringify(serializeSkillManifests(availableSkills), null, 2),
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
38
|
+
return skillMarkdown;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return `Failed to load skill "${skillName}": ${error instanceof Error ? error.message : String(error)}`;
|
|
42
|
+
}
|
|
43
|
+
}), {
|
|
44
|
+
name: "fetch_skill",
|
|
45
|
+
description: `Fetch the raw SKILL.md content for a custom AdminForth skill by name.${availableSkillNames.length > 0
|
|
46
|
+
? ` Available skills: ${availableSkillNames.join(", ")}.`
|
|
47
|
+
: ""}`,
|
|
48
|
+
schema: fetchSkillSchema,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { tool } from "langchain";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { serializeApiBasedTool, } from "../../apiBasedTools.js";
|
|
13
|
+
const fetchToolSchemaSchema = z.object({
|
|
14
|
+
toolName: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe("Name of the API-based tool to load, for example get_resource."),
|
|
17
|
+
});
|
|
18
|
+
export function createFetchToolSchemaTool(apiBasedTools) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
return tool((_a) => __awaiter(this, [_a], void 0, function* ({ toolName }) {
|
|
21
|
+
const toolDefinition = apiBasedTools[toolName];
|
|
22
|
+
if (!toolDefinition) {
|
|
23
|
+
return JSON.stringify({
|
|
24
|
+
status: 404,
|
|
25
|
+
error: "TOOL_NOT_FOUND",
|
|
26
|
+
message: `Tool "${toolName}" not found.`,
|
|
27
|
+
}, null, 2);
|
|
28
|
+
}
|
|
29
|
+
return JSON.stringify(Object.assign({ status: 200, name: toolName }, serializeApiBasedTool(toolDefinition)), null, 2);
|
|
30
|
+
}), {
|
|
31
|
+
name: "fetch_tool_schema",
|
|
32
|
+
description: "Fetch the schema for an API-based AdminForth tool by name and load it for later use.",
|
|
33
|
+
schema: fetchToolSchemaSchema,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { createFetchSkillTool } from "./fetchSkill.js";
|
|
11
|
+
import { createFetchToolSchemaTool } from "./fetchToolSchema.js";
|
|
12
|
+
import { createApiTool } from "./apiTool.js";
|
|
13
|
+
export const ALWAYS_AVAILABLE_API_TOOL_NAMES = ["get_resource"];
|
|
14
|
+
export function createAgentTools(customComponentsDir, apiBasedTools) {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
return [
|
|
17
|
+
...ALWAYS_AVAILABLE_API_TOOL_NAMES.map((toolName) => {
|
|
18
|
+
const apiBasedTool = apiBasedTools[toolName];
|
|
19
|
+
if (!apiBasedTool) {
|
|
20
|
+
throw new Error(`Required base API tool "${toolName}" is missing.`);
|
|
21
|
+
}
|
|
22
|
+
return createApiTool(toolName, apiBasedTool);
|
|
23
|
+
}),
|
|
24
|
+
yield createFetchSkillTool(customComponentsDir),
|
|
25
|
+
yield createFetchToolSchemaTool(apiBasedTools),
|
|
26
|
+
];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { AdminForthDataTypes, } from 'adminforth';
|
|
11
|
+
import dayjs from 'dayjs';
|
|
12
|
+
import timezone from 'dayjs/plugin/timezone.js';
|
|
13
|
+
import utc from 'dayjs/plugin/utc.js';
|
|
14
|
+
import { PassThrough } from 'stream';
|
|
15
|
+
import { inspect } from 'util';
|
|
16
|
+
import YAML from 'yaml';
|
|
17
|
+
dayjs.extend(utc);
|
|
18
|
+
dayjs.extend(timezone);
|
|
19
|
+
const DEFAULT_USER_TIME_ZONE = 'UTC';
|
|
20
|
+
const TOOL_OVERRIDES = {
|
|
21
|
+
get_resource: {
|
|
22
|
+
wipe_frontend_specific_data: [
|
|
23
|
+
'resource.columns[].filterOptions',
|
|
24
|
+
'resource.columns[].components',
|
|
25
|
+
'resource.options.actions[].customComponent',
|
|
26
|
+
'resource.options.pageInjections',
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
get_resource_data: {
|
|
30
|
+
post_process_response: (_a) => __awaiter(void 0, [_a], void 0, function* ({ output, inputs, invokeTool, userTimeZone }) {
|
|
31
|
+
if (hasToolError(output)) {
|
|
32
|
+
return output;
|
|
33
|
+
}
|
|
34
|
+
const resourceId = inputs === null || inputs === void 0 ? void 0 : inputs.resourceId;
|
|
35
|
+
const getResourceOutput = yield invokeTool('get_resource', {
|
|
36
|
+
inputs: { resourceId },
|
|
37
|
+
});
|
|
38
|
+
const dateTimeColumnNames = getDateTimeColumnNames(getResourceOutput);
|
|
39
|
+
if (dateTimeColumnNames.length === 0) {
|
|
40
|
+
return output;
|
|
41
|
+
}
|
|
42
|
+
const localizedTimeZone = userTimeZone !== null && userTimeZone !== void 0 ? userTimeZone : DEFAULT_USER_TIME_ZONE;
|
|
43
|
+
const response = output;
|
|
44
|
+
formatDateTimeColumns(response.data, dateTimeColumnNames, localizedTimeZone);
|
|
45
|
+
return response;
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
function sanitizeForYaml(value) {
|
|
50
|
+
const traversalStack = [];
|
|
51
|
+
const serialized = JSON.stringify(value, function (_key, nestedValue) {
|
|
52
|
+
if (typeof nestedValue === 'function' || typeof nestedValue === 'symbol' || nestedValue === undefined) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
if (typeof nestedValue === 'bigint') {
|
|
56
|
+
return nestedValue.toString();
|
|
57
|
+
}
|
|
58
|
+
if (typeof nestedValue !== 'object' || nestedValue === null) {
|
|
59
|
+
return nestedValue;
|
|
60
|
+
}
|
|
61
|
+
if (nestedValue instanceof Map) {
|
|
62
|
+
return Object.fromEntries(nestedValue);
|
|
63
|
+
}
|
|
64
|
+
if (nestedValue instanceof Set) {
|
|
65
|
+
return Array.from(nestedValue.values());
|
|
66
|
+
}
|
|
67
|
+
while (traversalStack.length > 0 && traversalStack[traversalStack.length - 1] !== this) {
|
|
68
|
+
traversalStack.pop();
|
|
69
|
+
}
|
|
70
|
+
if (traversalStack.includes(nestedValue)) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
traversalStack.push(nestedValue);
|
|
74
|
+
return nestedValue;
|
|
75
|
+
});
|
|
76
|
+
if (serialized === undefined) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return JSON.parse(serialized);
|
|
80
|
+
}
|
|
81
|
+
export function serializeUnknownError(error) {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
if (error instanceof Error) {
|
|
84
|
+
const errorWithCause = error;
|
|
85
|
+
const errorRecord = error;
|
|
86
|
+
const serialized = {
|
|
87
|
+
name: error.name,
|
|
88
|
+
message: error.message,
|
|
89
|
+
stack: error.stack,
|
|
90
|
+
};
|
|
91
|
+
if (errorWithCause.cause !== undefined) {
|
|
92
|
+
serialized.cause = serializeUnknownError(errorWithCause.cause);
|
|
93
|
+
}
|
|
94
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
95
|
+
if (key in serialized) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
serialized[key] = errorRecord[key];
|
|
99
|
+
}
|
|
100
|
+
return serialized;
|
|
101
|
+
}
|
|
102
|
+
if (typeof error === 'object' && error !== null) {
|
|
103
|
+
return {
|
|
104
|
+
type: (_b = (_a = error.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'Object',
|
|
105
|
+
inspected: inspect(error, { depth: 6, breakLength: 120 }),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
type: typeof error,
|
|
110
|
+
value: error,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function wipePath(target, pathParts) {
|
|
114
|
+
if (!target || typeof target !== 'object' || pathParts.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const [currentPart, ...rest] = pathParts;
|
|
118
|
+
const isArrayTraversal = currentPart.endsWith('[]');
|
|
119
|
+
const key = isArrayTraversal ? currentPart.slice(0, -2) : currentPart;
|
|
120
|
+
const targetRecord = target;
|
|
121
|
+
if (!(key in targetRecord)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (rest.length === 0) {
|
|
125
|
+
delete targetRecord[key];
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const nextValue = targetRecord[key];
|
|
129
|
+
if (isArrayTraversal) {
|
|
130
|
+
if (!Array.isArray(nextValue)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
for (const item of nextValue) {
|
|
134
|
+
wipePath(item, rest);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
wipePath(nextValue, rest);
|
|
139
|
+
}
|
|
140
|
+
function hasToolError(output) {
|
|
141
|
+
return typeof output === 'object' && output !== null && 'error' in output;
|
|
142
|
+
}
|
|
143
|
+
function getDateTimeColumnNames(output) {
|
|
144
|
+
const resource = output.resource;
|
|
145
|
+
return resource.columns
|
|
146
|
+
.filter((column) => column.type === AdminForthDataTypes.DATETIME)
|
|
147
|
+
.map((column) => column.name);
|
|
148
|
+
}
|
|
149
|
+
function formatGmtOffset(offsetMinutes) {
|
|
150
|
+
const sign = offsetMinutes >= 0 ? '+' : '-';
|
|
151
|
+
const absoluteOffsetMinutes = Math.abs(offsetMinutes);
|
|
152
|
+
const hours = Math.floor(absoluteOffsetMinutes / 60);
|
|
153
|
+
const minutes = absoluteOffsetMinutes % 60;
|
|
154
|
+
if (minutes === 0) {
|
|
155
|
+
return `GMT${sign}${hours}`;
|
|
156
|
+
}
|
|
157
|
+
return `GMT${sign}${hours}:${String(minutes).padStart(2, '0')}`;
|
|
158
|
+
}
|
|
159
|
+
function formatDateTimeValue(value, userTimeZone) {
|
|
160
|
+
const localizedValue = dayjs.utc(value).tz(userTimeZone);
|
|
161
|
+
return `${localizedValue.format('DD MMM YYYY, HH:mm:ss.SSS')} (${formatGmtOffset(localizedValue.utcOffset())})`;
|
|
162
|
+
}
|
|
163
|
+
function formatDateTimeColumns(rows, dateTimeColumnNames, userTimeZone) {
|
|
164
|
+
for (const row of rows) {
|
|
165
|
+
for (const columnName of dateTimeColumnNames) {
|
|
166
|
+
const value = row[columnName];
|
|
167
|
+
if (typeof value === 'string' && value) {
|
|
168
|
+
row[columnName] = formatDateTimeValue(value, userTimeZone);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function applyToolOverride(params) {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
var _a;
|
|
176
|
+
const { adminforth, adminUser, capturedEndpointsByToolName, httpExtra, inputs, output, toolName, userTimeZone, } = params;
|
|
177
|
+
const sanitizedOutput = sanitizeForYaml(output);
|
|
178
|
+
const override = TOOL_OVERRIDES[toolName];
|
|
179
|
+
if (!override) {
|
|
180
|
+
return sanitizedOutput;
|
|
181
|
+
}
|
|
182
|
+
for (const path of (_a = override.wipe_frontend_specific_data) !== null && _a !== void 0 ? _a : []) {
|
|
183
|
+
wipePath(sanitizedOutput, path.split('.'));
|
|
184
|
+
}
|
|
185
|
+
if (!override.post_process_response) {
|
|
186
|
+
return sanitizedOutput;
|
|
187
|
+
}
|
|
188
|
+
const postProcessedOutput = yield override.post_process_response({
|
|
189
|
+
output: sanitizedOutput,
|
|
190
|
+
adminUser,
|
|
191
|
+
httpExtra,
|
|
192
|
+
inputs,
|
|
193
|
+
userTimeZone,
|
|
194
|
+
invokeTool: (nestedToolName_1, ...args_1) => __awaiter(this, [nestedToolName_1, ...args_1], void 0, function* (nestedToolName, nestedParams = {}) {
|
|
195
|
+
var _a, _b, _c;
|
|
196
|
+
const nestedEndpoint = capturedEndpointsByToolName[nestedToolName];
|
|
197
|
+
if (!nestedEndpoint) {
|
|
198
|
+
throw new Error(`Tool ${nestedToolName} is not registered`);
|
|
199
|
+
}
|
|
200
|
+
const nestedInputs = (_a = nestedParams.inputs) !== null && _a !== void 0 ? _a : inputs;
|
|
201
|
+
const nestedHttpExtra = (_b = nestedParams.httpExtra) !== null && _b !== void 0 ? _b : httpExtra;
|
|
202
|
+
const nestedUserTimeZone = (_c = nestedParams.userTimeZone) !== null && _c !== void 0 ? _c : userTimeZone;
|
|
203
|
+
const nestedOutput = yield callCapturedEndpoint({
|
|
204
|
+
adminforth,
|
|
205
|
+
endpoint: nestedEndpoint,
|
|
206
|
+
adminUser,
|
|
207
|
+
inputs: nestedInputs,
|
|
208
|
+
httpExtra: nestedHttpExtra,
|
|
209
|
+
});
|
|
210
|
+
return applyToolOverride({
|
|
211
|
+
adminforth,
|
|
212
|
+
adminUser,
|
|
213
|
+
capturedEndpointsByToolName,
|
|
214
|
+
httpExtra: nestedHttpExtra,
|
|
215
|
+
inputs: nestedInputs,
|
|
216
|
+
output: nestedOutput,
|
|
217
|
+
toolName: nestedToolName,
|
|
218
|
+
userTimeZone: nestedUserTimeZone,
|
|
219
|
+
});
|
|
220
|
+
}),
|
|
221
|
+
});
|
|
222
|
+
return sanitizeForYaml(postProcessedOutput);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function endpointPathToToolName(path) {
|
|
226
|
+
return path
|
|
227
|
+
.replace(/^\/+/, '')
|
|
228
|
+
.replace(/[^a-zA-Z0-9_]+/g, '_')
|
|
229
|
+
.replace(/^_+|_+$/g, '');
|
|
230
|
+
}
|
|
231
|
+
function normalizeCookies(cookies) {
|
|
232
|
+
if (!cookies) {
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(cookies)) {
|
|
236
|
+
return cookies;
|
|
237
|
+
}
|
|
238
|
+
return Object.entries(cookies).map(([key, value]) => ({ key, value }));
|
|
239
|
+
}
|
|
240
|
+
function createToolResponse(baseResponse) {
|
|
241
|
+
return {
|
|
242
|
+
headers: [],
|
|
243
|
+
status: 200,
|
|
244
|
+
message: undefined,
|
|
245
|
+
setHeader(name, value) {
|
|
246
|
+
this.headers.push([name, value]);
|
|
247
|
+
baseResponse === null || baseResponse === void 0 ? void 0 : baseResponse.setHeader(name, value);
|
|
248
|
+
},
|
|
249
|
+
setStatus(code, message) {
|
|
250
|
+
this.status = code;
|
|
251
|
+
this.message = message;
|
|
252
|
+
baseResponse === null || baseResponse === void 0 ? void 0 : baseResponse.setStatus(code, message);
|
|
253
|
+
},
|
|
254
|
+
blobStream() {
|
|
255
|
+
var _a;
|
|
256
|
+
return (_a = baseResponse === null || baseResponse === void 0 ? void 0 : baseResponse.blobStream()) !== null && _a !== void 0 ? _a : new PassThrough();
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function createRawExpressRequest(params) {
|
|
261
|
+
const cookieHeader = params.cookies
|
|
262
|
+
.map(({ key, value }) => `${key}=${value}`)
|
|
263
|
+
.join('; ');
|
|
264
|
+
return {
|
|
265
|
+
adminUser: params.adminUser,
|
|
266
|
+
body: params.body,
|
|
267
|
+
destroyed: false,
|
|
268
|
+
headers: Object.assign(Object.assign({}, params.headers), (cookieHeader ? { cookie: cookieHeader } : {})),
|
|
269
|
+
method: params.method.toUpperCase(),
|
|
270
|
+
on: () => undefined,
|
|
271
|
+
query: params.query,
|
|
272
|
+
url: params.requestUrl,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function createRawExpressResponse(response) {
|
|
276
|
+
const rawResponse = {
|
|
277
|
+
destroyed: false,
|
|
278
|
+
on: () => undefined,
|
|
279
|
+
setHeader(name, value) {
|
|
280
|
+
response.setHeader(name, value);
|
|
281
|
+
return rawResponse;
|
|
282
|
+
},
|
|
283
|
+
status(code) {
|
|
284
|
+
response.status = code;
|
|
285
|
+
return rawResponse;
|
|
286
|
+
},
|
|
287
|
+
send(message) {
|
|
288
|
+
response.message = message;
|
|
289
|
+
return rawResponse;
|
|
290
|
+
},
|
|
291
|
+
json(payload) {
|
|
292
|
+
response.jsonPayload = payload;
|
|
293
|
+
response.message = JSON.stringify(payload);
|
|
294
|
+
return rawResponse;
|
|
295
|
+
},
|
|
296
|
+
write: () => true,
|
|
297
|
+
writeHead: () => rawResponse,
|
|
298
|
+
writableEnded: false,
|
|
299
|
+
end: () => rawResponse,
|
|
300
|
+
};
|
|
301
|
+
return rawResponse;
|
|
302
|
+
}
|
|
303
|
+
function callCapturedEndpoint(params) {
|
|
304
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
305
|
+
var _a, _b, _c, _d;
|
|
306
|
+
const { adminforth, adminUser, endpoint, httpExtra, inputs } = params;
|
|
307
|
+
const response = createToolResponse(httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.response);
|
|
308
|
+
const headers = Object.assign({ 'content-type': 'application/json' }, ((_a = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.headers) !== null && _a !== void 0 ? _a : {}));
|
|
309
|
+
const body = ((_b = inputs !== null && inputs !== void 0 ? inputs : httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.body) !== null && _b !== void 0 ? _b : {});
|
|
310
|
+
const query = (_c = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.query) !== null && _c !== void 0 ? _c : {};
|
|
311
|
+
const cookies = normalizeCookies(httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.cookies);
|
|
312
|
+
const requestUrl = (_d = httpExtra === null || httpExtra === void 0 ? void 0 : httpExtra.requestUrl) !== null && _d !== void 0 ? _d : `${adminforth.config.baseUrl}/adminapi/v1${endpoint.path}`;
|
|
313
|
+
const abortController = new AbortController();
|
|
314
|
+
const rawRequest = createRawExpressRequest({
|
|
315
|
+
adminUser,
|
|
316
|
+
body,
|
|
317
|
+
cookies,
|
|
318
|
+
headers,
|
|
319
|
+
method: endpoint.method,
|
|
320
|
+
query,
|
|
321
|
+
requestUrl,
|
|
322
|
+
});
|
|
323
|
+
const rawResponse = createRawExpressResponse(response);
|
|
324
|
+
const acceptLanguage = headers['accept-language'];
|
|
325
|
+
const tr = (msg, category = 'default', translationParams, pluralizationNumber) => adminforth.tr(msg, category, acceptLanguage, translationParams, pluralizationNumber);
|
|
326
|
+
const output = yield endpoint.handler({
|
|
327
|
+
body,
|
|
328
|
+
adminUser,
|
|
329
|
+
query,
|
|
330
|
+
headers,
|
|
331
|
+
cookies,
|
|
332
|
+
response,
|
|
333
|
+
requestUrl,
|
|
334
|
+
abortSignal: abortController.signal,
|
|
335
|
+
_raw_express_req: rawRequest,
|
|
336
|
+
_raw_express_res: rawResponse,
|
|
337
|
+
tr,
|
|
338
|
+
});
|
|
339
|
+
if (output !== undefined && output !== null) {
|
|
340
|
+
return output;
|
|
341
|
+
}
|
|
342
|
+
if (response.jsonPayload !== undefined) {
|
|
343
|
+
return response.jsonPayload;
|
|
344
|
+
}
|
|
345
|
+
if (response.message !== undefined) {
|
|
346
|
+
return response.message;
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
headers: response.headers,
|
|
350
|
+
status: response.status,
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
export function prepareApiBasedTools(adminforth) {
|
|
355
|
+
const capturedEndpoints = [];
|
|
356
|
+
const captureServer = {
|
|
357
|
+
setupSpaServer() { },
|
|
358
|
+
endpoint: ((options) => {
|
|
359
|
+
var _a;
|
|
360
|
+
const normalizedResponseSchema = (_a = options.response_schema) !== null && _a !== void 0 ? _a : options.responce_schema;
|
|
361
|
+
if (!options.request_schema && !normalizedResponseSchema) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
capturedEndpoints.push(Object.assign(Object.assign({}, options), { response_schema: normalizedResponseSchema, normalizedResponseSchema }));
|
|
365
|
+
}),
|
|
366
|
+
};
|
|
367
|
+
adminforth.setupEndpoints(captureServer);
|
|
368
|
+
const apiBasedTools = {};
|
|
369
|
+
const capturedEndpointsByToolName = Object.fromEntries(capturedEndpoints.map((endpoint) => [endpointPathToToolName(endpoint.path), endpoint]));
|
|
370
|
+
for (const endpoint of capturedEndpoints) {
|
|
371
|
+
const toolName = endpointPathToToolName(endpoint.path);
|
|
372
|
+
apiBasedTools[toolName] = {
|
|
373
|
+
description: endpoint.description,
|
|
374
|
+
input_schema: endpoint.request_schema,
|
|
375
|
+
input_schma: endpoint.request_schema,
|
|
376
|
+
output_schema: endpoint.normalizedResponseSchema,
|
|
377
|
+
call: (...args_1) => __awaiter(this, [...args_1], void 0, function* ({ adminUser, adminuser, inputs, httpExtra, userTimeZone } = {}) {
|
|
378
|
+
const output = yield callCapturedEndpoint({
|
|
379
|
+
adminforth,
|
|
380
|
+
endpoint,
|
|
381
|
+
adminUser: adminUser !== null && adminUser !== void 0 ? adminUser : adminuser,
|
|
382
|
+
inputs,
|
|
383
|
+
httpExtra,
|
|
384
|
+
});
|
|
385
|
+
const processedOutput = yield applyToolOverride({
|
|
386
|
+
adminforth,
|
|
387
|
+
adminUser: adminUser !== null && adminUser !== void 0 ? adminUser : adminuser,
|
|
388
|
+
capturedEndpointsByToolName,
|
|
389
|
+
httpExtra,
|
|
390
|
+
inputs,
|
|
391
|
+
output,
|
|
392
|
+
toolName,
|
|
393
|
+
userTimeZone,
|
|
394
|
+
});
|
|
395
|
+
return YAML.stringify(processedOutput);
|
|
396
|
+
}),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
return apiBasedTools;
|
|
400
|
+
}
|
|
401
|
+
export function serializeApiBasedTool(tool) {
|
|
402
|
+
if (!tool) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
description: tool.description,
|
|
407
|
+
input_schema: tool.input_schema,
|
|
408
|
+
input_schma: tool.input_schma,
|
|
409
|
+
output_schema: tool.output_schema,
|
|
410
|
+
call: '[Function]',
|
|
411
|
+
};
|
|
412
|
+
}
|