@exulu/backend 1.51.1 → 1.53.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/dist/index.cjs +301 -29
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +304 -32
- package/ee/chunking/markdown.ts +1 -0
- package/ee/python/documents/processing/doc_processor.ts +3 -2
- package/ee/workers.ts +27 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -4044,6 +4044,7 @@ var ExuluContext2 = class {
|
|
|
4044
4044
|
exuluConfig
|
|
4045
4045
|
});
|
|
4046
4046
|
if (!result) {
|
|
4047
|
+
console.log("[EXULU] Item filtered out by processor, skipping processing execution...");
|
|
4047
4048
|
return {
|
|
4048
4049
|
result: void 0,
|
|
4049
4050
|
job: void 0
|
|
@@ -4244,10 +4245,12 @@ var ExuluContext2 = class {
|
|
|
4244
4245
|
}
|
|
4245
4246
|
}
|
|
4246
4247
|
});
|
|
4248
|
+
console.log("[EXULU] Creating item", item);
|
|
4247
4249
|
const mutation = db2.from(getTableName(this.id)).insert({
|
|
4248
4250
|
...item,
|
|
4249
4251
|
tags: item.tags ? Array.isArray(item.tags) ? item.tags.join(",") : item.tags : void 0
|
|
4250
4252
|
}).returning("id");
|
|
4253
|
+
console.log("[EXULU] Upsert", upsert);
|
|
4251
4254
|
if (upsert) {
|
|
4252
4255
|
if (item.external_id) {
|
|
4253
4256
|
mutation.onConflict("external_id").merge();
|
|
@@ -4266,7 +4269,6 @@ var ExuluContext2 = class {
|
|
|
4266
4269
|
let shouldGenerateEmbeddings = this.embedder && generateEmbeddingsOverwrite !== false && (generateEmbeddingsOverwrite || this.configuration.calculateVectors === "onInsert" || this.configuration.calculateVectors === "always");
|
|
4267
4270
|
if (this.processor) {
|
|
4268
4271
|
const processor = this.processor;
|
|
4269
|
-
console.log("[EXULU] Processor found", processor);
|
|
4270
4272
|
if (processor && (processor?.config?.trigger === "onInsert" || processor?.config?.trigger === "onUpdate" || processor?.config?.trigger === "always")) {
|
|
4271
4273
|
const { job: processorJob, result: processorResult } = await this.processField(
|
|
4272
4274
|
"api",
|
|
@@ -4281,7 +4283,7 @@ var ExuluContext2 = class {
|
|
|
4281
4283
|
if (processorJob) {
|
|
4282
4284
|
jobs.push(processorJob);
|
|
4283
4285
|
}
|
|
4284
|
-
if (!processorJob) {
|
|
4286
|
+
if (!processorJob && processorResult) {
|
|
4285
4287
|
await db2.from(getTableName(this.id)).where({ id: results[0].id }).update({
|
|
4286
4288
|
...processorResult
|
|
4287
4289
|
});
|
|
@@ -4352,7 +4354,7 @@ var ExuluContext2 = class {
|
|
|
4352
4354
|
if (processorJob) {
|
|
4353
4355
|
jobs.push(processorJob);
|
|
4354
4356
|
}
|
|
4355
|
-
if (!processorJob) {
|
|
4357
|
+
if (!processorJob && processorResult) {
|
|
4356
4358
|
await db2.from(getTableName(this.id)).where({ id: record.id }).update({
|
|
4357
4359
|
...processorResult
|
|
4358
4360
|
});
|
|
@@ -7420,7 +7422,32 @@ var createWorkers = async (providers, queues2, config, contexts, rerankers, eval
|
|
|
7420
7422
|
);
|
|
7421
7423
|
}
|
|
7422
7424
|
const exuluStorage = new ExuluStorage({ config });
|
|
7423
|
-
|
|
7425
|
+
if (context.processor.filter) {
|
|
7426
|
+
const result2 = await context.processor.filter({
|
|
7427
|
+
item: data.inputs,
|
|
7428
|
+
user: data.user,
|
|
7429
|
+
role: data.role,
|
|
7430
|
+
utils: {
|
|
7431
|
+
storage: exuluStorage
|
|
7432
|
+
},
|
|
7433
|
+
exuluConfig: config
|
|
7434
|
+
});
|
|
7435
|
+
if (!result2) {
|
|
7436
|
+
console.log("[EXULU] Item filtered out by processor, skipping processing execution...");
|
|
7437
|
+
return {
|
|
7438
|
+
result: "Item filtered out by processor, skipping processing execution...",
|
|
7439
|
+
// last message
|
|
7440
|
+
metadata: {
|
|
7441
|
+
item: {
|
|
7442
|
+
name: data.inputs?.name,
|
|
7443
|
+
id: data.inputs?.id,
|
|
7444
|
+
external_id: data.inputs?.external_id
|
|
7445
|
+
}
|
|
7446
|
+
}
|
|
7447
|
+
};
|
|
7448
|
+
}
|
|
7449
|
+
}
|
|
7450
|
+
console.log("[EXULU] POS 2 -- EXULU CONTEXT PROCESS FIELD", data.inputs);
|
|
7424
7451
|
let processorResult = await context.processor.execute({
|
|
7425
7452
|
item: data.inputs,
|
|
7426
7453
|
user: data.user,
|
|
@@ -10863,7 +10890,6 @@ var providerRateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
10863
10890
|
|
|
10864
10891
|
// src/exulu/routes.ts
|
|
10865
10892
|
var import_zod_from_json_schema = require("zod-from-json-schema");
|
|
10866
|
-
var import_zod8 = require("zod");
|
|
10867
10893
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
10868
10894
|
var getExuluVersionNumber = async () => {
|
|
10869
10895
|
try {
|
|
@@ -11331,12 +11357,16 @@ Mood: friendly and intelligent.
|
|
|
11331
11357
|
message = req.body.message;
|
|
11332
11358
|
}
|
|
11333
11359
|
const approvedTools = req.body.approvedTools ? typeof req.body.approvedTools === "string" ? JSON.parse(req.body.approvedTools) : req.body.approvedTools : [];
|
|
11360
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11361
|
+
const instructions = customInstructions ? `${agent.instructions}
|
|
11362
|
+
|
|
11363
|
+
${customInstructions}` : agent.instructions;
|
|
11334
11364
|
const result = await provider.generateStream({
|
|
11335
11365
|
contexts,
|
|
11336
11366
|
rerankers: rerankers || [],
|
|
11337
11367
|
agent,
|
|
11338
11368
|
user,
|
|
11339
|
-
instructions
|
|
11369
|
+
instructions,
|
|
11340
11370
|
session: headers.session,
|
|
11341
11371
|
message,
|
|
11342
11372
|
previousMessages,
|
|
@@ -11437,6 +11467,10 @@ Mood: friendly and intelligent.
|
|
|
11437
11467
|
});
|
|
11438
11468
|
return;
|
|
11439
11469
|
} else {
|
|
11470
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11471
|
+
const instructions = customInstructions ? `${agent.instructions}
|
|
11472
|
+
|
|
11473
|
+
${customInstructions}` : agent.instructions;
|
|
11440
11474
|
const response = await provider.generateSync({
|
|
11441
11475
|
contexts,
|
|
11442
11476
|
rerankers: rerankers || [],
|
|
@@ -11444,7 +11478,7 @@ Mood: friendly and intelligent.
|
|
|
11444
11478
|
agent,
|
|
11445
11479
|
user,
|
|
11446
11480
|
req,
|
|
11447
|
-
instructions
|
|
11481
|
+
instructions,
|
|
11448
11482
|
session: headers.session,
|
|
11449
11483
|
inputMessages: [req.body.message],
|
|
11450
11484
|
currentTools: enabledTools,
|
|
@@ -11589,6 +11623,10 @@ Mood: friendly and intelligent.
|
|
|
11589
11623
|
providers,
|
|
11590
11624
|
user
|
|
11591
11625
|
);
|
|
11626
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11627
|
+
const agentInstructions = customInstructions ? `${agent?.instructions}
|
|
11628
|
+
|
|
11629
|
+
${customInstructions}` : agent?.instructions;
|
|
11592
11630
|
let system = req.body.system;
|
|
11593
11631
|
if (Array.isArray(req.body.system)) {
|
|
11594
11632
|
system = [
|
|
@@ -11598,7 +11636,7 @@ Mood: friendly and intelligent.
|
|
|
11598
11636
|
type: "text",
|
|
11599
11637
|
text: `
|
|
11600
11638
|
You are an agent named: ${agent?.name}
|
|
11601
|
-
Here are some additional instructions for you: ${
|
|
11639
|
+
Here are some additional instructions for you: ${agentInstructions}`
|
|
11602
11640
|
}
|
|
11603
11641
|
] : [],
|
|
11604
11642
|
...project ? [
|
|
@@ -11616,7 +11654,7 @@ Mood: friendly and intelligent.
|
|
|
11616
11654
|
|
|
11617
11655
|
|
|
11618
11656
|
${agent ? `You are an agent named: ${agent?.name}
|
|
11619
|
-
Here are some additional instructions for you: ${
|
|
11657
|
+
Here are some additional instructions for you: ${agentInstructions}` : ""}
|
|
11620
11658
|
|
|
11621
11659
|
${project?.id ? `Additional information:
|
|
11622
11660
|
|
|
@@ -11766,7 +11804,7 @@ var import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
11766
11804
|
var import_express4 = require("express");
|
|
11767
11805
|
var import_api3 = require("@opentelemetry/api");
|
|
11768
11806
|
var import_crypto_js7 = __toESM(require("crypto-js"), 1);
|
|
11769
|
-
var
|
|
11807
|
+
var import_zod8 = require("zod");
|
|
11770
11808
|
var SESSION_ID_HEADER = "mcp-session-id";
|
|
11771
11809
|
var ExuluMCP = class {
|
|
11772
11810
|
server = {};
|
|
@@ -11849,7 +11887,7 @@ var ExuluMCP = class {
|
|
|
11849
11887
|
title: tool3.name + " agent",
|
|
11850
11888
|
description: tool3.description,
|
|
11851
11889
|
inputSchema: {
|
|
11852
|
-
inputs: tool3.inputSchema ||
|
|
11890
|
+
inputs: tool3.inputSchema || import_zod8.z.object({})
|
|
11853
11891
|
}
|
|
11854
11892
|
},
|
|
11855
11893
|
async ({ inputs }, args) => {
|
|
@@ -11901,7 +11939,7 @@ var ExuluMCP = class {
|
|
|
11901
11939
|
title: "Get List of Prompt Templates",
|
|
11902
11940
|
description: "Retrieves a list of prompt templates available for this agent. Returns the name, description, and ID of each template.",
|
|
11903
11941
|
inputSchema: {
|
|
11904
|
-
inputs:
|
|
11942
|
+
inputs: import_zod8.z.object({})
|
|
11905
11943
|
}
|
|
11906
11944
|
},
|
|
11907
11945
|
async ({ inputs }, args) => {
|
|
@@ -11947,8 +11985,8 @@ var ExuluMCP = class {
|
|
|
11947
11985
|
title: "Get Prompt Template Details",
|
|
11948
11986
|
description: "Retrieves the full details of a specific prompt template by ID, including the actual template content with variables.",
|
|
11949
11987
|
inputSchema: {
|
|
11950
|
-
inputs:
|
|
11951
|
-
id:
|
|
11988
|
+
inputs: import_zod8.z.object({
|
|
11989
|
+
id: import_zod8.z.string().describe("The ID of the prompt template to retrieve")
|
|
11952
11990
|
})
|
|
11953
11991
|
}
|
|
11954
11992
|
},
|
|
@@ -12856,7 +12894,7 @@ var ExuluEval = class {
|
|
|
12856
12894
|
};
|
|
12857
12895
|
|
|
12858
12896
|
// src/templates/evals/index.ts
|
|
12859
|
-
var
|
|
12897
|
+
var import_zod9 = require("zod");
|
|
12860
12898
|
var llmAsJudgeEval = () => {
|
|
12861
12899
|
if (process.env.REDIS_HOST?.length && process.env.REDIS_PORT?.length) {
|
|
12862
12900
|
return new ExuluEval({
|
|
@@ -12901,8 +12939,8 @@ var llmAsJudgeEval = () => {
|
|
|
12901
12939
|
contexts: [],
|
|
12902
12940
|
rerankers: [],
|
|
12903
12941
|
prompt,
|
|
12904
|
-
outputSchema:
|
|
12905
|
-
score:
|
|
12942
|
+
outputSchema: import_zod9.z.object({
|
|
12943
|
+
score: import_zod9.z.number().min(0).max(100).describe("The score between 0 and 100.")
|
|
12906
12944
|
}),
|
|
12907
12945
|
providerapikey
|
|
12908
12946
|
});
|
|
@@ -13130,12 +13168,12 @@ Usage:
|
|
|
13130
13168
|
- If no todos exist yet, an empty list will be returned`;
|
|
13131
13169
|
|
|
13132
13170
|
// src/templates/tools/todo/todo.ts
|
|
13133
|
-
var
|
|
13134
|
-
var TodoSchema =
|
|
13135
|
-
content:
|
|
13136
|
-
status:
|
|
13137
|
-
priority:
|
|
13138
|
-
id:
|
|
13171
|
+
var import_zod10 = __toESM(require("zod"), 1);
|
|
13172
|
+
var TodoSchema = import_zod10.default.object({
|
|
13173
|
+
content: import_zod10.default.string().describe("Brief description of the task"),
|
|
13174
|
+
status: import_zod10.default.string().describe("Current status of the task: pending, in_progress, completed, cancelled"),
|
|
13175
|
+
priority: import_zod10.default.string().describe("Priority level of the task: high, medium, low"),
|
|
13176
|
+
id: import_zod10.default.string().describe("Unique identifier for the todo item")
|
|
13139
13177
|
});
|
|
13140
13178
|
var TodoWriteTool = new ExuluTool({
|
|
13141
13179
|
id: "todo_write",
|
|
@@ -13151,8 +13189,8 @@ var TodoWriteTool = new ExuluTool({
|
|
|
13151
13189
|
default: todowrite_default
|
|
13152
13190
|
}
|
|
13153
13191
|
],
|
|
13154
|
-
inputSchema:
|
|
13155
|
-
todos:
|
|
13192
|
+
inputSchema: import_zod10.default.object({
|
|
13193
|
+
todos: import_zod10.default.array(TodoSchema).describe("The updated todo list")
|
|
13156
13194
|
}),
|
|
13157
13195
|
execute: async (inputs) => {
|
|
13158
13196
|
const { sessionID, todos, user } = inputs;
|
|
@@ -13187,7 +13225,7 @@ var TodoReadTool = new ExuluTool({
|
|
|
13187
13225
|
id: "todo_read",
|
|
13188
13226
|
name: "Todo Read",
|
|
13189
13227
|
description: "Use this tool to read your todo list",
|
|
13190
|
-
inputSchema:
|
|
13228
|
+
inputSchema: import_zod10.default.object({}),
|
|
13191
13229
|
type: "function",
|
|
13192
13230
|
category: "todo",
|
|
13193
13231
|
config: [
|
|
@@ -13225,6 +13263,222 @@ async function getTodos(sessionID) {
|
|
|
13225
13263
|
}
|
|
13226
13264
|
var todoTools = [TodoWriteTool, TodoReadTool];
|
|
13227
13265
|
|
|
13266
|
+
// src/templates/tools/question/questionask.txt
|
|
13267
|
+
var questionask_default = `Use this tool to ask the user a question with multiple choice answer options during your session. This helps you gather user input, clarify requirements, and make informed decisions based on user preferences.
|
|
13268
|
+
|
|
13269
|
+
## When to Use This Tool
|
|
13270
|
+
|
|
13271
|
+
Use this tool when you need to:
|
|
13272
|
+
|
|
13273
|
+
1. Get user input on implementation choices - When there are multiple valid approaches and you need the user to decide
|
|
13274
|
+
2. Clarify ambiguous requirements - When the user's request could be interpreted in different ways
|
|
13275
|
+
3. Gather preferences - When you need to know the user's preference for styling, naming, architecture, etc.
|
|
13276
|
+
4. Validate assumptions - When you want to confirm your understanding before proceeding
|
|
13277
|
+
5. Offer options - When presenting multiple solutions and letting the user choose
|
|
13278
|
+
|
|
13279
|
+
## When NOT to Use This Tool
|
|
13280
|
+
|
|
13281
|
+
Skip using this tool when:
|
|
13282
|
+
1. The answer is clear from context or previous messages
|
|
13283
|
+
2. You're asking a yes/no question (use a simpler approach)
|
|
13284
|
+
3. The question requires a free-form text answer (this tool is for multiple choice only)
|
|
13285
|
+
4. You're asking for information that should be obvious from the codebase
|
|
13286
|
+
|
|
13287
|
+
## How It Works
|
|
13288
|
+
|
|
13289
|
+
- Provide a question and an array of answer option strings
|
|
13290
|
+
- The tool automatically adds "None of the above..." as a final option
|
|
13291
|
+
- Each answer option is assigned a unique ID
|
|
13292
|
+
- The question is stored with a "pending" status until the user answers
|
|
13293
|
+
- Use the Question Read tool to check if the question has been answered
|
|
13294
|
+
|
|
13295
|
+
## Examples
|
|
13296
|
+
|
|
13297
|
+
<example>
|
|
13298
|
+
User: Add authentication to my app
|
|
13299
|
+
Assistant: I need to ask the user which authentication method they prefer.
|
|
13300
|
+
*Uses Question Ask tool with:*
|
|
13301
|
+
question: "Which authentication method would you like to implement?"
|
|
13302
|
+
answerOptions: ["JWT tokens", "OAuth 2.0", "Session-based auth", "Firebase Auth"]
|
|
13303
|
+
|
|
13304
|
+
<reasoning>
|
|
13305
|
+
The assistant used the question tool because there are multiple valid authentication approaches and the user's preference will significantly impact the implementation.
|
|
13306
|
+
</reasoning>
|
|
13307
|
+
</example>
|
|
13308
|
+
|
|
13309
|
+
<example>
|
|
13310
|
+
User: Style this button
|
|
13311
|
+
Assistant: I need to know the user's styling preference.
|
|
13312
|
+
*Uses Question Ask tool with:*
|
|
13313
|
+
question: "What styling approach should I use for the button?"
|
|
13314
|
+
answerOptions: ["Tailwind CSS", "CSS Modules", "Styled Components", "Plain CSS"]
|
|
13315
|
+
|
|
13316
|
+
<reasoning>
|
|
13317
|
+
The assistant used the question tool because the codebase could support multiple styling approaches and the user's preference matters for consistency.
|
|
13318
|
+
</reasoning>
|
|
13319
|
+
</example>
|
|
13320
|
+
|
|
13321
|
+
<example>
|
|
13322
|
+
User: Add error handling
|
|
13323
|
+
Assistant: I'll implement comprehensive error handling with try-catch blocks and proper error messages.
|
|
13324
|
+
*Does not use the question tool*
|
|
13325
|
+
|
|
13326
|
+
<reasoning>
|
|
13327
|
+
The assistant did not use the question tool because error handling is a standard practice and there's a clear best approach that doesn't require user input.
|
|
13328
|
+
</reasoning>
|
|
13329
|
+
</example>
|
|
13330
|
+
|
|
13331
|
+
## Answer Format
|
|
13332
|
+
|
|
13333
|
+
When you call this tool, answer options are automatically converted to this format:
|
|
13334
|
+
\`\`\`json
|
|
13335
|
+
[
|
|
13336
|
+
{ "id": "randomId1", "text": "First option" },
|
|
13337
|
+
{ "id": "randomId2", "text": "Second option" },
|
|
13338
|
+
{ "id": "randomId3", "text": "Third option" },
|
|
13339
|
+
{ "id": "randomId4", "text": "None of the above..." }
|
|
13340
|
+
]
|
|
13341
|
+
\`\`\`
|
|
13342
|
+
|
|
13343
|
+
The "None of the above..." option is always added automatically, so you don't need to include it in your answerOptions array.
|
|
13344
|
+
|
|
13345
|
+
## Reading Answers
|
|
13346
|
+
|
|
13347
|
+
After asking a question, use the Question Read tool to check if the user has answered. The question status will change from "pending" to "answered" and the selectedAnswerId field will contain the ID of the chosen answer.
|
|
13348
|
+
`;
|
|
13349
|
+
|
|
13350
|
+
// src/templates/tools/question/questionread.txt
|
|
13351
|
+
var questionread_default = 'Use this tool to read questions you\'ve asked and check if they\'ve been answered by the user. This tool helps you track the status of questions and retrieve the user\'s selected answers.\n\n## When to Use This Tool\n\nUse this tool proactively in these situations:\n- After asking a question to check if the user has responded\n- To retrieve the user\'s answer before proceeding with implementation\n- To review all questions and answers in the current session\n- When you need to reference a previous answer\n\n## How It Works\n\n- This tool takes no parameters (leave the input blank or empty)\n- Returns an array of all questions in the session\n- Each question includes:\n - `id`: Unique identifier for the question\n - `question`: The question text\n - `answerOptions`: Array of answer options with their IDs and text\n - `status`: Either "pending" (not answered) or "answered"\n - `selectedAnswerId`: The ID of the chosen answer (only present if answered)\n\n## Usage Pattern\n\nTypically you\'ll:\n1. Use Question Ask to pose a question\n2. Wait for the user to respond\n3. Use Question Read to check the answer\n4. Find the selected answer by matching the `selectedAnswerId` with an option in `answerOptions`\n5. Proceed with implementation based on the user\'s choice\n\n## Example Response\n\n```json\n[\n {\n "id": "question123",\n "question": "Which authentication method would you like to implement?",\n "answerOptions": [\n { "id": "ans1", "text": "JWT tokens" },\n { "id": "ans2", "text": "OAuth 2.0" },\n { "id": "ans3", "text": "Session-based auth" },\n { "id": "ans4", "text": "None of the above..." }\n ],\n "status": "answered",\n "selectedAnswerId": "ans1"\n }\n]\n```\n\nIn this example, the user selected "JWT tokens" (id: ans1).\n\n## Important Notes\n\n- If no questions exist in the session, an empty array will be returned\n- Questions remain in the session even after being answered for reference\n- Use the `selectedAnswerId` to find which answer option the user chose by matching it against the `id` field in `answerOptions`\n';
|
|
13352
|
+
|
|
13353
|
+
// src/templates/tools/question/question.ts
|
|
13354
|
+
var import_zod11 = __toESM(require("zod"), 1);
|
|
13355
|
+
var import_node_crypto6 = require("crypto");
|
|
13356
|
+
var AnswerOptionSchema = import_zod11.default.object({
|
|
13357
|
+
id: import_zod11.default.string().describe("Unique identifier for the answer option"),
|
|
13358
|
+
text: import_zod11.default.string().describe("The text of the answer option")
|
|
13359
|
+
});
|
|
13360
|
+
var _QuestionSchema = import_zod11.default.object({
|
|
13361
|
+
id: import_zod11.default.string().describe("Unique identifier for the question"),
|
|
13362
|
+
question: import_zod11.default.string().describe("The question to ask the user"),
|
|
13363
|
+
answerOptions: import_zod11.default.array(AnswerOptionSchema).describe("Array of possible answer options"),
|
|
13364
|
+
selectedAnswerId: import_zod11.default.string().optional().describe("The ID of the answer option selected by the user"),
|
|
13365
|
+
status: import_zod11.default.enum(["pending", "answered"]).describe("Status of the question: pending or answered")
|
|
13366
|
+
});
|
|
13367
|
+
var QuestionAskTool = new ExuluTool({
|
|
13368
|
+
id: "question_ask",
|
|
13369
|
+
name: "Question Ask",
|
|
13370
|
+
description: "Use this tool to ask a question to the user with multiple choice answers",
|
|
13371
|
+
type: "function",
|
|
13372
|
+
category: "question",
|
|
13373
|
+
config: [
|
|
13374
|
+
{
|
|
13375
|
+
name: "description",
|
|
13376
|
+
description: "The description of the question tool, if set overwrites the default description.",
|
|
13377
|
+
type: "string",
|
|
13378
|
+
default: questionask_default
|
|
13379
|
+
}
|
|
13380
|
+
],
|
|
13381
|
+
inputSchema: import_zod11.default.object({
|
|
13382
|
+
question: import_zod11.default.string().describe("The question to ask the user"),
|
|
13383
|
+
answerOptions: import_zod11.default.array(import_zod11.default.string()).describe("Array of possible answer options (strings)")
|
|
13384
|
+
}),
|
|
13385
|
+
execute: async (inputs) => {
|
|
13386
|
+
const { sessionID, question, answerOptions, user } = inputs;
|
|
13387
|
+
if (!user) {
|
|
13388
|
+
throw new Error(
|
|
13389
|
+
"No authenticated user available, a user is required for the question ask tool, this likely means the tool was called outside a session like in an MCP or API call instead of as part of an authenticated session."
|
|
13390
|
+
);
|
|
13391
|
+
}
|
|
13392
|
+
if (!sessionID) {
|
|
13393
|
+
throw new Error(
|
|
13394
|
+
"Session ID is required for the question ask tool, this likely means the tool was called outside a session like in an MCP or API call instead of as part of a conversation."
|
|
13395
|
+
);
|
|
13396
|
+
}
|
|
13397
|
+
const session = await getSession({ sessionID });
|
|
13398
|
+
if (!session?.id) {
|
|
13399
|
+
throw new Error(
|
|
13400
|
+
"Session with ID " + sessionID + " not found in the question ask tool."
|
|
13401
|
+
);
|
|
13402
|
+
}
|
|
13403
|
+
const hasAccessToSession = await checkRecordAccess(session, "read", user);
|
|
13404
|
+
if (!hasAccessToSession) {
|
|
13405
|
+
throw new Error("You don't have access to this session " + session.id + ".");
|
|
13406
|
+
}
|
|
13407
|
+
const answerOptionsWithIds = answerOptions.map((text) => ({
|
|
13408
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
13409
|
+
text
|
|
13410
|
+
}));
|
|
13411
|
+
answerOptionsWithIds.push({
|
|
13412
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
13413
|
+
text: "None of the above..."
|
|
13414
|
+
});
|
|
13415
|
+
const newQuestion = {
|
|
13416
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
13417
|
+
question,
|
|
13418
|
+
answerOptions: answerOptionsWithIds,
|
|
13419
|
+
status: "pending"
|
|
13420
|
+
};
|
|
13421
|
+
await addQuestion({
|
|
13422
|
+
session,
|
|
13423
|
+
question: newQuestion
|
|
13424
|
+
});
|
|
13425
|
+
return {
|
|
13426
|
+
result: JSON.stringify(
|
|
13427
|
+
{
|
|
13428
|
+
questionId: newQuestion.id,
|
|
13429
|
+
question: newQuestion.question,
|
|
13430
|
+
answerOptions: newQuestion.answerOptions,
|
|
13431
|
+
status: newQuestion.status
|
|
13432
|
+
},
|
|
13433
|
+
null,
|
|
13434
|
+
2
|
|
13435
|
+
)
|
|
13436
|
+
};
|
|
13437
|
+
}
|
|
13438
|
+
});
|
|
13439
|
+
var QuestionReadTool = new ExuluTool({
|
|
13440
|
+
id: "question_read",
|
|
13441
|
+
name: "Question Read",
|
|
13442
|
+
description: "Use this tool to read questions and their answers",
|
|
13443
|
+
inputSchema: import_zod11.default.object({}),
|
|
13444
|
+
type: "function",
|
|
13445
|
+
category: "question",
|
|
13446
|
+
config: [
|
|
13447
|
+
{
|
|
13448
|
+
name: "description",
|
|
13449
|
+
description: "The description of the question read tool, if set overwrites the default description.",
|
|
13450
|
+
type: "string",
|
|
13451
|
+
default: questionread_default
|
|
13452
|
+
}
|
|
13453
|
+
],
|
|
13454
|
+
execute: async (inputs) => {
|
|
13455
|
+
const { sessionID } = inputs;
|
|
13456
|
+
const questions = await getQuestions(sessionID);
|
|
13457
|
+
return {
|
|
13458
|
+
result: JSON.stringify(questions, null, 2)
|
|
13459
|
+
};
|
|
13460
|
+
}
|
|
13461
|
+
});
|
|
13462
|
+
async function addQuestion(input) {
|
|
13463
|
+
const metadata = input.session.metadata ?? {};
|
|
13464
|
+
metadata["questions"] ??= [];
|
|
13465
|
+
metadata["questions"].push(input.question);
|
|
13466
|
+
const { db: db2 } = await postgresClient();
|
|
13467
|
+
await db2.from("agent_sessions").where({ id: input.session.id }).update({
|
|
13468
|
+
metadata
|
|
13469
|
+
});
|
|
13470
|
+
return input.session;
|
|
13471
|
+
}
|
|
13472
|
+
async function getQuestions(sessionID) {
|
|
13473
|
+
const { db: db2 } = await postgresClient();
|
|
13474
|
+
const session = await db2.from("agent_sessions").where({ id: sessionID }).first();
|
|
13475
|
+
if (!session) {
|
|
13476
|
+
throw new Error("Session not found for session ID: " + sessionID);
|
|
13477
|
+
}
|
|
13478
|
+
return session.metadata?.questions ?? [];
|
|
13479
|
+
}
|
|
13480
|
+
var questionTools = [QuestionAskTool, QuestionReadTool];
|
|
13481
|
+
|
|
13228
13482
|
// src/templates/tools/perplexity.ts
|
|
13229
13483
|
var import_zod12 = __toESM(require("zod"), 1);
|
|
13230
13484
|
var import_perplexity_ai = __toESM(require("@perplexity-ai/perplexity_ai"), 1);
|
|
@@ -13335,14 +13589,29 @@ var isValidPostgresName = (id) => {
|
|
|
13335
13589
|
|
|
13336
13590
|
// src/exulu/app/index.ts
|
|
13337
13591
|
var isDev = process.env.NODE_ENV !== "production";
|
|
13592
|
+
var lineLimitFormat = import_winston2.default.format((info) => {
|
|
13593
|
+
if (typeof info.message === "string") {
|
|
13594
|
+
const lines = info.message.split("\n");
|
|
13595
|
+
if (lines.length > 50) {
|
|
13596
|
+
const truncatedLines = lines.slice(0, 50);
|
|
13597
|
+
truncatedLines.push(`... (${lines.length - 50} more lines omitted)`);
|
|
13598
|
+
info.message = truncatedLines.join("\n");
|
|
13599
|
+
}
|
|
13600
|
+
}
|
|
13601
|
+
return info;
|
|
13602
|
+
});
|
|
13338
13603
|
var consoleTransport = new import_winston2.default.transports.Console({
|
|
13339
13604
|
format: isDev ? import_winston2.default.format.combine(
|
|
13605
|
+
lineLimitFormat(),
|
|
13340
13606
|
import_winston2.default.format.colorize(),
|
|
13341
13607
|
import_winston2.default.format.timestamp({ format: "HH:mm:ss" }),
|
|
13342
13608
|
import_winston2.default.format.printf(({ timestamp, level, message }) => {
|
|
13343
13609
|
return `${timestamp} [${level}] ${message}`;
|
|
13344
13610
|
})
|
|
13345
|
-
) : import_winston2.default.format.
|
|
13611
|
+
) : import_winston2.default.format.combine(
|
|
13612
|
+
lineLimitFormat(),
|
|
13613
|
+
import_winston2.default.format.json()
|
|
13614
|
+
)
|
|
13346
13615
|
});
|
|
13347
13616
|
var formatArg = (arg) => typeof arg === "object" ? import_util.default.inspect(arg, { depth: null, colors: isDev }) : String(arg);
|
|
13348
13617
|
var createLogMethod = (logger, logLevel) => {
|
|
@@ -13412,6 +13681,7 @@ var ExuluApp2 = class {
|
|
|
13412
13681
|
this._tools = [
|
|
13413
13682
|
...tools ?? [],
|
|
13414
13683
|
...todoTools,
|
|
13684
|
+
...questionTools,
|
|
13415
13685
|
...perplexityTools,
|
|
13416
13686
|
// Add contexts as tools
|
|
13417
13687
|
...Object.values(contexts || {}).map((context) => context.tool()).filter(Boolean)
|
|
@@ -15954,6 +16224,7 @@ var MarkdownChunker = class {
|
|
|
15954
16224
|
if (currentSlice.length === 0) {
|
|
15955
16225
|
currentPosition++;
|
|
15956
16226
|
targetPosition = currentPosition + chunkSize * this._CHARS_PER_TOKEN;
|
|
16227
|
+
contentLeft = text.length - currentPosition;
|
|
15957
16228
|
}
|
|
15958
16229
|
}
|
|
15959
16230
|
const mergedChunks = [];
|
|
@@ -16701,7 +16972,8 @@ var getMistralApiKey = async () => {
|
|
|
16701
16972
|
if (process.env.MISTRAL_API_KEY) {
|
|
16702
16973
|
return process.env.MISTRAL_API_KEY;
|
|
16703
16974
|
} else {
|
|
16704
|
-
|
|
16975
|
+
const variable = await ExuluVariables.get("MISTRAL_API_KEY");
|
|
16976
|
+
return variable;
|
|
16705
16977
|
}
|
|
16706
16978
|
};
|
|
16707
16979
|
async function processPdf(buffer, paths, config, verbose = false) {
|
|
@@ -16760,7 +17032,7 @@ ${setupResult.output || ""}`);
|
|
|
16760
17032
|
}];
|
|
16761
17033
|
} else if (config?.processor.name === "mistral") {
|
|
16762
17034
|
const MISTRAL_API_KEY = await getMistralApiKey();
|
|
16763
|
-
if (MISTRAL_API_KEY) {
|
|
17035
|
+
if (!MISTRAL_API_KEY) {
|
|
16764
17036
|
throw new Error('[EXULU] MISTRAL_API_KEY is not set, please set it in the environment variable via process.env or via an Exulu variable named "MISTRAL_API_KEY".');
|
|
16765
17037
|
}
|
|
16766
17038
|
await new Promise((resolve3) => setTimeout(resolve3, Math.floor(Math.random() * 4e3) + 1e3));
|
package/dist/index.d.cts
CHANGED
|
@@ -241,7 +241,7 @@ declare class ExuluStorage {
|
|
|
241
241
|
type ExuluContextProcessor = {
|
|
242
242
|
name: string;
|
|
243
243
|
description: string;
|
|
244
|
-
filter
|
|
244
|
+
filter?: ({ item, user, role, utils, exuluConfig, }: {
|
|
245
245
|
item: Item;
|
|
246
246
|
user?: number;
|
|
247
247
|
role?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -241,7 +241,7 @@ declare class ExuluStorage {
|
|
|
241
241
|
type ExuluContextProcessor = {
|
|
242
242
|
name: string;
|
|
243
243
|
description: string;
|
|
244
|
-
filter
|
|
244
|
+
filter?: ({ item, user, role, utils, exuluConfig, }: {
|
|
245
245
|
item: Item;
|
|
246
246
|
user?: number;
|
|
247
247
|
role?: string;
|
package/dist/index.js
CHANGED
|
@@ -4003,6 +4003,7 @@ var ExuluContext2 = class {
|
|
|
4003
4003
|
exuluConfig
|
|
4004
4004
|
});
|
|
4005
4005
|
if (!result) {
|
|
4006
|
+
console.log("[EXULU] Item filtered out by processor, skipping processing execution...");
|
|
4006
4007
|
return {
|
|
4007
4008
|
result: void 0,
|
|
4008
4009
|
job: void 0
|
|
@@ -4203,10 +4204,12 @@ var ExuluContext2 = class {
|
|
|
4203
4204
|
}
|
|
4204
4205
|
}
|
|
4205
4206
|
});
|
|
4207
|
+
console.log("[EXULU] Creating item", item);
|
|
4206
4208
|
const mutation = db2.from(getTableName(this.id)).insert({
|
|
4207
4209
|
...item,
|
|
4208
4210
|
tags: item.tags ? Array.isArray(item.tags) ? item.tags.join(",") : item.tags : void 0
|
|
4209
4211
|
}).returning("id");
|
|
4212
|
+
console.log("[EXULU] Upsert", upsert);
|
|
4210
4213
|
if (upsert) {
|
|
4211
4214
|
if (item.external_id) {
|
|
4212
4215
|
mutation.onConflict("external_id").merge();
|
|
@@ -4225,7 +4228,6 @@ var ExuluContext2 = class {
|
|
|
4225
4228
|
let shouldGenerateEmbeddings = this.embedder && generateEmbeddingsOverwrite !== false && (generateEmbeddingsOverwrite || this.configuration.calculateVectors === "onInsert" || this.configuration.calculateVectors === "always");
|
|
4226
4229
|
if (this.processor) {
|
|
4227
4230
|
const processor = this.processor;
|
|
4228
|
-
console.log("[EXULU] Processor found", processor);
|
|
4229
4231
|
if (processor && (processor?.config?.trigger === "onInsert" || processor?.config?.trigger === "onUpdate" || processor?.config?.trigger === "always")) {
|
|
4230
4232
|
const { job: processorJob, result: processorResult } = await this.processField(
|
|
4231
4233
|
"api",
|
|
@@ -4240,7 +4242,7 @@ var ExuluContext2 = class {
|
|
|
4240
4242
|
if (processorJob) {
|
|
4241
4243
|
jobs.push(processorJob);
|
|
4242
4244
|
}
|
|
4243
|
-
if (!processorJob) {
|
|
4245
|
+
if (!processorJob && processorResult) {
|
|
4244
4246
|
await db2.from(getTableName(this.id)).where({ id: results[0].id }).update({
|
|
4245
4247
|
...processorResult
|
|
4246
4248
|
});
|
|
@@ -4311,7 +4313,7 @@ var ExuluContext2 = class {
|
|
|
4311
4313
|
if (processorJob) {
|
|
4312
4314
|
jobs.push(processorJob);
|
|
4313
4315
|
}
|
|
4314
|
-
if (!processorJob) {
|
|
4316
|
+
if (!processorJob && processorResult) {
|
|
4315
4317
|
await db2.from(getTableName(this.id)).where({ id: record.id }).update({
|
|
4316
4318
|
...processorResult
|
|
4317
4319
|
});
|
|
@@ -7379,7 +7381,32 @@ var createWorkers = async (providers, queues2, config, contexts, rerankers, eval
|
|
|
7379
7381
|
);
|
|
7380
7382
|
}
|
|
7381
7383
|
const exuluStorage = new ExuluStorage({ config });
|
|
7382
|
-
|
|
7384
|
+
if (context.processor.filter) {
|
|
7385
|
+
const result2 = await context.processor.filter({
|
|
7386
|
+
item: data.inputs,
|
|
7387
|
+
user: data.user,
|
|
7388
|
+
role: data.role,
|
|
7389
|
+
utils: {
|
|
7390
|
+
storage: exuluStorage
|
|
7391
|
+
},
|
|
7392
|
+
exuluConfig: config
|
|
7393
|
+
});
|
|
7394
|
+
if (!result2) {
|
|
7395
|
+
console.log("[EXULU] Item filtered out by processor, skipping processing execution...");
|
|
7396
|
+
return {
|
|
7397
|
+
result: "Item filtered out by processor, skipping processing execution...",
|
|
7398
|
+
// last message
|
|
7399
|
+
metadata: {
|
|
7400
|
+
item: {
|
|
7401
|
+
name: data.inputs?.name,
|
|
7402
|
+
id: data.inputs?.id,
|
|
7403
|
+
external_id: data.inputs?.external_id
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
};
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7409
|
+
console.log("[EXULU] POS 2 -- EXULU CONTEXT PROCESS FIELD", data.inputs);
|
|
7383
7410
|
let processorResult = await context.processor.execute({
|
|
7384
7411
|
item: data.inputs,
|
|
7385
7412
|
user: data.user,
|
|
@@ -10829,7 +10856,6 @@ var providerRateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
10829
10856
|
|
|
10830
10857
|
// src/exulu/routes.ts
|
|
10831
10858
|
import { convertJsonSchemaToZod } from "zod-from-json-schema";
|
|
10832
|
-
import "zod";
|
|
10833
10859
|
var REQUEST_SIZE_LIMIT = "50mb";
|
|
10834
10860
|
var getExuluVersionNumber = async () => {
|
|
10835
10861
|
try {
|
|
@@ -11297,12 +11323,16 @@ Mood: friendly and intelligent.
|
|
|
11297
11323
|
message = req.body.message;
|
|
11298
11324
|
}
|
|
11299
11325
|
const approvedTools = req.body.approvedTools ? typeof req.body.approvedTools === "string" ? JSON.parse(req.body.approvedTools) : req.body.approvedTools : [];
|
|
11326
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11327
|
+
const instructions = customInstructions ? `${agent.instructions}
|
|
11328
|
+
|
|
11329
|
+
${customInstructions}` : agent.instructions;
|
|
11300
11330
|
const result = await provider.generateStream({
|
|
11301
11331
|
contexts,
|
|
11302
11332
|
rerankers: rerankers || [],
|
|
11303
11333
|
agent,
|
|
11304
11334
|
user,
|
|
11305
|
-
instructions
|
|
11335
|
+
instructions,
|
|
11306
11336
|
session: headers.session,
|
|
11307
11337
|
message,
|
|
11308
11338
|
previousMessages,
|
|
@@ -11403,6 +11433,10 @@ Mood: friendly and intelligent.
|
|
|
11403
11433
|
});
|
|
11404
11434
|
return;
|
|
11405
11435
|
} else {
|
|
11436
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11437
|
+
const instructions = customInstructions ? `${agent.instructions}
|
|
11438
|
+
|
|
11439
|
+
${customInstructions}` : agent.instructions;
|
|
11406
11440
|
const response = await provider.generateSync({
|
|
11407
11441
|
contexts,
|
|
11408
11442
|
rerankers: rerankers || [],
|
|
@@ -11410,7 +11444,7 @@ Mood: friendly and intelligent.
|
|
|
11410
11444
|
agent,
|
|
11411
11445
|
user,
|
|
11412
11446
|
req,
|
|
11413
|
-
instructions
|
|
11447
|
+
instructions,
|
|
11414
11448
|
session: headers.session,
|
|
11415
11449
|
inputMessages: [req.body.message],
|
|
11416
11450
|
currentTools: enabledTools,
|
|
@@ -11555,6 +11589,10 @@ Mood: friendly and intelligent.
|
|
|
11555
11589
|
providers,
|
|
11556
11590
|
user
|
|
11557
11591
|
);
|
|
11592
|
+
const customInstructions = req.body.customInstructions ? typeof req.body.customInstructions === "string" ? req.body.customInstructions : JSON.stringify(req.body.customInstructions) : "";
|
|
11593
|
+
const agentInstructions = customInstructions ? `${agent?.instructions}
|
|
11594
|
+
|
|
11595
|
+
${customInstructions}` : agent?.instructions;
|
|
11558
11596
|
let system = req.body.system;
|
|
11559
11597
|
if (Array.isArray(req.body.system)) {
|
|
11560
11598
|
system = [
|
|
@@ -11564,7 +11602,7 @@ Mood: friendly and intelligent.
|
|
|
11564
11602
|
type: "text",
|
|
11565
11603
|
text: `
|
|
11566
11604
|
You are an agent named: ${agent?.name}
|
|
11567
|
-
Here are some additional instructions for you: ${
|
|
11605
|
+
Here are some additional instructions for you: ${agentInstructions}`
|
|
11568
11606
|
}
|
|
11569
11607
|
] : [],
|
|
11570
11608
|
...project ? [
|
|
@@ -11582,7 +11620,7 @@ Mood: friendly and intelligent.
|
|
|
11582
11620
|
|
|
11583
11621
|
|
|
11584
11622
|
${agent ? `You are an agent named: ${agent?.name}
|
|
11585
|
-
Here are some additional instructions for you: ${
|
|
11623
|
+
Here are some additional instructions for you: ${agentInstructions}` : ""}
|
|
11586
11624
|
|
|
11587
11625
|
${project?.id ? `Additional information:
|
|
11588
11626
|
|
|
@@ -11732,7 +11770,7 @@ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
|
11732
11770
|
import "express";
|
|
11733
11771
|
import "@opentelemetry/api";
|
|
11734
11772
|
import CryptoJS7 from "crypto-js";
|
|
11735
|
-
import { z as
|
|
11773
|
+
import { z as z8 } from "zod";
|
|
11736
11774
|
var SESSION_ID_HEADER = "mcp-session-id";
|
|
11737
11775
|
var ExuluMCP = class {
|
|
11738
11776
|
server = {};
|
|
@@ -11815,7 +11853,7 @@ var ExuluMCP = class {
|
|
|
11815
11853
|
title: tool3.name + " agent",
|
|
11816
11854
|
description: tool3.description,
|
|
11817
11855
|
inputSchema: {
|
|
11818
|
-
inputs: tool3.inputSchema ||
|
|
11856
|
+
inputs: tool3.inputSchema || z8.object({})
|
|
11819
11857
|
}
|
|
11820
11858
|
},
|
|
11821
11859
|
async ({ inputs }, args) => {
|
|
@@ -11867,7 +11905,7 @@ var ExuluMCP = class {
|
|
|
11867
11905
|
title: "Get List of Prompt Templates",
|
|
11868
11906
|
description: "Retrieves a list of prompt templates available for this agent. Returns the name, description, and ID of each template.",
|
|
11869
11907
|
inputSchema: {
|
|
11870
|
-
inputs:
|
|
11908
|
+
inputs: z8.object({})
|
|
11871
11909
|
}
|
|
11872
11910
|
},
|
|
11873
11911
|
async ({ inputs }, args) => {
|
|
@@ -11913,8 +11951,8 @@ var ExuluMCP = class {
|
|
|
11913
11951
|
title: "Get Prompt Template Details",
|
|
11914
11952
|
description: "Retrieves the full details of a specific prompt template by ID, including the actual template content with variables.",
|
|
11915
11953
|
inputSchema: {
|
|
11916
|
-
inputs:
|
|
11917
|
-
id:
|
|
11954
|
+
inputs: z8.object({
|
|
11955
|
+
id: z8.string().describe("The ID of the prompt template to retrieve")
|
|
11918
11956
|
})
|
|
11919
11957
|
}
|
|
11920
11958
|
},
|
|
@@ -12822,7 +12860,7 @@ var ExuluEval = class {
|
|
|
12822
12860
|
};
|
|
12823
12861
|
|
|
12824
12862
|
// src/templates/evals/index.ts
|
|
12825
|
-
import { z as
|
|
12863
|
+
import { z as z9 } from "zod";
|
|
12826
12864
|
var llmAsJudgeEval = () => {
|
|
12827
12865
|
if (process.env.REDIS_HOST?.length && process.env.REDIS_PORT?.length) {
|
|
12828
12866
|
return new ExuluEval({
|
|
@@ -12867,8 +12905,8 @@ var llmAsJudgeEval = () => {
|
|
|
12867
12905
|
contexts: [],
|
|
12868
12906
|
rerankers: [],
|
|
12869
12907
|
prompt,
|
|
12870
|
-
outputSchema:
|
|
12871
|
-
score:
|
|
12908
|
+
outputSchema: z9.object({
|
|
12909
|
+
score: z9.number().min(0).max(100).describe("The score between 0 and 100.")
|
|
12872
12910
|
}),
|
|
12873
12911
|
providerapikey
|
|
12874
12912
|
});
|
|
@@ -13096,12 +13134,12 @@ Usage:
|
|
|
13096
13134
|
- If no todos exist yet, an empty list will be returned`;
|
|
13097
13135
|
|
|
13098
13136
|
// src/templates/tools/todo/todo.ts
|
|
13099
|
-
import
|
|
13100
|
-
var TodoSchema =
|
|
13101
|
-
content:
|
|
13102
|
-
status:
|
|
13103
|
-
priority:
|
|
13104
|
-
id:
|
|
13137
|
+
import z10 from "zod";
|
|
13138
|
+
var TodoSchema = z10.object({
|
|
13139
|
+
content: z10.string().describe("Brief description of the task"),
|
|
13140
|
+
status: z10.string().describe("Current status of the task: pending, in_progress, completed, cancelled"),
|
|
13141
|
+
priority: z10.string().describe("Priority level of the task: high, medium, low"),
|
|
13142
|
+
id: z10.string().describe("Unique identifier for the todo item")
|
|
13105
13143
|
});
|
|
13106
13144
|
var TodoWriteTool = new ExuluTool({
|
|
13107
13145
|
id: "todo_write",
|
|
@@ -13117,8 +13155,8 @@ var TodoWriteTool = new ExuluTool({
|
|
|
13117
13155
|
default: todowrite_default
|
|
13118
13156
|
}
|
|
13119
13157
|
],
|
|
13120
|
-
inputSchema:
|
|
13121
|
-
todos:
|
|
13158
|
+
inputSchema: z10.object({
|
|
13159
|
+
todos: z10.array(TodoSchema).describe("The updated todo list")
|
|
13122
13160
|
}),
|
|
13123
13161
|
execute: async (inputs) => {
|
|
13124
13162
|
const { sessionID, todos, user } = inputs;
|
|
@@ -13153,7 +13191,7 @@ var TodoReadTool = new ExuluTool({
|
|
|
13153
13191
|
id: "todo_read",
|
|
13154
13192
|
name: "Todo Read",
|
|
13155
13193
|
description: "Use this tool to read your todo list",
|
|
13156
|
-
inputSchema:
|
|
13194
|
+
inputSchema: z10.object({}),
|
|
13157
13195
|
type: "function",
|
|
13158
13196
|
category: "todo",
|
|
13159
13197
|
config: [
|
|
@@ -13191,6 +13229,222 @@ async function getTodos(sessionID) {
|
|
|
13191
13229
|
}
|
|
13192
13230
|
var todoTools = [TodoWriteTool, TodoReadTool];
|
|
13193
13231
|
|
|
13232
|
+
// src/templates/tools/question/questionask.txt
|
|
13233
|
+
var questionask_default = `Use this tool to ask the user a question with multiple choice answer options during your session. This helps you gather user input, clarify requirements, and make informed decisions based on user preferences.
|
|
13234
|
+
|
|
13235
|
+
## When to Use This Tool
|
|
13236
|
+
|
|
13237
|
+
Use this tool when you need to:
|
|
13238
|
+
|
|
13239
|
+
1. Get user input on implementation choices - When there are multiple valid approaches and you need the user to decide
|
|
13240
|
+
2. Clarify ambiguous requirements - When the user's request could be interpreted in different ways
|
|
13241
|
+
3. Gather preferences - When you need to know the user's preference for styling, naming, architecture, etc.
|
|
13242
|
+
4. Validate assumptions - When you want to confirm your understanding before proceeding
|
|
13243
|
+
5. Offer options - When presenting multiple solutions and letting the user choose
|
|
13244
|
+
|
|
13245
|
+
## When NOT to Use This Tool
|
|
13246
|
+
|
|
13247
|
+
Skip using this tool when:
|
|
13248
|
+
1. The answer is clear from context or previous messages
|
|
13249
|
+
2. You're asking a yes/no question (use a simpler approach)
|
|
13250
|
+
3. The question requires a free-form text answer (this tool is for multiple choice only)
|
|
13251
|
+
4. You're asking for information that should be obvious from the codebase
|
|
13252
|
+
|
|
13253
|
+
## How It Works
|
|
13254
|
+
|
|
13255
|
+
- Provide a question and an array of answer option strings
|
|
13256
|
+
- The tool automatically adds "None of the above..." as a final option
|
|
13257
|
+
- Each answer option is assigned a unique ID
|
|
13258
|
+
- The question is stored with a "pending" status until the user answers
|
|
13259
|
+
- Use the Question Read tool to check if the question has been answered
|
|
13260
|
+
|
|
13261
|
+
## Examples
|
|
13262
|
+
|
|
13263
|
+
<example>
|
|
13264
|
+
User: Add authentication to my app
|
|
13265
|
+
Assistant: I need to ask the user which authentication method they prefer.
|
|
13266
|
+
*Uses Question Ask tool with:*
|
|
13267
|
+
question: "Which authentication method would you like to implement?"
|
|
13268
|
+
answerOptions: ["JWT tokens", "OAuth 2.0", "Session-based auth", "Firebase Auth"]
|
|
13269
|
+
|
|
13270
|
+
<reasoning>
|
|
13271
|
+
The assistant used the question tool because there are multiple valid authentication approaches and the user's preference will significantly impact the implementation.
|
|
13272
|
+
</reasoning>
|
|
13273
|
+
</example>
|
|
13274
|
+
|
|
13275
|
+
<example>
|
|
13276
|
+
User: Style this button
|
|
13277
|
+
Assistant: I need to know the user's styling preference.
|
|
13278
|
+
*Uses Question Ask tool with:*
|
|
13279
|
+
question: "What styling approach should I use for the button?"
|
|
13280
|
+
answerOptions: ["Tailwind CSS", "CSS Modules", "Styled Components", "Plain CSS"]
|
|
13281
|
+
|
|
13282
|
+
<reasoning>
|
|
13283
|
+
The assistant used the question tool because the codebase could support multiple styling approaches and the user's preference matters for consistency.
|
|
13284
|
+
</reasoning>
|
|
13285
|
+
</example>
|
|
13286
|
+
|
|
13287
|
+
<example>
|
|
13288
|
+
User: Add error handling
|
|
13289
|
+
Assistant: I'll implement comprehensive error handling with try-catch blocks and proper error messages.
|
|
13290
|
+
*Does not use the question tool*
|
|
13291
|
+
|
|
13292
|
+
<reasoning>
|
|
13293
|
+
The assistant did not use the question tool because error handling is a standard practice and there's a clear best approach that doesn't require user input.
|
|
13294
|
+
</reasoning>
|
|
13295
|
+
</example>
|
|
13296
|
+
|
|
13297
|
+
## Answer Format
|
|
13298
|
+
|
|
13299
|
+
When you call this tool, answer options are automatically converted to this format:
|
|
13300
|
+
\`\`\`json
|
|
13301
|
+
[
|
|
13302
|
+
{ "id": "randomId1", "text": "First option" },
|
|
13303
|
+
{ "id": "randomId2", "text": "Second option" },
|
|
13304
|
+
{ "id": "randomId3", "text": "Third option" },
|
|
13305
|
+
{ "id": "randomId4", "text": "None of the above..." }
|
|
13306
|
+
]
|
|
13307
|
+
\`\`\`
|
|
13308
|
+
|
|
13309
|
+
The "None of the above..." option is always added automatically, so you don't need to include it in your answerOptions array.
|
|
13310
|
+
|
|
13311
|
+
## Reading Answers
|
|
13312
|
+
|
|
13313
|
+
After asking a question, use the Question Read tool to check if the user has answered. The question status will change from "pending" to "answered" and the selectedAnswerId field will contain the ID of the chosen answer.
|
|
13314
|
+
`;
|
|
13315
|
+
|
|
13316
|
+
// src/templates/tools/question/questionread.txt
|
|
13317
|
+
var questionread_default = 'Use this tool to read questions you\'ve asked and check if they\'ve been answered by the user. This tool helps you track the status of questions and retrieve the user\'s selected answers.\n\n## When to Use This Tool\n\nUse this tool proactively in these situations:\n- After asking a question to check if the user has responded\n- To retrieve the user\'s answer before proceeding with implementation\n- To review all questions and answers in the current session\n- When you need to reference a previous answer\n\n## How It Works\n\n- This tool takes no parameters (leave the input blank or empty)\n- Returns an array of all questions in the session\n- Each question includes:\n - `id`: Unique identifier for the question\n - `question`: The question text\n - `answerOptions`: Array of answer options with their IDs and text\n - `status`: Either "pending" (not answered) or "answered"\n - `selectedAnswerId`: The ID of the chosen answer (only present if answered)\n\n## Usage Pattern\n\nTypically you\'ll:\n1. Use Question Ask to pose a question\n2. Wait for the user to respond\n3. Use Question Read to check the answer\n4. Find the selected answer by matching the `selectedAnswerId` with an option in `answerOptions`\n5. Proceed with implementation based on the user\'s choice\n\n## Example Response\n\n```json\n[\n {\n "id": "question123",\n "question": "Which authentication method would you like to implement?",\n "answerOptions": [\n { "id": "ans1", "text": "JWT tokens" },\n { "id": "ans2", "text": "OAuth 2.0" },\n { "id": "ans3", "text": "Session-based auth" },\n { "id": "ans4", "text": "None of the above..." }\n ],\n "status": "answered",\n "selectedAnswerId": "ans1"\n }\n]\n```\n\nIn this example, the user selected "JWT tokens" (id: ans1).\n\n## Important Notes\n\n- If no questions exist in the session, an empty array will be returned\n- Questions remain in the session even after being answered for reference\n- Use the `selectedAnswerId` to find which answer option the user chose by matching it against the `id` field in `answerOptions`\n';
|
|
13318
|
+
|
|
13319
|
+
// src/templates/tools/question/question.ts
|
|
13320
|
+
import z11 from "zod";
|
|
13321
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
13322
|
+
var AnswerOptionSchema = z11.object({
|
|
13323
|
+
id: z11.string().describe("Unique identifier for the answer option"),
|
|
13324
|
+
text: z11.string().describe("The text of the answer option")
|
|
13325
|
+
});
|
|
13326
|
+
var _QuestionSchema = z11.object({
|
|
13327
|
+
id: z11.string().describe("Unique identifier for the question"),
|
|
13328
|
+
question: z11.string().describe("The question to ask the user"),
|
|
13329
|
+
answerOptions: z11.array(AnswerOptionSchema).describe("Array of possible answer options"),
|
|
13330
|
+
selectedAnswerId: z11.string().optional().describe("The ID of the answer option selected by the user"),
|
|
13331
|
+
status: z11.enum(["pending", "answered"]).describe("Status of the question: pending or answered")
|
|
13332
|
+
});
|
|
13333
|
+
var QuestionAskTool = new ExuluTool({
|
|
13334
|
+
id: "question_ask",
|
|
13335
|
+
name: "Question Ask",
|
|
13336
|
+
description: "Use this tool to ask a question to the user with multiple choice answers",
|
|
13337
|
+
type: "function",
|
|
13338
|
+
category: "question",
|
|
13339
|
+
config: [
|
|
13340
|
+
{
|
|
13341
|
+
name: "description",
|
|
13342
|
+
description: "The description of the question tool, if set overwrites the default description.",
|
|
13343
|
+
type: "string",
|
|
13344
|
+
default: questionask_default
|
|
13345
|
+
}
|
|
13346
|
+
],
|
|
13347
|
+
inputSchema: z11.object({
|
|
13348
|
+
question: z11.string().describe("The question to ask the user"),
|
|
13349
|
+
answerOptions: z11.array(z11.string()).describe("Array of possible answer options (strings)")
|
|
13350
|
+
}),
|
|
13351
|
+
execute: async (inputs) => {
|
|
13352
|
+
const { sessionID, question, answerOptions, user } = inputs;
|
|
13353
|
+
if (!user) {
|
|
13354
|
+
throw new Error(
|
|
13355
|
+
"No authenticated user available, a user is required for the question ask tool, this likely means the tool was called outside a session like in an MCP or API call instead of as part of an authenticated session."
|
|
13356
|
+
);
|
|
13357
|
+
}
|
|
13358
|
+
if (!sessionID) {
|
|
13359
|
+
throw new Error(
|
|
13360
|
+
"Session ID is required for the question ask tool, this likely means the tool was called outside a session like in an MCP or API call instead of as part of a conversation."
|
|
13361
|
+
);
|
|
13362
|
+
}
|
|
13363
|
+
const session = await getSession({ sessionID });
|
|
13364
|
+
if (!session?.id) {
|
|
13365
|
+
throw new Error(
|
|
13366
|
+
"Session with ID " + sessionID + " not found in the question ask tool."
|
|
13367
|
+
);
|
|
13368
|
+
}
|
|
13369
|
+
const hasAccessToSession = await checkRecordAccess(session, "read", user);
|
|
13370
|
+
if (!hasAccessToSession) {
|
|
13371
|
+
throw new Error("You don't have access to this session " + session.id + ".");
|
|
13372
|
+
}
|
|
13373
|
+
const answerOptionsWithIds = answerOptions.map((text) => ({
|
|
13374
|
+
id: randomUUID6(),
|
|
13375
|
+
text
|
|
13376
|
+
}));
|
|
13377
|
+
answerOptionsWithIds.push({
|
|
13378
|
+
id: randomUUID6(),
|
|
13379
|
+
text: "None of the above..."
|
|
13380
|
+
});
|
|
13381
|
+
const newQuestion = {
|
|
13382
|
+
id: randomUUID6(),
|
|
13383
|
+
question,
|
|
13384
|
+
answerOptions: answerOptionsWithIds,
|
|
13385
|
+
status: "pending"
|
|
13386
|
+
};
|
|
13387
|
+
await addQuestion({
|
|
13388
|
+
session,
|
|
13389
|
+
question: newQuestion
|
|
13390
|
+
});
|
|
13391
|
+
return {
|
|
13392
|
+
result: JSON.stringify(
|
|
13393
|
+
{
|
|
13394
|
+
questionId: newQuestion.id,
|
|
13395
|
+
question: newQuestion.question,
|
|
13396
|
+
answerOptions: newQuestion.answerOptions,
|
|
13397
|
+
status: newQuestion.status
|
|
13398
|
+
},
|
|
13399
|
+
null,
|
|
13400
|
+
2
|
|
13401
|
+
)
|
|
13402
|
+
};
|
|
13403
|
+
}
|
|
13404
|
+
});
|
|
13405
|
+
var QuestionReadTool = new ExuluTool({
|
|
13406
|
+
id: "question_read",
|
|
13407
|
+
name: "Question Read",
|
|
13408
|
+
description: "Use this tool to read questions and their answers",
|
|
13409
|
+
inputSchema: z11.object({}),
|
|
13410
|
+
type: "function",
|
|
13411
|
+
category: "question",
|
|
13412
|
+
config: [
|
|
13413
|
+
{
|
|
13414
|
+
name: "description",
|
|
13415
|
+
description: "The description of the question read tool, if set overwrites the default description.",
|
|
13416
|
+
type: "string",
|
|
13417
|
+
default: questionread_default
|
|
13418
|
+
}
|
|
13419
|
+
],
|
|
13420
|
+
execute: async (inputs) => {
|
|
13421
|
+
const { sessionID } = inputs;
|
|
13422
|
+
const questions = await getQuestions(sessionID);
|
|
13423
|
+
return {
|
|
13424
|
+
result: JSON.stringify(questions, null, 2)
|
|
13425
|
+
};
|
|
13426
|
+
}
|
|
13427
|
+
});
|
|
13428
|
+
async function addQuestion(input) {
|
|
13429
|
+
const metadata = input.session.metadata ?? {};
|
|
13430
|
+
metadata["questions"] ??= [];
|
|
13431
|
+
metadata["questions"].push(input.question);
|
|
13432
|
+
const { db: db2 } = await postgresClient();
|
|
13433
|
+
await db2.from("agent_sessions").where({ id: input.session.id }).update({
|
|
13434
|
+
metadata
|
|
13435
|
+
});
|
|
13436
|
+
return input.session;
|
|
13437
|
+
}
|
|
13438
|
+
async function getQuestions(sessionID) {
|
|
13439
|
+
const { db: db2 } = await postgresClient();
|
|
13440
|
+
const session = await db2.from("agent_sessions").where({ id: sessionID }).first();
|
|
13441
|
+
if (!session) {
|
|
13442
|
+
throw new Error("Session not found for session ID: " + sessionID);
|
|
13443
|
+
}
|
|
13444
|
+
return session.metadata?.questions ?? [];
|
|
13445
|
+
}
|
|
13446
|
+
var questionTools = [QuestionAskTool, QuestionReadTool];
|
|
13447
|
+
|
|
13194
13448
|
// src/templates/tools/perplexity.ts
|
|
13195
13449
|
import z12 from "zod";
|
|
13196
13450
|
import Perplexity from "@perplexity-ai/perplexity_ai";
|
|
@@ -13301,14 +13555,29 @@ var isValidPostgresName = (id) => {
|
|
|
13301
13555
|
|
|
13302
13556
|
// src/exulu/app/index.ts
|
|
13303
13557
|
var isDev = process.env.NODE_ENV !== "production";
|
|
13558
|
+
var lineLimitFormat = winston2.format((info) => {
|
|
13559
|
+
if (typeof info.message === "string") {
|
|
13560
|
+
const lines = info.message.split("\n");
|
|
13561
|
+
if (lines.length > 50) {
|
|
13562
|
+
const truncatedLines = lines.slice(0, 50);
|
|
13563
|
+
truncatedLines.push(`... (${lines.length - 50} more lines omitted)`);
|
|
13564
|
+
info.message = truncatedLines.join("\n");
|
|
13565
|
+
}
|
|
13566
|
+
}
|
|
13567
|
+
return info;
|
|
13568
|
+
});
|
|
13304
13569
|
var consoleTransport = new winston2.transports.Console({
|
|
13305
13570
|
format: isDev ? winston2.format.combine(
|
|
13571
|
+
lineLimitFormat(),
|
|
13306
13572
|
winston2.format.colorize(),
|
|
13307
13573
|
winston2.format.timestamp({ format: "HH:mm:ss" }),
|
|
13308
13574
|
winston2.format.printf(({ timestamp, level, message }) => {
|
|
13309
13575
|
return `${timestamp} [${level}] ${message}`;
|
|
13310
13576
|
})
|
|
13311
|
-
) : winston2.format.
|
|
13577
|
+
) : winston2.format.combine(
|
|
13578
|
+
lineLimitFormat(),
|
|
13579
|
+
winston2.format.json()
|
|
13580
|
+
)
|
|
13312
13581
|
});
|
|
13313
13582
|
var formatArg = (arg) => typeof arg === "object" ? util.inspect(arg, { depth: null, colors: isDev }) : String(arg);
|
|
13314
13583
|
var createLogMethod = (logger, logLevel) => {
|
|
@@ -13378,6 +13647,7 @@ var ExuluApp2 = class {
|
|
|
13378
13647
|
this._tools = [
|
|
13379
13648
|
...tools ?? [],
|
|
13380
13649
|
...todoTools,
|
|
13650
|
+
...questionTools,
|
|
13381
13651
|
...perplexityTools,
|
|
13382
13652
|
// Add contexts as tools
|
|
13383
13653
|
...Object.values(contexts || {}).map((context) => context.tool()).filter(Boolean)
|
|
@@ -15920,6 +16190,7 @@ var MarkdownChunker = class {
|
|
|
15920
16190
|
if (currentSlice.length === 0) {
|
|
15921
16191
|
currentPosition++;
|
|
15922
16192
|
targetPosition = currentPosition + chunkSize * this._CHARS_PER_TOKEN;
|
|
16193
|
+
contentLeft = text.length - currentPosition;
|
|
15923
16194
|
}
|
|
15924
16195
|
}
|
|
15925
16196
|
const mergedChunks = [];
|
|
@@ -16161,7 +16432,7 @@ import * as path from "path";
|
|
|
16161
16432
|
import { generateText as generateText3, Output as Output3 } from "ai";
|
|
16162
16433
|
import { z as z13 } from "zod";
|
|
16163
16434
|
import pLimit from "p-limit";
|
|
16164
|
-
import { randomUUID as
|
|
16435
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
16165
16436
|
import * as mammoth from "mammoth";
|
|
16166
16437
|
import TurndownService from "turndown";
|
|
16167
16438
|
import WordExtractor from "word-extractor";
|
|
@@ -16667,7 +16938,8 @@ var getMistralApiKey = async () => {
|
|
|
16667
16938
|
if (process.env.MISTRAL_API_KEY) {
|
|
16668
16939
|
return process.env.MISTRAL_API_KEY;
|
|
16669
16940
|
} else {
|
|
16670
|
-
|
|
16941
|
+
const variable = await ExuluVariables.get("MISTRAL_API_KEY");
|
|
16942
|
+
return variable;
|
|
16671
16943
|
}
|
|
16672
16944
|
};
|
|
16673
16945
|
async function processPdf(buffer, paths, config, verbose = false) {
|
|
@@ -16726,7 +16998,7 @@ ${setupResult.output || ""}`);
|
|
|
16726
16998
|
}];
|
|
16727
16999
|
} else if (config?.processor.name === "mistral") {
|
|
16728
17000
|
const MISTRAL_API_KEY = await getMistralApiKey();
|
|
16729
|
-
if (MISTRAL_API_KEY) {
|
|
17001
|
+
if (!MISTRAL_API_KEY) {
|
|
16730
17002
|
throw new Error('[EXULU] MISTRAL_API_KEY is not set, please set it in the environment variable via process.env or via an Exulu variable named "MISTRAL_API_KEY".');
|
|
16731
17003
|
}
|
|
16732
17004
|
await new Promise((resolve3) => setTimeout(resolve3, Math.floor(Math.random() * 4e3) + 1e3));
|
|
@@ -16858,7 +17130,7 @@ var loadFile = async (file, name, tempDir) => {
|
|
|
16858
17130
|
if (!fileType) {
|
|
16859
17131
|
throw new Error("[EXULU] File name does not include extension, extension is required for document processing.");
|
|
16860
17132
|
}
|
|
16861
|
-
const UUID =
|
|
17133
|
+
const UUID = randomUUID7();
|
|
16862
17134
|
let buffer;
|
|
16863
17135
|
if (Buffer.isBuffer(file)) {
|
|
16864
17136
|
filePath = path.join(tempDir, `${UUID}.${fileType}`);
|
|
@@ -16888,7 +17160,7 @@ async function documentProcessor({
|
|
|
16888
17160
|
if (!license["advanced-document-processing"]) {
|
|
16889
17161
|
throw new Error("Advanced document processing is an enterprise feature, please add a valid Exulu enterprise license key to use it.");
|
|
16890
17162
|
}
|
|
16891
|
-
const uuid =
|
|
17163
|
+
const uuid = randomUUID7();
|
|
16892
17164
|
const tempDir = path.join(process.cwd(), "temp", uuid);
|
|
16893
17165
|
const localFilesAndFoldersToDelete = [tempDir];
|
|
16894
17166
|
console.log(`[EXULU] Temporary directory for processing document ${name}: ${tempDir}`);
|
package/ee/chunking/markdown.ts
CHANGED
|
@@ -591,7 +591,8 @@ const getMistralApiKey = async () => {
|
|
|
591
591
|
if (process.env.MISTRAL_API_KEY) {
|
|
592
592
|
return process.env.MISTRAL_API_KEY;
|
|
593
593
|
} else {
|
|
594
|
-
|
|
594
|
+
const variable = await ExuluVariables.get("MISTRAL_API_KEY");
|
|
595
|
+
return variable;
|
|
595
596
|
}
|
|
596
597
|
}
|
|
597
598
|
|
|
@@ -667,7 +668,7 @@ async function processPdf(
|
|
|
667
668
|
} else if (config?.processor.name === "mistral") {
|
|
668
669
|
|
|
669
670
|
const MISTRAL_API_KEY = await getMistralApiKey();
|
|
670
|
-
if (MISTRAL_API_KEY) {
|
|
671
|
+
if (!MISTRAL_API_KEY) {
|
|
671
672
|
throw new Error('[EXULU] MISTRAL_API_KEY is not set, please set it in the environment variable via process.env or via an Exulu variable named "MISTRAL_API_KEY".');
|
|
672
673
|
}
|
|
673
674
|
|
package/ee/workers.ts
CHANGED
|
@@ -358,7 +358,33 @@ export const createWorkers = async (
|
|
|
358
358
|
|
|
359
359
|
const exuluStorage = new ExuluStorage({ config });
|
|
360
360
|
|
|
361
|
-
|
|
361
|
+
if (context.processor.filter) {
|
|
362
|
+
const result = await context.processor.filter({
|
|
363
|
+
item: data.inputs,
|
|
364
|
+
user: data.user,
|
|
365
|
+
role: data.role,
|
|
366
|
+
utils: {
|
|
367
|
+
storage: exuluStorage,
|
|
368
|
+
},
|
|
369
|
+
exuluConfig: config,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
if (!result) {
|
|
373
|
+
console.log("[EXULU] Item filtered out by processor, skipping processing execution...");
|
|
374
|
+
return {
|
|
375
|
+
result: "Item filtered out by processor, skipping processing execution...", // last message
|
|
376
|
+
metadata: {
|
|
377
|
+
item: {
|
|
378
|
+
name: data.inputs?.name,
|
|
379
|
+
id: data.inputs?.id,
|
|
380
|
+
external_id: data.inputs?.external_id
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
console.log("[EXULU] POS 2 -- EXULU CONTEXT PROCESS FIELD", data.inputs);
|
|
362
388
|
let processorResult = await context.processor.execute({
|
|
363
389
|
item: data.inputs,
|
|
364
390
|
user: data.user,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exulu/backend",
|
|
3
3
|
"author": "Qventu Bv.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.53.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
7
7
|
"publishConfig": {
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"@ai-sdk/cerebras": "^2.0.29",
|
|
91
91
|
"@ai-sdk/google-vertex": "^4.0.28",
|
|
92
92
|
"@ai-sdk/openai": "^3.0.18",
|
|
93
|
+
"@ai-sdk/openai-compatible": "^2.0.37",
|
|
93
94
|
"@anthropic-ai/sdk": "^0.56.0",
|
|
94
95
|
"@apollo/server": "^5.4.0",
|
|
95
96
|
"@as-integrations/express5": "^1.0.0",
|