@m4trix/core 0.12.0 → 0.12.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/index.cjs +0 -271
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +2 -272
- package/dist/index.js.map +1 -1
- package/package.json +18 -35
- package/dist/helper/index.cjs +0 -279
- package/dist/helper/index.cjs.map +0 -1
- package/dist/helper/index.d.ts +0 -108
- package/dist/helper/index.js +0 -277
- package/dist/helper/index.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m4trix/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "A powerful TypeScript library for building AI-driven web applications",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -23,12 +23,6 @@
|
|
|
23
23
|
"import": "./dist/stream/index.js",
|
|
24
24
|
"require": "./dist/stream/index.cjs",
|
|
25
25
|
"default": "./dist/stream/index.js"
|
|
26
|
-
},
|
|
27
|
-
"./helper": {
|
|
28
|
-
"types": "./dist/helper/index.d.ts",
|
|
29
|
-
"import": "./dist/helper/index.js",
|
|
30
|
-
"require": "./dist/helper/index.cjs",
|
|
31
|
-
"default": "./dist/helper/index.js"
|
|
32
26
|
}
|
|
33
27
|
},
|
|
34
28
|
"files": [
|
|
@@ -52,52 +46,41 @@
|
|
|
52
46
|
"author": "Pascal Lohscheidt",
|
|
53
47
|
"license": "MIT",
|
|
54
48
|
"devDependencies": {
|
|
49
|
+
"@floating-ui/dom": "^1.6.13",
|
|
50
|
+
"animejs": "^4.0.1",
|
|
55
51
|
"@types/node": "^20.0.0",
|
|
52
|
+
"@types/react": "^19.1.2",
|
|
53
|
+
"@types/react-dom": "^19.1.2",
|
|
56
54
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
57
55
|
"@typescript-eslint/parser": "^6.0.0",
|
|
58
56
|
"@vitest/coverage-v8": "^1.0.0",
|
|
59
57
|
"eslint": "^8.0.0",
|
|
58
|
+
"lit": "^3.3.0",
|
|
60
59
|
"prettier": "^3.0.0",
|
|
60
|
+
"react": "^19.1.0",
|
|
61
|
+
"react-dom": "^19.1.0",
|
|
62
|
+
"solid-js": "^1.9.5",
|
|
61
63
|
"tsup": "^7.0.0",
|
|
62
64
|
"tsup-preset-solid": "^2.2.0",
|
|
63
65
|
"typescript": "^5.0.0",
|
|
64
|
-
"vitest": "^1.0.0"
|
|
65
|
-
},
|
|
66
|
-
"publishConfig": {
|
|
67
|
-
"access": "public"
|
|
68
|
-
},
|
|
69
|
-
"dependencies": {
|
|
70
|
-
"@floating-ui/dom": "^1.6.13",
|
|
66
|
+
"vitest": "^1.0.0",
|
|
71
67
|
"@langchain/community": "^0.3.47",
|
|
72
68
|
"@langchain/core": "^0.3.61",
|
|
73
69
|
"@langchain/langgraph": "^0.3.6",
|
|
74
70
|
"@langchain/langgraph-sdk": "^0.0.84",
|
|
75
71
|
"@langchain/openai": "^0.5.16",
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
72
|
+
"ai": "^5.0.28"
|
|
73
|
+
},
|
|
74
|
+
"publishConfig": {
|
|
75
|
+
"access": "public"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
80
78
|
"effect": "^3.16.10",
|
|
81
|
-
"lit": "^3.3.0",
|
|
82
|
-
"react": "^19.1.0",
|
|
83
|
-
"react-dom": "^19.1.0",
|
|
84
79
|
"socket.io": "^4.7.2",
|
|
85
|
-
"socket.io-client": "^4.7.2"
|
|
86
|
-
"solid-js": "^1.9.5"
|
|
80
|
+
"socket.io-client": "^4.7.2"
|
|
87
81
|
},
|
|
88
82
|
"peerDependencies": {
|
|
89
|
-
"
|
|
90
|
-
"@langchain/community": ">=0.3.0",
|
|
91
|
-
"@langchain/core": ">=0.3.0",
|
|
92
|
-
"@langchain/langgraph": ">=0.3.0",
|
|
93
|
-
"@langchain/langgraph-sdk": ">=0.3.0",
|
|
94
|
-
"@langchain/openai": ">=0.3.0",
|
|
95
|
-
"animejs": ">=4.0.1",
|
|
96
|
-
"effect": ">=3.0.0",
|
|
97
|
-
"lit": ">=3.3.0",
|
|
98
|
-
"react": ">=16.8.0 <21.0.0",
|
|
99
|
-
"react-dom": ">=16.8.0 <21.0.0",
|
|
100
|
-
"solid-js": ">=1.9.5"
|
|
83
|
+
"effect": ">=3.0.0"
|
|
101
84
|
},
|
|
102
85
|
"browser": {},
|
|
103
86
|
"type": "module",
|
package/dist/helper/index.cjs
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var messages = require('@langchain/core/messages');
|
|
4
|
-
var effect = require('effect');
|
|
5
|
-
|
|
6
|
-
// src/helper/transform-messages/TransformMessages.ts
|
|
7
|
-
var humanAndAI = (message) => message instanceof messages.HumanMessage || message instanceof messages.AIMessage;
|
|
8
|
-
var humanOnly = (message) => message instanceof messages.HumanMessage;
|
|
9
|
-
var aiOnly = (message) => message instanceof messages.AIMessage;
|
|
10
|
-
var includingTags = (message, tags) => {
|
|
11
|
-
if (tags) {
|
|
12
|
-
return tags.some(
|
|
13
|
-
(tag) => Array.isArray(message.additional_kwargs?.tags) ? message.additional_kwargs?.tags.includes(tag) : false
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
return true;
|
|
17
|
-
};
|
|
18
|
-
var excludingTags = (message, tags) => {
|
|
19
|
-
if (tags) {
|
|
20
|
-
return !tags.some(
|
|
21
|
-
(tag) => Array.isArray(message.additional_kwargs?.tags) ? message.additional_kwargs?.tags.includes(tag) : false
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
return true;
|
|
25
|
-
};
|
|
26
|
-
var typeOnFilter = {
|
|
27
|
-
["HumanAndAI" /* HumanAndAI */]: humanAndAI,
|
|
28
|
-
["HumanOnly" /* HumanOnly */]: humanOnly,
|
|
29
|
-
["AIOnly" /* AIOnly */]: aiOnly,
|
|
30
|
-
["IncludingTags" /* IncludingTags */]: includingTags,
|
|
31
|
-
["ExcludingTags" /* ExcludingTags */]: excludingTags
|
|
32
|
-
};
|
|
33
|
-
function concise(messages$1) {
|
|
34
|
-
return messages$1.map((message) => {
|
|
35
|
-
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
36
|
-
return `${prefix}: ${message.content}`;
|
|
37
|
-
}).join("\n");
|
|
38
|
-
}
|
|
39
|
-
function verbose(messages$1) {
|
|
40
|
-
return messages$1.map((message) => {
|
|
41
|
-
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
42
|
-
return `${prefix}:
|
|
43
|
-
${message.content}`;
|
|
44
|
-
}).join("\n-------------------\n");
|
|
45
|
-
}
|
|
46
|
-
function redactAi(messages$1) {
|
|
47
|
-
return messages$1.map((message) => {
|
|
48
|
-
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
49
|
-
const content = message instanceof messages.AIMessage ? "[...]" : message.content;
|
|
50
|
-
return `${prefix}: ${content}`;
|
|
51
|
-
}).join("\n");
|
|
52
|
-
}
|
|
53
|
-
function redactHuman(messages$1) {
|
|
54
|
-
return messages$1.map((message) => {
|
|
55
|
-
const prefix = message instanceof messages.AIMessage ? "AI" : "Human";
|
|
56
|
-
const content = message instanceof messages.AIMessage ? "[...]" : message.content;
|
|
57
|
-
return `${prefix}: ${content}`;
|
|
58
|
-
}).join("\n");
|
|
59
|
-
}
|
|
60
|
-
var typeOnFormatter = {
|
|
61
|
-
["concise" /* Concise */]: concise,
|
|
62
|
-
["verbose" /* Verbose */]: verbose,
|
|
63
|
-
["redact-ai" /* RedactAi */]: redactAi,
|
|
64
|
-
["redact-human" /* RedactHuman */]: redactHuman
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// src/helper/transform-messages/TransformMessages.ts
|
|
68
|
-
var TransformMessages = class _TransformMessages {
|
|
69
|
-
constructor(effect) {
|
|
70
|
-
this.effect = effect;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Create a new TransformMessages from an array of messages.
|
|
74
|
-
*/
|
|
75
|
-
static from(messages) {
|
|
76
|
-
return new _TransformMessages(effect.Effect.succeed(messages));
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Filter messages based on a predicate function
|
|
80
|
-
*/
|
|
81
|
-
filter(predicate, tags) {
|
|
82
|
-
let finalPredicate;
|
|
83
|
-
if (typeof predicate === "string") {
|
|
84
|
-
finalPredicate = typeOnFilter[predicate];
|
|
85
|
-
} else {
|
|
86
|
-
finalPredicate = predicate;
|
|
87
|
-
}
|
|
88
|
-
return new _TransformMessages(
|
|
89
|
-
effect.pipe(
|
|
90
|
-
this.effect,
|
|
91
|
-
effect.Effect.map(
|
|
92
|
-
(messages) => messages.filter((message) => finalPredicate(message, tags))
|
|
93
|
-
)
|
|
94
|
-
)
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Take only the last n messages, but safely.
|
|
99
|
-
* Tool calls should not be separated from the last human message.
|
|
100
|
-
* Ensures all tool call conversations in the last n messages are complete.
|
|
101
|
-
*/
|
|
102
|
-
safelyTakeLast(n, pruneAfterNOvershootingMessages = 0) {
|
|
103
|
-
return new _TransformMessages(
|
|
104
|
-
effect.pipe(
|
|
105
|
-
this.effect,
|
|
106
|
-
effect.Effect.map((messages$1) => {
|
|
107
|
-
const total = messages$1.length;
|
|
108
|
-
if (n <= 0 || total === 0)
|
|
109
|
-
return [];
|
|
110
|
-
const start = Math.max(0, total - n);
|
|
111
|
-
const end = total;
|
|
112
|
-
const lastSlice = messages$1.slice(start, end);
|
|
113
|
-
if (lastSlice[0] instanceof messages.ToolMessage && lastSlice[0].tool_call_id) {
|
|
114
|
-
let messagesToInclude = [];
|
|
115
|
-
const remainingMessages = messages$1.slice(0, start);
|
|
116
|
-
for (let i = remainingMessages.length - 1; i >= 0; i--) {
|
|
117
|
-
const msg = remainingMessages[i];
|
|
118
|
-
if (pruneAfterNOvershootingMessages > 0 && messagesToInclude.length - 1 >= pruneAfterNOvershootingMessages) {
|
|
119
|
-
messagesToInclude = [];
|
|
120
|
-
const filteredSlice = [];
|
|
121
|
-
let foundFirstNonToolMessage = false;
|
|
122
|
-
for (let i2 = 0; i2 < lastSlice.length; i2++) {
|
|
123
|
-
const msg2 = lastSlice[i2];
|
|
124
|
-
if (msg2 instanceof messages.ToolMessage) {
|
|
125
|
-
if (foundFirstNonToolMessage) {
|
|
126
|
-
filteredSlice.push(msg2);
|
|
127
|
-
}
|
|
128
|
-
} else {
|
|
129
|
-
foundFirstNonToolMessage = true;
|
|
130
|
-
filteredSlice.push(msg2);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return filteredSlice;
|
|
134
|
-
}
|
|
135
|
-
if (msg instanceof messages.AIMessage && Array.isArray(msg.tool_calls)) {
|
|
136
|
-
messagesToInclude.push(msg);
|
|
137
|
-
break;
|
|
138
|
-
} else if (msg instanceof messages.ToolMessage) {
|
|
139
|
-
messagesToInclude.push(msg);
|
|
140
|
-
} else {
|
|
141
|
-
throw new Error(
|
|
142
|
-
"Messages array invalid no adjacent AI message found"
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return [...messagesToInclude.reverse(), ...lastSlice];
|
|
147
|
-
} else {
|
|
148
|
-
return lastSlice;
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
)
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Take only the last n messages
|
|
156
|
-
*/
|
|
157
|
-
last(n) {
|
|
158
|
-
return new _TransformMessages(
|
|
159
|
-
effect.pipe(
|
|
160
|
-
this.effect,
|
|
161
|
-
effect.Effect.map((messages) => messages.slice(-n))
|
|
162
|
-
)
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Take only the first n messages
|
|
167
|
-
*/
|
|
168
|
-
first(n) {
|
|
169
|
-
return new _TransformMessages(
|
|
170
|
-
effect.pipe(
|
|
171
|
-
this.effect,
|
|
172
|
-
effect.Effect.map((messages) => messages.slice(0, n))
|
|
173
|
-
)
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Skip the first n messages
|
|
178
|
-
*/
|
|
179
|
-
skip(n) {
|
|
180
|
-
return new _TransformMessages(
|
|
181
|
-
effect.pipe(
|
|
182
|
-
this.effect,
|
|
183
|
-
effect.Effect.map((messages) => messages.slice(n))
|
|
184
|
-
)
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Reverse the order of messages
|
|
189
|
-
*/
|
|
190
|
-
reverse() {
|
|
191
|
-
return new _TransformMessages(
|
|
192
|
-
effect.pipe(
|
|
193
|
-
this.effect,
|
|
194
|
-
effect.Effect.map((messages) => [...messages].reverse())
|
|
195
|
-
)
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Map over messages with a transformation function
|
|
200
|
-
*/
|
|
201
|
-
map(fn) {
|
|
202
|
-
return new _TransformMessages(
|
|
203
|
-
effect.pipe(
|
|
204
|
-
this.effect,
|
|
205
|
-
effect.Effect.map((messages) => messages.map(fn))
|
|
206
|
-
)
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Format messages according to the specified format type
|
|
211
|
-
*/
|
|
212
|
-
format(formatType) {
|
|
213
|
-
const result = effect.Effect.runSync(
|
|
214
|
-
effect.pipe(
|
|
215
|
-
this.effect,
|
|
216
|
-
effect.Effect.map((messages) => {
|
|
217
|
-
if (formatType === "json" /* JSON */) {
|
|
218
|
-
return JSON.stringify(messages, null, 2);
|
|
219
|
-
}
|
|
220
|
-
const formatter = typeOnFormatter[formatType];
|
|
221
|
-
return formatter(messages);
|
|
222
|
-
})
|
|
223
|
-
)
|
|
224
|
-
);
|
|
225
|
-
return result;
|
|
226
|
-
}
|
|
227
|
-
// Sink methods
|
|
228
|
-
/**
|
|
229
|
-
* Convert to array - runs the effect and returns the result
|
|
230
|
-
return pipe(
|
|
231
|
-
this.effect,
|
|
232
|
-
Effect.map((messages) => {
|
|
233
|
-
if (formatType === FormatType.JSON) {
|
|
234
|
-
return JSON.stringify(messages, null, 2);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const formatter = typeOnFormatter[formatType];
|
|
238
|
-
return formatter(messages);
|
|
239
|
-
})
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Sink methods
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Convert to array - runs the effect and returns the result
|
|
247
|
-
*/
|
|
248
|
-
toArray() {
|
|
249
|
-
return effect.Effect.runSync(this.effect);
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Convert to string - runs the effect and returns JSON string
|
|
253
|
-
*/
|
|
254
|
-
toString() {
|
|
255
|
-
const result = effect.Effect.runSync(
|
|
256
|
-
effect.pipe(
|
|
257
|
-
this.effect,
|
|
258
|
-
effect.Effect.map((messages) => JSON.stringify(messages, null, 2))
|
|
259
|
-
)
|
|
260
|
-
);
|
|
261
|
-
return result;
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Get the count of messages
|
|
265
|
-
*/
|
|
266
|
-
count() {
|
|
267
|
-
const result = effect.Effect.runSync(
|
|
268
|
-
effect.pipe(
|
|
269
|
-
this.effect,
|
|
270
|
-
effect.Effect.map((messages) => messages.length)
|
|
271
|
-
)
|
|
272
|
-
);
|
|
273
|
-
return result;
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
exports.TransformMessages = TransformMessages;
|
|
278
|
-
//# sourceMappingURL=out.js.map
|
|
279
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/helper/transform-messages/TransformMessages.ts","../../src/helper/transform-messages/message-filter.ts","../../src/helper/transform-messages/formatter.ts"],"names":["AIMessage","i","msg"],"mappings":"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","sourcesContent":["import { BaseMessage, AIMessage, ToolMessage } from '@langchain/core/messages';\nimport { Effect, pipe } from 'effect';\nimport {\n MessageFilter,\n MessageFilterType,\n typeOnFilter,\n} from './message-filter';\nimport { FormatType, typeOnFormatter } from './formatter';\n\n/**\n * # Transform Messages\n * In order to manage the context size often you want to slice messages or only pass certain types of messages.\n * This class is a helper to do that.\n *\n * ## Example\n * ```ts\n * const messages = [\n * new HumanMessage('Hello, how are you?'),\n * new AIMessage('I am good, thank you!'),\n * ];\n *\n * const transformedMessages = TransformMessages.from(messages).filter(HumanAndAI).last(10).format(FormatType.Concise);\n *\n * ```\n */\n\nclass TransformMessages {\n private effect: Effect.Effect<Array<BaseMessage>, never, never>;\n\n private constructor(effect: Effect.Effect<Array<BaseMessage>, never, never>) {\n this.effect = effect;\n }\n\n /**\n * Create a new TransformMessages from an array of messages.\n */\n static from(messages: Array<BaseMessage>): TransformMessages {\n return new TransformMessages(Effect.succeed(messages));\n }\n\n /**\n * Filter messages based on a predicate function\n */\n filter(\n predicate: MessageFilter | MessageFilterType,\n tags?: Array<string>\n ): TransformMessages {\n let finalPredicate: MessageFilter;\n if (typeof predicate === 'string') {\n finalPredicate = typeOnFilter[predicate];\n } else {\n finalPredicate = predicate;\n }\n\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) =>\n messages.filter((message) => finalPredicate(message, tags))\n )\n )\n );\n }\n\n /**\n * Take only the last n messages, but safely.\n * Tool calls should not be separated from the last human message.\n * Ensures all tool call conversations in the last n messages are complete.\n */\n safelyTakeLast(\n n: number,\n pruneAfterNOvershootingMessages: number = 0\n ): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => {\n const total = messages.length;\n if (n <= 0 || total === 0) return [];\n\n // Start with the last n messages\n const start = Math.max(0, total - n);\n const end = total;\n const lastSlice = messages.slice(start, end);\n\n // due to the fact that the calling AI message needs to be adjecent to the succeeding tool call message\n // we just need to check the last n messages for tool call ids\n\n // Check the first message if it is a tool call message\n // if it is iterate backwards until we find the AI message\n if (\n lastSlice[0] instanceof ToolMessage &&\n lastSlice[0].tool_call_id\n ) {\n let messagesToInclude: Array<BaseMessage> = [];\n const remainingMessages = messages.slice(0, start);\n for (let i = remainingMessages.length - 1; i >= 0; i--) {\n const msg = remainingMessages[i];\n if (\n pruneAfterNOvershootingMessages > 0 &&\n messagesToInclude.length - 1 >= pruneAfterNOvershootingMessages\n ) {\n messagesToInclude = [];\n // Return the slice but remove all the tool call messages that are at the beginning of the slice\n const filteredSlice: Array<BaseMessage> = [];\n let foundFirstNonToolMessage = false;\n for (let i = 0; i < lastSlice.length; i++) {\n const msg = lastSlice[i];\n if (msg instanceof ToolMessage) {\n if (foundFirstNonToolMessage) {\n filteredSlice.push(msg);\n }\n } else {\n foundFirstNonToolMessage = true;\n filteredSlice.push(msg);\n }\n }\n return filteredSlice;\n }\n if (msg instanceof AIMessage && Array.isArray(msg.tool_calls)) {\n messagesToInclude.push(msg);\n break;\n } else if (msg instanceof ToolMessage) {\n messagesToInclude.push(msg);\n } else {\n // This should not happen messages invalid\n throw new Error(\n 'Messages array invalid no adjacent AI message found'\n );\n }\n }\n return [...messagesToInclude.reverse(), ...lastSlice];\n } else {\n return lastSlice;\n }\n })\n )\n );\n }\n\n /**\n * Take only the last n messages\n */\n last(n: number): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => messages.slice(-n))\n )\n );\n }\n\n /**\n * Take only the first n messages\n */\n first(n: number): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => messages.slice(0, n))\n )\n );\n }\n\n /**\n * Skip the first n messages\n */\n skip(n: number): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => messages.slice(n))\n )\n );\n }\n\n /**\n * Reverse the order of messages\n */\n reverse(): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => [...messages].reverse())\n )\n );\n }\n\n /**\n * Map over messages with a transformation function\n */\n map<T extends BaseMessage>(\n fn: (message: BaseMessage) => T\n ): TransformMessages {\n return new TransformMessages(\n pipe(\n this.effect,\n Effect.map((messages) => messages.map(fn))\n )\n );\n }\n\n /**\n * Format messages according to the specified format type\n */\n format(formatType: FormatType): string {\n const result = Effect.runSync(\n pipe(\n this.effect,\n Effect.map((messages) => {\n if (formatType === FormatType.JSON) {\n return JSON.stringify(messages, null, 2);\n }\n const formatter = typeOnFormatter[formatType];\n return formatter(messages);\n })\n )\n );\n return result;\n }\n\n // Sink methods\n\n /**\n * Convert to array - runs the effect and returns the result\n return pipe(\n this.effect,\n Effect.map((messages) => {\n if (formatType === FormatType.JSON) {\n return JSON.stringify(messages, null, 2);\n }\n\n const formatter = typeOnFormatter[formatType];\n return formatter(messages);\n })\n );\n }\n\n // Sink methods\n\n /**\n * Convert to array - runs the effect and returns the result\n */\n toArray(): Array<BaseMessage> {\n return Effect.runSync(this.effect);\n }\n\n /**\n * Convert to string - runs the effect and returns JSON string\n */\n toString(): string {\n const result = Effect.runSync(\n pipe(\n this.effect,\n Effect.map((messages) => JSON.stringify(messages, null, 2))\n )\n );\n return result;\n }\n\n /**\n * Get the count of messages\n */\n count(): number {\n const result = Effect.runSync(\n pipe(\n this.effect,\n Effect.map((messages) => messages.length)\n )\n );\n return result;\n }\n}\n\nexport { TransformMessages };\n","import { BaseMessage, HumanMessage, AIMessage } from '@langchain/core/messages';\n\n// Type for message filters\nexport type MessageFilter = (\n message: BaseMessage,\n tags?: Array<string>\n) => boolean;\n// Predefined filters\nconst humanAndAI: MessageFilter = (message) =>\n message instanceof HumanMessage || message instanceof AIMessage;\nconst humanOnly: MessageFilter = (message) => message instanceof HumanMessage;\nconst aiOnly: MessageFilter = (message) => message instanceof AIMessage;\n\nconst includingTags: MessageFilter = (message, tags) => {\n if (tags) {\n return tags.some((tag) =>\n Array.isArray(message.additional_kwargs?.tags)\n ? message.additional_kwargs?.tags.includes(tag)\n : false\n );\n }\n return true;\n};\n\nconst excludingTags: MessageFilter = (message, tags) => {\n if (tags) {\n return !tags.some((tag) =>\n Array.isArray(message.additional_kwargs?.tags)\n ? message.additional_kwargs?.tags.includes(tag)\n : false\n );\n }\n return true;\n};\n\nexport enum MessageFilterType {\n HumanAndAI = 'HumanAndAI',\n HumanOnly = 'HumanOnly',\n AIOnly = 'AIOnly',\n IncludingTags = 'IncludingTags',\n ExcludingTags = 'ExcludingTags',\n}\nexport const typeOnFilter = {\n [MessageFilterType.HumanAndAI]: humanAndAI,\n [MessageFilterType.HumanOnly]: humanOnly,\n [MessageFilterType.AIOnly]: aiOnly,\n [MessageFilterType.IncludingTags]: includingTags,\n [MessageFilterType.ExcludingTags]: excludingTags,\n};\n","import { AIMessage, BaseMessage } from '@langchain/core/messages';\n\n// Format types\nexport enum FormatType {\n Concise = 'concise',\n Verbose = 'verbose',\n RedactAi = 'redact-ai',\n RedactHuman = 'redact-human',\n JSON = 'json',\n}\n\n/**\n * Formats messages in a concise markdown format with alternating AI and Human prefixes.\n *\n * ### Example\n * ```markdown\n * AI: Hello, how are you?\n * Human: I am good, thank you!\n * AI: What is your name?\n * Human: My name is John.\n * AI: What is your favorite color?\n * Human: My favorite color is blue.\n * AI: What is your favorite food?\n * Human: My favorite food is pizza.\n * ```\n */\nfunction concise(messages: Array<BaseMessage>): string {\n return messages\n .map((message) => {\n const prefix = message instanceof AIMessage ? 'AI' : 'Human';\n return `${prefix}: ${message.content}`;\n })\n .join('\\n');\n}\n\n/**\n * Formats messages in a verbose markdown format with alternating AI and Human prefixes.\n *\n * ### Example\n * ```markdown\n * AI:\n * Hello, how are you?\n * -------------------\n * Human:\n * I am good, thank you!\n * -------------------\n * AI:\n * What is your name?\n * -------------------\n * Human:\n * My name is John.\n * ```\n */\nfunction verbose(messages: Array<BaseMessage>): string {\n return messages\n .map((message) => {\n const prefix = message instanceof AIMessage ? 'AI' : 'Human';\n return `${prefix}:\\n${message.content}`;\n })\n .join('\\n-------------------\\n');\n}\n\n/**\n * Formats messages in a concise markdown format, redacting AI messages with [...]\n *\n * ### Example\n * ```markdown\n * AI: [...]\n * Human: Hello, how are you?\n * AI: [...]\n * Human: I am good, thank you!\n * AI: [...]\n * Human: What is your name?\n * AI: [...]\n * Human: My name is John.\n * AI: [...]\n * ```\n */\nfunction redactAi(messages: Array<BaseMessage>): string {\n return messages\n .map((message) => {\n const prefix = message instanceof AIMessage ? 'AI' : 'Human';\n const content = message instanceof AIMessage ? '[...]' : message.content;\n return `${prefix}: ${content}`;\n })\n .join('\\n');\n}\n\n/**\n * Formats messages in a concise markdown format, redacting Human messages with [...]\n *\n * ### Example\n * ```markdown\n * AI: Hello, how are you?\n * Human: [...]\n * AI: What is your name?\n * Human: [...]\n * AI: What is your favorite color?\n * Human: [...]\n * AI: What is your favorite food?\n * Human: [...]\n * ```\n */\nfunction redactHuman(messages: Array<BaseMessage>): string {\n return messages\n .map((message) => {\n const prefix = message instanceof AIMessage ? 'AI' : 'Human';\n const content = message instanceof AIMessage ? '[...]' : message.content;\n return `${prefix}: ${content}`;\n })\n .join('\\n');\n}\nconst typeOnFormatter = {\n [FormatType.Concise]: concise,\n [FormatType.Verbose]: verbose,\n [FormatType.RedactAi]: redactAi,\n [FormatType.RedactHuman]: redactHuman,\n};\n\nexport { typeOnFormatter };\n"]}
|
package/dist/helper/index.d.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { BaseMessage } from '@langchain/core/messages';
|
|
2
|
-
|
|
3
|
-
declare enum FormatType {
|
|
4
|
-
Concise = "concise",
|
|
5
|
-
Verbose = "verbose",
|
|
6
|
-
RedactAi = "redact-ai",
|
|
7
|
-
RedactHuman = "redact-human",
|
|
8
|
-
JSON = "json"
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type MessageFilter = (message: BaseMessage, tags?: Array<string>) => boolean;
|
|
12
|
-
declare enum MessageFilterType {
|
|
13
|
-
HumanAndAI = "HumanAndAI",
|
|
14
|
-
HumanOnly = "HumanOnly",
|
|
15
|
-
AIOnly = "AIOnly",
|
|
16
|
-
IncludingTags = "IncludingTags",
|
|
17
|
-
ExcludingTags = "ExcludingTags"
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* # Transform Messages
|
|
22
|
-
* In order to manage the context size often you want to slice messages or only pass certain types of messages.
|
|
23
|
-
* This class is a helper to do that.
|
|
24
|
-
*
|
|
25
|
-
* ## Example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const messages = [
|
|
28
|
-
* new HumanMessage('Hello, how are you?'),
|
|
29
|
-
* new AIMessage('I am good, thank you!'),
|
|
30
|
-
* ];
|
|
31
|
-
*
|
|
32
|
-
* const transformedMessages = TransformMessages.from(messages).filter(HumanAndAI).last(10).format(FormatType.Concise);
|
|
33
|
-
*
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
declare class TransformMessages {
|
|
37
|
-
private effect;
|
|
38
|
-
private constructor();
|
|
39
|
-
/**
|
|
40
|
-
* Create a new TransformMessages from an array of messages.
|
|
41
|
-
*/
|
|
42
|
-
static from(messages: Array<BaseMessage>): TransformMessages;
|
|
43
|
-
/**
|
|
44
|
-
* Filter messages based on a predicate function
|
|
45
|
-
*/
|
|
46
|
-
filter(predicate: MessageFilter | MessageFilterType, tags?: Array<string>): TransformMessages;
|
|
47
|
-
/**
|
|
48
|
-
* Take only the last n messages, but safely.
|
|
49
|
-
* Tool calls should not be separated from the last human message.
|
|
50
|
-
* Ensures all tool call conversations in the last n messages are complete.
|
|
51
|
-
*/
|
|
52
|
-
safelyTakeLast(n: number, pruneAfterNOvershootingMessages?: number): TransformMessages;
|
|
53
|
-
/**
|
|
54
|
-
* Take only the last n messages
|
|
55
|
-
*/
|
|
56
|
-
last(n: number): TransformMessages;
|
|
57
|
-
/**
|
|
58
|
-
* Take only the first n messages
|
|
59
|
-
*/
|
|
60
|
-
first(n: number): TransformMessages;
|
|
61
|
-
/**
|
|
62
|
-
* Skip the first n messages
|
|
63
|
-
*/
|
|
64
|
-
skip(n: number): TransformMessages;
|
|
65
|
-
/**
|
|
66
|
-
* Reverse the order of messages
|
|
67
|
-
*/
|
|
68
|
-
reverse(): TransformMessages;
|
|
69
|
-
/**
|
|
70
|
-
* Map over messages with a transformation function
|
|
71
|
-
*/
|
|
72
|
-
map<T extends BaseMessage>(fn: (message: BaseMessage) => T): TransformMessages;
|
|
73
|
-
/**
|
|
74
|
-
* Format messages according to the specified format type
|
|
75
|
-
*/
|
|
76
|
-
format(formatType: FormatType): string;
|
|
77
|
-
/**
|
|
78
|
-
* Convert to array - runs the effect and returns the result
|
|
79
|
-
return pipe(
|
|
80
|
-
this.effect,
|
|
81
|
-
Effect.map((messages) => {
|
|
82
|
-
if (formatType === FormatType.JSON) {
|
|
83
|
-
return JSON.stringify(messages, null, 2);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const formatter = typeOnFormatter[formatType];
|
|
87
|
-
return formatter(messages);
|
|
88
|
-
})
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Sink methods
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Convert to array - runs the effect and returns the result
|
|
96
|
-
*/
|
|
97
|
-
toArray(): Array<BaseMessage>;
|
|
98
|
-
/**
|
|
99
|
-
* Convert to string - runs the effect and returns JSON string
|
|
100
|
-
*/
|
|
101
|
-
toString(): string;
|
|
102
|
-
/**
|
|
103
|
-
* Get the count of messages
|
|
104
|
-
*/
|
|
105
|
-
count(): number;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export { FormatType, MessageFilterType, TransformMessages };
|