@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.
Files changed (66) hide show
  1. package/.woodpecker/buildRelease.sh +13 -0
  2. package/.woodpecker/buildSlackNotify.sh +46 -0
  3. package/.woodpecker/release.yml +57 -0
  4. package/agent/middleware/apiBasedTools.ts +109 -0
  5. package/agent/middleware/sequenceDebug.ts +302 -0
  6. package/agent/simpleAgent.ts +291 -0
  7. package/agent/skills/registry.ts +135 -0
  8. package/agent/systemPrompt.ts +69 -0
  9. package/agent/toolCallEvents.ts +17 -0
  10. package/agent/tools/apiTool.ts +99 -0
  11. package/agent/tools/fetchSkill.ts +58 -0
  12. package/agent/tools/fetchToolSchema.ts +50 -0
  13. package/agent/tools/index.ts +26 -0
  14. package/apiBasedTools.ts +625 -0
  15. package/build.log +30 -0
  16. package/custom/ChatSurface.vue +184 -0
  17. package/custom/ConversationArea.vue +175 -0
  18. package/custom/Message.vue +206 -0
  19. package/custom/SessionsHistory.vue +93 -0
  20. package/custom/ToolRenderer.vue +131 -0
  21. package/custom/ToolsGroup.vue +67 -0
  22. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +301 -0
  23. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +285 -0
  24. package/custom/incremark_code_renderers/incremarkRenderer.ts +653 -0
  25. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +118 -0
  26. package/custom/package.json +26 -0
  27. package/custom/pnpm-lock.yaml +1467 -0
  28. package/custom/skills/fetch_data/SKILL.md +15 -0
  29. package/custom/skills/mutate_data/SKILL.md +108 -0
  30. package/custom/tsconfig.json +16 -0
  31. package/custom/types.ts +34 -0
  32. package/custom/useAgentStore.ts +349 -0
  33. package/dist/agent/middleware/apiBasedTools.js +91 -0
  34. package/dist/agent/middleware/sequenceDebug.js +210 -0
  35. package/dist/agent/simpleAgent.js +173 -0
  36. package/dist/agent/skills/registry.js +108 -0
  37. package/dist/agent/systemPrompt.js +64 -0
  38. package/dist/agent/toolCallEvents.js +1 -0
  39. package/dist/agent/tools/apiTool.js +93 -0
  40. package/dist/agent/tools/fetchSkill.js +51 -0
  41. package/dist/agent/tools/fetchToolSchema.js +36 -0
  42. package/dist/agent/tools/index.js +28 -0
  43. package/dist/apiBasedTools.js +412 -0
  44. package/dist/custom/ChatSurface.vue +184 -0
  45. package/dist/custom/ConversationArea.vue +175 -0
  46. package/dist/custom/Message.vue +206 -0
  47. package/dist/custom/SessionsHistory.vue +93 -0
  48. package/dist/custom/ToolRenderer.vue +131 -0
  49. package/dist/custom/ToolsGroup.vue +67 -0
  50. package/dist/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +301 -0
  51. package/dist/custom/incremark_code_renderers/incremarkCodeHighlight.ts +285 -0
  52. package/dist/custom/incremark_code_renderers/incremarkRenderer.ts +653 -0
  53. package/dist/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +118 -0
  54. package/dist/custom/package.json +26 -0
  55. package/dist/custom/pnpm-lock.yaml +1467 -0
  56. package/dist/custom/skills/fetch_data/SKILL.md +15 -0
  57. package/dist/custom/skills/mutate_data/SKILL.md +108 -0
  58. package/dist/custom/tsconfig.json +16 -0
  59. package/dist/custom/types.ts +34 -0
  60. package/dist/custom/useAgentStore.ts +349 -0
  61. package/dist/index.js +415 -0
  62. package/dist/types.js +1 -0
  63. package/index.ts +457 -0
  64. package/package.json +58 -0
  65. package/tsconfig.json +13 -0
  66. package/types.ts +45 -0
@@ -0,0 +1,210 @@
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
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import { createMiddleware } from "langchain";
22
+ import YAML from "yaml";
23
+ function createPendingSequenceDebug(sequenceId) {
24
+ return {
25
+ sequenceId,
26
+ startedAt: new Date().toISOString(),
27
+ prompt: "",
28
+ reasoning: "",
29
+ text: "",
30
+ toolCalls: [],
31
+ pendingToolCalls: 0,
32
+ resultType: null,
33
+ };
34
+ }
35
+ function hasSequenceDebugContent(sequence) {
36
+ return Boolean(sequence &&
37
+ (sequence.prompt ||
38
+ sequence.reasoning ||
39
+ sequence.text ||
40
+ sequence.toolCalls.length > 0));
41
+ }
42
+ function finalizeSequenceDebug(sequence) {
43
+ var _a;
44
+ return {
45
+ sequenceId: sequence.sequenceId,
46
+ startedAt: sequence.startedAt,
47
+ prompt: sequence.prompt,
48
+ reasoning: sequence.reasoning,
49
+ text: sequence.text,
50
+ toolCalls: sequence.toolCalls.map((_a) => {
51
+ var { completed: _completed } = _a, toolCall = __rest(_a, ["completed"]);
52
+ return toolCall;
53
+ }),
54
+ endedAt: new Date().toISOString(),
55
+ resultType: (_a = sequence.resultType) !== null && _a !== void 0 ? _a : "final_text",
56
+ };
57
+ }
58
+ function stringifyPromptForDebug(params) {
59
+ const { systemMessage, messages, tools, modelSettings } = params;
60
+ return YAML.stringify(Object.assign({ systemMessage: systemMessage.toDict(), messages: messages.map((message) => message.toDict()), tools: tools.map((tool) => {
61
+ if (typeof tool === "object" &&
62
+ tool !== null &&
63
+ "name" in tool &&
64
+ typeof tool.name === "string") {
65
+ return tool.name;
66
+ }
67
+ if (typeof tool === "object" &&
68
+ tool !== null &&
69
+ "schema" in tool &&
70
+ typeof tool.schema === "object" &&
71
+ tool.schema !== null &&
72
+ "name" in tool.schema &&
73
+ typeof tool.schema.name === "string") {
74
+ return tool.schema.name;
75
+ }
76
+ return "";
77
+ }) }, (modelSettings && Object.keys(modelSettings).length > 0
78
+ ? { modelSettings }
79
+ : {})));
80
+ }
81
+ function getMessageBlocks(message) {
82
+ if (Array.isArray(message.contentBlocks)) {
83
+ return message.contentBlocks;
84
+ }
85
+ if (Array.isArray(message.content)) {
86
+ return message.content;
87
+ }
88
+ return [];
89
+ }
90
+ function hasToolCallSignal(message) {
91
+ var _a;
92
+ return Boolean((Array.isArray(message.tool_calls) && message.tool_calls.length > 0) ||
93
+ (Array.isArray(message.tool_call_chunks) && message.tool_call_chunks.length > 0) ||
94
+ (Array.isArray((_a = message.additional_kwargs) === null || _a === void 0 ? void 0 : _a.tool_calls) &&
95
+ message.additional_kwargs.tool_calls.length > 0));
96
+ }
97
+ function extractSequenceResponseDebug(message) {
98
+ const blocks = getMessageBlocks(message);
99
+ const reasoning = blocks
100
+ .filter((block) => (block === null || block === void 0 ? void 0 : block.type) === "reasoning")
101
+ .map((block) => { var _a; return String((_a = block.reasoning) !== null && _a !== void 0 ? _a : ""); })
102
+ .join("");
103
+ const textFromBlocks = blocks
104
+ .filter((block) => (block === null || block === void 0 ? void 0 : block.type) === "text")
105
+ .map((block) => { var _a; return String((_a = block.text) !== null && _a !== void 0 ? _a : ""); })
106
+ .join("");
107
+ return {
108
+ reasoning,
109
+ text: textFromBlocks || (typeof message.content === "string" ? message.content : ""),
110
+ resultType: hasToolCallSignal(message) ? "tool_calls" : "final_text",
111
+ };
112
+ }
113
+ export function createSequenceDebugCollector() {
114
+ let nextSequenceId = 1;
115
+ let currentSequenceDebug = null;
116
+ const history = [];
117
+ const ensureSequenceDebug = () => {
118
+ if (!currentSequenceDebug) {
119
+ currentSequenceDebug = createPendingSequenceDebug(nextSequenceId++);
120
+ }
121
+ return currentSequenceDebug;
122
+ };
123
+ const flush = () => {
124
+ if (!hasSequenceDebugContent(currentSequenceDebug)) {
125
+ currentSequenceDebug = null;
126
+ return;
127
+ }
128
+ const finalizedSequenceDebug = finalizeSequenceDebug(currentSequenceDebug);
129
+ history.push(finalizedSequenceDebug);
130
+ currentSequenceDebug = null;
131
+ };
132
+ return {
133
+ handleModelCallStart(prompt) {
134
+ if ((currentSequenceDebug === null || currentSequenceDebug === void 0 ? void 0 : currentSequenceDebug.resultType) &&
135
+ currentSequenceDebug.pendingToolCalls === 0) {
136
+ flush();
137
+ }
138
+ const sequenceDebug = ensureSequenceDebug();
139
+ sequenceDebug.prompt = prompt;
140
+ },
141
+ handleModelCallComplete(params) {
142
+ const sequenceDebug = ensureSequenceDebug();
143
+ sequenceDebug.reasoning = params.reasoning;
144
+ sequenceDebug.text = params.text;
145
+ sequenceDebug.resultType = params.resultType;
146
+ if (sequenceDebug.resultType === "final_text" &&
147
+ sequenceDebug.pendingToolCalls === 0) {
148
+ flush();
149
+ }
150
+ },
151
+ handleToolCallEvent(event) {
152
+ const sequenceDebug = ensureSequenceDebug();
153
+ if (event.phase === "start") {
154
+ sequenceDebug.toolCalls.push({
155
+ toolCallId: event.toolCallId,
156
+ toolName: event.toolName,
157
+ input: event.input,
158
+ output: null,
159
+ error: null,
160
+ completed: false,
161
+ });
162
+ sequenceDebug.pendingToolCalls += 1;
163
+ return;
164
+ }
165
+ const pendingToolCall = sequenceDebug.toolCalls.find((toolCall) => toolCall.toolCallId === event.toolCallId && !toolCall.completed);
166
+ if (pendingToolCall) {
167
+ pendingToolCall.output = event.output;
168
+ pendingToolCall.error = event.error;
169
+ pendingToolCall.completed = true;
170
+ }
171
+ else {
172
+ sequenceDebug.toolCalls.push({
173
+ toolCallId: event.toolCallId,
174
+ toolName: event.toolName,
175
+ input: "",
176
+ output: event.output,
177
+ error: event.error,
178
+ completed: true,
179
+ });
180
+ }
181
+ sequenceDebug.pendingToolCalls = Math.max(0, sequenceDebug.pendingToolCalls - 1);
182
+ if (sequenceDebug.resultType === "tool_calls" &&
183
+ sequenceDebug.pendingToolCalls === 0) {
184
+ flush();
185
+ }
186
+ },
187
+ flush,
188
+ getHistory() {
189
+ return history;
190
+ },
191
+ };
192
+ }
193
+ export function createSequenceDebugMiddleware(sink) {
194
+ return createMiddleware({
195
+ name: "SequenceDebugMiddleware",
196
+ wrapModelCall(request, handler) {
197
+ return __awaiter(this, void 0, void 0, function* () {
198
+ sink.handleModelCallStart(stringifyPromptForDebug({
199
+ systemMessage: request.systemMessage,
200
+ messages: request.messages,
201
+ tools: request.tools,
202
+ modelSettings: request.modelSettings,
203
+ }));
204
+ const response = yield handler(request);
205
+ sink.handleModelCallComplete(extractSequenceResponseDebug(response));
206
+ return response;
207
+ });
208
+ },
209
+ });
210
+ }
@@ -0,0 +1,173 @@
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 { createAgent, summarizationMiddleware } from "langchain";
11
+ import { logger } from "adminforth";
12
+ import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
13
+ import { MemorySaver } from "@langchain/langgraph";
14
+ import { z } from "zod";
15
+ import { ChatOpenAI } from "@langchain/openai";
16
+ import { createAgentTools } from "./tools/index.js";
17
+ import { createApiBasedToolsMiddleware } from "./middleware/apiBasedTools.js";
18
+ import { createSequenceDebugMiddleware, } from "./middleware/sequenceDebug.js";
19
+ const checkpointer = new MemorySaver();
20
+ export const contextSchema = z.object({
21
+ adminUser: z.custom(),
22
+ userTimeZone: z.string(),
23
+ sessionId: z.string(),
24
+ turnId: z.string(),
25
+ emitToolCallEvent: z.custom(),
26
+ });
27
+ function getFiniteNumber(value) {
28
+ return typeof value === "number" && Number.isFinite(value)
29
+ ? value
30
+ : undefined;
31
+ }
32
+ function extractTokenUsage(output) {
33
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
34
+ const llmOutputTokenUsage = (_a = output.llmOutput) === null || _a === void 0 ? void 0 : _a.tokenUsage;
35
+ const promptTokens = getFiniteNumber(llmOutputTokenUsage === null || llmOutputTokenUsage === void 0 ? void 0 : llmOutputTokenUsage.promptTokens);
36
+ const completionTokens = getFiniteNumber(llmOutputTokenUsage === null || llmOutputTokenUsage === void 0 ? void 0 : llmOutputTokenUsage.completionTokens);
37
+ if (promptTokens !== undefined || completionTokens !== undefined) {
38
+ return {
39
+ InputTokens: promptTokens !== null && promptTokens !== void 0 ? promptTokens : 0,
40
+ outputTokens: completionTokens !== null && completionTokens !== void 0 ? completionTokens : 0,
41
+ };
42
+ }
43
+ let InputTokens = 0;
44
+ let outputTokens = 0;
45
+ for (const generationBatch of output.generations) {
46
+ for (const generation of generationBatch) {
47
+ if (!("message" in generation) || !generation.message) {
48
+ continue;
49
+ }
50
+ const message = generation.message;
51
+ InputTokens +=
52
+ (_f = (_c = getFiniteNumber((_b = message.usage_metadata) === null || _b === void 0 ? void 0 : _b.input_tokens)) !== null && _c !== void 0 ? _c : getFiniteNumber((_e = (_d = message.response_metadata) === null || _d === void 0 ? void 0 : _d.tokenUsage) === null || _e === void 0 ? void 0 : _e.promptTokens)) !== null && _f !== void 0 ? _f : 0;
53
+ outputTokens +=
54
+ (_l = (_h = getFiniteNumber((_g = message.usage_metadata) === null || _g === void 0 ? void 0 : _g.output_tokens)) !== null && _h !== void 0 ? _h : getFiniteNumber((_k = (_j = message.response_metadata) === null || _j === void 0 ? void 0 : _j.tokenUsage) === null || _k === void 0 ? void 0 : _k.completionTokens)) !== null && _l !== void 0 ? _l : 0;
55
+ }
56
+ }
57
+ return { InputTokens, outputTokens };
58
+ }
59
+ class AgentLlmMetricsLogger extends BaseCallbackHandler {
60
+ constructor() {
61
+ super(...arguments);
62
+ this.name = "AgentLlmMetricsLogger";
63
+ this.lc_prefer_streaming = true;
64
+ this.pendingRuns = new Map();
65
+ }
66
+ handleLLMStart(_llm, _prompts, runId) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ this.pendingRuns.set(runId, { startedAt: Date.now() });
69
+ });
70
+ }
71
+ handleLLMNewToken(_token, _chunk, runId) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ const pendingRun = this.pendingRuns.get(runId);
74
+ if (!pendingRun || pendingRun.firstTokenAt !== undefined) {
75
+ return;
76
+ }
77
+ pendingRun.firstTokenAt = Date.now();
78
+ });
79
+ }
80
+ handleLLMEnd(output, runId) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ const pendingRun = this.pendingRuns.get(runId);
83
+ if (!pendingRun) {
84
+ return;
85
+ }
86
+ this.pendingRuns.delete(runId);
87
+ const finishedAt = Date.now();
88
+ const rtt = finishedAt - pendingRun.startedAt;
89
+ const ttft = pendingRun.firstTokenAt === undefined
90
+ ? rtt
91
+ : pendingRun.firstTokenAt - pendingRun.startedAt;
92
+ const { InputTokens, outputTokens } = extractTokenUsage(output);
93
+ logger.info({ InputTokens, outputTokens, ttft, rtt }, "LLM call finished");
94
+ });
95
+ }
96
+ handleLLMError(_error, runId) {
97
+ return __awaiter(this, void 0, void 0, function* () {
98
+ this.pendingRuns.delete(runId);
99
+ });
100
+ }
101
+ }
102
+ function createAgentLlmMetricsLogger() {
103
+ return new AgentLlmMetricsLogger();
104
+ }
105
+ function normalizeReasoning(reasoning) {
106
+ if (reasoning === "none") {
107
+ return undefined;
108
+ }
109
+ return {
110
+ effort: reasoning,
111
+ summary: "auto",
112
+ };
113
+ }
114
+ export function createAgentChatModel(params) {
115
+ var _a, _b, _c, _d;
116
+ const adapter = params.adapter;
117
+ const options = (_a = adapter.options) !== null && _a !== void 0 ? _a : {};
118
+ if (!options.openAiApiKey) {
119
+ throw new Error("CompletionAdapter must expose options.openAiApiKey for ChatOpenAI");
120
+ }
121
+ const model = (_c = (_b = params.modelName) !== null && _b !== void 0 ? _b : options.model) !== null && _c !== void 0 ? _c : "gpt-5-nano";
122
+ const baseURL = (_d = options.baseURL) !== null && _d !== void 0 ? _d : options.baseUrl;
123
+ const reasoning = normalizeReasoning(params.reasoning);
124
+ return new ChatOpenAI(Object.assign(Object.assign(Object.assign({ apiKey: options.openAiApiKey, model, maxTokens: params.maxTokens, useResponsesApi: true, outputVersion: "v1" }, (reasoning ? { reasoning } : {})), (typeof options.timeoutMs === "number"
125
+ ? { timeout: options.timeoutMs }
126
+ : {})), (baseURL
127
+ ? {
128
+ configuration: {
129
+ baseURL,
130
+ },
131
+ }
132
+ : {})));
133
+ }
134
+ export function callAgent(params) {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ const { name, model, summaryModel, messages, adminUser, apiBasedTools, customComponentsDir, sessionId, turnId, userTimeZone, emitToolCallEvent, sequenceDebugSink, } = params;
137
+ const tools = yield createAgentTools(customComponentsDir, apiBasedTools);
138
+ const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools);
139
+ const sequenceDebugMiddleware = createSequenceDebugMiddleware(sequenceDebugSink);
140
+ const middleware = [
141
+ apiBasedToolsMiddleware,
142
+ sequenceDebugMiddleware,
143
+ summarizationMiddleware({
144
+ model: summaryModel,
145
+ trigger: { tokens: 1024 * 8 },
146
+ keep: { messages: 10 },
147
+ }),
148
+ ];
149
+ const agent = createAgent({
150
+ name,
151
+ model,
152
+ checkpointer,
153
+ tools,
154
+ contextSchema,
155
+ middleware,
156
+ });
157
+ return yield agent.stream({ messages }, {
158
+ streamMode: "messages",
159
+ recursionLimit: 50,
160
+ callbacks: [createAgentLlmMetricsLogger()],
161
+ configurable: {
162
+ thread_id: sessionId,
163
+ },
164
+ context: {
165
+ adminUser,
166
+ userTimeZone,
167
+ sessionId,
168
+ turnId,
169
+ emitToolCallEvent,
170
+ },
171
+ });
172
+ });
173
+ }
@@ -0,0 +1,108 @@
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 { readdir, readFile } from "fs/promises";
11
+ import path from "path";
12
+ import { fileURLToPath } from "url";
13
+ import { parse as parseYaml } from "yaml";
14
+ const PLUGIN_SKILLS_DIRECTORY_PATH = fileURLToPath(new URL("../../custom/skills/", import.meta.url));
15
+ const SKILL_MARKDOWN_FILENAME = "SKILL.md";
16
+ const SKILL_FRONTMATTER_SEPARATOR = "\n---\n";
17
+ function parseSkillManifest(directoryName, markdown) {
18
+ var _a, _b;
19
+ const [frontmatterBlock, instructions = ""] = markdown.split("\r\n").join("\n").split(SKILL_FRONTMATTER_SEPARATOR, 2);
20
+ const metadata = parseYaml(frontmatterBlock);
21
+ return {
22
+ directoryName,
23
+ name: (_a = metadata.name) !== null && _a !== void 0 ? _a : directoryName,
24
+ description: (_b = metadata.description) !== null && _b !== void 0 ? _b : "",
25
+ instructions: instructions.trim(),
26
+ };
27
+ }
28
+ function readSkillManifest(skillsDirectoryPath, directoryName) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ const markdown = yield readFile(path.join(skillsDirectoryPath, directoryName, SKILL_MARKDOWN_FILENAME), "utf8");
31
+ return parseSkillManifest(directoryName, markdown);
32
+ });
33
+ }
34
+ function listDirectorySkillManifests(skillsDirectoryPath) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ try {
37
+ const entries = yield readdir(skillsDirectoryPath, { withFileTypes: true });
38
+ return yield Promise.all(entries
39
+ .filter((entry) => entry.isDirectory())
40
+ .map((entry) => entry.name)
41
+ .sort()
42
+ .map((directoryName) => readSkillManifest(skillsDirectoryPath, directoryName)));
43
+ }
44
+ catch (error) {
45
+ if (error.code === "ENOENT") {
46
+ return [];
47
+ }
48
+ throw error;
49
+ }
50
+ });
51
+ }
52
+ function mergeSkillManifests(skillGroups) {
53
+ return Array.from(new Map(skillGroups.flat().map((skill) => [
54
+ `${skill.name}:${skill.directoryName}`,
55
+ skill,
56
+ ])).values());
57
+ }
58
+ export function getProjectSkillsDirectoryPath(customComponentsDir) {
59
+ return path.resolve(customComponentsDir, "skills");
60
+ }
61
+ export function listBundledSkillManifests() {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ return yield listDirectorySkillManifests(PLUGIN_SKILLS_DIRECTORY_PATH);
64
+ });
65
+ }
66
+ export function listProjectSkillManifests(customComponentsDir) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ return yield listDirectorySkillManifests(getProjectSkillsDirectoryPath(customComponentsDir));
69
+ });
70
+ }
71
+ export function listSkillManifests(customComponentsDir) {
72
+ return __awaiter(this, void 0, void 0, function* () {
73
+ return mergeSkillManifests([
74
+ yield listProjectSkillManifests(customComponentsDir),
75
+ yield listBundledSkillManifests(),
76
+ ]);
77
+ });
78
+ }
79
+ export function loadSkillManifest(skillName, customComponentsDir) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ var _a;
82
+ const manifests = yield listSkillManifests(customComponentsDir);
83
+ return ((_a = manifests.find((manifest) => manifest.name === skillName || manifest.directoryName === skillName)) !== null && _a !== void 0 ? _a : null);
84
+ });
85
+ }
86
+ export function loadSkillMarkdown(skillName, customComponentsDir) {
87
+ return __awaiter(this, void 0, void 0, function* () {
88
+ const manifest = yield loadSkillManifest(skillName, customComponentsDir);
89
+ if (!manifest) {
90
+ return null;
91
+ }
92
+ const directories = [
93
+ getProjectSkillsDirectoryPath(customComponentsDir),
94
+ PLUGIN_SKILLS_DIRECTORY_PATH,
95
+ ];
96
+ for (const skillsDirectoryPath of directories) {
97
+ try {
98
+ return yield readFile(path.join(skillsDirectoryPath, manifest.directoryName, SKILL_MARKDOWN_FILENAME), "utf8");
99
+ }
100
+ catch (error) {
101
+ if (error.code !== "ENOENT") {
102
+ throw error;
103
+ }
104
+ }
105
+ }
106
+ return null;
107
+ });
108
+ }
@@ -0,0 +1,64 @@
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 { listBundledSkillManifests, listProjectSkillManifests, } from "./skills/registry.js";
11
+ import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "./tools/index.js";
12
+ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
13
+ "You are helpful AI Assistant for Admin Panel.",
14
+ // about admin
15
+ "Admin panel has resources which represent some physical data storage (e.g. table/collection), each resource defines list of columns.",
16
+ "Each resource stores data records. Record represents a data item of resource.",
17
+ //about user
18
+ "Assume user is not technical so does not talk to him in terms of API calls, databases/sql/json etc.",
19
+ // prevent extra talk
20
+ "Try to achieve user's goal with as few steps as possible. Talk with him only when you need some important decision, otherwise act immediately and call tools asap",
21
+ // tone of voice
22
+ "Be warm, friendly, and sincere.",
23
+ "Keep responses short, clear, and practical.",
24
+ "Answer only what is needed.",
25
+ "Do not add extra explanations or suggestions unless the user asks.",
26
+ "Adapt to the user's tone and style of speaking, mirroring their vibe and wording.",
27
+ "if the user speaks casually, you should respond casually too",
28
+ ].join(" ");
29
+ function formatResources(resources) {
30
+ return resources
31
+ .map((resource) => `- resourceId: ${resource.resourceId}\n label: ${resource.label}`)
32
+ .join("\n");
33
+ }
34
+ function formatSkills(skills, label) {
35
+ return skills
36
+ .map((skill) => `- ${label}: ${skill.name}\n description: ${skill.description}`)
37
+ .join("\n");
38
+ }
39
+ export function buildAgentSystemPrompt(adminforth) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ const [primarySkills, defaultSkills] = yield Promise.all([
42
+ listProjectSkillManifests(adminforth.config.customization.customComponentsDir),
43
+ listBundledSkillManifests(),
44
+ ]);
45
+ const alwaysAvailableTools = ALWAYS_AVAILABLE_API_TOOL_NAMES.join(", ");
46
+ const sections = [
47
+ DEFAULT_AGENT_SYSTEM_PROMPT,
48
+ `BASE_URL: ${adminforth.config.baseUrl}`,
49
+ `List of resources:\n${formatResources(adminforth.config.resources)}`,
50
+ `You have always-available base tools: ${alwaysAvailableTools}.`,
51
+ primarySkills.length > 0
52
+ ? `You have primary skills set:\n${formatSkills(primarySkills, "skill_name")}`
53
+ : "",
54
+ "You have next default skills which you can fallback to if primary skill set does not provide a good skill:\n" +
55
+ formatSkills(defaultSkills, "skill_name"),
56
+ "Before using any skill, call fetch_skill to load its full instructions.",
57
+ "You can use get_resource immediately to inspect resource structure and column names.",
58
+ "Only call fetch_tool_schema for tool names that are explicitly mentioned in a fetched skill and are not already available as base tools.",
59
+ "When fetch_tool_schema succeeds, that tool becomes available on the next step.",
60
+ "Try to call as many tools as possible in parallel in one step.",
61
+ ];
62
+ return sections.filter(Boolean).join("\n\n");
63
+ });
64
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,93 @@
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 { randomUUID } from "crypto";
12
+ import YAML from "yaml";
13
+ import { serializeUnknownError } from "../../apiBasedTools.js";
14
+ const emptyToolSchema = {
15
+ type: "object",
16
+ properties: {},
17
+ additionalProperties: true,
18
+ };
19
+ function normalizeToolInputSchema(inputSchema) {
20
+ if (!inputSchema || typeof inputSchema !== "object" || Array.isArray(inputSchema)) {
21
+ return emptyToolSchema;
22
+ }
23
+ const schema = JSON.parse(JSON.stringify(inputSchema));
24
+ if (schema.type !== "object") {
25
+ return emptyToolSchema;
26
+ }
27
+ const notes = [];
28
+ if ("if" in schema || "then" in schema || "else" in schema || "allOf" in schema) {
29
+ delete schema.if;
30
+ delete schema.then;
31
+ delete schema.else;
32
+ delete schema.allOf;
33
+ notes.push("Runtime applies additional conditional validation rules.");
34
+ }
35
+ if ("oneOf" in schema || "anyOf" in schema || "not" in schema || "enum" in schema) {
36
+ delete schema.oneOf;
37
+ delete schema.anyOf;
38
+ delete schema.not;
39
+ delete schema.enum;
40
+ notes.push("Top-level composite validation rules are omitted for tool compatibility.");
41
+ }
42
+ if (notes.length > 0) {
43
+ schema.description = typeof schema.description === "string"
44
+ ? `${schema.description}\n\n${notes.join(" ")}`
45
+ : notes.join(" ");
46
+ }
47
+ return schema;
48
+ }
49
+ export function createApiTool(toolName, apiBasedTool) {
50
+ var _a;
51
+ return tool((input, runtime) => __awaiter(this, void 0, void 0, function* () {
52
+ const normalizedInput = (input !== null && input !== void 0 ? input : {});
53
+ const toolCallId = randomUUID();
54
+ const startedAt = Date.now();
55
+ runtime.context.emitToolCallEvent({
56
+ toolCallId,
57
+ toolName,
58
+ phase: "start",
59
+ input: YAML.stringify(normalizedInput),
60
+ });
61
+ try {
62
+ const output = yield apiBasedTool.call({
63
+ adminUser: runtime.context.adminUser,
64
+ inputs: normalizedInput,
65
+ userTimeZone: runtime.context.userTimeZone,
66
+ });
67
+ runtime.context.emitToolCallEvent({
68
+ toolCallId,
69
+ toolName,
70
+ phase: "end",
71
+ durationMs: Date.now() - startedAt,
72
+ output,
73
+ error: null,
74
+ });
75
+ return output;
76
+ }
77
+ catch (error) {
78
+ runtime.context.emitToolCallEvent({
79
+ toolCallId,
80
+ toolName,
81
+ phase: "end",
82
+ durationMs: Date.now() - startedAt,
83
+ output: null,
84
+ error: YAML.stringify(serializeUnknownError(error)),
85
+ });
86
+ throw error;
87
+ }
88
+ }), {
89
+ name: toolName,
90
+ description: (_a = apiBasedTool.description) !== null && _a !== void 0 ? _a : `${toolName} tool`,
91
+ schema: normalizeToolInputSchema(apiBasedTool.input_schema),
92
+ });
93
+ }