@adminforth/agent 2.6.0 → 2.7.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/dist/application/ports.d.ts +1 -0
- package/dist/application/runTurnUseCase.d.ts +6 -3
- package/dist/application/runTurnUseCase.js +31 -21
- package/dist/domain/systemPrompt.d.ts +2 -3
- package/dist/domain/systemPrompt.js +3 -3
- package/dist/domain/turnTypes.d.ts +3 -5
- package/dist/llm/agentContext.d.ts +3 -0
- package/dist/llm/agentContext.js +1 -0
- package/dist/llm/agentModels.d.ts +1 -0
- package/dist/llm/agentRuntime.js +18 -4
- package/dist/llm/langGraphLlm.js +3 -4
- package/dist/llm/middleware/legacySystemMessages.d.ts +15 -0
- package/dist/llm/middleware/legacySystemMessages.js +45 -0
- package/package.json +5 -5
- package/dist/llm/middleware/systemMessages.d.ts +0 -1
- package/dist/llm/middleware/systemMessages.js +0 -55
|
@@ -60,6 +60,7 @@ export type RunTurnUseCaseDeps = {
|
|
|
60
60
|
export declare class RunTurnUseCase {
|
|
61
61
|
private readonly deps;
|
|
62
62
|
private readonly pendingInterrupts;
|
|
63
|
+
private readonly lastDetectedLanguage;
|
|
63
64
|
constructor(deps: RunTurnUseCaseDeps);
|
|
64
65
|
private resolveMode;
|
|
65
66
|
private buildContext;
|
|
@@ -69,15 +70,17 @@ export declare class RunTurnUseCase {
|
|
|
69
70
|
* MemorySaver the in-process cache is authoritative (single process, cannot be stale).
|
|
70
71
|
*/
|
|
71
72
|
private resolvePendingInterrupts;
|
|
73
|
+
private requiresSessionOwnership;
|
|
72
74
|
/** Verify the session exists and belongs to the requesting admin user. */
|
|
73
75
|
private assertSessionOwnership;
|
|
74
76
|
/**
|
|
75
|
-
* Prepare an edit/branch turn:
|
|
76
|
-
*
|
|
77
|
-
*
|
|
77
|
+
* Prepare an edit/branch turn: resolve the fork checkpoint from the previous turn,
|
|
78
|
+
* truncate the conversation after the edited turn, and reuse the edited turn's id
|
|
79
|
+
* for the regenerated response. Ownership is already asserted by `prepareTurn`.
|
|
78
80
|
*/
|
|
79
81
|
private prepareEditTurn;
|
|
80
82
|
private prepareTurn;
|
|
83
|
+
private resolveUserLanguage;
|
|
81
84
|
private buildMessages;
|
|
82
85
|
private handleInterrupt;
|
|
83
86
|
private runAgentTurn;
|
|
@@ -17,7 +17,6 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
17
17
|
import { logger, Filters } from "adminforth";
|
|
18
18
|
import { randomUUID } from "crypto";
|
|
19
19
|
import { VegaLiteStreamBuffer } from "../domain/vegaLiteStreamBuffer.js";
|
|
20
|
-
import { buildAgentTurnSystemPrompt } from "../domain/systemPrompt.js";
|
|
21
20
|
import { getErrorMessage, isAbortError } from "../shared/errors.js";
|
|
22
21
|
function getApprovalDecision(input) {
|
|
23
22
|
return "approvalDecision" in input
|
|
@@ -77,6 +76,7 @@ export class RunTurnUseCase {
|
|
|
77
76
|
constructor(deps) {
|
|
78
77
|
this.deps = deps;
|
|
79
78
|
this.pendingInterrupts = new Map();
|
|
79
|
+
this.lastDetectedLanguage = new Map();
|
|
80
80
|
}
|
|
81
81
|
resolveMode(modeName) {
|
|
82
82
|
var _a;
|
|
@@ -121,6 +121,9 @@ export class RunTurnUseCase {
|
|
|
121
121
|
return (_a = this.pendingInterrupts.get(sessionId)) !== null && _a !== void 0 ? _a : [];
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
|
+
requiresSessionOwnership(input) {
|
|
125
|
+
return !input.chatSurface;
|
|
126
|
+
}
|
|
124
127
|
/** Verify the session exists and belongs to the requesting admin user. */
|
|
125
128
|
assertSessionOwnership(sessionId, adminUser) {
|
|
126
129
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -135,9 +138,9 @@ export class RunTurnUseCase {
|
|
|
135
138
|
});
|
|
136
139
|
}
|
|
137
140
|
/**
|
|
138
|
-
* Prepare an edit/branch turn:
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
+
* Prepare an edit/branch turn: resolve the fork checkpoint from the previous turn,
|
|
142
|
+
* truncate the conversation after the edited turn, and reuse the edited turn's id
|
|
143
|
+
* for the regenerated response. Ownership is already asserted by `prepareTurn`.
|
|
141
144
|
*/
|
|
142
145
|
prepareEditTurn(input) {
|
|
143
146
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -147,7 +150,6 @@ export class RunTurnUseCase {
|
|
|
147
150
|
if (!this.deps.turnCheckpointsEnabled) {
|
|
148
151
|
throw new Error("Edit/fork requires checkpointIdField to be configured on turnResource.");
|
|
149
152
|
}
|
|
150
|
-
yield this.assertSessionOwnership(input.sessionId, input.adminUser);
|
|
151
153
|
const agentTurns = yield this.deps.sessions.getAgentTurns(input.sessionId);
|
|
152
154
|
const targetIndex = agentTurns.findIndex((turn) => turn.id === editTurnId);
|
|
153
155
|
if (targetIndex === -1) {
|
|
@@ -175,6 +177,7 @@ export class RunTurnUseCase {
|
|
|
175
177
|
// Editing supersedes any in-flight turn state for this session.
|
|
176
178
|
this.deps.steerBuffer.clear(input.sessionId);
|
|
177
179
|
this.pendingInterrupts.delete(input.sessionId);
|
|
180
|
+
this.lastDetectedLanguage.delete(input.sessionId);
|
|
178
181
|
// Apply the edit + truncate (deletes later turns first, then rewrites the edited turn).
|
|
179
182
|
yield this.deps.sessions.editTurnAndTruncateAfter({
|
|
180
183
|
sessionId: input.sessionId,
|
|
@@ -200,6 +203,11 @@ export class RunTurnUseCase {
|
|
|
200
203
|
const mode = this.resolveMode(input.modeName);
|
|
201
204
|
const approvalDecision = getApprovalDecision(input);
|
|
202
205
|
const shouldResume = Boolean(approvalDecision);
|
|
206
|
+
console.log(`Preparing turn for session "${input.sessionId}" (resume=${shouldResume})`);
|
|
207
|
+
if (this.requiresSessionOwnership(input)) {
|
|
208
|
+
console.log(`Asserting session ownership for session "${input.sessionId}"`);
|
|
209
|
+
yield this.assertSessionOwnership(input.sessionId, input.adminUser);
|
|
210
|
+
}
|
|
203
211
|
if (input.editTurnId && !shouldResume) {
|
|
204
212
|
return this.prepareEditTurn(input);
|
|
205
213
|
}
|
|
@@ -239,9 +247,13 @@ export class RunTurnUseCase {
|
|
|
239
247
|
};
|
|
240
248
|
});
|
|
241
249
|
}
|
|
242
|
-
|
|
250
|
+
resolveUserLanguage(prepared) {
|
|
243
251
|
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
-
|
|
252
|
+
var _a;
|
|
253
|
+
if (prepared.resume) {
|
|
254
|
+
return (_a = this.lastDetectedLanguage.get(prepared.sessionId)) !== null && _a !== void 0 ? _a : null;
|
|
255
|
+
}
|
|
256
|
+
const detected = yield this.deps.llm
|
|
245
257
|
.detectLanguage({
|
|
246
258
|
completionAdapter: prepared.mode.completionAdapter,
|
|
247
259
|
prompt: prepared.prompt,
|
|
@@ -255,20 +267,13 @@ export class RunTurnUseCase {
|
|
|
255
267
|
logger.warn(`Failed to detect user language: ${getErrorMessage(error)}`);
|
|
256
268
|
return null;
|
|
257
269
|
});
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
agentSystemPrompt: yield this.deps.getAgentSystemPrompt(),
|
|
261
|
-
adminUser: prepared.context.adminUser,
|
|
262
|
-
usernameField: adminforth.config.auth.usernameField,
|
|
263
|
-
userLanguage,
|
|
264
|
-
chatSurface: prepared.context.chatSurface,
|
|
265
|
-
});
|
|
266
|
-
return [
|
|
267
|
-
{ role: "system", content: systemPrompt },
|
|
268
|
-
{ role: "user", content: prepared.prompt },
|
|
269
|
-
];
|
|
270
|
+
this.lastDetectedLanguage.set(prepared.sessionId, detected);
|
|
271
|
+
return detected;
|
|
270
272
|
});
|
|
271
273
|
}
|
|
274
|
+
buildMessages(prepared) {
|
|
275
|
+
return [{ role: "user", content: prepared.prompt }];
|
|
276
|
+
}
|
|
272
277
|
handleInterrupt(prepared, interrupt, descriptors) {
|
|
273
278
|
return __awaiter(this, void 0, void 0, function* () {
|
|
274
279
|
var _a, _b, _c;
|
|
@@ -290,6 +295,7 @@ export class RunTurnUseCase {
|
|
|
290
295
|
runAgentTurn(prepared) {
|
|
291
296
|
return __awaiter(this, void 0, void 0, function* () {
|
|
292
297
|
var _a, e_1, _b, _c;
|
|
298
|
+
const userLanguage = yield this.resolveUserLanguage(prepared);
|
|
293
299
|
const streamInput = prepared.resume
|
|
294
300
|
? {
|
|
295
301
|
resume: buildResumeValue({
|
|
@@ -298,11 +304,12 @@ export class RunTurnUseCase {
|
|
|
298
304
|
prompt: prepared.prompt,
|
|
299
305
|
}),
|
|
300
306
|
}
|
|
301
|
-
: { messages:
|
|
307
|
+
: { messages: this.buildMessages(prepared) };
|
|
302
308
|
const stream = yield this.deps.llm.streamTurn({
|
|
303
309
|
completionAdapter: prepared.mode.completionAdapter,
|
|
310
|
+
systemPrompt: yield this.deps.getAgentSystemPrompt(),
|
|
304
311
|
input: streamInput,
|
|
305
|
-
context: prepared.context,
|
|
312
|
+
context: Object.assign(Object.assign({}, prepared.context), { userLanguage }),
|
|
306
313
|
observability: prepared.observability,
|
|
307
314
|
branchFromCheckpointId: prepared.branchFromCheckpointId,
|
|
308
315
|
});
|
|
@@ -353,6 +360,9 @@ export class RunTurnUseCase {
|
|
|
353
360
|
// done and leftover (unconsumed) steers must not leak into the next turn.
|
|
354
361
|
if (!interrupted) {
|
|
355
362
|
this.deps.steerBuffer.clear(prepared.sessionId);
|
|
363
|
+
// The detected language is only needed to bridge an interrupt -> resume; once
|
|
364
|
+
// the turn is done the next one re-detects.
|
|
365
|
+
this.lastDetectedLanguage.delete(prepared.sessionId);
|
|
356
366
|
}
|
|
357
367
|
if (!this.deps.hasPersistentCheckpointer && !interrupted) {
|
|
358
368
|
this.pendingInterrupts.delete(prepared.sessionId);
|
|
@@ -2,11 +2,10 @@ import type { AdminUser, IAdminForth } from "adminforth";
|
|
|
2
2
|
import type { DetectedLanguage } from "./languageDetect.js";
|
|
3
3
|
export declare const DEFAULT_AGENT_SYSTEM_PROMPT: string;
|
|
4
4
|
export declare function appendCustomSystemPrompt(systemPrompt: string, customSystemPrompt?: string): string;
|
|
5
|
-
export declare function
|
|
6
|
-
agentSystemPrompt: string;
|
|
5
|
+
export declare function buildDynamicSystemPrompt(input: {
|
|
7
6
|
adminUser: AdminUser;
|
|
8
7
|
usernameField: string;
|
|
9
|
-
userLanguage
|
|
8
|
+
userLanguage?: DetectedLanguage | null;
|
|
10
9
|
chatSurface?: string;
|
|
11
10
|
}): string;
|
|
12
11
|
export declare function buildAgentSystemPrompt(adminforth: IAdminForth, hiddenResourceIds?: Iterable<string>): Promise<string>;
|
|
@@ -51,14 +51,14 @@ function formatAdminUserPrompt(adminUser, usernameField) {
|
|
|
51
51
|
"Use this admin user email when the user asks to send information to themselves, the current admin, or the logged-in user.",
|
|
52
52
|
].join("\n");
|
|
53
53
|
}
|
|
54
|
-
export function
|
|
54
|
+
export function buildDynamicSystemPrompt(input) {
|
|
55
|
+
var _a;
|
|
55
56
|
return [
|
|
56
|
-
input.agentSystemPrompt,
|
|
57
57
|
formatAdminUserPrompt(input.adminUser, input.usernameField),
|
|
58
58
|
input.chatSurface
|
|
59
59
|
? `Current chat surface: ${input.chatSurface}. The user is not in the AdminForth web UI, so tools cannot move their browser. When navigate_user returns a link, send that link to the user.`
|
|
60
60
|
: "",
|
|
61
|
-
formatLanguagePrompt(input.userLanguage),
|
|
61
|
+
formatLanguagePrompt((_a = input.userLanguage) !== null && _a !== void 0 ? _a : null),
|
|
62
62
|
].filter(Boolean).join("\n\n");
|
|
63
63
|
}
|
|
64
64
|
function formatResources(resources) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AdminUser, AudioAdapter } from "adminforth";
|
|
2
|
+
import type { DetectedLanguage } from "./languageDetect.js";
|
|
2
3
|
import type { CurrentPageContext } from "../tools/getUserLocation.js";
|
|
3
4
|
import type { AgentEventEmitter } from "./agentEvents.js";
|
|
4
5
|
/**
|
|
@@ -53,6 +54,7 @@ export type AgentTurnContext = {
|
|
|
53
54
|
currentPage?: CurrentPageContext;
|
|
54
55
|
chatSurface?: string;
|
|
55
56
|
adminPublicOrigin?: string;
|
|
57
|
+
userLanguage?: DetectedLanguage | null;
|
|
56
58
|
};
|
|
57
59
|
export type AgentTurnObservability = {
|
|
58
60
|
emit?: AgentEventEmitter;
|
|
@@ -76,12 +78,8 @@ export type HandleSpeechTurnInput = SpeechAgentTurnInput;
|
|
|
76
78
|
export type HandleEditTurnInput = TextAgentTurnInput & {
|
|
77
79
|
turnId: string;
|
|
78
80
|
};
|
|
79
|
-
/**
|
|
80
|
-
* Provider-agnostic message passed from the application layer to the LLM port.
|
|
81
|
-
* The infrastructure adapter maps it onto concrete LangChain messages.
|
|
82
|
-
*/
|
|
83
81
|
export type AgentMessage = {
|
|
84
|
-
role: "
|
|
82
|
+
role: "user";
|
|
85
83
|
content: string;
|
|
86
84
|
};
|
|
87
85
|
/**
|
|
@@ -4,6 +4,7 @@ import type { AgentEventEmitter } from "../domain/agentEvents.js";
|
|
|
4
4
|
import type { SequenceDebugCollector } from "./middleware/sequenceDebug.js";
|
|
5
5
|
import type { CurrentPageContext } from "../tools/getUserLocation.js";
|
|
6
6
|
import type { AgentTurnContext } from "../domain/turnTypes.js";
|
|
7
|
+
import type { DetectedLanguage } from "../domain/languageDetect.js";
|
|
7
8
|
export declare const contextSchema: z.ZodObject<{
|
|
8
9
|
adminUser: z.ZodCustom<AdminUser, AdminUser>;
|
|
9
10
|
userTimeZone: z.ZodString;
|
|
@@ -14,9 +15,11 @@ export declare const contextSchema: z.ZodObject<{
|
|
|
14
15
|
chatSurface: z.ZodOptional<z.ZodString>;
|
|
15
16
|
adminBaseUrl: z.ZodOptional<z.ZodString>;
|
|
16
17
|
adminPublicOrigin: z.ZodOptional<z.ZodString>;
|
|
18
|
+
userLanguage: z.ZodOptional<z.ZodCustom<DetectedLanguage | null, DetectedLanguage | null>>;
|
|
17
19
|
emit: z.ZodOptional<z.ZodCustom<AgentEventEmitter, AgentEventEmitter>>;
|
|
18
20
|
sequenceDebugSink: z.ZodCustom<SequenceDebugCollector, SequenceDebugCollector>;
|
|
19
21
|
}, z.core.$strip>;
|
|
22
|
+
export type AgentContext = z.infer<typeof contextSchema>;
|
|
20
23
|
export declare function toLangchainAgentContext(context: AgentTurnContext & {
|
|
21
24
|
adminBaseUrl: string;
|
|
22
25
|
emit?: AgentEventEmitter;
|
package/dist/llm/agentContext.js
CHANGED
|
@@ -9,6 +9,7 @@ export const contextSchema = z.object({
|
|
|
9
9
|
chatSurface: z.string().optional(),
|
|
10
10
|
adminBaseUrl: z.string().optional(),
|
|
11
11
|
adminPublicOrigin: z.string().optional(),
|
|
12
|
+
userLanguage: z.custom().optional(),
|
|
12
13
|
emit: z.custom().optional(),
|
|
13
14
|
sequenceDebugSink: z.custom(),
|
|
14
15
|
});
|
package/dist/llm/agentRuntime.js
CHANGED
|
@@ -7,13 +7,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { createAgent, summarizationMiddleware, humanInTheLoopMiddleware } from "langchain";
|
|
10
|
+
import { createAgent, summarizationMiddleware, humanInTheLoopMiddleware, dynamicSystemPromptMiddleware, } from "langchain";
|
|
11
11
|
import { createApiBasedToolsMiddleware } from "./middleware/apiToolsMiddleware.js";
|
|
12
12
|
import { createSequenceDebugMiddleware } from "./middleware/sequenceDebug.js";
|
|
13
13
|
import { createSteerMiddleware } from "./middleware/steerMiddleware.js";
|
|
14
14
|
import { createAgentLlmMetricsLogger } from "./agentModels.js";
|
|
15
15
|
import { contextSchema, toLangchainAgentContext } from "./agentContext.js";
|
|
16
|
-
import {
|
|
16
|
+
import { createLegacySystemMessagesMiddleware } from "./middleware/legacySystemMessages.js";
|
|
17
|
+
import { buildDynamicSystemPrompt } from "../domain/systemPrompt.js";
|
|
17
18
|
function createHumanInTheLoopInterrupts(apiBasedTools) {
|
|
18
19
|
return Object.fromEntries(Object.entries(apiBasedTools)
|
|
19
20
|
.filter(([, apiBasedTool]) => { var _a; return ((_a = apiBasedTool.agent) === null || _a === void 0 ? void 0 : _a.isDangerous) === true; })
|
|
@@ -44,14 +45,22 @@ export class AgentRuntime {
|
|
|
44
45
|
descriptionPrefix: "Tool execution pending approval",
|
|
45
46
|
});
|
|
46
47
|
const steerMiddleware = createSteerMiddleware(this.options.steerBuffer);
|
|
47
|
-
const
|
|
48
|
+
const legacySystemMessagesMiddleware = createLegacySystemMessagesMiddleware();
|
|
49
|
+
const usernameField = adminforth.config.auth.usernameField;
|
|
50
|
+
const dynamicPromptMiddleware = dynamicSystemPromptMiddleware((_state, runtime) => buildDynamicSystemPrompt({
|
|
51
|
+
adminUser: runtime.context.adminUser,
|
|
52
|
+
usernameField,
|
|
53
|
+
userLanguage: runtime.context.userLanguage,
|
|
54
|
+
chatSurface: runtime.context.chatSurface,
|
|
55
|
+
}));
|
|
48
56
|
const middleware = [
|
|
49
57
|
steerMiddleware,
|
|
50
58
|
apiBasedToolsMiddleware,
|
|
51
59
|
hitlMiddleware,
|
|
60
|
+
legacySystemMessagesMiddleware,
|
|
61
|
+
dynamicPromptMiddleware,
|
|
52
62
|
...((_a = input.models.modelMiddleware) !== null && _a !== void 0 ? _a : []),
|
|
53
63
|
sequenceDebugMiddleware,
|
|
54
|
-
systemMessagesMiddleware,
|
|
55
64
|
summarizationMiddleware({
|
|
56
65
|
model: input.models.summaryModel,
|
|
57
66
|
trigger: { tokens: 1024 * 64 },
|
|
@@ -61,6 +70,11 @@ export class AgentRuntime {
|
|
|
61
70
|
const agent = createAgent({
|
|
62
71
|
name: this.options.name,
|
|
63
72
|
model: input.models.model,
|
|
73
|
+
// Passed as a plain string on purpose: LangChain normalizes it to a single text
|
|
74
|
+
// block, and DynamicSystemPromptMiddleware appends the per-turn half as a second
|
|
75
|
+
// one. That block split is all the agent owes the provider — whether the boundary
|
|
76
|
+
// becomes a cache breakpoint is the adapter's call.
|
|
77
|
+
systemPrompt: input.systemPrompt,
|
|
64
78
|
checkpointer: this.options.getCheckpointer(),
|
|
65
79
|
tools,
|
|
66
80
|
contextSchema,
|
package/dist/llm/langGraphLlm.js
CHANGED
|
@@ -8,13 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { Command } from "@langchain/langgraph";
|
|
11
|
-
import { HumanMessage
|
|
11
|
+
import { HumanMessage } from "langchain";
|
|
12
12
|
import { detectUserLanguage } from "../domain/languageDetect.js";
|
|
13
13
|
import { adaptRawStream, normalizeInterrupts } from "./streamAdapter.js";
|
|
14
14
|
function toLangchainMessages(messages) {
|
|
15
|
-
return messages.map((message) => message.
|
|
16
|
-
? new SystemMessage(message.content)
|
|
17
|
-
: new HumanMessage(message.content));
|
|
15
|
+
return messages.map((message) => new HumanMessage(message.content));
|
|
18
16
|
}
|
|
19
17
|
/**
|
|
20
18
|
* LangChain/LangGraph implementation of {@link LlmPort}. This is the single
|
|
@@ -34,6 +32,7 @@ export class LangGraphLlm {
|
|
|
34
32
|
: { messages: toLangchainMessages(input.input.messages) };
|
|
35
33
|
const rawStream = yield this.runtime.stream({
|
|
36
34
|
models,
|
|
35
|
+
systemPrompt: input.systemPrompt,
|
|
37
36
|
input: runtimeInput,
|
|
38
37
|
context: input.context,
|
|
39
38
|
observability: input.observability,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration shield for threads checkpointed before the system prompt moved out of the
|
|
3
|
+
* message history.
|
|
4
|
+
*
|
|
5
|
+
* Turns used to be started with `[SystemMessage, HumanMessage]`, so every such turn left
|
|
6
|
+
* a system message inside the thread's persisted state. Those messages are still in old
|
|
7
|
+
* checkpoints and would now arrive mid-history — both an invalid shape for providers that
|
|
8
|
+
* take the system prompt out-of-band, and a stale duplicate of a prompt the agent already
|
|
9
|
+
* supplies. So they are dropped, not re-hoisted: the authoritative prompt is
|
|
10
|
+
* `createAgent({ systemPrompt })` plus DynamicSystemPromptMiddleware.
|
|
11
|
+
*
|
|
12
|
+
* Nothing writes system messages into state any more, so for new threads this is a no-op.
|
|
13
|
+
* It stays as a cheap guard (and can be deleted once no pre-refactor checkpoints remain).
|
|
14
|
+
*/
|
|
15
|
+
export declare function createLegacySystemMessagesMiddleware(): import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[]>;
|
|
@@ -0,0 +1,45 @@
|
|
|
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 { createMiddleware } from "langchain";
|
|
11
|
+
function isSystemMessage(message) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
return (((_a = message._getType) === null || _a === void 0 ? void 0 : _a.call(message)) === "system" ||
|
|
14
|
+
((_b = message.getType) === null || _b === void 0 ? void 0 : _b.call(message)) === "system" ||
|
|
15
|
+
message.type === "system");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Migration shield for threads checkpointed before the system prompt moved out of the
|
|
19
|
+
* message history.
|
|
20
|
+
*
|
|
21
|
+
* Turns used to be started with `[SystemMessage, HumanMessage]`, so every such turn left
|
|
22
|
+
* a system message inside the thread's persisted state. Those messages are still in old
|
|
23
|
+
* checkpoints and would now arrive mid-history — both an invalid shape for providers that
|
|
24
|
+
* take the system prompt out-of-band, and a stale duplicate of a prompt the agent already
|
|
25
|
+
* supplies. So they are dropped, not re-hoisted: the authoritative prompt is
|
|
26
|
+
* `createAgent({ systemPrompt })` plus DynamicSystemPromptMiddleware.
|
|
27
|
+
*
|
|
28
|
+
* Nothing writes system messages into state any more, so for new threads this is a no-op.
|
|
29
|
+
* It stays as a cheap guard (and can be deleted once no pre-refactor checkpoints remain).
|
|
30
|
+
*/
|
|
31
|
+
export function createLegacySystemMessagesMiddleware() {
|
|
32
|
+
return createMiddleware({
|
|
33
|
+
name: "LegacySystemMessagesMiddleware",
|
|
34
|
+
wrapModelCall(request, handler) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const typed = request;
|
|
37
|
+
const messages = typed.messages.filter((message) => !isSystemMessage(message));
|
|
38
|
+
if (messages.length === typed.messages.length) {
|
|
39
|
+
return handler(request);
|
|
40
|
+
}
|
|
41
|
+
return handler(Object.assign(Object.assign({}, request), { messages }));
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"typescript": "^5.7.3"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@langchain/core": "
|
|
48
|
-
"@langchain/langgraph": "
|
|
49
|
-
"@langchain/langgraph-checkpoint": "
|
|
47
|
+
"@langchain/core": "1.2.5",
|
|
48
|
+
"@langchain/langgraph": "1.2.8",
|
|
49
|
+
"@langchain/langgraph-checkpoint": "1.0.1",
|
|
50
50
|
"dayjs": "^1.11.20",
|
|
51
|
-
"langchain": "
|
|
51
|
+
"langchain": "1.3.3",
|
|
52
52
|
"multer": "^2.1.1",
|
|
53
53
|
"vue-i18n": "^11.4.0",
|
|
54
54
|
"yaml": "^2.8.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function createSystemMessagesMiddleware(): import("langchain").AgentMiddleware<undefined, undefined, unknown, readonly (import("@langchain/core/tools").ClientTool | import("@langchain/core/tools").ServerTool)[]>;
|
|
@@ -1,55 +0,0 @@
|
|
|
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 { createMiddleware } from "langchain";
|
|
11
|
-
function isSystemMessage(message) {
|
|
12
|
-
var _a, _b;
|
|
13
|
-
return (((_a = message._getType) === null || _a === void 0 ? void 0 : _a.call(message)) === "system" ||
|
|
14
|
-
((_b = message.getType) === null || _b === void 0 ? void 0 : _b.call(message)) === "system" ||
|
|
15
|
-
message.type === "system");
|
|
16
|
-
}
|
|
17
|
-
function contentToText(content, text) {
|
|
18
|
-
if (text)
|
|
19
|
-
return text;
|
|
20
|
-
if (typeof content === "string")
|
|
21
|
-
return content;
|
|
22
|
-
if (!Array.isArray(content))
|
|
23
|
-
return "";
|
|
24
|
-
return content
|
|
25
|
-
.map((block) => {
|
|
26
|
-
var _a;
|
|
27
|
-
if (typeof block === "string")
|
|
28
|
-
return block;
|
|
29
|
-
if (block && typeof block === "object" && "text" in block) {
|
|
30
|
-
return String((_a = block.text) !== null && _a !== void 0 ? _a : "");
|
|
31
|
-
}
|
|
32
|
-
return "";
|
|
33
|
-
})
|
|
34
|
-
.join("");
|
|
35
|
-
}
|
|
36
|
-
function normalizeSystemMessages(request) {
|
|
37
|
-
const extraSystemText = request.messages
|
|
38
|
-
.filter(isSystemMessage)
|
|
39
|
-
.map((message) => contentToText(message.content, message.text))
|
|
40
|
-
.filter(Boolean)
|
|
41
|
-
.join("\n\n");
|
|
42
|
-
return Object.assign(Object.assign({}, request), { systemMessage: extraSystemText
|
|
43
|
-
? request.systemMessage.concat(extraSystemText)
|
|
44
|
-
: request.systemMessage, messages: request.messages.filter((message) => !isSystemMessage(message)) });
|
|
45
|
-
}
|
|
46
|
-
export function createSystemMessagesMiddleware() {
|
|
47
|
-
return createMiddleware({
|
|
48
|
-
name: "SystemMessagesMiddleware",
|
|
49
|
-
wrapModelCall(request, handler) {
|
|
50
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
return handler(normalizeSystemMessages(request));
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|