@exulu/backend 1.42.2 → 1.43.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.js CHANGED
@@ -1435,6 +1435,10 @@ var addCoreFields = (schema) => {
1435
1435
  name: "last_processed_at",
1436
1436
  type: "date"
1437
1437
  });
1438
+ schema.fields.push({
1439
+ name: "embeddings_updated_at",
1440
+ type: "date"
1441
+ });
1438
1442
  if (schema.RBAC) {
1439
1443
  if (!schema.fields.some((field) => field.name === "rights_mode")) {
1440
1444
  schema.fields.push({
@@ -1648,7 +1652,8 @@ var checkRecordAccess = async (record, request, user) => {
1648
1652
  const isPublic = record.rights_mode === "public";
1649
1653
  const byUsers = record.rights_mode === "users";
1650
1654
  const byRoles = record.rights_mode === "roles";
1651
- const isCreator = user ? record.created_by === user.id.toString() : false;
1655
+ const createdBy = typeof record.created_by === "string" ? record.created_by : record.created_by?.toString();
1656
+ const isCreator = user ? createdBy === user.id.toString() : false;
1652
1657
  const isAdmin = user ? user.super_admin : false;
1653
1658
  const isApi = user ? user.type === "api" : false;
1654
1659
  let hasAccess = "none";
@@ -1855,6 +1860,7 @@ ${enumValues}
1855
1860
  fields.push(" maxContextLength: Int");
1856
1861
  fields.push(" provider: String");
1857
1862
  fields.push(" authenticationInformation: String");
1863
+ fields.push(" systemInstructions: String");
1858
1864
  fields.push(" slug: String");
1859
1865
  }
1860
1866
  const rbacField = table.RBAC ? " RBAC: RBACData" : "";
@@ -1919,6 +1925,8 @@ input FilterOperatorDate {
1919
1925
  input FilterOperatorFloat {
1920
1926
  eq: Float
1921
1927
  ne: Float
1928
+ lte: Float
1929
+ gte: Float
1922
1930
  in: [Float]
1923
1931
  and: [FilterOperatorFloat]
1924
1932
  or: [FilterOperatorFloat]
@@ -1982,7 +1990,11 @@ var getRequestedFields = (info) => {
1982
1990
  return fields.filter((field) => field !== "pageInfo" && field !== "items" && field !== "RBAC");
1983
1991
  };
1984
1992
  var handleRBACUpdate = async (db3, entityName, resourceId, rbacData, existingRbacRecords) => {
1985
- const { users = [], roles = [], projects = [] } = rbacData;
1993
+ const {
1994
+ users = [],
1995
+ roles = []
1996
+ /* projects = [] */
1997
+ } = rbacData;
1986
1998
  if (!existingRbacRecords) {
1987
1999
  existingRbacRecords = await db3.from("rbac").where({
1988
2000
  entity: entityName,
@@ -1991,25 +2003,19 @@ var handleRBACUpdate = async (db3, entityName, resourceId, rbacData, existingRba
1991
2003
  }
1992
2004
  const newUserRecords = new Set(users.map((u) => `${u.id}:${u.rights}`));
1993
2005
  const newRoleRecords = new Set(roles.map((r) => `${r.id}:${r.rights}`));
1994
- const newProjectRecords = new Set(projects.map((p) => `${p.id}:${p.rights}`));
1995
2006
  const existingUserRecords = new Set(existingRbacRecords.filter((r) => r.access_type === "User").map((r) => `${r.user_id}:${r.rights}`));
1996
2007
  const existingRoleRecords = new Set(existingRbacRecords.filter((r) => r.access_type === "Role").map((r) => `${r.role_id}:${r.rights}`));
1997
2008
  const existingProjectRecords = new Set(existingRbacRecords.filter((r) => r.access_type === "Project").map((r) => `${r.project_id}:${r.rights}`));
1998
2009
  const usersToCreate = users.filter((u) => !existingUserRecords.has(`${u.id}:${u.rights}`));
1999
2010
  const rolesToCreate = roles.filter((r) => !existingRoleRecords.has(`${r.id}:${r.rights}`));
2000
- const projectsToCreate = projects.filter((p) => !existingProjectRecords.has(`${p.id}:${p.rights}`));
2001
2011
  const usersToRemove = existingRbacRecords.filter((r) => r.access_type === "User" && !newUserRecords.has(`${r.user_id}:${r.rights}`));
2002
2012
  const rolesToRemove = existingRbacRecords.filter((r) => r.access_type === "Role" && !newRoleRecords.has(`${r.role_id}:${r.rights}`));
2003
- const projectsToRemove = existingRbacRecords.filter((r) => r.access_type === "Project" && !newProjectRecords.has(`${r.project_id}:${r.rights}`));
2004
2013
  if (usersToRemove.length > 0) {
2005
2014
  await db3.from("rbac").whereIn("id", usersToRemove.map((r) => r.id)).del();
2006
2015
  }
2007
2016
  if (rolesToRemove.length > 0) {
2008
2017
  await db3.from("rbac").whereIn("id", rolesToRemove.map((r) => r.id)).del();
2009
2018
  }
2010
- if (projectsToRemove.length > 0) {
2011
- await db3.from("rbac").whereIn("id", projectsToRemove.map((r) => r.id)).del();
2012
- }
2013
2019
  const recordsToInsert = [];
2014
2020
  usersToCreate.forEach((user) => {
2015
2021
  recordsToInsert.push({
@@ -2033,17 +2039,6 @@ var handleRBACUpdate = async (db3, entityName, resourceId, rbacData, existingRba
2033
2039
  updatedAt: /* @__PURE__ */ new Date()
2034
2040
  });
2035
2041
  });
2036
- projectsToCreate.forEach((project) => {
2037
- recordsToInsert.push({
2038
- entity: entityName,
2039
- access_type: "Project",
2040
- target_resource_id: resourceId,
2041
- project_id: project.id,
2042
- rights: project.rights,
2043
- createdAt: /* @__PURE__ */ new Date(),
2044
- updatedAt: /* @__PURE__ */ new Date()
2045
- });
2046
- });
2047
2042
  if (recordsToInsert.length > 0) {
2048
2043
  await db3.from("rbac").insert(recordsToInsert);
2049
2044
  }
@@ -2057,7 +2052,7 @@ function createMutations(table, agents, contexts, tools, config) {
2057
2052
  if (user.super_admin === true) {
2058
2053
  return true;
2059
2054
  }
2060
- if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && user.role.agents === "write") && !(table.name.plural === "workflow_templates" && user.role.workflows === "write") && !(table.name.plural === "variables" && user.role.variables === "write") && !(table.name.plural === "users" && user.role.users === "write") && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && user.role.evals === "write"))) {
2055
+ if (!user.super_admin && (table.name.plural === "agents" || table.name.plural === "workflow_templates" || table.name.plural === "variables" || table.name.plural === "users" || table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (!user.role || !(table.name.plural === "agents" && user.role.agents === "write") && !(table.name.plural === "workflow_templates" && user.role.workflows === "write") && !(table.name.plural === "variables" && user.role.variables === "write") && !(table.name.plural === "users" && user.role.users === "write") && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && user.role.evals === "write"))) {
2061
2056
  console.error("Access control error: no role found for current user or no access to entity type.");
2062
2057
  throw new Error("Access control error: no role found for current user or no access to entity type.");
2063
2058
  }
@@ -2111,6 +2106,61 @@ function createMutations(table, agents, contexts, tools, config) {
2111
2106
  }
2112
2107
  };
2113
2108
  const mutations = {
2109
+ [`${tableNamePlural}CopyOneById`]: async (_, args, context, info) => {
2110
+ const { db: db3 } = context;
2111
+ const requestedFields = getRequestedFields(info);
2112
+ let { id } = args;
2113
+ if (!id) {
2114
+ throw new Error("ID is required for copying a record.");
2115
+ }
2116
+ await validateWriteAccess(id, context);
2117
+ const item = await db3.from(tableNamePlural).select("*").where({ id }).first();
2118
+ if (!item) {
2119
+ throw new Error("Record not found");
2120
+ }
2121
+ if (item.rights_mode) {
2122
+ item.rights_mode = "private";
2123
+ }
2124
+ if (item.created_at) {
2125
+ item.created_at = /* @__PURE__ */ new Date();
2126
+ }
2127
+ if (item.createdAt) {
2128
+ item.createdAt = /* @__PURE__ */ new Date();
2129
+ }
2130
+ if (item.updated_at) {
2131
+ item.updated_at = /* @__PURE__ */ new Date();
2132
+ }
2133
+ if (item.updatedAt) {
2134
+ item.updatedAt = /* @__PURE__ */ new Date();
2135
+ }
2136
+ if (item.created_by) {
2137
+ item.created_by = context.user.id;
2138
+ }
2139
+ if (item.createdBy) {
2140
+ item.createdBy = context.user.id;
2141
+ }
2142
+ if (item.name) {
2143
+ item.name = item.name + " (Copy)";
2144
+ }
2145
+ Object.keys(item).forEach((key) => {
2146
+ if (table.fields.find((field) => field.name === key)?.type === "json") {
2147
+ if (typeof item[key] === "object" || Array.isArray(item[key])) {
2148
+ item[key] = JSON.stringify(item[key]);
2149
+ }
2150
+ }
2151
+ });
2152
+ const insert = db3(tableNamePlural).insert({
2153
+ ...item,
2154
+ id: db3.fn.uuid()
2155
+ }).returning("*");
2156
+ const result = await insert;
2157
+ if (!result[0]) {
2158
+ throw new Error("Failed to copy record.");
2159
+ }
2160
+ return {
2161
+ item: finalizeRequestedFields({ args, table, requestedFields, agents, contexts, tools, result: result[0], user: context.user })
2162
+ };
2163
+ },
2114
2164
  [`${tableNamePlural}CreateOne`]: async (_, args, context, info) => {
2115
2165
  const { db: db3 } = context;
2116
2166
  const requestedFields = getRequestedFields(info);
@@ -2368,7 +2418,7 @@ function createMutations(table, agents, contexts, tools, config) {
2368
2418
  }
2369
2419
  const { limit = 10, filters = [], sort } = args;
2370
2420
  const { db: db3 } = context;
2371
- const { items } = await paginationRequest({
2421
+ const { items } = await itemsPaginationRequest({
2372
2422
  db: db3,
2373
2423
  limit,
2374
2424
  page: 0,
@@ -2467,9 +2517,6 @@ function createMutations(table, agents, contexts, tools, config) {
2467
2517
  };
2468
2518
  };
2469
2519
  mutations[`${tableNameSingular}GenerateChunks`] = async (_, args, context, info) => {
2470
- if (!context.user?.super_admin) {
2471
- throw new Error("You are not authorized to generate chunks via API, user must be super admin.");
2472
- }
2473
2520
  const { db: db3 } = await postgresClient();
2474
2521
  const exists = contexts.find((context2) => context2.id === table.id);
2475
2522
  if (!exists) {
@@ -2480,13 +2527,17 @@ function createMutations(table, agents, contexts, tools, config) {
2480
2527
  const columns = await db3(mainTable).columnInfo();
2481
2528
  let query = db3.from(mainTable).select(Object.keys(columns));
2482
2529
  if (!args.where) {
2530
+ if (!context.user?.super_admin) {
2531
+ throw new Error("You are not authorized to generate all chunks via API, user must be super admin.");
2532
+ }
2483
2533
  const {
2484
2534
  jobs: jobs2,
2485
2535
  items: items2
2486
2536
  } = await embeddings.generate.all(
2487
2537
  config,
2488
2538
  context.user.id,
2489
- context.user.role?.id
2539
+ context.user.role?.id,
2540
+ args.limit
2490
2541
  );
2491
2542
  return {
2492
2543
  message: "Chunks generated successfully.",
@@ -2495,6 +2546,9 @@ function createMutations(table, agents, contexts, tools, config) {
2495
2546
  };
2496
2547
  }
2497
2548
  query = applyFilters(query, args.where, table);
2549
+ if (args.limit) {
2550
+ query = query.limit(args.limit);
2551
+ }
2498
2552
  const items = await query;
2499
2553
  if (items.length === 0) {
2500
2554
  throw new Error("No items found to generate chunks for.");
@@ -2519,9 +2573,6 @@ function createMutations(table, agents, contexts, tools, config) {
2519
2573
  };
2520
2574
  };
2521
2575
  mutations[`${tableNameSingular}DeleteChunks`] = async (_, args, context, info) => {
2522
- if (!context.user?.super_admin) {
2523
- throw new Error("You are not authorized to delete chunks via API, user must be super admin.");
2524
- }
2525
2576
  const { db: db3 } = await postgresClient();
2526
2577
  const id = contexts.find((context2) => context2.id === table.id)?.id;
2527
2578
  if (!id) {
@@ -2530,6 +2581,10 @@ function createMutations(table, agents, contexts, tools, config) {
2530
2581
  if (args.where) {
2531
2582
  let query = db3.from(getTableName(id)).select("id");
2532
2583
  query = applyFilters(query, args.where, table);
2584
+ query = applyAccessControl(table, query, context.user);
2585
+ if (args.limit) {
2586
+ query = query.limit(args.limit);
2587
+ }
2533
2588
  const items = await query;
2534
2589
  if (items.length === 0) {
2535
2590
  throw new Error("No items found to delete chunks for.");
@@ -2543,11 +2598,20 @@ function createMutations(table, agents, contexts, tools, config) {
2543
2598
  jobs: []
2544
2599
  };
2545
2600
  } else {
2546
- const count = await db3.from(getChunksTableName(id)).count();
2547
- await db3.from(getChunksTableName(id)).truncate();
2601
+ if (!context.user?.super_admin) {
2602
+ throw new Error("You are not authorized to delete all chunks via API, user must be super admin.");
2603
+ }
2604
+ let count = 0;
2605
+ if (!args.limit) {
2606
+ const result = await db3.from(getChunksTableName(id)).count();
2607
+ count = parseInt(result[0].count);
2608
+ await db3.from(getChunksTableName(id)).truncate();
2609
+ } else {
2610
+ count = await db3.from(getChunksTableName(id)).limit(args.limit).delete();
2611
+ }
2548
2612
  return {
2549
2613
  message: "Chunks deleted successfully.",
2550
- items: parseInt(count[0].count),
2614
+ items: count,
2551
2615
  jobs: []
2552
2616
  };
2553
2617
  }
@@ -2562,8 +2626,8 @@ var applyAccessControl = (table, query, user, field_prefix) => {
2562
2626
  }
2563
2627
  console.log("[EXULU] user.role", user?.role);
2564
2628
  console.log("[EXULU] table.name.plural", table.name.plural);
2565
- if (user && !user?.super_admin && (!user?.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2566
- console.error("==== Access control error: no role found or no access to entity type. ====");
2629
+ if (user && !user?.super_admin && (table.name.plural === "agents" || table.name.plural === "workflow_templates" || table.name.plural === "variables" || table.name.plural === "users" || table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (!user?.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2630
+ console.error("==== Access control error: no role found or no access to entity type. ====", user, table.name.plural);
2567
2631
  throw new Error("Access control error: no role found or no access to entity type.");
2568
2632
  }
2569
2633
  const hasRBAC = table.RBAC === true;
@@ -2606,6 +2670,7 @@ var converOperatorToQuery = (query, fieldName, operators, table, field_prefix) =
2606
2670
  const isJsonField = field?.type === "json";
2607
2671
  const prefix = field_prefix ? field_prefix + "." : "";
2608
2672
  fieldName = prefix + fieldName;
2673
+ console.log("[EXULU] operators", operators);
2609
2674
  if (operators.eq !== void 0) {
2610
2675
  if (isJsonField) {
2611
2676
  query = query.whereRaw(`?? = ?::jsonb`, [fieldName, JSON.stringify(operators.eq)]);
@@ -2637,7 +2702,13 @@ var converOperatorToQuery = (query, fieldName, operators, table, field_prefix) =
2637
2702
  }
2638
2703
  }
2639
2704
  if (operators.lte !== void 0) {
2640
- query = query.where(fieldName, "<=", operators.lte);
2705
+ console.log("[EXULU] operators.lte", operators.lte);
2706
+ console.log("[EXULU] fieldName", fieldName);
2707
+ if (operators.lte === 0 || operators.lte === "0") {
2708
+ query = query.whereNull(fieldName).orWhere(fieldName, "=", 0);
2709
+ } else {
2710
+ query = query.where(fieldName, "<=", operators.lte);
2711
+ }
2641
2712
  }
2642
2713
  if (operators.gte !== void 0) {
2643
2714
  query = query.where(fieldName, ">=", operators.gte);
@@ -2653,7 +2724,8 @@ var backendAgentFields = [
2653
2724
  "capabilities",
2654
2725
  "maxContextLength",
2655
2726
  "provider",
2656
- "authenticationInformation"
2727
+ "authenticationInformation",
2728
+ "systemInstructions"
2657
2729
  ];
2658
2730
  var removeAgentFields = (requestedFields) => {
2659
2731
  const filtered = requestedFields.filter((field) => !backendAgentFields.includes(field));
@@ -2738,6 +2810,9 @@ var addAgentFields = async (args, requestedFields, agents, result, tools, user,
2738
2810
  if (requestedFields.includes("provider")) {
2739
2811
  result.provider = backend?.provider || "";
2740
2812
  }
2813
+ if (requestedFields.includes("systemInstructions")) {
2814
+ result.systemInstructions = backend?.config?.instructions || void 0;
2815
+ }
2741
2816
  if (!requestedFields.includes("backend")) {
2742
2817
  delete result.backend;
2743
2818
  }
@@ -2962,7 +3037,7 @@ var applySorting = (query, sort, field_prefix) => {
2962
3037
  }
2963
3038
  return query;
2964
3039
  };
2965
- var paginationRequest = async ({
3040
+ var itemsPaginationRequest = async ({
2966
3041
  db: db3,
2967
3042
  limit,
2968
3043
  page,
@@ -2992,7 +3067,8 @@ var paginationRequest = async ({
2992
3067
  if (page > 1) {
2993
3068
  dataQuery = dataQuery.offset((page - 1) * limit);
2994
3069
  }
2995
- let items = await dataQuery.select(fields ? fields : "*").limit(limit);
3070
+ dataQuery = dataQuery.select(fields ? fields : "*").limit(limit);
3071
+ let items = await dataQuery;
2996
3072
  return {
2997
3073
  items,
2998
3074
  pageInfo: {
@@ -3043,7 +3119,7 @@ function createQueries(table, agents, tools, contexts) {
3043
3119
  const { limit = 10, page = 0, filters = [], sort } = args;
3044
3120
  const requestedFields = getRequestedFields(info);
3045
3121
  const sanitizedFields = sanitizeRequestedFields(table, requestedFields);
3046
- const { items, pageInfo } = await paginationRequest({
3122
+ const { items, pageInfo } = await itemsPaginationRequest({
3047
3123
  db: db3,
3048
3124
  limit,
3049
3125
  page,
@@ -3118,6 +3194,46 @@ function createQueries(table, agents, tools, contexts) {
3118
3194
  expand: args.expand
3119
3195
  });
3120
3196
  };
3197
+ queries[`${tableNameSingular}ChunkById`] = async (_, args, context, info) => {
3198
+ const exists = contexts.find((ctx) => ctx.id === table.id);
3199
+ if (!exists) {
3200
+ throw new Error("Context " + table.id + " not found in registry.");
3201
+ }
3202
+ const { db: db3 } = context;
3203
+ const chunksTable = getChunksTableName(exists.id);
3204
+ const mainTable = getTableName(exists.id);
3205
+ const chunk = await db3(chunksTable + " as chunks").select([
3206
+ "chunks.id as chunk_id",
3207
+ "chunks.source as chunk_source",
3208
+ "chunks.content as chunk_content",
3209
+ "chunks.chunk_index",
3210
+ "chunks.metadata as chunk_metadata",
3211
+ db3.raw('chunks."createdAt" as chunk_created_at'),
3212
+ db3.raw('chunks."updatedAt" as chunk_updated_at'),
3213
+ "items.id as item_id",
3214
+ "items.name as item_name",
3215
+ "items.external_id as item_external_id",
3216
+ db3.raw('items."updatedAt" as item_updated_at'),
3217
+ db3.raw('items."createdAt" as item_created_at')
3218
+ ]).leftJoin(mainTable + " as items", "chunks.source", "items.id").where("chunks.id", args.id).first();
3219
+ if (!chunk) {
3220
+ return null;
3221
+ }
3222
+ return {
3223
+ chunk_content: chunk.chunk_content,
3224
+ chunk_index: chunk.chunk_index,
3225
+ chunk_id: chunk.chunk_id,
3226
+ chunk_source: chunk.chunk_source,
3227
+ chunk_metadata: chunk.chunk_metadata,
3228
+ chunk_created_at: chunk.chunk_created_at,
3229
+ chunk_updated_at: chunk.chunk_updated_at,
3230
+ item_id: chunk.item_id,
3231
+ item_name: chunk.item_name,
3232
+ item_external_id: chunk.item_external_id,
3233
+ item_updated_at: chunk.item_updated_at,
3234
+ item_created_at: chunk.item_created_at
3235
+ };
3236
+ };
3121
3237
  }
3122
3238
  return queries;
3123
3239
  }
@@ -3250,120 +3366,52 @@ var vectorSearch = async ({
3250
3366
  const fullTextWeight = 2;
3251
3367
  const semanticWeight = 1;
3252
3368
  const rrfK = 50;
3253
- const hybridSQL = `
3254
- WITH full_text AS (
3255
- SELECT
3256
- chunks.id,
3257
- chunks.source,
3258
- row_number() OVER (
3259
- ORDER BY ts_rank(chunks.fts, plainto_tsquery(?, ?)) DESC
3260
- ) AS rank_ix
3261
- FROM ${chunksTable} as chunks
3262
- LEFT JOIN ${mainTable} as items ON items.id = chunks.source
3263
- WHERE chunks.fts @@ plainto_tsquery(?, ?)
3264
- AND ts_rank(chunks.fts, plainto_tsquery(?, ?)) > ?
3265
- AND (items.archived IS FALSE OR items.archived IS NULL)
3266
- ORDER BY rank_ix
3267
- LIMIT LEAST(?, 250) * 2
3268
- ),
3269
- semantic AS (
3270
- SELECT
3271
- chunks.id,
3272
- chunks.source,
3273
- row_number() OVER (
3274
- ORDER BY chunks.embedding <=> ${vectorExpr} ASC
3275
- ) AS rank_ix
3276
- FROM ${chunksTable} as chunks
3277
- LEFT JOIN ${mainTable} as items ON items.id = chunks.source
3278
- WHERE chunks.embedding IS NOT NULL
3279
- AND (1 - (chunks.embedding <=> ${vectorExpr})) >= ?
3280
- AND (items.archived IS FALSE OR items.archived IS NULL)
3281
- ORDER BY rank_ix
3282
- LIMIT LEAST(?, 250) * 2
3283
- )
3284
- SELECT
3285
- items.id as item_id,
3286
- items.name as item_name,
3287
- items.external_id as item_external_id,
3288
- chunks.id AS chunk_id,
3289
- chunks.source,
3290
- chunks.content,
3291
- chunks.chunk_index,
3292
- chunks.metadata,
3293
- chunks."createdAt" as chunk_created_at,
3294
- chunks."updatedAt" as chunk_updated_at,
3295
- items."updatedAt" as item_updated_at,
3296
- items."createdAt" as item_created_at,
3297
- /* Per-signal scores for introspection */
3298
- ts_rank(chunks.fts, plainto_tsquery(?, ?)) AS fts_rank,
3299
- (1 - (chunks.embedding <=> ${vectorExpr})) AS cosine_distance,
3300
-
3301
- /* Hybrid RRF score */
3302
- (
3303
- COALESCE(1.0 / (? + ft.rank_ix), 0.0) * ?
3304
- +
3305
- COALESCE(1.0 / (? + se.rank_ix), 0.0) * ?
3306
- )::float AS hybrid_score
3307
-
3308
- FROM full_text ft
3309
- FULL OUTER JOIN semantic se
3310
- ON ft.id = se.id
3311
- JOIN ${chunksTable} as chunks
3312
- ON COALESCE(ft.id, se.id) = chunks.id
3313
- JOIN ${mainTable} as items
3314
- ON items.id = chunks.source
3315
- WHERE (
3316
- COALESCE(1.0 / (? + ft.rank_ix), 0.0) * ?
3317
- +
3318
- COALESCE(1.0 / (? + se.rank_ix), 0.0) * ?
3319
- ) >= ?
3320
- AND (chunks.fts IS NULL OR ts_rank(chunks.fts, plainto_tsquery(?, ?)) > ?)
3321
- AND (chunks.embedding IS NULL OR (1 - (chunks.embedding <=> ${vectorExpr})) >= ?)
3322
- ORDER BY hybrid_score DESC
3323
- LIMIT LEAST(?, 250)
3324
- OFFSET 0
3325
- `;
3326
- const bindings = [
3327
- // full_text: plainto_tsquery(lang, query) in rank and where
3328
- language,
3329
- query,
3330
- language,
3331
- query,
3332
- language,
3333
- query,
3334
- cutoffs?.tsvector || 0,
3335
- // full_text tsvector cutoff
3336
- matchCount,
3337
- // full_text limit
3338
- cutoffs?.cosineDistance || 0,
3339
- // semantic cosine distance cutoff
3340
- matchCount,
3341
- // semantic limit
3342
- // fts_rank (ts_rank) call
3343
- language,
3344
- query,
3345
- // RRF fusion parameters
3346
- rrfK,
3347
- fullTextWeight,
3348
- rrfK,
3349
- semanticWeight,
3350
- // WHERE clause hybrid_score filter
3351
- rrfK,
3352
- fullTextWeight,
3353
- rrfK,
3354
- semanticWeight,
3355
- cutoffs?.hybrid || 0,
3356
- // Additional cutoff filters in main WHERE clause
3357
- language,
3358
- query,
3359
- cutoffs?.tsvector || 0,
3360
- // tsvector cutoff for results from semantic CTE
3361
- cutoffs?.cosineDistance || 0,
3362
- // cosine distance cutoff for results from full_text CTE
3363
- matchCount
3364
- // final limit
3365
- ];
3366
- resultChunks = await db3.raw(hybridSQL, bindings).then((r) => r.rows ?? r);
3369
+ let fullTextQuery = db3(chunksTable + " as chunks").select([
3370
+ "chunks.id",
3371
+ "chunks.source",
3372
+ db3.raw(`row_number() OVER (ORDER BY ts_rank(chunks.fts, plainto_tsquery(?, ?)) DESC) AS rank_ix`, [language, query])
3373
+ ]).leftJoin(mainTable + " as items", "items.id", "chunks.source").whereRaw(`chunks.fts @@ plainto_tsquery(?, ?)`, [language, query]).whereRaw(`ts_rank(chunks.fts, plainto_tsquery(?, ?)) > ?`, [language, query, cutoffs?.tsvector || 0]).whereRaw(`(items.archived IS FALSE OR items.archived IS NULL)`).limit(Math.min(matchCount * 2, 500));
3374
+ fullTextQuery = applyFilters(fullTextQuery, filters, table, "items");
3375
+ fullTextQuery = applyAccessControl(table, fullTextQuery, user, "items");
3376
+ let semanticQuery = db3(chunksTable + " as chunks").select([
3377
+ "chunks.id",
3378
+ "chunks.source",
3379
+ db3.raw(`row_number() OVER (ORDER BY chunks.embedding <=> ${vectorExpr} ASC) AS rank_ix`)
3380
+ ]).leftJoin(mainTable + " as items", "items.id", "chunks.source").whereNotNull("chunks.embedding").whereRaw(`(1 - (chunks.embedding <=> ${vectorExpr})) >= ?`, [cutoffs?.cosineDistance || 0]).whereRaw(`(items.archived IS FALSE OR items.archived IS NULL)`).limit(Math.min(matchCount * 2, 500));
3381
+ semanticQuery = applyFilters(semanticQuery, filters, table, "items");
3382
+ semanticQuery = applyAccessControl(table, semanticQuery, user, "items");
3383
+ let hybridQuery = db3.with("full_text", fullTextQuery).with("semantic", semanticQuery).select([
3384
+ "items.id as item_id",
3385
+ "items.name as item_name",
3386
+ "items.external_id as item_external_id",
3387
+ "chunks.id as chunk_id",
3388
+ "chunks.source",
3389
+ "chunks.content",
3390
+ "chunks.chunk_index",
3391
+ "chunks.metadata",
3392
+ db3.raw('chunks."createdAt" as chunk_created_at'),
3393
+ db3.raw('chunks."updatedAt" as chunk_updated_at'),
3394
+ db3.raw('items."updatedAt" as item_updated_at'),
3395
+ db3.raw('items."createdAt" as item_created_at'),
3396
+ db3.raw(`ts_rank(chunks.fts, plainto_tsquery(?, ?)) AS fts_rank`, [language, query]),
3397
+ db3.raw(`(1 - (chunks.embedding <=> ${vectorExpr})) AS cosine_distance`),
3398
+ db3.raw(`
3399
+ (
3400
+ COALESCE(1.0 / (? + ft.rank_ix), 0.0) * ?
3401
+ +
3402
+ COALESCE(1.0 / (? + se.rank_ix), 0.0) * ?
3403
+ )::float AS hybrid_score
3404
+ `, [rrfK, fullTextWeight, rrfK, semanticWeight])
3405
+ ]).from("full_text as ft").fullOuterJoin("semantic as se", "ft.id", "se.id").join(chunksTable + " as chunks", function() {
3406
+ this.on(db3.raw("COALESCE(ft.id, se.id)"), "=", "chunks.id");
3407
+ }).join(mainTable + " as items", "items.id", "chunks.source").whereRaw(`
3408
+ (
3409
+ COALESCE(1.0 / (? + ft.rank_ix), 0.0) * ?
3410
+ +
3411
+ COALESCE(1.0 / (? + se.rank_ix), 0.0) * ?
3412
+ ) >= ?
3413
+ `, [rrfK, fullTextWeight, rrfK, semanticWeight, cutoffs?.hybrid || 0]).whereRaw(`(chunks.fts IS NULL OR ts_rank(chunks.fts, plainto_tsquery(?, ?)) > ?)`, [language, query, cutoffs?.tsvector || 0]).whereRaw(`(chunks.embedding IS NULL OR (1 - (chunks.embedding <=> ${vectorExpr})) >= ?)`, [cutoffs?.cosineDistance || 0]).orderByRaw("hybrid_score DESC").limit(Math.min(matchCount, 250));
3414
+ resultChunks = await hybridQuery;
3367
3415
  }
3368
3416
  console.log("[EXULU] Vector search chunk results:", resultChunks?.length);
3369
3417
  let results = resultChunks.map((chunk) => ({
@@ -3599,8 +3647,8 @@ var contextToTableDefinition = (context) => {
3599
3647
  type: "text"
3600
3648
  });
3601
3649
  definition.fields.push({
3602
- name: "embeddings_updated_at",
3603
- type: "date"
3650
+ name: "chunks_count",
3651
+ type: "number"
3604
3652
  });
3605
3653
  definition.fields.push({
3606
3654
  name: "name",
@@ -3703,10 +3751,13 @@ function createSDL(tables, contexts, agents, tools, config, evals, queues2) {
3703
3751
  if (table.type === "items") {
3704
3752
  typeDefs += `
3705
3753
  ${tableNamePlural}VectorSearch(query: String!, method: VectorMethodEnum!, filters: [Filter${tableNameSingularUpperCaseFirst}], cutoffs: SearchCutoffs, expand: SearchExpand): ${tableNameSingular}VectorSearchResult
3754
+ ${tableNameSingular}ChunkById(id: ID!): ${tableNameSingular}VectorSearchChunk
3706
3755
  `;
3707
3756
  }
3708
3757
  mutationDefs += `
3709
3758
  ${tableNamePlural}CreateOne(input: ${tableNameSingular}Input!, upsert: Boolean): ${tableNameSingular}MutationPayload
3759
+ ${tableNamePlural}CopyOneById(id: ID!): ${tableNameSingular}MutationPayload
3760
+
3710
3761
  ${tableNamePlural}UpdateOne(where: [Filter${tableNameSingularUpperCaseFirst}], input: ${tableNameSingular}Input!): ${tableNameSingular}MutationPayload
3711
3762
  ${tableNamePlural}UpdateOneById(id: ID!, input: ${tableNameSingular}Input!): ${tableNameSingular}MutationPayload
3712
3763
  ${tableNamePlural}RemoveOneById(id: ID!): ${tableNameSingular}
@@ -3714,9 +3765,9 @@ function createSDL(tables, contexts, agents, tools, config, evals, queues2) {
3714
3765
  `;
3715
3766
  if (table.type === "items") {
3716
3767
  mutationDefs += `
3717
- ${tableNameSingular}GenerateChunks(where: [Filter${tableNameSingularUpperCaseFirst}]): ${tableNameSingular}GenerateChunksReturnPayload
3768
+ ${tableNameSingular}GenerateChunks(where: [Filter${tableNameSingularUpperCaseFirst}], limit: Int): ${tableNameSingular}GenerateChunksReturnPayload
3718
3769
  ${tableNameSingular}ExecuteSource(source: ID!, inputs: JSON!): ${tableNameSingular}ExecuteSourceReturnPayload
3719
- ${tableNameSingular}DeleteChunks(where: [Filter${tableNameSingularUpperCaseFirst}]): ${tableNameSingular}DeleteChunksReturnPayload
3770
+ ${tableNameSingular}DeleteChunks(where: [Filter${tableNameSingularUpperCaseFirst}], limit: Int): ${tableNameSingular}DeleteChunksReturnPayload
3720
3771
  `;
3721
3772
  if (table.processor) {
3722
3773
  mutationDefs += `
@@ -3850,6 +3901,9 @@ type PageInfo {
3850
3901
  typeDefs += `
3851
3902
  contextById(id: ID!): Context
3852
3903
  `;
3904
+ typeDefs += `
3905
+ getUniquePromptTags: [String!]!
3906
+ `;
3853
3907
  mutationDefs += `
3854
3908
  runEval(id: ID!, test_case_ids: [ID!]): RunEvalReturnPayload
3855
3909
  `;
@@ -4307,6 +4361,38 @@ type PageInfo {
4307
4361
  array.push("agents");
4308
4362
  return [...new Set(array)].sort();
4309
4363
  };
4364
+ resolvers.Query["getUniquePromptTags"] = async (_, args, context, info) => {
4365
+ const { db: db3 } = context;
4366
+ const user = context.user;
4367
+ const promptTable = tables.find((t) => t.name.plural === "prompt_library");
4368
+ if (!promptTable) {
4369
+ throw new Error("Prompt library table not found");
4370
+ }
4371
+ let query = db3.from("prompt_library").select("tags");
4372
+ query = applyAccessControl(promptTable, query, user);
4373
+ const results = await query;
4374
+ const allTags = [];
4375
+ for (const row of results) {
4376
+ if (row.tags) {
4377
+ let tags = [];
4378
+ if (typeof row.tags === "string") {
4379
+ try {
4380
+ tags = JSON.parse(row.tags);
4381
+ } catch (e) {
4382
+ tags = [row.tags];
4383
+ }
4384
+ } else if (Array.isArray(row.tags)) {
4385
+ tags = row.tags;
4386
+ }
4387
+ tags.forEach((tag) => {
4388
+ if (tag && typeof tag === "string" && tag.trim()) {
4389
+ allTags.push(tag.trim().toLowerCase());
4390
+ }
4391
+ });
4392
+ }
4393
+ }
4394
+ return [...new Set(allTags)].sort();
4395
+ };
4310
4396
  modelDefs += `
4311
4397
  type ProviderPaginationResult {
4312
4398
  items: [Provider]!
@@ -4697,14 +4783,16 @@ var addBucketPrefixToKey = (key, bucket) => {
4697
4783
  }
4698
4784
  return `${bucket}/${key}`;
4699
4785
  };
4700
- var uploadFile = async (file, fileName, config, options = {}, user, customBucket) => {
4786
+ var uploadFile = async (file, fileName, config, options = {}, user, customBucket, global) => {
4701
4787
  if (!config.fileUploads) {
4702
4788
  throw new Error("File uploads are not configured (in the exported uploadFile function)");
4703
4789
  }
4704
4790
  const client2 = getS3Client(config);
4705
4791
  let defaultBucket = config.fileUploads.s3Bucket;
4706
4792
  let key = fileName;
4707
- key = addUserPrefixToKey(key, user || "api");
4793
+ if (!global) {
4794
+ key = addUserPrefixToKey(key, user || "api");
4795
+ }
4708
4796
  key = addGeneralPrefixToKey(key, config);
4709
4797
  const sanitizedMetadata = sanitizeMetadata(options.metadata);
4710
4798
  const command = new PutObjectCommand({
@@ -4855,7 +4943,7 @@ var createUppyRoutes = async (app, contexts, config) => {
4855
4943
  return;
4856
4944
  }
4857
4945
  let allowed = false;
4858
- if (user.type === "api" || user.super_admin || key.includes(`user_${user.id}/`)) {
4946
+ if (user.type === "api" || user.super_admin || !key.includes(`user_`) || key.includes(`user_${user.id}/`)) {
4859
4947
  allowed = true;
4860
4948
  }
4861
4949
  if (!allowed) {
@@ -4933,9 +5021,16 @@ var createUppyRoutes = async (app, contexts, config) => {
4933
5021
  return;
4934
5022
  }
4935
5023
  const client2 = getS3Client(config);
5024
+ let prefix = `${config.fileUploads.s3prefix ? config.fileUploads.s3prefix.replace(/\/$/, "") + "/" : ""}`;
5025
+ if (!req.headers.global) {
5026
+ prefix += `user_${authenticationResult.user.id}`;
5027
+ } else {
5028
+ prefix += "global";
5029
+ }
5030
+ console.log("[EXULU] prefix", prefix);
4936
5031
  const command = new ListObjectsV2Command({
4937
5032
  Bucket: config.fileUploads.s3Bucket,
4938
- Prefix: `${config.fileUploads.s3prefix ? config.fileUploads.s3prefix.replace(/\/$/, "") + "/" : ""}user_${authenticationResult.user.id}`,
5033
+ Prefix: prefix,
4939
5034
  MaxKeys: 9,
4940
5035
  ...req.query.continuationToken && { ContinuationToken: req.query.continuationToken }
4941
5036
  });
@@ -5018,7 +5113,13 @@ var createUppyRoutes = async (app, contexts, config) => {
5018
5113
  const { filename, contentType } = extractFileParameters(req);
5019
5114
  validateFileParameters(filename, contentType);
5020
5115
  const key = generateS3Key2(filename);
5021
- let fullKey = addUserPrefixToKey(key, user.type === "api" ? "api" : user.id);
5116
+ let fullKey = key;
5117
+ console.log("[EXULU] global", req.headers.global);
5118
+ if (!req.headers.global) {
5119
+ fullKey = addUserPrefixToKey(key, user.type === "api" ? "api" : user.id);
5120
+ } else {
5121
+ fullKey = "global/" + key;
5122
+ }
5022
5123
  fullKey = addGeneralPrefixToKey(fullKey, config);
5023
5124
  console.log("[EXULU] signing on server for user", user.id, "with key", fullKey);
5024
5125
  getSignedUrl(
@@ -5074,7 +5175,13 @@ var createUppyRoutes = async (app, contexts, config) => {
5074
5175
  return res.status(400).json({ error: "s3: content type must be a string" });
5075
5176
  }
5076
5177
  const key = `${randomUUID()}-_EXULU_${filename}`;
5077
- let fullKey = addUserPrefixToKey(key, user.type === "api" ? "api" : user.id);
5178
+ let fullKey = key;
5179
+ console.log("[EXULU] global", req.headers.global);
5180
+ if (!req.headers.global) {
5181
+ fullKey = addUserPrefixToKey(key, user.type === "api" ? "api" : user.id);
5182
+ } else {
5183
+ fullKey = "global/" + key;
5184
+ }
5078
5185
  fullKey = addGeneralPrefixToKey(fullKey, config);
5079
5186
  console.log("[EXULU] signing on server for user", user.id, "with key", fullKey);
5080
5187
  const params = {
@@ -5722,6 +5829,31 @@ var ExuluAgent2 = class {
5722
5829
  they are talking with the current date in mind as a reference.`;
5723
5830
  let system = instructions || "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.";
5724
5831
  system += "\n\n" + genericContext;
5832
+ const includesContextSearchTool = currentTools?.some((tool2) => tool2.name.toLowerCase().includes("context_search") || tool2.id.includes("context_search"));
5833
+ console.log("[EXULU] Current tools: " + currentTools?.map((tool2) => tool2.name));
5834
+ console.log("[EXULU] Includes context search tool: " + includesContextSearchTool);
5835
+ if (includesContextSearchTool) {
5836
+ system += `
5837
+
5838
+
5839
+
5840
+ When you use a context search tool, you will include references to the items
5841
+ retrieved from the context search tool inline in the response using this exact JSON format
5842
+ (all on one line, no line breaks):
5843
+ {item_name: <item_name>, item_id: <item_id>, context: <context_id>, chunk_id: <chunk_id>, chunk_index: <chunk_index>}
5844
+
5845
+ IMPORTANT formatting rules:
5846
+ - Use the exact format shown above, all on ONE line
5847
+ - Do NOT use quotes around field names or values
5848
+ - Use the context ID (e.g., "dx-newlift-newton-knowledge-g3y6r1") from the tool result
5849
+ - Include the file/item name, not the full path
5850
+ - Separate multiple citations with spaces
5851
+
5852
+ Example: {item_name: document.pdf, item_id: abc123, context: my-context-id, chunk_id: chunk_456, chunk_index: 0}
5853
+
5854
+ The citations will be rendered as interactive badges in the UI.
5855
+ `;
5856
+ }
5725
5857
  if (prompt) {
5726
5858
  let result = { object: null, text: "" };
5727
5859
  let inputTokens = 0;
@@ -5982,6 +6114,31 @@ ${extractedText}
5982
6114
  const genericContext = "IMPORTANT: \n\n The current date is " + (/* @__PURE__ */ new Date()).toLocaleDateString() + " and the current time is " + (/* @__PURE__ */ new Date()).toLocaleTimeString() + ". If the user does not explicitly provide the current date, for examle when saying ' this weekend', you should assume they are talking with the current date in mind as a reference.";
5983
6115
  let system = instructions || "You are a helpful assistant. When you use a tool to answer a question do not explicitly comment on the result of the tool call unless the user has explicitly you to do something with the result.";
5984
6116
  system += "\n\n" + genericContext;
6117
+ const includesContextSearchTool = currentTools?.some((tool2) => tool2.name.toLowerCase().includes("context_search") || tool2.id.includes("context_search"));
6118
+ console.log("[EXULU] Current tools: " + currentTools?.map((tool2) => tool2.name));
6119
+ console.log("[EXULU] Includes context search tool: " + includesContextSearchTool);
6120
+ if (includesContextSearchTool) {
6121
+ system += `
6122
+
6123
+
6124
+
6125
+ When you use a context search tool, you will include references to the items
6126
+ retrieved from the context search tool inline in the response using this exact JSON format
6127
+ (all on one line, no line breaks):
6128
+ {item_name: <item_name>, item_id: <item_id>, context: <context_id>, chunk_id: <chunk_id>, chunk_index: <chunk_index>}
6129
+
6130
+ IMPORTANT formatting rules:
6131
+ - Use the exact format shown above, all on ONE line
6132
+ - Do NOT use quotes around field names or values
6133
+ - Use the context ID (e.g., "dx-newlift-newton-knowledge-g3y6r1") from the tool result
6134
+ - Include the file/item name, not the full path
6135
+ - Separate multiple citations with spaces
6136
+
6137
+ Example: {item_name: document.pdf, item_id: abc123, context: my-context-id, chunk_id: chunk_456, chunk_index: 0}
6138
+
6139
+ The citations will be rendered as interactive badges in the UI.
6140
+ `;
6141
+ }
5985
6142
  const result = streamText({
5986
6143
  model,
5987
6144
  // Should be a LanguageModelV1
@@ -6525,6 +6682,7 @@ var ExuluContext = class {
6525
6682
  })));
6526
6683
  }
6527
6684
  await db3.from(getTableName(this.id)).where({ id: item.id }).update({
6685
+ chunks_count: chunks?.length || 0,
6528
6686
  embeddings_updated_at: (/* @__PURE__ */ new Date()).toISOString()
6529
6687
  }).returning("id");
6530
6688
  return {
@@ -6794,9 +6952,13 @@ var ExuluContext = class {
6794
6952
  trigger: trigger || "agent"
6795
6953
  }, role, void 0);
6796
6954
  },
6797
- all: async (config, userId, roleId) => {
6955
+ all: async (config, userId, roleId, limit) => {
6798
6956
  const { db: db3 } = await postgresClient();
6799
- const items = await db3.from(getTableName(this.id)).select("*");
6957
+ let query = db3.from(getTableName(this.id)).select("*");
6958
+ if (limit) {
6959
+ query = query.limit(limit);
6960
+ }
6961
+ const items = await query;
6800
6962
  const jobs = [];
6801
6963
  const queue = await this.embedder?.queue;
6802
6964
  if (!queue?.queue.name && items.length > 2e3) {
@@ -6841,7 +7003,7 @@ var ExuluContext = class {
6841
7003
  table.text("rights_mode").defaultTo(this.configuration?.defaultRightsMode ?? "private");
6842
7004
  table.integer("textlength");
6843
7005
  table.text("source");
6844
- table.timestamp("embeddings_updated_at");
7006
+ table.integer("chunks_count").defaultTo(0);
6845
7007
  for (const field of this.fields) {
6846
7008
  let { type, name, unique } = field;
6847
7009
  if (!type || !name) {
@@ -7370,12 +7532,6 @@ Mood: friendly and intelligent.
7370
7532
  return;
7371
7533
  }
7372
7534
  }
7373
- if (user?.type !== "api" && !user?.super_admin && req.body.resourceId !== user?.id) {
7374
- res.status(400).json({
7375
- message: "The provided user id in the resourceId field is not the same as the authenticated user. Only super admins and API users can impersonate other users."
7376
- });
7377
- return;
7378
- }
7379
7535
  console.log("[EXULU] agent tools", agentInstance.tools?.map((x) => x.name + " (" + x.id + ")"));
7380
7536
  const disabledTools = req.body.disabledTools ? req.body.disabledTools : [];
7381
7537
  let enabledTools = await getEnabledTools(agentInstance, tools, disabledTools, agents, user);
@@ -9420,45 +9576,6 @@ var createLogger = ({
9420
9576
  };
9421
9577
  var logger_default = createLogger;
9422
9578
 
9423
- // src/templates/contexts/code-standards.ts
9424
- var codeStandardsContext = new ExuluContext({
9425
- id: "code_standards",
9426
- name: "Code Standards",
9427
- description: "Code standards that can be used with the Exulu CLI.",
9428
- configuration: {
9429
- defaultRightsMode: "public"
9430
- },
9431
- fields: [{
9432
- name: "Best practices",
9433
- type: "longText"
9434
- }, {
9435
- name: "Code style",
9436
- type: "longText"
9437
- }, {
9438
- name: "Tech stack",
9439
- type: "longText"
9440
- }],
9441
- active: true
9442
- });
9443
-
9444
- // src/templates/contexts/outputs.ts
9445
- var outputsContext = new ExuluContext({
9446
- id: "outputs_default_context",
9447
- name: "Outputs",
9448
- description: "Outputs from agent sessions that you have saved for re-used later.",
9449
- configuration: {
9450
- defaultRightsMode: "private",
9451
- calculateVectors: "manual"
9452
- },
9453
- fields: [
9454
- {
9455
- name: "content",
9456
- type: "longText"
9457
- }
9458
- ],
9459
- active: true
9460
- });
9461
-
9462
9579
  // src/registry/index.ts
9463
9580
  import winston2 from "winston";
9464
9581
  import util from "util";
@@ -10585,9 +10702,7 @@ var ExuluApp = class {
10585
10702
  ...evals ?? []
10586
10703
  ] : [];
10587
10704
  this._contexts = {
10588
- ...contexts,
10589
- codeStandardsContext,
10590
- outputsContext
10705
+ ...contexts
10591
10706
  };
10592
10707
  this._agents = [
10593
10708
  claudeSonnet4Agent,
@@ -12323,10 +12438,6 @@ var ExuluJobs = {
12323
12438
  validate: validateJob
12324
12439
  }
12325
12440
  };
12326
- var ExuluDefaultContexts = {
12327
- codeStandards: codeStandardsContext,
12328
- outputs: outputsContext
12329
- };
12330
12441
  var ExuluDefaultAgents = {
12331
12442
  anthropic: {
12332
12443
  opus4: claudeOpus4Agent,
@@ -12484,7 +12595,6 @@ export {
12484
12595
  ExuluChunkers,
12485
12596
  ExuluContext,
12486
12597
  ExuluDefaultAgents,
12487
- ExuluDefaultContexts,
12488
12598
  ExuluEmbedder,
12489
12599
  ExuluEval2 as ExuluEval,
12490
12600
  ExuluJobs,