@adminforth/agent 1.28.0 → 1.29.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 +79 -0
- package/agent/systemPrompt.ts +0 -4
- package/build.log +1 -1
- package/dist/agent/languageDetect.js +74 -0
- package/dist/agent/systemPrompt.js +0 -4
- package/dist/index.js +7 -1
- package/index.ts +10 -1
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { logger } from "adminforth";
|
|
2
|
+
import type { PluginOptions } from "../types.js";
|
|
3
|
+
|
|
4
|
+
export type UserLanguage = {
|
|
5
|
+
language: string;
|
|
6
|
+
code: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const USER_LANGUAGE_OUTPUT_SCHEMA = {
|
|
10
|
+
name: "user_language",
|
|
11
|
+
strict: true,
|
|
12
|
+
schema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
additionalProperties: false,
|
|
15
|
+
properties: {
|
|
16
|
+
language: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Full English language name, for example English, Ukrainian, French.",
|
|
19
|
+
},
|
|
20
|
+
code: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Uppercase two-letter language code, for example EN, UA, FR.",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ["language", "code"],
|
|
26
|
+
},
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
29
|
+
export function formatLanguagePrompt(language: UserLanguage | null) {
|
|
30
|
+
if (!language) {
|
|
31
|
+
return "Respond in the user's language.";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return `Respond in ${language.language} (${language.code}).`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function parseUserLanguage(content: string | undefined): UserLanguage | null {
|
|
38
|
+
if (!content) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(content) as UserLanguage;
|
|
44
|
+
return {
|
|
45
|
+
language: parsed.language,
|
|
46
|
+
code: parsed.code,
|
|
47
|
+
};
|
|
48
|
+
} catch (error) {
|
|
49
|
+
logger.warn(`Failed to parse detected user language: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function detectUserLanguage(
|
|
55
|
+
completionAdapter: PluginOptions["modes"][number]["completionAdapter"],
|
|
56
|
+
prompt: string,
|
|
57
|
+
): Promise<UserLanguage | null> {
|
|
58
|
+
const response = await completionAdapter.complete({
|
|
59
|
+
content: [
|
|
60
|
+
"Detect the language of the user's message.",
|
|
61
|
+
"Return only the requested structured output.",
|
|
62
|
+
"The language must be the full English language name.",
|
|
63
|
+
"The code must be an uppercase two-letter code like EN, UA, FR.",
|
|
64
|
+
"",
|
|
65
|
+
"User message:",
|
|
66
|
+
prompt,
|
|
67
|
+
].join("\n"),
|
|
68
|
+
maxTokens: 80,
|
|
69
|
+
outputSchema: USER_LANGUAGE_OUTPUT_SCHEMA,
|
|
70
|
+
reasoningEffort: "none",
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (response.error) {
|
|
74
|
+
logger.warn(`Failed to detect user language: ${response.error}`);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return parseUserLanguage(response.content);
|
|
79
|
+
}
|
package/agent/systemPrompt.ts
CHANGED
|
@@ -24,10 +24,6 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
|
|
|
24
24
|
"Keep responses short, clear, and practical.",
|
|
25
25
|
"Answer only what is needed.",
|
|
26
26
|
"Do not add extra explanations or suggestions unless the user asks.",
|
|
27
|
-
"Always respond in the same natural language as the user's latest message.",
|
|
28
|
-
"This rule applies to confirmations, clarifying questions, progress updates, errors, and final answers.",
|
|
29
|
-
"Do not switch to English just because tool outputs, schemas, skills, or internal instructions are written in English.",
|
|
30
|
-
"Only switch language if the user explicitly asks you to do so.",
|
|
31
27
|
"Adapt to the user's tone and style of speaking, mirroring their vibe and wording.",
|
|
32
28
|
"if the user speaks casually, you should respond casually too",
|
|
33
29
|
"Never mutate data without user confirmation for a clearly described mutation plan.",
|
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 208,
|
|
41
|
+
sent 208,066 bytes received 562 bytes 417,256.00 bytes/sec
|
|
42
42
|
total size is 205,786 speedup is 0.99
|
|
@@ -0,0 +1,74 @@
|
|
|
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 { logger } from "adminforth";
|
|
11
|
+
const USER_LANGUAGE_OUTPUT_SCHEMA = {
|
|
12
|
+
name: "user_language",
|
|
13
|
+
strict: true,
|
|
14
|
+
schema: {
|
|
15
|
+
type: "object",
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
properties: {
|
|
18
|
+
language: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Full English language name, for example English, Ukrainian, French.",
|
|
21
|
+
},
|
|
22
|
+
code: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Uppercase two-letter language code, for example EN, UA, FR.",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["language", "code"],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export function formatLanguagePrompt(language) {
|
|
31
|
+
if (!language) {
|
|
32
|
+
return "Respond in the user's language.";
|
|
33
|
+
}
|
|
34
|
+
return `Respond in ${language.language} (${language.code}).`;
|
|
35
|
+
}
|
|
36
|
+
function parseUserLanguage(content) {
|
|
37
|
+
if (!content) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(content);
|
|
42
|
+
return {
|
|
43
|
+
language: parsed.language,
|
|
44
|
+
code: parsed.code,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger.warn(`Failed to parse detected user language: ${error instanceof Error ? error.message : String(error)}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function detectUserLanguage(completionAdapter, prompt) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const response = yield completionAdapter.complete({
|
|
55
|
+
content: [
|
|
56
|
+
"Detect the language of the user's message.",
|
|
57
|
+
"Return only the requested structured output.",
|
|
58
|
+
"The language must be the full English language name.",
|
|
59
|
+
"The code must be an uppercase two-letter code like EN, UA, FR.",
|
|
60
|
+
"",
|
|
61
|
+
"User message:",
|
|
62
|
+
prompt,
|
|
63
|
+
].join("\n"),
|
|
64
|
+
maxTokens: 80,
|
|
65
|
+
outputSchema: USER_LANGUAGE_OUTPUT_SCHEMA,
|
|
66
|
+
reasoningEffort: "none",
|
|
67
|
+
});
|
|
68
|
+
if (response.error) {
|
|
69
|
+
logger.warn(`Failed to detect user language: ${response.error}`);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return parseUserLanguage(response.content);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -23,10 +23,6 @@ export const DEFAULT_AGENT_SYSTEM_PROMPT = [
|
|
|
23
23
|
"Keep responses short, clear, and practical.",
|
|
24
24
|
"Answer only what is needed.",
|
|
25
25
|
"Do not add extra explanations or suggestions unless the user asks.",
|
|
26
|
-
"Always respond in the same natural language as the user's latest message.",
|
|
27
|
-
"This rule applies to confirmations, clarifying questions, progress updates, errors, and final answers.",
|
|
28
|
-
"Do not switch to English just because tool outputs, schemas, skills, or internal instructions are written in English.",
|
|
29
|
-
"Only switch language if the user explicitly asks you to do so.",
|
|
30
26
|
"Adapt to the user's tone and style of speaking, mirroring their vibe and wording.",
|
|
31
27
|
"if the user speaks casually, you should respond casually too",
|
|
32
28
|
"Never mutate data without user confirmation for a clearly described mutation plan.",
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { MemorySaver } from "@langchain/langgraph";
|
|
|
21
21
|
import { createAgentChatModel, callAgent, } from "./agent/simpleAgent.js";
|
|
22
22
|
import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
|
|
23
23
|
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
|
|
24
|
+
import { detectUserLanguage, formatLanguagePrompt, } from "./agent/languageDetect.js";
|
|
24
25
|
import { prepareApiBasedTools as buildApiBasedTools, } from './apiBasedTools.js';
|
|
25
26
|
import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT, } from "./agent/systemPrompt.js";
|
|
26
27
|
import { ALWAYS_AVAILABLE_API_TOOL_NAMES } from "./agent/tools/index.js";
|
|
@@ -59,7 +60,6 @@ function formatAdminUserPrompt(adminUser, usernameField) {
|
|
|
59
60
|
].join("\n");
|
|
60
61
|
}
|
|
61
62
|
function formatCurrentPagePrompt(currentPage) {
|
|
62
|
-
console.log("Current page context:", currentPage);
|
|
63
63
|
if (!currentPage) {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
@@ -306,9 +306,15 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
306
306
|
const maxTokens = (_f = this.options.maxTokens) !== null && _f !== void 0 ? _f : 10000;
|
|
307
307
|
const selectedMode = (_g = this.options.modes.find((mode) => mode.name === body.mode)) !== null && _g !== void 0 ? _g : this.options.modes[0];
|
|
308
308
|
const { model, summaryModel, modelMiddleware } = yield this.getModeModels(selectedMode, maxTokens);
|
|
309
|
+
const userLanguage = yield detectUserLanguage(selectedMode.completionAdapter, prompt)
|
|
310
|
+
.catch((error) => {
|
|
311
|
+
logger.warn(`Failed to detect user language: ${error instanceof Error ? error.message : String(error)}`);
|
|
312
|
+
return null;
|
|
313
|
+
});
|
|
309
314
|
const systemPrompt = [
|
|
310
315
|
yield this.agentSystemPromptPromise,
|
|
311
316
|
formatAdminUserPrompt(adminUser, this.adminforth.config.auth.usernameField),
|
|
317
|
+
formatLanguagePrompt(userLanguage),
|
|
312
318
|
].join("\n\n");
|
|
313
319
|
const apiBasedTools = buildApiBasedTools(this.adminforth);
|
|
314
320
|
for (const toolName of ALWAYS_AVAILABLE_API_TOOL_NAMES) {
|
package/index.ts
CHANGED
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
} from "./agent/simpleAgent.js";
|
|
19
19
|
import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
|
|
20
20
|
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
|
|
21
|
+
import {
|
|
22
|
+
detectUserLanguage,
|
|
23
|
+
formatLanguagePrompt,
|
|
24
|
+
} from "./agent/languageDetect.js";
|
|
21
25
|
import {
|
|
22
26
|
prepareApiBasedTools as buildApiBasedTools,
|
|
23
27
|
} from './apiBasedTools.js';
|
|
@@ -84,7 +88,6 @@ function formatAdminUserPrompt(adminUser: AdminUser, usernameField: string) {
|
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
function formatCurrentPagePrompt(currentPage: CurrentPageContext | undefined) {
|
|
87
|
-
console.log("Current page context:", currentPage);
|
|
88
91
|
if (!currentPage) {
|
|
89
92
|
return null;
|
|
90
93
|
}
|
|
@@ -379,9 +382,15 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
379
382
|
const selectedMode = this.options.modes.find((mode) => mode.name === body.mode) ?? this.options.modes[0];
|
|
380
383
|
const { model, summaryModel, modelMiddleware } =
|
|
381
384
|
await this.getModeModels(selectedMode, maxTokens);
|
|
385
|
+
const userLanguage = await detectUserLanguage(selectedMode.completionAdapter, prompt)
|
|
386
|
+
.catch((error) => {
|
|
387
|
+
logger.warn(`Failed to detect user language: ${error instanceof Error ? error.message : String(error)}`);
|
|
388
|
+
return null;
|
|
389
|
+
});
|
|
382
390
|
const systemPrompt = [
|
|
383
391
|
await this.agentSystemPromptPromise,
|
|
384
392
|
formatAdminUserPrompt(adminUser, this.adminforth.config.auth.usernameField),
|
|
393
|
+
formatLanguagePrompt(userLanguage),
|
|
385
394
|
].join("\n\n");
|
|
386
395
|
const apiBasedTools = buildApiBasedTools(this.adminforth);
|
|
387
396
|
for (const toolName of ALWAYS_AVAILABLE_API_TOOL_NAMES) {
|