@adminforth/agent 1.36.0 → 1.38.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/agent/languageDetect.ts +0 -8
- package/agent/simpleAgent.ts +5 -5
- package/agent/systemPrompt.ts +35 -4
- package/agent/toolCallEvents.ts +31 -2
- package/agent/tools/apiTool.ts +1 -1
- package/agentResponseEvents.ts +197 -0
- package/apiBasedTools.ts +118 -284
- package/build.log +12 -2
- package/custom/ChatSurface.vue +31 -21
- package/custom/composables/agentAudio/agent-processing.mp3 +0 -0
- package/custom/composables/agentStore/constants.ts +8 -1
- package/custom/composables/agentStore/useAgentSessions.ts +88 -13
- package/custom/composables/useAgentAudio.ts +392 -0
- package/custom/composables/useAgentStore.ts +52 -5
- package/custom/conversation_area/ConversationArea.vue +1 -1
- package/custom/conversation_area/MessageRenderer.vue +12 -1
- package/custom/conversation_area/SystemMessageRenderer.vue +28 -0
- package/custom/conversation_area/TextRenderer.vue +4 -3
- package/custom/conversation_area/ToolRenderer.vue +1 -1
- package/custom/package.json +2 -1
- package/custom/pnpm-lock.yaml +29 -0
- package/custom/speech_recognition_frontend/AudioLines.vue +97 -0
- package/custom/speech_recognition_frontend/MicrophoneButon.vue +157 -0
- package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +22 -0
- package/custom/speech_recognition_frontend/voiceActivityDetection.ts +151 -0
- package/custom/types.ts +52 -2
- package/dist/agent/languageDetect.js +0 -6
- package/dist/agent/simpleAgent.js +4 -3
- package/dist/agent/systemPrompt.js +24 -3
- package/dist/agent/toolCallEvents.js +24 -2
- package/dist/agent/tools/apiTool.js +1 -1
- package/dist/agentResponseEvents.js +141 -0
- package/dist/apiBasedTools.js +95 -211
- package/dist/custom/ChatSurface.vue +31 -21
- package/dist/custom/composables/agentAudio/agent-processing.mp3 +0 -0
- package/dist/custom/composables/agentStore/constants.ts +8 -1
- package/dist/custom/composables/agentStore/useAgentSessions.ts +88 -13
- package/dist/custom/composables/useAgentAudio.ts +392 -0
- package/dist/custom/composables/useAgentStore.ts +52 -5
- package/dist/custom/conversation_area/ConversationArea.vue +1 -1
- package/dist/custom/conversation_area/MessageRenderer.vue +12 -1
- package/dist/custom/conversation_area/SystemMessageRenderer.vue +28 -0
- package/dist/custom/conversation_area/TextRenderer.vue +4 -3
- package/dist/custom/conversation_area/ToolRenderer.vue +1 -1
- package/dist/custom/package.json +2 -1
- package/dist/custom/pnpm-lock.yaml +29 -0
- package/dist/custom/speech_recognition_frontend/AudioLines.vue +97 -0
- package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +157 -0
- package/dist/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +22 -0
- package/dist/custom/speech_recognition_frontend/voiceActivityDetection.ts +151 -0
- package/dist/custom/types.ts +52 -2
- package/dist/index.js +290 -400
- package/index.ts +318 -492
- package/package.json +4 -2
- package/types.ts +1 -1
|
@@ -19,8 +19,8 @@ export const contextSchema = z.object({
|
|
|
19
19
|
userTimeZone: z.string(),
|
|
20
20
|
sessionId: z.string(),
|
|
21
21
|
turnId: z.string(),
|
|
22
|
+
abortSignal: z.custom().optional(),
|
|
22
23
|
currentPage: z.custom().optional(),
|
|
23
|
-
httpExtra: z.custom().optional(),
|
|
24
24
|
emitToolCallEvent: z.custom(),
|
|
25
25
|
});
|
|
26
26
|
function isLangChainAgentCompletionAdapter(adapter) {
|
|
@@ -132,7 +132,7 @@ export function createAgentChatModel(params) {
|
|
|
132
132
|
}
|
|
133
133
|
export function callAgent(params) {
|
|
134
134
|
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
-
const { name, model, summaryModel, modelMiddleware = [], checkpointer, messages, adminUser, adminforth, apiBasedTools, customComponentsDir, sessionId, turnId, currentPage,
|
|
135
|
+
const { name, model, summaryModel, modelMiddleware = [], checkpointer, messages, adminUser, adminforth, apiBasedTools, customComponentsDir, sessionId, turnId, currentPage, userTimeZone, abortSignal, emitToolCallEvent, sequenceDebugSink, } = params;
|
|
136
136
|
const tools = yield createAgentTools(customComponentsDir, apiBasedTools);
|
|
137
137
|
const apiBasedToolsMiddleware = createApiBasedToolsMiddleware(apiBasedTools, adminforth);
|
|
138
138
|
const sequenceDebugMiddleware = createSequenceDebugMiddleware(sequenceDebugSink);
|
|
@@ -158,6 +158,7 @@ export function callAgent(params) {
|
|
|
158
158
|
streamMode: "messages",
|
|
159
159
|
recursionLimit: 100,
|
|
160
160
|
callbacks: [createAgentLlmMetricsLogger()],
|
|
161
|
+
signal: abortSignal,
|
|
161
162
|
configurable: {
|
|
162
163
|
thread_id: sessionId,
|
|
163
164
|
},
|
|
@@ -166,8 +167,8 @@ export function callAgent(params) {
|
|
|
166
167
|
userTimeZone,
|
|
167
168
|
sessionId,
|
|
168
169
|
turnId,
|
|
170
|
+
abortSignal,
|
|
169
171
|
currentPage,
|
|
170
|
-
httpExtra,
|
|
171
172
|
emitToolCallEvent,
|
|
172
173
|
},
|
|
173
174
|
});
|
|
@@ -8,7 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { listBundledSkillManifests, listProjectSkillManifests, } from "./skills/registry.js";
|
|
11
|
-
import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "./tools/index.js";
|
|
12
11
|
export const DEFAULT_AGENT_SYSTEM_PROMPT = [
|
|
13
12
|
"You are helpful AI Assistant for Admin Panel.",
|
|
14
13
|
// about admin
|
|
@@ -38,6 +37,30 @@ export function appendCustomSystemPrompt(systemPrompt, customSystemPrompt) {
|
|
|
38
37
|
}
|
|
39
38
|
return `${systemPrompt}\n\n${normalizedCustomSystemPrompt}`;
|
|
40
39
|
}
|
|
40
|
+
function formatLanguagePrompt(language) {
|
|
41
|
+
if (!language) {
|
|
42
|
+
return "Respond in the user's language.";
|
|
43
|
+
}
|
|
44
|
+
return `Respond in ${language.language} (${language.code}).`;
|
|
45
|
+
}
|
|
46
|
+
function formatAdminUserPrompt(adminUser, usernameField) {
|
|
47
|
+
const adminUserContext = {
|
|
48
|
+
id: adminUser.pk,
|
|
49
|
+
email: adminUser.dbUser[usernameField],
|
|
50
|
+
};
|
|
51
|
+
return [
|
|
52
|
+
"Current admin user context:",
|
|
53
|
+
JSON.stringify(adminUserContext, null, 2),
|
|
54
|
+
"Use this admin user email when the user asks to send information to themselves, the current admin, or the logged-in user.",
|
|
55
|
+
].join("\n");
|
|
56
|
+
}
|
|
57
|
+
export function buildAgentTurnSystemPrompt(input) {
|
|
58
|
+
return [
|
|
59
|
+
input.agentSystemPrompt,
|
|
60
|
+
formatAdminUserPrompt(input.adminUser, input.usernameField),
|
|
61
|
+
formatLanguagePrompt(input.userLanguage),
|
|
62
|
+
].join("\n\n");
|
|
63
|
+
}
|
|
41
64
|
function formatResources(resources) {
|
|
42
65
|
return resources
|
|
43
66
|
.map((resource) => `- resourceId: ${resource.resourceId}\n label: ${resource.label}`)
|
|
@@ -54,7 +77,6 @@ export function buildAgentSystemPrompt(adminforth_1) {
|
|
|
54
77
|
listProjectSkillManifests(adminforth.config.customization.customComponentsDir),
|
|
55
78
|
listBundledSkillManifests(),
|
|
56
79
|
]);
|
|
57
|
-
const alwaysAvailableTools = ALWAYS_AVAILABLE_API_TOOL_NAMES.join(", ");
|
|
58
80
|
const adminBasePath = adminforth.config.baseUrlSlashed;
|
|
59
81
|
const hiddenResourceIdSet = new Set(hiddenResourceIds);
|
|
60
82
|
const visibleResources = adminforth.config.resources.filter((resource) => !hiddenResourceIdSet.has(resource.resourceId));
|
|
@@ -62,7 +84,6 @@ export function buildAgentSystemPrompt(adminforth_1) {
|
|
|
62
84
|
DEFAULT_AGENT_SYSTEM_PROMPT,
|
|
63
85
|
`ADMIN_BASE_PATH: ${adminBasePath}`,
|
|
64
86
|
`List of resources:\n${formatResources(visibleResources)}`,
|
|
65
|
-
`You have always-available base tools: ${alwaysAvailableTools}.`,
|
|
66
87
|
primarySkills.length > 0
|
|
67
88
|
? `You have primary skills set:\n${formatSkills(primarySkills, "skill_name")}`
|
|
68
89
|
: "",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import YAML from "yaml";
|
|
3
|
-
import { serializeUnknownError } from "../apiBasedTools.js";
|
|
4
3
|
const TOOL_MESSAGE_DEBUG_KEYS = new Set([
|
|
5
4
|
"metadata",
|
|
6
5
|
"additional_kwargs",
|
|
@@ -29,6 +28,29 @@ function sanitizeToolCallOutputForDebug(output) {
|
|
|
29
28
|
}
|
|
30
29
|
return Object.fromEntries(Object.entries(debugPayload).filter(([key]) => !TOOL_MESSAGE_DEBUG_KEYS.has(key)));
|
|
31
30
|
}
|
|
31
|
+
function serializeErrorForDebug(error) {
|
|
32
|
+
if (!(error instanceof Error)) {
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
const errorWithCause = error;
|
|
36
|
+
const serialized = {
|
|
37
|
+
name: error.name,
|
|
38
|
+
message: error.message,
|
|
39
|
+
};
|
|
40
|
+
if (error.stack) {
|
|
41
|
+
serialized.stack = error.stack;
|
|
42
|
+
}
|
|
43
|
+
if (errorWithCause.cause !== undefined) {
|
|
44
|
+
serialized.cause = serializeErrorForDebug(errorWithCause.cause);
|
|
45
|
+
}
|
|
46
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
47
|
+
if (key in serialized) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
serialized[key] = error[key];
|
|
51
|
+
}
|
|
52
|
+
return serialized;
|
|
53
|
+
}
|
|
32
54
|
export function createToolCallTracker(params) {
|
|
33
55
|
var _a, _b;
|
|
34
56
|
const toolCallId = (_a = params.toolCallId) !== null && _a !== void 0 ? _a : randomUUID();
|
|
@@ -61,7 +83,7 @@ export function createToolCallTracker(params) {
|
|
|
61
83
|
phase: "end",
|
|
62
84
|
durationMs: Date.now() - startedAt,
|
|
63
85
|
output: null,
|
|
64
|
-
error: YAML.stringify(
|
|
86
|
+
error: YAML.stringify(serializeErrorForDebug(error)).trimEnd(),
|
|
65
87
|
});
|
|
66
88
|
},
|
|
67
89
|
};
|
|
@@ -49,7 +49,7 @@ export function createApiTool(toolName, apiBasedTool) {
|
|
|
49
49
|
const normalizedInput = (input !== null && input !== void 0 ? input : {});
|
|
50
50
|
return apiBasedTool.call({
|
|
51
51
|
adminUser: runtime.context.adminUser,
|
|
52
|
-
|
|
52
|
+
abortSignal: runtime.context.abortSignal,
|
|
53
53
|
inputs: normalizedInput,
|
|
54
54
|
userTimeZone: runtime.context.userTimeZone,
|
|
55
55
|
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
export function createAgentEventStream(res, options = {}) {
|
|
3
|
+
let isStreamClosed = false;
|
|
4
|
+
let activeBlock = null;
|
|
5
|
+
res.writeHead(200, Object.assign({ "Content-Type": "text/event-stream", "Cache-Control": "no-cache", "Connection": "keep-alive" }, (options.vercelAiUiMessageStream
|
|
6
|
+
? { "x-vercel-ai-ui-message-stream": "v1" }
|
|
7
|
+
: {})));
|
|
8
|
+
const stream = {
|
|
9
|
+
send(obj) {
|
|
10
|
+
if (isStreamClosed || res.writableEnded || res.destroyed) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
res.write(`data: ${JSON.stringify(obj)}\n\n`);
|
|
14
|
+
},
|
|
15
|
+
endActiveBlock() {
|
|
16
|
+
if (!activeBlock) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
stream.send({
|
|
20
|
+
type: `${activeBlock.type}-end`,
|
|
21
|
+
id: activeBlock.id,
|
|
22
|
+
});
|
|
23
|
+
activeBlock = null;
|
|
24
|
+
},
|
|
25
|
+
startBlock(type) {
|
|
26
|
+
if ((activeBlock === null || activeBlock === void 0 ? void 0 : activeBlock.type) === type) {
|
|
27
|
+
return activeBlock.id;
|
|
28
|
+
}
|
|
29
|
+
stream.endActiveBlock();
|
|
30
|
+
const id = randomUUID();
|
|
31
|
+
activeBlock = { type, id };
|
|
32
|
+
stream.send({
|
|
33
|
+
type: `${type}-start`,
|
|
34
|
+
id,
|
|
35
|
+
});
|
|
36
|
+
return id;
|
|
37
|
+
},
|
|
38
|
+
start(messageId) {
|
|
39
|
+
stream.send({
|
|
40
|
+
type: "start",
|
|
41
|
+
messageId,
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
textDelta(delta) {
|
|
45
|
+
const textId = stream.startBlock("text");
|
|
46
|
+
stream.send({
|
|
47
|
+
type: "text-delta",
|
|
48
|
+
id: textId,
|
|
49
|
+
delta,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
reasoningDelta(delta) {
|
|
53
|
+
const reasoningId = stream.startBlock("reasoning");
|
|
54
|
+
stream.send({
|
|
55
|
+
type: "reasoning-delta",
|
|
56
|
+
id: reasoningId,
|
|
57
|
+
delta,
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
toolCall(event) {
|
|
61
|
+
if (options.closeActiveBlockOnToolStart && event.phase === "start") {
|
|
62
|
+
stream.endActiveBlock();
|
|
63
|
+
}
|
|
64
|
+
stream.send({
|
|
65
|
+
type: "data-tool-call",
|
|
66
|
+
data: event,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
transcript(text, language) {
|
|
70
|
+
stream.send({
|
|
71
|
+
type: "transcript",
|
|
72
|
+
data: {
|
|
73
|
+
text,
|
|
74
|
+
language,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
response(text, sessionId, turnId) {
|
|
79
|
+
stream.send({
|
|
80
|
+
type: "response",
|
|
81
|
+
data: {
|
|
82
|
+
text,
|
|
83
|
+
sessionId,
|
|
84
|
+
turnId,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
speechResponse(transcript, response, sessionId, turnId) {
|
|
89
|
+
stream.send({
|
|
90
|
+
type: "speech-response",
|
|
91
|
+
data: {
|
|
92
|
+
transcript,
|
|
93
|
+
response,
|
|
94
|
+
sessionId,
|
|
95
|
+
turnId,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
audioStart(mimeType, format) {
|
|
100
|
+
stream.send({
|
|
101
|
+
type: "audio-start",
|
|
102
|
+
data: {
|
|
103
|
+
mimeType,
|
|
104
|
+
format,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
audioDelta(value) {
|
|
109
|
+
stream.send({
|
|
110
|
+
type: "audio-delta",
|
|
111
|
+
data: {
|
|
112
|
+
base64: Buffer.from(value).toString("base64"),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
audioDone() {
|
|
117
|
+
stream.send({
|
|
118
|
+
type: "audio-done",
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
error(error) {
|
|
122
|
+
stream.send({
|
|
123
|
+
type: "error",
|
|
124
|
+
error,
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
end() {
|
|
128
|
+
if (isStreamClosed || res.writableEnded || res.destroyed) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
stream.endActiveBlock();
|
|
132
|
+
stream.send({
|
|
133
|
+
type: "finish",
|
|
134
|
+
});
|
|
135
|
+
res.write("data: [DONE]\n\n");
|
|
136
|
+
isStreamClosed = true;
|
|
137
|
+
res.end();
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return stream;
|
|
141
|
+
}
|