@dyrected/core 2.14.0 → 2.16.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/server.cjs CHANGED
@@ -2307,6 +2307,12 @@ var init_chunker = __esm({
2307
2307
  });
2308
2308
 
2309
2309
  // src/services/rag/embedding.service.ts
2310
+ function hasEmbeddingApiKey(config) {
2311
+ const ai = config?.ai;
2312
+ return Boolean(
2313
+ ai?.apiKey || process.env.OPENROUTER_API_KEY || process.env.OPENAI_API_KEY || process.env.GEMINI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY
2314
+ );
2315
+ }
2310
2316
  function getEmbeddingModel(config) {
2311
2317
  const ai = config?.ai;
2312
2318
  const provider = ai?.provider;
@@ -2649,6 +2655,9 @@ var init_rag_service = __esm({
2649
2655
  if (!col || !this.isCollectionRAGEnabled(config, col)) {
2650
2656
  return { indexed: 0, skipped: 0 };
2651
2657
  }
2658
+ if (!hasEmbeddingApiKey(config)) {
2659
+ return { indexed: 0, skipped: 0 };
2660
+ }
2652
2661
  const docId = String(doc.id || doc._id || "");
2653
2662
  if (!docId) return { indexed: 0, skipped: 0 };
2654
2663
  const ragConfig = col.ai?.rag;
@@ -3988,6 +3997,7 @@ __export(server_exports, {
3988
3997
  getLockedUntilMs: () => getLockedUntilMs,
3989
3998
  getObservabilityRuntime: () => getObservabilityRuntime,
3990
3999
  getRequestLogger: () => getRequestLogger,
4000
+ hasEmbeddingApiKey: () => hasEmbeddingApiKey,
3991
4001
  hashContent: () => hashContent,
3992
4002
  hashPassword: () => hashPassword,
3993
4003
  isAuthSessionActive: () => isAuthSessionActive,
@@ -6456,6 +6466,134 @@ function isPlainObject2(value) {
6456
6466
  return typeof value === "object" && value !== null && !Array.isArray(value);
6457
6467
  }
6458
6468
 
6469
+ // src/utils/id.ts
6470
+ var import_node_crypto2 = require("crypto");
6471
+ var NANOID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
6472
+ var BASE62_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
6473
+ var CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
6474
+ var COMMON_SLUG_PREFIXES = {
6475
+ users: "usr",
6476
+ members: "mem",
6477
+ accounts: "acc",
6478
+ applications: "app",
6479
+ customers: "cus",
6480
+ products: "prd",
6481
+ orders: "ord",
6482
+ reports: "rpt",
6483
+ sessions: "ses",
6484
+ transactions: "txn",
6485
+ wallets: "wal",
6486
+ media: "med",
6487
+ files: "fil",
6488
+ posts: "post",
6489
+ pages: "page",
6490
+ tags: "tag",
6491
+ categories: "cat",
6492
+ comments: "com"
6493
+ };
6494
+ function nanoid(size = 21, alphabet = NANOID_ALPHABET) {
6495
+ const mask = (2 << 31 - Math.clz32(alphabet.length - 1 | 1)) - 1;
6496
+ const step = Math.ceil(1.6 * mask * size / alphabet.length);
6497
+ let id = "";
6498
+ while (true) {
6499
+ const bytes = (0, import_node_crypto2.randomBytes)(step);
6500
+ for (let i = 0; i < step; i++) {
6501
+ const byte = bytes[i] & mask;
6502
+ if (alphabet[byte]) {
6503
+ id += alphabet[byte];
6504
+ if (id.length === size) return id;
6505
+ }
6506
+ }
6507
+ }
6508
+ }
6509
+ function encodeUlidTime(now2, len = 10) {
6510
+ let str = "";
6511
+ let time = Math.floor(now2);
6512
+ for (let i = len - 1; i >= 0; i--) {
6513
+ const mod = time % 32;
6514
+ str = CROCKFORD_BASE32[mod] + str;
6515
+ time = (time - mod) / 32;
6516
+ }
6517
+ return str;
6518
+ }
6519
+ function encodeUlidRandom(bytes) {
6520
+ let str = "";
6521
+ let bitBuffer = 0;
6522
+ let bitsInBuffer = 0;
6523
+ for (let i = 0; i < bytes.length; i++) {
6524
+ bitBuffer = bitBuffer << 8 | bytes[i];
6525
+ bitsInBuffer += 8;
6526
+ while (bitsInBuffer >= 5) {
6527
+ bitsInBuffer -= 5;
6528
+ const index = bitBuffer >> bitsInBuffer & 31;
6529
+ str += CROCKFORD_BASE32[index];
6530
+ }
6531
+ }
6532
+ return str;
6533
+ }
6534
+ function ulid(seedTime = Date.now()) {
6535
+ const timePart = encodeUlidTime(seedTime);
6536
+ const randPart = encodeUlidRandom((0, import_node_crypto2.randomBytes)(10));
6537
+ return timePart + randPart;
6538
+ }
6539
+ function uuid() {
6540
+ return (0, import_node_crypto2.randomUUID)();
6541
+ }
6542
+ function resolvePrefix(slug, explicitPrefix) {
6543
+ if (explicitPrefix && typeof explicitPrefix === "string" && explicitPrefix.trim().length > 0) {
6544
+ const cleaned = explicitPrefix.trim().toLowerCase().replace(/[^a-z0-9_]/g, "");
6545
+ if (cleaned.length > 0) return cleaned;
6546
+ }
6547
+ if (!slug || typeof slug !== "string") return "col";
6548
+ const s = slug.trim().toLowerCase();
6549
+ if (COMMON_SLUG_PREFIXES[s]) return COMMON_SLUG_PREFIXES[s];
6550
+ const pieces = s.split(/[-_]/).filter(Boolean);
6551
+ if (pieces.length > 1 && pieces[0].length >= 2) {
6552
+ const first2 = pieces[0].replace(/[^a-z0-9]/g, "");
6553
+ if (first2.length >= 2) return first2.slice(0, 4);
6554
+ }
6555
+ const cleanWord = s.replace(/[^a-z0-9]/g, "");
6556
+ if (cleanWord.length <= 4) return cleanWord || "col";
6557
+ return cleanWord.slice(0, 3) || "col";
6558
+ }
6559
+ function prefixedId(prefix = "col", size = 16) {
6560
+ const cleanPrefix = (prefix || "col").toLowerCase().replace(/[^a-z0-9_]/g, "") || "col";
6561
+ return `${cleanPrefix}_${nanoid(size, BASE62_ALPHABET)}`;
6562
+ }
6563
+ function generateId(options) {
6564
+ if (typeof options === "string") {
6565
+ return prefixedId(resolvePrefix(options));
6566
+ }
6567
+ const opts = options || {};
6568
+ const type = opts.type || "prefixed-nanoid";
6569
+ switch (type) {
6570
+ case "uuid":
6571
+ return uuid();
6572
+ case "ulid":
6573
+ return ulid();
6574
+ case "nanoid":
6575
+ return nanoid(opts.size || 21);
6576
+ case "prefixed-nanoid":
6577
+ default:
6578
+ return prefixedId(opts.prefix || "col", opts.size || 16);
6579
+ }
6580
+ }
6581
+ function generateDocumentId(collectionOrSlug) {
6582
+ if (!collectionOrSlug) {
6583
+ return prefixedId("col");
6584
+ }
6585
+ if (typeof collectionOrSlug === "string") {
6586
+ const prefix2 = resolvePrefix(collectionOrSlug);
6587
+ return prefixedId(prefix2);
6588
+ }
6589
+ if (typeof collectionOrSlug.idGenerator === "function") {
6590
+ return collectionOrSlug.idGenerator(collectionOrSlug.slug);
6591
+ }
6592
+ const type = collectionOrSlug.idType || "prefixed-nanoid";
6593
+ const prefix = resolvePrefix(collectionOrSlug.slug, collectionOrSlug.idPrefix);
6594
+ return generateId({ prefix, type });
6595
+ }
6596
+
6459
6597
  // src/workflows.ts
6460
6598
  var WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
6461
6599
  var LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
@@ -7424,6 +7562,9 @@ var CollectionController = class {
7424
7562
  surface: "collection.beforeChange",
7425
7563
  path: `collection:${this.collection.slug}.hooks.beforeChange`
7426
7564
  });
7565
+ if (!data.id) {
7566
+ data = { ...data, id: generateDocumentId(this.collection) };
7567
+ }
7427
7568
  const doc = this.collection.workflow ? (await createWorkflowDocument({
7428
7569
  config,
7429
7570
  collection: this.collection,
@@ -7574,6 +7715,9 @@ var CollectionController = class {
7574
7715
  surface: "collection.beforeChange",
7575
7716
  path: `collection:${this.collection.slug}.hooks.beforeChange`
7576
7717
  });
7718
+ if (!data.id) {
7719
+ data = { ...data, id: generateDocumentId(this.collection) };
7720
+ }
7577
7721
  const doc = await db.create({
7578
7722
  collection: this.collection.slug,
7579
7723
  data
@@ -7814,13 +7958,13 @@ var CollectionController = class {
7814
7958
  const config = c.get("config");
7815
7959
  const db = config.db;
7816
7960
  if (!db) return c.json({ message: "Database not configured" }, 500);
7817
- if (!this.collection.views?.length) {
7818
- return c.json({ error: true, message: `Collection ${this.collection.slug} has no views` }, 404);
7961
+ if (!this.collection.views?.length && !this.collection.actions?.length) {
7962
+ return c.json({ error: true, message: `Collection ${this.collection.slug} has no views or actions` }, 404);
7819
7963
  }
7820
7964
  const actionName = c.req.param("action");
7821
7965
  const viewSlugParam = c.req.param("viewSlug");
7822
7966
  let action;
7823
- for (const view2 of this.collection.views) {
7967
+ for (const view2 of this.collection.views ?? []) {
7824
7968
  if (viewSlugParam && view2.slug !== viewSlugParam) continue;
7825
7969
  const match = view2.actions?.find((candidate) => candidate.name === actionName);
7826
7970
  if (match) {
@@ -7828,6 +7972,9 @@ var CollectionController = class {
7828
7972
  break;
7829
7973
  }
7830
7974
  }
7975
+ if (!action && !viewSlugParam) {
7976
+ action = this.collection.actions?.find((candidate) => candidate.name === actionName);
7977
+ }
7831
7978
  if (!action) {
7832
7979
  return c.json(
7833
7980
  { error: true, message: `Action "${actionName}" was not found${viewSlugParam ? ` in view "${viewSlugParam}"` : ""}` },
@@ -7836,7 +7983,8 @@ var CollectionController = class {
7836
7983
  }
7837
7984
  const body = await c.req.json().catch(() => ({}));
7838
7985
  const requestedIds = Array.isArray(body?.ids) ? body.ids.filter((value) => typeof value === "string") : typeof body?.id === "string" ? [body.id] : [];
7839
- if (!requestedIds.length) {
7986
+ const isHeaderAction = action.type === "header";
7987
+ if (!requestedIds.length && !isHeaderAction) {
7840
7988
  return c.json(
7841
7989
  { error: true, message: "Provide an `id` or an `ids` array of documents to act on." },
7842
7990
  400
@@ -7845,7 +7993,7 @@ var CollectionController = class {
7845
7993
  const input = body?.input ?? {};
7846
7994
  const user = c.get("user");
7847
7995
  const accessArgs = { user, req: this.toHookRequestContext(c) };
7848
- const view = viewSlugParam ? this.collection.views.find((candidate) => candidate.slug === viewSlugParam) : void 0;
7996
+ const view = viewSlugParam ? this.collection.views?.find((candidate) => candidate.slug === viewSlugParam) : void 0;
7849
7997
  if (view?.access) {
7850
7998
  const allowed = await resolveBooleanAccess(config, view.access.update ?? view.access.read ?? true, {
7851
7999
  ...accessArgs,
@@ -7864,6 +8012,30 @@ var CollectionController = class {
7864
8012
  return c.json({ error: true, message: `Access denied: action "${action.name}"` }, 403);
7865
8013
  }
7866
8014
  }
8015
+ if (isHeaderAction && !requestedIds.length) {
8016
+ if (typeof action.handler === "function") {
8017
+ try {
8018
+ const handlerResult = await action.handler({
8019
+ doc: null,
8020
+ docs: [],
8021
+ user: user ?? null,
8022
+ input,
8023
+ collection: {
8024
+ slug: this.collection.slug,
8025
+ label: this.collection.labels?.singular ?? this.collection.slug
8026
+ }
8027
+ });
8028
+ return c.json(handlerResult ?? { success: true });
8029
+ } catch (error) {
8030
+ const status = typeof error.statusCode === "number" ? error.statusCode : 500;
8031
+ return c.json(
8032
+ { error: true, message: error instanceof Error ? error.message : String(error) },
8033
+ status
8034
+ );
8035
+ }
8036
+ }
8037
+ return c.json({ success: true });
8038
+ }
7867
8039
  const results = [];
7868
8040
  for (const id of requestedIds) {
7869
8041
  const targetDoc = await db.findOne({ collection: this.collection.slug, id });
@@ -7883,7 +8055,8 @@ var CollectionController = class {
7883
8055
  });
7884
8056
  resolvedData = handlerResult ?? {};
7885
8057
  } catch (error) {
7886
- results.push({ id, ok: false, status: 500, error: error instanceof Error ? error.message : String(error) });
8058
+ const status = typeof error.statusCode === "number" ? error.statusCode : 500;
8059
+ results.push({ id, ok: false, status, error: error instanceof Error ? error.message : String(error) });
7887
8060
  continue;
7888
8061
  }
7889
8062
  } else {
@@ -7906,7 +8079,8 @@ var CollectionController = class {
7906
8079
  if (requestedIds.length === 1) {
7907
8080
  const single = results[0];
7908
8081
  if (!single.ok) {
7909
- return c.json(single.error ?? { error: true, message: "Action failed" }, single.status ?? 500);
8082
+ const body2 = typeof single.error === "string" ? { error: true, message: single.error } : single.error ?? { error: true, message: "Action failed" };
8083
+ return c.json(body2, single.status ?? 500);
7910
8084
  }
7911
8085
  return c.json(single.doc);
7912
8086
  }
@@ -9270,7 +9444,7 @@ var MediaFolderController = class {
9270
9444
  };
9271
9445
 
9272
9446
  // src/controllers/auth.controller.ts
9273
- var import_node_crypto2 = require("crypto");
9447
+ var import_node_crypto3 = require("crypto");
9274
9448
 
9275
9449
  // src/auth/lockout.ts
9276
9450
  var DEFAULT_MAX_LOGIN_ATTEMPTS = 5;
@@ -9581,7 +9755,7 @@ var AuthController = class {
9581
9755
  const data = {
9582
9756
  ...safeExtraFields,
9583
9757
  email,
9584
- password: await hashPassword((0, import_node_crypto2.randomBytes)(32).toString("hex"))
9758
+ password: await hashPassword((0, import_node_crypto3.randomBytes)(32).toString("hex"))
9585
9759
  };
9586
9760
  if (this.hasField("status")) {
9587
9761
  data.status = "pending";
@@ -10184,7 +10358,7 @@ var AuthController = class {
10184
10358
  };
10185
10359
 
10186
10360
  // src/controllers/admin-auth.controller.ts
10187
- var import_node_crypto3 = require("crypto");
10361
+ var import_node_crypto4 = require("crypto");
10188
10362
  var import_node_util2 = require("util");
10189
10363
  var import_jose2 = require("jose");
10190
10364
  var AdminAuthController = class {
@@ -10394,7 +10568,7 @@ var AdminAuthController = class {
10394
10568
  access.roles,
10395
10569
  access.data
10396
10570
  ),
10397
- password: await hashPassword((0, import_node_crypto3.randomBytes)(32).toString("hex"))
10571
+ password: await hashPassword((0, import_node_crypto4.randomBytes)(32).toString("hex"))
10398
10572
  }
10399
10573
  });
10400
10574
  } else if (user) {
@@ -10481,7 +10655,7 @@ var AdminAuthController = class {
10481
10655
  }
10482
10656
  async buildOidcStartUrl(provider, returnTo, siteId, origin) {
10483
10657
  const discovery = await this.getOidcDiscovery(provider);
10484
- const nonce = (0, import_node_crypto3.randomBytes)(16).toString("hex");
10658
+ const nonce = (0, import_node_crypto4.randomBytes)(16).toString("hex");
10485
10659
  const state = await this.signState({
10486
10660
  providerId: provider.id,
10487
10661
  returnTo,
@@ -11042,7 +11216,7 @@ function formatAIErrorMessage(error) {
11042
11216
  }
11043
11217
  return msg;
11044
11218
  }
11045
- function generateId() {
11219
+ function generateId2() {
11046
11220
  return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
11047
11221
  }
11048
11222
  function buildDyrectedSystemPrompt(context) {
@@ -11188,7 +11362,7 @@ var AIAgent = class {
11188
11362
  }
11189
11363
  async createThread(title, id) {
11190
11364
  const thread = {
11191
- id: id || generateId(),
11365
+ id: id || generateId2(),
11192
11366
  projectId: this.projectId,
11193
11367
  userId: this.userId,
11194
11368
  title: title || "New Conversation",
@@ -11255,7 +11429,7 @@ var AIAgent = class {
11255
11429
  }
11256
11430
  async persistUserMessage(threadId, content) {
11257
11431
  const message = {
11258
- id: generateId(),
11432
+ id: generateId2(),
11259
11433
  threadId,
11260
11434
  role: "user",
11261
11435
  content,
@@ -11271,7 +11445,7 @@ var AIAgent = class {
11271
11445
  }
11272
11446
  async persistAssistantMessage(threadId, content, metadata, parts) {
11273
11447
  const message = {
11274
- id: generateId(),
11448
+ id: generateId2(),
11275
11449
  threadId,
11276
11450
  role: "assistant",
11277
11451
  content,
@@ -14351,6 +14525,8 @@ function registerRoutes(app, config) {
14351
14525
  app.post(`${path}/aggregate`, (c) => controller.aggregate(c));
14352
14526
  if (collection.views?.length) {
14353
14527
  app.post(`${path}/views/:viewSlug/actions/:action`, optionalAuth(config), (c) => controller.runViewAction(c));
14528
+ }
14529
+ if (collection.views?.length || collection.actions?.length) {
14354
14530
  app.post(`${path}/actions/:action`, optionalAuth(config), (c) => controller.runViewAction(c));
14355
14531
  }
14356
14532
  if (collection.audit) {
@@ -14831,11 +15007,31 @@ function normalizeConfig(config) {
14831
15007
  }
14832
15008
  const updatedFieldNames = new Set(fields.map((f) => f.name));
14833
15009
  const fieldsToInject = SYSTEM_FIELDS.filter((f) => !updatedFieldNames.has(f.name));
15010
+ const indexedFieldNames = /* @__PURE__ */ new Set();
15011
+ if (col.indexes) {
15012
+ for (const idx of col.indexes) {
15013
+ if (Array.isArray(idx.fields)) {
15014
+ for (const f of idx.fields) {
15015
+ indexedFieldNames.add(f);
15016
+ }
15017
+ }
15018
+ }
15019
+ }
15020
+ const allFields = [...fields, ...fieldsToInject].map((field) => {
15021
+ if (field.unique || field.name && indexedFieldNames.has(field.name)) {
15022
+ return { ...field, promoted: true };
15023
+ }
15024
+ return field;
15025
+ });
14834
15026
  const workflow = col.workflow || (col.drafts ? simplePublishingWorkflow() : void 0);
15027
+ const idPrefix = col.idPrefix || resolvePrefix(col.slug);
15028
+ const idType = col.idType || "prefixed-nanoid";
14835
15029
  return {
14836
15030
  ...col,
15031
+ idPrefix,
15032
+ idType,
14837
15033
  workflow,
14838
- fields: [...fields, ...fieldsToInject]
15034
+ fields: allFields
14839
15035
  };
14840
15036
  });
14841
15037
  const hasAuditCollection = normalizedCollections.some((col) => col.slug === AUDIT_COLLECTION_SLUG);
@@ -15128,6 +15324,8 @@ async function createDyrectedApp(rawConfig) {
15128
15324
  if (err instanceof import_http_exception6.HTTPException) {
15129
15325
  return c.json({ error: true, message: err.message }, err.status);
15130
15326
  }
15327
+ const statusCode = err.statusCode;
15328
+ const status = typeof statusCode === "number" && Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599 ? statusCode : 500;
15131
15329
  const logger = getRequestLogger(c, "core");
15132
15330
  logger.error({
15133
15331
  err,
@@ -15140,9 +15338,10 @@ async function createDyrectedApp(rawConfig) {
15140
15338
  method: c.req.method
15141
15339
  });
15142
15340
  return c.json({
15341
+ error: true,
15143
15342
  message: err.message || "Internal Server Error",
15144
15343
  stack: process.env.NODE_ENV === "development" ? err.stack : void 0
15145
- }, 500);
15344
+ }, status);
15146
15345
  });
15147
15346
  registerRoutes(app, config);
15148
15347
  return app;
@@ -15198,6 +15397,7 @@ init_embedding_service();
15198
15397
  getLockedUntilMs,
15199
15398
  getObservabilityRuntime,
15200
15399
  getRequestLogger,
15400
+ hasEmbeddingApiKey,
15201
15401
  hashContent,
15202
15402
  hashPassword,
15203
15403
  isAuthSessionActive,
package/dist/server.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { J as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig, bj as DatabaseAdapter, b as AuthenticatedUser, bE as DyrectedAIContext, al as AIThread, ah as AIMessage, cu as RAGSearchResult, ak as AIRateLimitStore, aj as AIRateLimitResult } from './app-Cp8RudRI.cjs';
2
- export { d8 as CollectionTokenPayload, d9 as DEFAULT_SESSION_EXPIRY, da as DyrectedObservabilityRuntime, db as RequestBodyCapture, dc as RequestTraceContext, dd as ResolvedObservabilityConfig, de as attachRequestMetrics, df as bindObservabilityRuntime, dg as buildRequestLogger, dh as captureRequestBody, di as createDyrectedApp, dj as createObservabilityRuntime, dk as createRequestSpan, dl as decodeCollectionToken, dm as endRequestSpan, dn as getConfigLogger, dp as getObservabilityRuntime, dq as getRequestLogger, dr as redactBody, ds as redactHeaders, dt as renderPrometheusMetrics, du as resolveObservabilityConfig, dv as resolveSessionTokenExpiry, dw as shouldSampleRequest, dx as signCollectionToken, dy as verifyCollectionToken } from './app-Cp8RudRI.cjs';
1
+ import { M as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig, bn as DatabaseAdapter, b as AuthenticatedUser, bI as DyrectedAIContext, ao as AIThread, ak as AIMessage, cz as RAGSearchResult, an as AIRateLimitStore, am as AIRateLimitResult } from './app-KSDgfXsw.cjs';
2
+ export { dd as CollectionTokenPayload, de as DEFAULT_SESSION_EXPIRY, df as DyrectedObservabilityRuntime, dg as RequestBodyCapture, dh as RequestTraceContext, di as ResolvedObservabilityConfig, dj as attachRequestMetrics, dk as bindObservabilityRuntime, dl as buildRequestLogger, dm as captureRequestBody, dn as createDyrectedApp, dp as createObservabilityRuntime, dq as createRequestSpan, dr as decodeCollectionToken, ds as endRequestSpan, dt as getConfigLogger, du as getObservabilityRuntime, dv as getRequestLogger, dw as redactBody, dx as redactHeaders, dy as renderPrometheusMetrics, dz as resolveObservabilityConfig, dA as resolveSessionTokenExpiry, dB as shouldSampleRequest, dC as signCollectionToken, dD as verifyCollectionToken } from './app-KSDgfXsw.cjs';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context, Next } from 'hono';
5
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
@@ -716,6 +716,13 @@ declare function estimateTokens(text: string): number;
716
716
  */
717
717
  declare function chunkText(text: string, options?: ChunkOptions): ChunkResult[];
718
718
 
719
+ /**
720
+ * Whether any embedding API key is resolvable for this config. Mirrors the
721
+ * key sources consulted by `getEmbeddingModel` without constructing a
722
+ * provider. When this returns false, RAG indexing can never succeed, so
723
+ * callers should skip silently instead of throwing and logging noise.
724
+ */
725
+ declare function hasEmbeddingApiKey(config?: DyrectedConfig): boolean;
719
726
  declare function getEmbeddingModel(config?: DyrectedConfig): EmbeddingModel;
720
727
  declare class EmbeddingService {
721
728
  private config?;
@@ -738,4 +745,4 @@ declare class InMemoryRateLimitStore implements AIRateLimitStore {
738
745
  }
739
746
  declare function aiRateLimit(config?: DyrectedConfig): (c: Context<DyrectedContext>, next: Next) => Promise<void>;
740
747
 
741
- export { AIAgent, type AIAgentOptions, AIController, AUTH_SESSIONS_COLLECTION, AuthController, type AuthSessionRecord, type ChunkOptions, type ChunkResult, CollectionController, DEFAULT_LOCK_TIME_MS, DEFAULT_MAX_LOGIN_ATTEMPTS, type DeleteDocumentChunksOptions, DyrectedContext, EmbeddingService, GlobalController, InMemoryRateLimitStore, type IndexDocumentOptions, MediaController, PreviewController, type RAGSearchOptions, RAGService, type ReindexAllOptions, type ReindexCollectionOptions, type ResolvedAuthLockoutConfig, aiRateLimit, buildDyrectedSystemPrompt, buildInviteEmail, buildPasswordChangedEmail, buildResetPasswordEmail, buildWelcomeEmail, chunkText, cosineSimilarity, createDyrectedAITools, estimateTokens, extractTextFromDoc, formatAIErrorMessage, getAIModel, getAuthSession, getEmbeddingModel, getLockedUntilMs, hashContent, hashPassword, isAuthSessionActive, issueAuthSessionToken, normalizeFieldValue, registerRoutes, resolveAuthLockoutConfig, revokeAllAuthSessions, revokeAuthSession, sendEmail, serializeDetailForApi, serializeViewForApi, touchAuthSession, validatePayloadAgainstFields, verifyPassword };
748
+ export { AIAgent, type AIAgentOptions, AIController, AUTH_SESSIONS_COLLECTION, AuthController, type AuthSessionRecord, type ChunkOptions, type ChunkResult, CollectionController, DEFAULT_LOCK_TIME_MS, DEFAULT_MAX_LOGIN_ATTEMPTS, type DeleteDocumentChunksOptions, DyrectedContext, EmbeddingService, GlobalController, InMemoryRateLimitStore, type IndexDocumentOptions, MediaController, PreviewController, type RAGSearchOptions, RAGService, type ReindexAllOptions, type ReindexCollectionOptions, type ResolvedAuthLockoutConfig, aiRateLimit, buildDyrectedSystemPrompt, buildInviteEmail, buildPasswordChangedEmail, buildResetPasswordEmail, buildWelcomeEmail, chunkText, cosineSimilarity, createDyrectedAITools, estimateTokens, extractTextFromDoc, formatAIErrorMessage, getAIModel, getAuthSession, getEmbeddingModel, getLockedUntilMs, hasEmbeddingApiKey, hashContent, hashPassword, isAuthSessionActive, issueAuthSessionToken, normalizeFieldValue, registerRoutes, resolveAuthLockoutConfig, revokeAllAuthSessions, revokeAuthSession, sendEmail, serializeDetailForApi, serializeViewForApi, touchAuthSession, validatePayloadAgainstFields, verifyPassword };
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { J as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig, bj as DatabaseAdapter, b as AuthenticatedUser, bE as DyrectedAIContext, al as AIThread, ah as AIMessage, cu as RAGSearchResult, ak as AIRateLimitStore, aj as AIRateLimitResult } from './app-Cp8RudRI.js';
2
- export { d8 as CollectionTokenPayload, d9 as DEFAULT_SESSION_EXPIRY, da as DyrectedObservabilityRuntime, db as RequestBodyCapture, dc as RequestTraceContext, dd as ResolvedObservabilityConfig, de as attachRequestMetrics, df as bindObservabilityRuntime, dg as buildRequestLogger, dh as captureRequestBody, di as createDyrectedApp, dj as createObservabilityRuntime, dk as createRequestSpan, dl as decodeCollectionToken, dm as endRequestSpan, dn as getConfigLogger, dp as getObservabilityRuntime, dq as getRequestLogger, dr as redactBody, ds as redactHeaders, dt as renderPrometheusMetrics, du as resolveObservabilityConfig, dv as resolveSessionTokenExpiry, dw as shouldSampleRequest, dx as signCollectionToken, dy as verifyCollectionToken } from './app-Cp8RudRI.js';
1
+ import { M as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig, bn as DatabaseAdapter, b as AuthenticatedUser, bI as DyrectedAIContext, ao as AIThread, ak as AIMessage, cz as RAGSearchResult, an as AIRateLimitStore, am as AIRateLimitResult } from './app-KSDgfXsw.js';
2
+ export { dd as CollectionTokenPayload, de as DEFAULT_SESSION_EXPIRY, df as DyrectedObservabilityRuntime, dg as RequestBodyCapture, dh as RequestTraceContext, di as ResolvedObservabilityConfig, dj as attachRequestMetrics, dk as bindObservabilityRuntime, dl as buildRequestLogger, dm as captureRequestBody, dn as createDyrectedApp, dp as createObservabilityRuntime, dq as createRequestSpan, dr as decodeCollectionToken, ds as endRequestSpan, dt as getConfigLogger, du as getObservabilityRuntime, dv as getRequestLogger, dw as redactBody, dx as redactHeaders, dy as renderPrometheusMetrics, dz as resolveObservabilityConfig, dA as resolveSessionTokenExpiry, dB as shouldSampleRequest, dC as signCollectionToken, dD as verifyCollectionToken } from './app-KSDgfXsw.js';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context, Next } from 'hono';
5
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
@@ -716,6 +716,13 @@ declare function estimateTokens(text: string): number;
716
716
  */
717
717
  declare function chunkText(text: string, options?: ChunkOptions): ChunkResult[];
718
718
 
719
+ /**
720
+ * Whether any embedding API key is resolvable for this config. Mirrors the
721
+ * key sources consulted by `getEmbeddingModel` without constructing a
722
+ * provider. When this returns false, RAG indexing can never succeed, so
723
+ * callers should skip silently instead of throwing and logging noise.
724
+ */
725
+ declare function hasEmbeddingApiKey(config?: DyrectedConfig): boolean;
719
726
  declare function getEmbeddingModel(config?: DyrectedConfig): EmbeddingModel;
720
727
  declare class EmbeddingService {
721
728
  private config?;
@@ -738,4 +745,4 @@ declare class InMemoryRateLimitStore implements AIRateLimitStore {
738
745
  }
739
746
  declare function aiRateLimit(config?: DyrectedConfig): (c: Context<DyrectedContext>, next: Next) => Promise<void>;
740
747
 
741
- export { AIAgent, type AIAgentOptions, AIController, AUTH_SESSIONS_COLLECTION, AuthController, type AuthSessionRecord, type ChunkOptions, type ChunkResult, CollectionController, DEFAULT_LOCK_TIME_MS, DEFAULT_MAX_LOGIN_ATTEMPTS, type DeleteDocumentChunksOptions, DyrectedContext, EmbeddingService, GlobalController, InMemoryRateLimitStore, type IndexDocumentOptions, MediaController, PreviewController, type RAGSearchOptions, RAGService, type ReindexAllOptions, type ReindexCollectionOptions, type ResolvedAuthLockoutConfig, aiRateLimit, buildDyrectedSystemPrompt, buildInviteEmail, buildPasswordChangedEmail, buildResetPasswordEmail, buildWelcomeEmail, chunkText, cosineSimilarity, createDyrectedAITools, estimateTokens, extractTextFromDoc, formatAIErrorMessage, getAIModel, getAuthSession, getEmbeddingModel, getLockedUntilMs, hashContent, hashPassword, isAuthSessionActive, issueAuthSessionToken, normalizeFieldValue, registerRoutes, resolveAuthLockoutConfig, revokeAllAuthSessions, revokeAuthSession, sendEmail, serializeDetailForApi, serializeViewForApi, touchAuthSession, validatePayloadAgainstFields, verifyPassword };
748
+ export { AIAgent, type AIAgentOptions, AIController, AUTH_SESSIONS_COLLECTION, AuthController, type AuthSessionRecord, type ChunkOptions, type ChunkResult, CollectionController, DEFAULT_LOCK_TIME_MS, DEFAULT_MAX_LOGIN_ATTEMPTS, type DeleteDocumentChunksOptions, DyrectedContext, EmbeddingService, GlobalController, InMemoryRateLimitStore, type IndexDocumentOptions, MediaController, PreviewController, type RAGSearchOptions, RAGService, type ReindexAllOptions, type ReindexCollectionOptions, type ResolvedAuthLockoutConfig, aiRateLimit, buildDyrectedSystemPrompt, buildInviteEmail, buildPasswordChangedEmail, buildResetPasswordEmail, buildWelcomeEmail, chunkText, cosineSimilarity, createDyrectedAITools, estimateTokens, extractTextFromDoc, formatAIErrorMessage, getAIModel, getAuthSession, getEmbeddingModel, getLockedUntilMs, hasEmbeddingApiKey, hashContent, hashPassword, isAuthSessionActive, issueAuthSessionToken, normalizeFieldValue, registerRoutes, resolveAuthLockoutConfig, revokeAllAuthSessions, revokeAuthSession, sendEmail, serializeDetailForApi, serializeViewForApi, touchAuthSession, validatePayloadAgainstFields, verifyPassword };