@ai-matrx/associations 0.11.4 → 0.13.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.
@@ -278,8 +278,6 @@ interface CandidateRecord {
278
278
  }
279
279
  interface ListCandidatesArgs {
280
280
  token: EntityTypeToken;
281
- /** Scope to this owner's rows when the entity declares an owner column. */
282
- ownerId?: string | null;
283
281
  /** Case-insensitive title filter. */
284
282
  search?: string;
285
283
  limit?: number;
@@ -298,12 +296,25 @@ interface SearchAcrossTokensArgs {
298
296
  /** Tokens to search. Defaults to every curated token in the registry. */
299
297
  tokens?: EntityTypeToken[];
300
298
  search: string;
301
- ownerId?: string | null;
302
299
  /** Cap per token — a universal search shows a few of everything. */
303
300
  perTokenLimit?: number;
304
301
  /** Max in-flight token queries. */
305
302
  concurrency?: number;
306
303
  }
304
+ /** One token whose candidate read failed during a cross-token search. */
305
+ interface TokenSearchFailure {
306
+ token: EntityTypeToken;
307
+ error: string;
308
+ }
309
+ /**
310
+ * A cross-token search's honest answer: what could be read, AND what could
311
+ * not. An empty `results` with non-empty `failures` is "we couldn't look",
312
+ * never "there is nothing".
313
+ */
314
+ interface SearchAcrossTokensResult {
315
+ results: UniversalCandidate[];
316
+ failures: TokenSearchFailure[];
317
+ }
307
318
  interface ReferenceSearchCandidatesFn {
308
319
  (args: {
309
320
  p_token: string;
@@ -333,10 +344,12 @@ interface CandidatesServiceApi {
333
344
  /**
334
345
  * ONE search over EVERY listable entity type — the "attach anything from
335
346
  * anywhere" primitive. Registry-driven client fan-out, capped and
336
- * concurrency-limited. Per-token failures are screamed and skipped — one
337
- * broken table never blanks the search.
347
+ * concurrency-limited. One broken table never blanks the search: a failed
348
+ * token is screamed (errorSink) AND reported in `failures` (registry
349
+ * order), so a face can say what it could not search instead of showing
350
+ * "no results".
338
351
  */
339
- searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<UniversalCandidate[]>;
352
+ searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<SearchAcrossTokensResult>;
340
353
  }
341
354
  declare function createCandidatesService(deps: CoreDeps): CandidatesServiceApi;
342
355
 
@@ -725,4 +738,4 @@ declare function buildCategoryHierarchy(categories: PlatformCategory[]): Categor
725
738
  */
726
739
  declare function createDefaultErrorSink(): ErrorSink;
727
740
 
728
- export { type AddAssociationArgs, type AddCommentArgs, type AssociationGuards, type AssociationHelpersApi, type AssociationWriteResult, type AssociationsServiceApi, type AssociationsStore, type CandidateRecord, type CandidatesResult, type CandidatesServiceApi, type CategoriesServiceApi, type CategoryHierarchy, type CategoryHierarchyItem, type CategoryMutationResult, type CommentMutationResult, type CommentsServiceApi, type ContainerRef, type ContentRole, type ConversationFileLink, type CoreDeps, type CreateEntityRowArgs, DEFAULT_ORG_COLUMN, DEFAULT_OWNER_COLUMN, type EdgeAttrs, type EdgeSpec, type EntityInfo, type EntityRef, type EntityRegistry, type EntityRowResult, type EntityRowsServiceApi, type FavoritesServiceApi, type ListCandidatesArgs, NON_CONTENT_SOURCE_TYPES, type PgErrorMapper, type RpcResultHelpers, type SearchAcrossTokensArgs, type TitlesServiceApi, type UniversalCandidate, associationsKey, buildCategoryHierarchy, createAssociationGuards, createAssociationHelpers, createAssociationsService, createAssociationsStore, createCandidatesService, createCategoriesService, createCommentsService, createDefaultErrorSink, createEntityRegistry, createEntityRowsService, createFavoritesService, createRpcResultHelpers, createTitlesService, entityTitleCacheKey, err, firstError, isContentRole, isContentSourceEdge, isMembershipMetadata, isTransportFailure, ok, resolveEntityToken };
741
+ export { type AddAssociationArgs, type AddCommentArgs, type AssociationGuards, type AssociationHelpersApi, type AssociationWriteResult, type AssociationsServiceApi, type AssociationsStore, type CandidateRecord, type CandidatesResult, type CandidatesServiceApi, type CategoriesServiceApi, type CategoryHierarchy, type CategoryHierarchyItem, type CategoryMutationResult, type CommentMutationResult, type CommentsServiceApi, type ContainerRef, type ContentRole, type ConversationFileLink, type CoreDeps, type CreateEntityRowArgs, DEFAULT_ORG_COLUMN, DEFAULT_OWNER_COLUMN, type EdgeAttrs, type EdgeSpec, type EntityInfo, type EntityRef, type EntityRegistry, type EntityRowResult, type EntityRowsServiceApi, type FavoritesServiceApi, type ListCandidatesArgs, NON_CONTENT_SOURCE_TYPES, type PgErrorMapper, type RpcResultHelpers, type SearchAcrossTokensArgs, type SearchAcrossTokensResult, type TitlesServiceApi, type TokenSearchFailure, type UniversalCandidate, associationsKey, buildCategoryHierarchy, createAssociationGuards, createAssociationHelpers, createAssociationsService, createAssociationsStore, createCandidatesService, createCategoriesService, createCommentsService, createDefaultErrorSink, createEntityRegistry, createEntityRowsService, createFavoritesService, createRpcResultHelpers, createTitlesService, entityTitleCacheKey, err, firstError, isContentRole, isContentSourceEdge, isMembershipMetadata, isTransportFailure, ok, resolveEntityToken };
@@ -278,8 +278,6 @@ interface CandidateRecord {
278
278
  }
279
279
  interface ListCandidatesArgs {
280
280
  token: EntityTypeToken;
281
- /** Scope to this owner's rows when the entity declares an owner column. */
282
- ownerId?: string | null;
283
281
  /** Case-insensitive title filter. */
284
282
  search?: string;
285
283
  limit?: number;
@@ -298,12 +296,25 @@ interface SearchAcrossTokensArgs {
298
296
  /** Tokens to search. Defaults to every curated token in the registry. */
299
297
  tokens?: EntityTypeToken[];
300
298
  search: string;
301
- ownerId?: string | null;
302
299
  /** Cap per token — a universal search shows a few of everything. */
303
300
  perTokenLimit?: number;
304
301
  /** Max in-flight token queries. */
305
302
  concurrency?: number;
306
303
  }
304
+ /** One token whose candidate read failed during a cross-token search. */
305
+ interface TokenSearchFailure {
306
+ token: EntityTypeToken;
307
+ error: string;
308
+ }
309
+ /**
310
+ * A cross-token search's honest answer: what could be read, AND what could
311
+ * not. An empty `results` with non-empty `failures` is "we couldn't look",
312
+ * never "there is nothing".
313
+ */
314
+ interface SearchAcrossTokensResult {
315
+ results: UniversalCandidate[];
316
+ failures: TokenSearchFailure[];
317
+ }
307
318
  interface ReferenceSearchCandidatesFn {
308
319
  (args: {
309
320
  p_token: string;
@@ -333,10 +344,12 @@ interface CandidatesServiceApi {
333
344
  /**
334
345
  * ONE search over EVERY listable entity type — the "attach anything from
335
346
  * anywhere" primitive. Registry-driven client fan-out, capped and
336
- * concurrency-limited. Per-token failures are screamed and skipped — one
337
- * broken table never blanks the search.
347
+ * concurrency-limited. One broken table never blanks the search: a failed
348
+ * token is screamed (errorSink) AND reported in `failures` (registry
349
+ * order), so a face can say what it could not search instead of showing
350
+ * "no results".
338
351
  */
339
- searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<UniversalCandidate[]>;
352
+ searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<SearchAcrossTokensResult>;
340
353
  }
341
354
  declare function createCandidatesService(deps: CoreDeps): CandidatesServiceApi;
342
355
 
@@ -725,4 +738,4 @@ declare function buildCategoryHierarchy(categories: PlatformCategory[]): Categor
725
738
  */
726
739
  declare function createDefaultErrorSink(): ErrorSink;
727
740
 
728
- export { type AddAssociationArgs, type AddCommentArgs, type AssociationGuards, type AssociationHelpersApi, type AssociationWriteResult, type AssociationsServiceApi, type AssociationsStore, type CandidateRecord, type CandidatesResult, type CandidatesServiceApi, type CategoriesServiceApi, type CategoryHierarchy, type CategoryHierarchyItem, type CategoryMutationResult, type CommentMutationResult, type CommentsServiceApi, type ContainerRef, type ContentRole, type ConversationFileLink, type CoreDeps, type CreateEntityRowArgs, DEFAULT_ORG_COLUMN, DEFAULT_OWNER_COLUMN, type EdgeAttrs, type EdgeSpec, type EntityInfo, type EntityRef, type EntityRegistry, type EntityRowResult, type EntityRowsServiceApi, type FavoritesServiceApi, type ListCandidatesArgs, NON_CONTENT_SOURCE_TYPES, type PgErrorMapper, type RpcResultHelpers, type SearchAcrossTokensArgs, type TitlesServiceApi, type UniversalCandidate, associationsKey, buildCategoryHierarchy, createAssociationGuards, createAssociationHelpers, createAssociationsService, createAssociationsStore, createCandidatesService, createCategoriesService, createCommentsService, createDefaultErrorSink, createEntityRegistry, createEntityRowsService, createFavoritesService, createRpcResultHelpers, createTitlesService, entityTitleCacheKey, err, firstError, isContentRole, isContentSourceEdge, isMembershipMetadata, isTransportFailure, ok, resolveEntityToken };
741
+ export { type AddAssociationArgs, type AddCommentArgs, type AssociationGuards, type AssociationHelpersApi, type AssociationWriteResult, type AssociationsServiceApi, type AssociationsStore, type CandidateRecord, type CandidatesResult, type CandidatesServiceApi, type CategoriesServiceApi, type CategoryHierarchy, type CategoryHierarchyItem, type CategoryMutationResult, type CommentMutationResult, type CommentsServiceApi, type ContainerRef, type ContentRole, type ConversationFileLink, type CoreDeps, type CreateEntityRowArgs, DEFAULT_ORG_COLUMN, DEFAULT_OWNER_COLUMN, type EdgeAttrs, type EdgeSpec, type EntityInfo, type EntityRef, type EntityRegistry, type EntityRowResult, type EntityRowsServiceApi, type FavoritesServiceApi, type ListCandidatesArgs, NON_CONTENT_SOURCE_TYPES, type PgErrorMapper, type RpcResultHelpers, type SearchAcrossTokensArgs, type SearchAcrossTokensResult, type TitlesServiceApi, type TokenSearchFailure, type UniversalCandidate, associationsKey, buildCategoryHierarchy, createAssociationGuards, createAssociationHelpers, createAssociationsService, createAssociationsStore, createCandidatesService, createCategoriesService, createCommentsService, createDefaultErrorSink, createEntityRegistry, createEntityRowsService, createFavoritesService, createRpcResultHelpers, createTitlesService, entityTitleCacheKey, err, firstError, isContentRole, isContentSourceEdge, isMembershipMetadata, isTransportFailure, ok, resolveEntityToken };
@@ -3060,10 +3060,11 @@ function createCandidatesService(deps) {
3060
3060
  };
3061
3061
  }
3062
3062
  async function searchCandidatesAcrossTokens(args) {
3063
- const { tokens, search, ownerId, perTokenLimit = 5, concurrency = 6 } = args;
3063
+ const { tokens, search, perTokenLimit = 5, concurrency = 6 } = args;
3064
3064
  const list = tokens ?? registry.listableTokens();
3065
- if (list.length === 0) return [];
3065
+ if (list.length === 0) return { results: [], failures: [] };
3066
3066
  const out = [];
3067
+ const failures = [];
3067
3068
  let cursor = 0;
3068
3069
  async function worker() {
3069
3070
  while (cursor < list.length) {
@@ -3072,12 +3073,13 @@ function createCandidatesService(deps) {
3072
3073
  if (!token) continue;
3073
3074
  const res = await listAssociationCandidates({
3074
3075
  token,
3075
- ownerId: ownerId ?? null,
3076
3076
  search,
3077
3077
  limit: perTokenLimit
3078
3078
  });
3079
3079
  if (res.ok) {
3080
3080
  for (const c of res.data) out.push({ ...c, token });
3081
+ } else {
3082
+ failures.push({ token, error: res.error });
3081
3083
  }
3082
3084
  }
3083
3085
  }
@@ -3091,7 +3093,10 @@ function createCandidatesService(deps) {
3091
3093
  if (ta !== tb) return ta - tb;
3092
3094
  return a.title.localeCompare(b.title);
3093
3095
  });
3094
- return out;
3096
+ failures.sort(
3097
+ (a, b) => (tokenOrder.get(a.token) ?? 0) - (tokenOrder.get(b.token) ?? 0)
3098
+ );
3099
+ return { results: out, failures };
3095
3100
  }
3096
3101
  return {
3097
3102
  callReferenceSearchCandidates,