@exulu/backend 1.10.0 → 1.12.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 CHANGED
@@ -44,7 +44,6 @@ __export(index_exports, {
44
44
  ExuluQueues: () => queues,
45
45
  ExuluSource: () => ExuluSource,
46
46
  ExuluTool: () => ExuluTool,
47
- ExuluWorkflow: () => ExuluWorkflow,
48
47
  ExuluZodFileType: () => ExuluZodFileType,
49
48
  db: () => db2
50
49
  });
@@ -367,17 +366,6 @@ var sanitizeName = (name) => {
367
366
  return name.toLowerCase().replace(/ /g, "_");
368
367
  };
369
368
 
370
- // types/enums/jobs.ts
371
- var JOB_STATUS_ENUM = {
372
- completed: "completed",
373
- failed: "failed",
374
- delayed: "delayed",
375
- active: "active",
376
- waiting: "waiting",
377
- paused: "paused",
378
- stuck: "stuck"
379
- };
380
-
381
369
  // src/evals/utils/index.tsx
382
370
  var ExuluEvalUtils = {
383
371
  niahTestSet: ({
@@ -752,116 +740,6 @@ var ExuluEmbedder = class {
752
740
  return await this.generateEmbeddings(output);
753
741
  }
754
742
  };
755
- var ExuluWorkflow = class {
756
- id;
757
- name;
758
- description = "";
759
- enable_batch = false;
760
- slug = "";
761
- queue;
762
- steps;
763
- constructor({ id, name, description, steps, queue, enable_batch }) {
764
- this.id = id;
765
- this.name = name;
766
- this.description = description;
767
- this.enable_batch = enable_batch;
768
- this.slug = `/workflows/${generateSlug(this.name)}/run`;
769
- this.queue = queue;
770
- this.steps = steps;
771
- }
772
- start = async ({
773
- inputs: initialInputs,
774
- user,
775
- logger,
776
- job,
777
- session,
778
- agent,
779
- label
780
- }) => {
781
- let inputs;
782
- const { db: db3 } = await postgresClient();
783
- if (!job?.id) {
784
- logger.write(`Creating new job for workflow ${this.name} with inputs: ${JSON.stringify(initialInputs)}`, "INFO");
785
- const result = await db3("jobs").insert({
786
- status: JOB_STATUS_ENUM.active,
787
- name: `Job running '${this.name}' for '${label}'`,
788
- agent,
789
- workflow: this.id,
790
- type: "workflow",
791
- steps: this.steps?.length || 0,
792
- inputs: initialInputs,
793
- session,
794
- user
795
- }).returning(["id", "status"]);
796
- job = result[0];
797
- logger.write(`Created new job for workflow ${this.name}, job id: ${job?.id}`, "INFO");
798
- }
799
- if (!job) {
800
- throw new Error("Job not found, or failed to be created.");
801
- }
802
- if (job.status !== JOB_STATUS_ENUM.active) {
803
- await db3("jobs").update({
804
- status: JOB_STATUS_ENUM.active,
805
- inputs: initialInputs
806
- }).where({ id: job?.id }).returning("id");
807
- }
808
- const runStep = async (step, inputs2) => {
809
- let result;
810
- try {
811
- result = await step.fn({
812
- inputs: inputs2,
813
- logger,
814
- job,
815
- user
816
- });
817
- return result;
818
- } catch (error) {
819
- logger.write(`Step ${step.name} failed with error: ${error.message}`, "ERROR");
820
- if (step.retries && step.retries > 0) {
821
- logger.write(`Retrying step ${step.name} with ${step.retries} retries left`, "INFO");
822
- step.retries--;
823
- let result2 = await runStep(step, inputs2);
824
- return result2;
825
- }
826
- logger.write(`Step ${step.name} failed with error: ${error.message}`, "ERROR");
827
- throw error;
828
- }
829
- };
830
- let final;
831
- try {
832
- for (let i = 0; i < this.steps.length; i++) {
833
- const step = this.steps[i];
834
- if (!step) {
835
- throw new Error("Step not found.");
836
- }
837
- if (i === 0) {
838
- inputs = initialInputs;
839
- }
840
- logger.write(`Running step ${step.name} with inputs: ${JSON.stringify(inputs)}`, "INFO");
841
- let result = await runStep(step, inputs);
842
- inputs = result;
843
- logger.write(`Step ${step.name} output: ${JSON.stringify(result)}`, "INFO");
844
- final = result;
845
- }
846
- await db3("jobs").update({
847
- status: JOB_STATUS_ENUM.completed,
848
- result: JSON.stringify(final),
849
- finished_at: db3.fn.now()
850
- }).where({ id: job?.id }).returning("id");
851
- return final;
852
- } catch (error) {
853
- logger.write(`Workflow ${this.name} failed with error: ${error.message} for job ${job?.id}`, "ERROR");
854
- await db3("jobs").update({
855
- status: JOB_STATUS_ENUM.failed,
856
- result: JSON.stringify({
857
- error: error.message || error,
858
- stack: error.stack || "No stack trace available"
859
- })
860
- }).where({ id: job?.id }).returning("id");
861
- throw error;
862
- }
863
- };
864
- };
865
743
  var ExuluLogger = class {
866
744
  logPath;
867
745
  job;
@@ -1658,7 +1536,15 @@ var authentication = async ({
1658
1536
  user: {
1659
1537
  type: "api",
1660
1538
  id: "XXXX-XXXX-XXXX-XXXX",
1661
- email: "internal@exulu.com"
1539
+ email: "internal@exulu.com",
1540
+ role: {
1541
+ id: "internal",
1542
+ name: "Internal",
1543
+ agents: "read",
1544
+ workflows: "read",
1545
+ variables: "read",
1546
+ users: "read"
1547
+ }
1662
1548
  }
1663
1549
  };
1664
1550
  }
@@ -1673,6 +1559,12 @@ var authentication = async ({
1673
1559
  };
1674
1560
  }
1675
1561
  const user = await db3.from("users").select("*").where("email", authtoken?.email).first();
1562
+ if (user?.role) {
1563
+ const role = await db3.from("roles").select("*").where("id", user?.role).first();
1564
+ if (role) {
1565
+ user.role = role;
1566
+ }
1567
+ }
1676
1568
  if (!user) {
1677
1569
  return {
1678
1570
  error: true,
@@ -1730,6 +1622,12 @@ var authentication = async ({
1730
1622
  await db3.from("users").where({ id: user.id }).update({
1731
1623
  last_used: /* @__PURE__ */ new Date()
1732
1624
  }).returning("id");
1625
+ if (user?.role) {
1626
+ const role = await db3.from("roles").select("*").where("id", user?.role).first();
1627
+ if (role) {
1628
+ user.role = role;
1629
+ }
1630
+ }
1733
1631
  return {
1734
1632
  error: false,
1735
1633
  code: 200,
@@ -1921,7 +1819,7 @@ var ExuluQueues = class {
1921
1819
  return existing;
1922
1820
  }
1923
1821
  if (!redisServer.host?.length || !redisServer.port?.length) {
1924
- console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or workflow (look for ExuluQueues.use() ).`);
1822
+ console.error(`[EXULU] no redis server configured, but you are trying to use a queue ( ${name}), likely in an agent or embedder (look for ExuluQueues.use() ).`);
1925
1823
  throw new Error(`[EXULU] no redis server configured.`);
1926
1824
  }
1927
1825
  const newQueue = new import_bullmq4.Queue(`${name}`, { connection: redisServer });
@@ -2163,9 +2061,13 @@ function createMutations(table) {
2163
2061
  if (!hasRBAC) {
2164
2062
  return true;
2165
2063
  }
2166
- if (user.type === "api" || user.super_admin === true) {
2064
+ if (user.super_admin === true) {
2167
2065
  return true;
2168
2066
  }
2067
+ if (!user.role || !(table.name.plural.includes("agent") && user.role.agents === "write") && !(table.name.plural.includes("workflow") && user.role.workflows === "write") && !(table.name.plural.includes("variable") && user.role.variables === "write") && !(table.name.plural.includes("user") && user.role.users === "write")) {
2068
+ console.error("Access control error: no role found for current user or no access to entity type.");
2069
+ throw new Error("Access control error: no role found for current user or no access to entity type.");
2070
+ }
2169
2071
  try {
2170
2072
  const authResult = await requestValidators.authenticate(req);
2171
2073
  if (authResult.error || !authResult.user) {
@@ -2360,9 +2262,13 @@ var applyAccessControl = (table, user, query) => {
2360
2262
  if (!hasRBAC) {
2361
2263
  return query;
2362
2264
  }
2363
- if (user.type === "api" || user.super_admin === true) {
2265
+ if (user.super_admin === true) {
2364
2266
  return query;
2365
2267
  }
2268
+ if (!user.role || !(table.name.plural.includes("agent") && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural.includes("workflow") && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural.includes("variable") && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural.includes("user") && (user.role.users === "read" || user.role.users === "write"))) {
2269
+ console.error("Access control error: no role found or no access to entity type.");
2270
+ return query.where("1", "=", "0");
2271
+ }
2366
2272
  try {
2367
2273
  query = query.where(function() {
2368
2274
  this.where("rights_mode", "public");
@@ -2752,12 +2658,130 @@ var agentSessionsSchema = {
2752
2658
  // next auth stores users with id type SERIAL, so we need to use number
2753
2659
  type: "number"
2754
2660
  },
2661
+ {
2662
+ name: "role",
2663
+ type: "uuid"
2664
+ },
2755
2665
  {
2756
2666
  name: "title",
2757
2667
  type: "text"
2758
2668
  }
2759
2669
  ]
2760
2670
  };
2671
+ var variablesSchema = {
2672
+ name: {
2673
+ plural: "variables",
2674
+ singular: "variable"
2675
+ },
2676
+ fields: [
2677
+ {
2678
+ name: "name",
2679
+ type: "text",
2680
+ index: true,
2681
+ unique: true
2682
+ },
2683
+ {
2684
+ name: "value",
2685
+ type: "longText"
2686
+ },
2687
+ {
2688
+ name: "encrypted",
2689
+ type: "boolean",
2690
+ default: false
2691
+ }
2692
+ ]
2693
+ };
2694
+ var workflowTemplatesSchema = {
2695
+ name: {
2696
+ plural: "workflow_templates",
2697
+ singular: "workflow_template"
2698
+ },
2699
+ RBAC: true,
2700
+ fields: [
2701
+ {
2702
+ name: "name",
2703
+ type: "text",
2704
+ required: true
2705
+ },
2706
+ {
2707
+ name: "description",
2708
+ type: "text"
2709
+ },
2710
+ {
2711
+ name: "owner",
2712
+ type: "number",
2713
+ required: true
2714
+ },
2715
+ {
2716
+ name: "visibility",
2717
+ type: "text",
2718
+ required: true
2719
+ },
2720
+ {
2721
+ name: "shared_user_ids",
2722
+ type: "json"
2723
+ },
2724
+ {
2725
+ name: "shared_role_ids",
2726
+ type: "json"
2727
+ },
2728
+ {
2729
+ name: "variables",
2730
+ type: "json"
2731
+ },
2732
+ {
2733
+ name: "steps_json",
2734
+ type: "json",
2735
+ required: true
2736
+ },
2737
+ {
2738
+ name: "example_metadata_json",
2739
+ type: "json"
2740
+ }
2741
+ ]
2742
+ };
2743
+ var agentsSchema = {
2744
+ name: {
2745
+ plural: "agents",
2746
+ singular: "agent"
2747
+ },
2748
+ RBAC: true,
2749
+ fields: [
2750
+ {
2751
+ name: "name",
2752
+ type: "text"
2753
+ },
2754
+ {
2755
+ name: "description",
2756
+ type: "text"
2757
+ },
2758
+ {
2759
+ name: "providerApiKey",
2760
+ type: "text"
2761
+ },
2762
+ {
2763
+ name: "extensions",
2764
+ type: "json"
2765
+ },
2766
+ {
2767
+ name: "backend",
2768
+ type: "text"
2769
+ },
2770
+ {
2771
+ name: "type",
2772
+ type: "text"
2773
+ },
2774
+ {
2775
+ name: "active",
2776
+ type: "boolean",
2777
+ default: false
2778
+ },
2779
+ {
2780
+ name: "tools",
2781
+ type: "json"
2782
+ }
2783
+ ]
2784
+ };
2761
2785
  var usersSchema = {
2762
2786
  name: {
2763
2787
  plural: "users",
@@ -2845,13 +2869,24 @@ var rolesSchema = {
2845
2869
  type: "text"
2846
2870
  },
2847
2871
  {
2848
- name: "is_admin",
2849
- type: "boolean",
2850
- default: false
2872
+ name: agentsSchema.name.plural,
2873
+ type: "text"
2874
+ // write | read access to agents
2851
2875
  },
2852
2876
  {
2853
- name: "agents",
2854
- type: "json"
2877
+ name: "workflows",
2878
+ type: "text"
2879
+ // write | read access to workflows
2880
+ },
2881
+ {
2882
+ name: variablesSchema.name.plural,
2883
+ type: "text"
2884
+ // write | read access to variables
2885
+ },
2886
+ {
2887
+ name: usersSchema.name.plural,
2888
+ type: "text"
2889
+ // write | read access to users
2855
2890
  }
2856
2891
  ]
2857
2892
  };
@@ -2879,26 +2914,6 @@ var statisticsSchema = {
2879
2914
  }
2880
2915
  ]
2881
2916
  };
2882
- var workflowSchema = {
2883
- name: {
2884
- plural: "workflows",
2885
- singular: "workflow"
2886
- },
2887
- fields: [
2888
- {
2889
- name: "workflow_name",
2890
- type: "text"
2891
- },
2892
- {
2893
- name: "run_id",
2894
- type: "text"
2895
- },
2896
- {
2897
- name: "snapshot",
2898
- type: "text"
2899
- }
2900
- ]
2901
- };
2902
2917
  var evalResultsSchema = {
2903
2918
  name: {
2904
2919
  plural: "eval_results",
@@ -3016,71 +3031,6 @@ var jobsSchema = {
3016
3031
  }
3017
3032
  ]
3018
3033
  };
3019
- var agentsSchema = {
3020
- name: {
3021
- plural: "agents",
3022
- singular: "agent"
3023
- },
3024
- RBAC: true,
3025
- fields: [
3026
- {
3027
- name: "name",
3028
- type: "text"
3029
- },
3030
- {
3031
- name: "description",
3032
- type: "text"
3033
- },
3034
- {
3035
- name: "providerApiKey",
3036
- type: "text"
3037
- },
3038
- {
3039
- name: "extensions",
3040
- type: "json"
3041
- },
3042
- {
3043
- name: "backend",
3044
- type: "text"
3045
- },
3046
- {
3047
- name: "type",
3048
- type: "text"
3049
- },
3050
- {
3051
- name: "active",
3052
- type: "boolean",
3053
- default: false
3054
- },
3055
- {
3056
- name: "tools",
3057
- type: "json"
3058
- }
3059
- ]
3060
- };
3061
- var variablesSchema = {
3062
- name: {
3063
- plural: "variables",
3064
- singular: "variable"
3065
- },
3066
- fields: [
3067
- {
3068
- name: "name",
3069
- type: "text",
3070
- index: true,
3071
- unique: true
3072
- },
3073
- {
3074
- name: "value",
3075
- type: "longText"
3076
- },
3077
- {
3078
- name: "encrypted",
3079
- type: "boolean",
3080
- default: false
3081
- }
3082
- ]
3083
- };
3084
3034
  var rbacSchema = {
3085
3035
  name: {
3086
3036
  plural: "rbac",
@@ -3118,55 +3068,6 @@ var rbacSchema = {
3118
3068
  }
3119
3069
  ]
3120
3070
  };
3121
- var workflowTemplatesSchema = {
3122
- name: {
3123
- plural: "workflow_templates",
3124
- singular: "workflow_template"
3125
- },
3126
- RBAC: true,
3127
- fields: [
3128
- {
3129
- name: "name",
3130
- type: "text",
3131
- required: true
3132
- },
3133
- {
3134
- name: "description",
3135
- type: "text"
3136
- },
3137
- {
3138
- name: "owner",
3139
- type: "number",
3140
- required: true
3141
- },
3142
- {
3143
- name: "visibility",
3144
- type: "text",
3145
- required: true
3146
- },
3147
- {
3148
- name: "shared_user_ids",
3149
- type: "json"
3150
- },
3151
- {
3152
- name: "shared_role_ids",
3153
- type: "json"
3154
- },
3155
- {
3156
- name: "variables",
3157
- type: "json"
3158
- },
3159
- {
3160
- name: "steps_json",
3161
- type: "json",
3162
- required: true
3163
- },
3164
- {
3165
- name: "example_metadata_json",
3166
- type: "json"
3167
- }
3168
- ]
3169
- };
3170
3071
  var addRBACfields = (schema) => {
3171
3072
  if (schema.RBAC) {
3172
3073
  console.log(`[EXULU] Adding rights_mode field to ${schema.name.plural} table.`);
@@ -3194,7 +3095,6 @@ var coreSchemas = {
3194
3095
  usersSchema: () => addRBACfields(usersSchema),
3195
3096
  rolesSchema: () => addRBACfields(rolesSchema),
3196
3097
  statisticsSchema: () => addRBACfields(statisticsSchema),
3197
- workflowSchema: () => addRBACfields(workflowSchema),
3198
3098
  evalResultsSchema: () => addRBACfields(evalResultsSchema),
3199
3099
  jobsSchema: () => addRBACfields(jobsSchema),
3200
3100
  variablesSchema: () => addRBACfields(variablesSchema),
@@ -3636,7 +3536,7 @@ var REQUEST_SIZE_LIMIT = "50mb";
3636
3536
  var global_queues = {
3637
3537
  logs_cleaner: "logs-cleaner"
3638
3538
  };
3639
- var { agentsSchema: agentsSchema2, evalResultsSchema: evalResultsSchema2, jobsSchema: jobsSchema2, agentSessionsSchema: agentSessionsSchema2, agentMessagesSchema: agentMessagesSchema2, rolesSchema: rolesSchema2, usersSchema: usersSchema2, workflowSchema: workflowSchema2, variablesSchema: variablesSchema2, workflowTemplatesSchema: workflowTemplatesSchema2, rbacSchema: rbacSchema2 } = coreSchemas.get();
3539
+ var { agentsSchema: agentsSchema2, evalResultsSchema: evalResultsSchema2, jobsSchema: jobsSchema2, agentSessionsSchema: agentSessionsSchema2, agentMessagesSchema: agentMessagesSchema2, rolesSchema: rolesSchema2, usersSchema: usersSchema2, variablesSchema: variablesSchema2, workflowTemplatesSchema: workflowTemplatesSchema2, rbacSchema: rbacSchema2, statisticsSchema: statisticsSchema2 } = coreSchemas.get();
3640
3540
  var createRecurringJobs = async () => {
3641
3541
  console.log("[EXULU] creating recurring jobs.");
3642
3542
  const recurringJobSchedulersLogs = [];
@@ -3670,7 +3570,7 @@ var createRecurringJobs = async () => {
3670
3570
  console.table(recurringJobSchedulersLogs);
3671
3571
  return queue;
3672
3572
  };
3673
- var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
3573
+ var createExpressRoutes = async (app, agents, tools, contexts) => {
3674
3574
  const routeLogs = [];
3675
3575
  var corsOptions = {
3676
3576
  origin: "*",
@@ -3720,8 +3620,6 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
3720
3620
  routeLogs.push(
3721
3621
  { route: "/agents", method: "GET", note: "List all agents" },
3722
3622
  { route: "/agents/:id", method: "GET", note: "Get specific agent" },
3723
- { route: "/workflows", method: "GET", note: "List all workflows" },
3724
- { route: "/workflows/:id", method: "GET", note: "Get specific workflow" },
3725
3623
  { route: "/contexts", method: "GET", note: "List all contexts" },
3726
3624
  { route: "/contexts/:id", method: "GET", note: "Get specific context" },
3727
3625
  { route: "/contexts/statistics", method: "GET", note: "Get context statistics" },
@@ -3745,12 +3643,12 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
3745
3643
  rolesSchema2(),
3746
3644
  agentsSchema2(),
3747
3645
  jobsSchema2(),
3748
- workflowSchema2(),
3749
3646
  evalResultsSchema2(),
3750
3647
  agentSessionsSchema2(),
3751
3648
  agentMessagesSchema2(),
3752
3649
  variablesSchema2(),
3753
3650
  workflowTemplatesSchema2(),
3651
+ statisticsSchema2(),
3754
3652
  rbacSchema2()
3755
3653
  ]
3756
3654
  );
@@ -4474,50 +4372,6 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
4474
4372
  }))
4475
4373
  })));
4476
4374
  });
4477
- console.log("[EXULU] workflows get list");
4478
- app.get(`/workflows`, async (req, res) => {
4479
- const authenticationResult = await requestValidators.authenticate(req);
4480
- if (!authenticationResult.user?.id) {
4481
- res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
4482
- return;
4483
- }
4484
- res.status(200).json(workflows.map((workflow) => ({
4485
- id: workflow.id,
4486
- name: workflow.name,
4487
- slug: workflow.slug,
4488
- enable_batch: workflow.enable_batch,
4489
- queue: workflow.queue?.name,
4490
- inputSchema: workflow.steps[0]?.inputSchema ? (0, import_zodex.zerialize)(workflow.steps[0].inputSchema) : null
4491
- })));
4492
- });
4493
- console.log("[EXULU] workflow by id");
4494
- app.get(`/workflows/:id`, async (req, res) => {
4495
- const authenticationResult = await requestValidators.authenticate(req);
4496
- if (!authenticationResult.user?.id) {
4497
- res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
4498
- return;
4499
- }
4500
- const id = req.params.id;
4501
- if (!id) {
4502
- res.status(400).json({
4503
- message: "Missing id in request."
4504
- });
4505
- return;
4506
- }
4507
- const workflow = workflows.find((workflow2) => workflow2.id === id);
4508
- if (!workflow) {
4509
- res.status(400).json({
4510
- message: "Workflow not found."
4511
- });
4512
- return;
4513
- }
4514
- res.status(200).json({
4515
- ...workflow,
4516
- queue: workflow.queue?.name,
4517
- inputSchema: workflow.steps[0]?.inputSchema ? (0, import_zodex.zerialize)(workflow.steps[0].inputSchema) : null,
4518
- workflow: void 0
4519
- });
4520
- });
4521
4375
  console.log("[EXULU] contexts");
4522
4376
  contexts.forEach((context) => {
4523
4377
  const sources = context.sources.get();
@@ -4646,66 +4500,6 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
4646
4500
  }
4647
4501
  });
4648
4502
  });
4649
- console.log("[EXULU] workflows");
4650
- workflows.forEach((workflow) => {
4651
- routeLogs.push({
4652
- route: workflow.slug,
4653
- method: "POST",
4654
- note: `Execute workflow ${workflow.name}`
4655
- });
4656
- app.post(`${workflow.slug}`, async (req, res) => {
4657
- const authenticationResult = await requestValidators.authenticate(req);
4658
- if (!authenticationResult.user?.id) {
4659
- res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
4660
- return;
4661
- }
4662
- const requestValidationResult = requestValidators.workflows(req);
4663
- if (requestValidationResult.error) {
4664
- res.status(requestValidationResult.code || 500).json({ detail: `${requestValidationResult.message}` });
4665
- return;
4666
- }
4667
- const inputs = await preprocessInputs(req.body.inputs);
4668
- if (workflow.queue) {
4669
- const job = await bullmqDecorator({
4670
- label: `Job running '${workflow.name}' for '${req.body.label}'`,
4671
- agent: req.body.agent,
4672
- workflow: workflow.id,
4673
- steps: workflow.steps?.length || 0,
4674
- type: "workflow",
4675
- inputs,
4676
- session: req.body.session,
4677
- queue: workflow.queue,
4678
- user: authenticationResult.user.id
4679
- });
4680
- res.status(200).json({
4681
- "job": {
4682
- "status": "waiting",
4683
- "name": job.name,
4684
- "queue": workflow.queue.name,
4685
- "redisId": job.redis,
4686
- "jobId": job.id
4687
- },
4688
- "output": {}
4689
- });
4690
- return;
4691
- }
4692
- console.log("[EXULU] running workflow with inputs.", inputs);
4693
- const logger = new ExuluLogger();
4694
- const result = await workflow.start({
4695
- inputs,
4696
- user: authenticationResult.user.id,
4697
- logger,
4698
- session: req.body.session,
4699
- agent: req.body.agent,
4700
- label: req.body.label
4701
- });
4702
- res.status(200).json({
4703
- "job": {},
4704
- "output": result
4705
- });
4706
- return;
4707
- });
4708
- });
4709
4503
  if (process.env.COMPANION_S3_REGION && process.env.COMPANION_S3_KEY && process.env.COMPANION_S3_SECRET) {
4710
4504
  await createUppyRoutes(app);
4711
4505
  } else {
@@ -4728,9 +4522,11 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
4728
4522
  return;
4729
4523
  }
4730
4524
  const { db: db3 } = await postgresClient();
4731
- const agent = await db3.from("agents").where({
4732
- id: req.params.id
4733
- }).first();
4525
+ let query = db3("agents");
4526
+ query.select("*");
4527
+ query = applyAccessControl(agentsSchema2(), authenticationResult.user, query);
4528
+ query.where({ id: req.params.id });
4529
+ const agent = await query.first();
4734
4530
  if (!agent) {
4735
4531
  const arrayBuffer = createCustomAnthropicStreamingMessage(`
4736
4532
  \x1B[41m -- Agent ${req.params.id} not found or you do not have access to it. --
@@ -4828,48 +4624,6 @@ var createExpressRoutes = async (app, agents, tools, workflows, contexts) => {
4828
4624
  });
4829
4625
  return app;
4830
4626
  };
4831
- var preprocessInputs = async (data) => {
4832
- for (const key in data) {
4833
- if (key.includes("exulu_file_")) {
4834
- const url = await getPresignedFileUrl(data[key]);
4835
- const newKey = key.replace("exulu_file_", "");
4836
- data[newKey] = url;
4837
- delete data[key];
4838
- } else if (Array.isArray(data[key])) {
4839
- for (let i = 0; i < data[key].length; i++) {
4840
- if (typeof data[key][i] === "object") {
4841
- await preprocessInputs(data[key][i]);
4842
- }
4843
- }
4844
- } else if (typeof data[key] === "object") {
4845
- await preprocessInputs(data[key]);
4846
- }
4847
- }
4848
- return data;
4849
- };
4850
- var getPresignedFileUrl = async (key) => {
4851
- if (!process.env.NEXT_BACKEND) {
4852
- throw new Error("Missing process.env.NEXT_BACKEND");
4853
- }
4854
- if (!process.env.INTERNAL_SECRET) {
4855
- throw new Error("Missing process.env.NEXT_BACKEND");
4856
- }
4857
- console.log(`[EXULU] fetching presigned url for file with key: ${key}`);
4858
- let url = `${process.env.NEXT_BACKEND}/s3/download?key=${key}`;
4859
- const response = await fetch(url, {
4860
- method: "GET",
4861
- headers: {
4862
- "Content-Type": "application/json",
4863
- "Internal-Key": process.env.INTERNAL_SECRET
4864
- }
4865
- });
4866
- const json = await response.json();
4867
- if (!json.url) {
4868
- throw new Error(`Could not generate presigned url for file with key: ${key}`);
4869
- }
4870
- console.log(`[EXULU] presigned url for file with key: ${key}, generated: ${json.url}`);
4871
- return json.url;
4872
- };
4873
4627
  var createCustomAnthropicStreamingMessage = (message) => {
4874
4628
  const responseData = {
4875
4629
  type: "message",
@@ -4887,10 +4641,10 @@ var createCustomAnthropicStreamingMessage = (message) => {
4887
4641
 
4888
4642
  // src/registry/workers.ts
4889
4643
  var import_ioredis = __toESM(require("ioredis"), 1);
4890
- var import_bullmq7 = require("bullmq");
4644
+ var import_bullmq6 = require("bullmq");
4891
4645
 
4892
4646
  // src/registry/utils.ts
4893
- var import_bullmq6 = require("bullmq");
4647
+ var import_bullmq5 = require("bullmq");
4894
4648
  var bullmq = {
4895
4649
  validate: (bullmqJob) => {
4896
4650
  if (!bullmqJob.data) {
@@ -4936,7 +4690,7 @@ var fs2 = __toESM(require("fs"), 1);
4936
4690
  var import_path = __toESM(require("path"), 1);
4937
4691
  var defaultLogsDir = import_path.default.join(process.cwd(), "logs");
4938
4692
  var redisConnection;
4939
- var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
4693
+ var createWorkers = async (queues2, contexts, _logsDir) => {
4940
4694
  if (!redisServer.host || !redisServer.port) {
4941
4695
  console.error("[EXULU] you are trying to start worker, but no redis server is configured in the environment.");
4942
4696
  throw new Error("No redis server configured in the environment, so cannot start worker.");
@@ -4950,7 +4704,7 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
4950
4704
  const logsDir = _logsDir || defaultLogsDir;
4951
4705
  const workers = queues2.map((queue) => {
4952
4706
  console.log(`[EXULU] creating worker for queue ${queue}.`);
4953
- const worker = new import_bullmq7.Worker(
4707
+ const worker = new import_bullmq6.Worker(
4954
4708
  `${queue}`,
4955
4709
  async (bullmqJob) => {
4956
4710
  const { db: db3 } = await postgresClient();
@@ -5062,7 +4816,7 @@ var createWorkers = async (queues2, contexts, workflows, _logsDir) => {
5062
4816
  return workers;
5063
4817
  };
5064
4818
  var createLogsCleanerWorker = (logsDir) => {
5065
- const logsCleaner = new import_bullmq7.Worker(
4819
+ const logsCleaner = new import_bullmq6.Worker(
5066
4820
  global_queues.logs_cleaner,
5067
4821
  async (job) => {
5068
4822
  console.log(`[EXULU] recurring job ${job.id}.`);
@@ -5107,7 +4861,7 @@ var ExuluMCP = class {
5107
4861
  express;
5108
4862
  constructor() {
5109
4863
  }
5110
- create = async ({ express: express3, contexts, agents, workflows, config, tools }) => {
4864
+ create = async ({ express: express3, contexts, agents, config, tools }) => {
5111
4865
  this.express = express3;
5112
4866
  if (!this.server) {
5113
4867
  console.log("[EXULU] Creating MCP server.");
@@ -5288,7 +5042,6 @@ var defaultAgent = new ExuluAgent({
5288
5042
  // src/registry/index.ts
5289
5043
  var ExuluApp = class {
5290
5044
  _agents = [];
5291
- _workflows = [];
5292
5045
  _config;
5293
5046
  _queues = [];
5294
5047
  _contexts = {};
@@ -5298,8 +5051,7 @@ var ExuluApp = class {
5298
5051
  }
5299
5052
  // Factory function so we can async
5300
5053
  // initialize the MCP server if needed.
5301
- create = async ({ contexts, agents, workflows, config, tools }) => {
5302
- this._workflows = workflows ?? [];
5054
+ create = async ({ contexts, agents, config, tools }) => {
5303
5055
  this._contexts = contexts ?? {};
5304
5056
  this._agents = [
5305
5057
  claudeCodeAgent,
@@ -5316,8 +5068,7 @@ var ExuluApp = class {
5316
5068
  ];
5317
5069
  const contextsArray = Object.values(contexts || {});
5318
5070
  const queues2 = [
5319
- ...contextsArray?.length ? contextsArray.map((context) => context.embedder.queue?.name || null) : [],
5320
- ...workflows?.length ? workflows.map((workflow) => workflow.queue?.name || null) : []
5071
+ ...contextsArray?.length ? contextsArray.map((context) => context.embedder.queue?.name || null) : []
5321
5072
  ];
5322
5073
  this._queues = [...new Set(queues2.filter((o) => !!o))];
5323
5074
  if (!this._expressApp) {
@@ -5345,15 +5096,9 @@ var ExuluApp = class {
5345
5096
  agent(id) {
5346
5097
  return this._agents.find((x) => x.id === id);
5347
5098
  }
5348
- workflow(id) {
5349
- return this._workflows.find((x) => x.id === id);
5350
- }
5351
5099
  get contexts() {
5352
5100
  return Object.values(this._contexts ?? {});
5353
5101
  }
5354
- get workflows() {
5355
- return this._workflows;
5356
- }
5357
5102
  get agents() {
5358
5103
  return this._agents;
5359
5104
  }
@@ -5363,7 +5108,6 @@ var ExuluApp = class {
5363
5108
  return await createWorkers(
5364
5109
  this._queues,
5365
5110
  Object.values(this._contexts ?? {}),
5366
- this._workflows,
5367
5111
  this._config?.workers?.logsDir
5368
5112
  );
5369
5113
  }
@@ -5380,7 +5124,6 @@ var ExuluApp = class {
5380
5124
  app,
5381
5125
  this._agents,
5382
5126
  this._tools,
5383
- this._workflows,
5384
5127
  Object.values(this._contexts ?? {})
5385
5128
  );
5386
5129
  if (this._config?.MCP.enabled) {
@@ -5389,7 +5132,6 @@ var ExuluApp = class {
5389
5132
  express: app,
5390
5133
  contexts: this._contexts,
5391
5134
  agents: this._agents,
5392
- workflows: this._workflows,
5393
5135
  config: this._config,
5394
5136
  tools: this._tools
5395
5137
  });
@@ -6611,8 +6353,10 @@ var generateApiKey = async (name, email) => {
6611
6353
  console.log("[EXULU] Creating default admin role.");
6612
6354
  const role = await db3.from("roles").insert({
6613
6355
  name: "admin",
6614
- is_admin: true,
6615
- agents: []
6356
+ agents: "write",
6357
+ workflows: "write",
6358
+ variables: "write",
6359
+ users: "write"
6616
6360
  }).returning("id");
6617
6361
  roleId = role[0].id;
6618
6362
  } else {
@@ -6647,7 +6391,7 @@ var generateApiKey = async (name, email) => {
6647
6391
  };
6648
6392
 
6649
6393
  // src/postgres/init-db.ts
6650
- var { agentsSchema: agentsSchema3, evalResultsSchema: evalResultsSchema3, jobsSchema: jobsSchema3, agentSessionsSchema: agentSessionsSchema3, agentMessagesSchema: agentMessagesSchema3, rolesSchema: rolesSchema3, usersSchema: usersSchema3, statisticsSchema: statisticsSchema2, variablesSchema: variablesSchema3, workflowTemplatesSchema: workflowTemplatesSchema3, rbacSchema: rbacSchema3 } = coreSchemas.get();
6394
+ var { agentsSchema: agentsSchema3, evalResultsSchema: evalResultsSchema3, jobsSchema: jobsSchema3, agentSessionsSchema: agentSessionsSchema3, agentMessagesSchema: agentMessagesSchema3, rolesSchema: rolesSchema3, usersSchema: usersSchema3, statisticsSchema: statisticsSchema3, variablesSchema: variablesSchema3, workflowTemplatesSchema: workflowTemplatesSchema3, rbacSchema: rbacSchema3 } = coreSchemas.get();
6651
6395
  var addMissingFields = async (knex, tableName, fields, skipFields = []) => {
6652
6396
  for (const field of fields) {
6653
6397
  const { type, name, default: defaultValue, unique } = field;
@@ -6675,7 +6419,7 @@ var up = async function(knex) {
6675
6419
  agentMessagesSchema3(),
6676
6420
  rolesSchema3(),
6677
6421
  evalResultsSchema3(),
6678
- statisticsSchema2(),
6422
+ statisticsSchema3(),
6679
6423
  jobsSchema3(),
6680
6424
  rbacSchema3(),
6681
6425
  agentsSchema3(),
@@ -6769,8 +6513,10 @@ var execute = async () => {
6769
6513
  console.log("[EXULU] Creating default admin role.");
6770
6514
  const role = await db3.from("roles").insert({
6771
6515
  name: "admin",
6772
- is_admin: true,
6773
- agents: JSON.stringify([])
6516
+ agents: "write",
6517
+ workflows: "write",
6518
+ variables: "write",
6519
+ users: "write"
6774
6520
  }).returning("id");
6775
6521
  roleId = role[0].id;
6776
6522
  } else {
@@ -6800,6 +6546,17 @@ var execute = async () => {
6800
6546
  return;
6801
6547
  };
6802
6548
 
6549
+ // types/enums/jobs.ts
6550
+ var JOB_STATUS_ENUM = {
6551
+ completed: "completed",
6552
+ failed: "failed",
6553
+ delayed: "delayed",
6554
+ active: "active",
6555
+ waiting: "waiting",
6556
+ paused: "paused",
6557
+ stuck: "stuck"
6558
+ };
6559
+
6803
6560
  // src/index.ts
6804
6561
  var ExuluJobs = {
6805
6562
  redis: redisClient,
@@ -6835,7 +6592,6 @@ var ExuluChunkers = {
6835
6592
  ExuluQueues,
6836
6593
  ExuluSource,
6837
6594
  ExuluTool,
6838
- ExuluWorkflow,
6839
6595
  ExuluZodFileType,
6840
6596
  db
6841
6597
  });