@howells/stow-server 2.0.1 → 2.2.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.d.mts CHANGED
@@ -453,6 +453,8 @@ interface ConfirmUploadRequest {
453
453
  }
454
454
  /** Input payload for similarity search. */
455
455
  interface SimilarSearchRequest {
456
+ /** Use an anchor's embedding as the query vector */
457
+ anchorId?: string;
456
458
  /** Bucket name or ID to scope search */
457
459
  bucket?: string;
458
460
  /** Use a specific cluster centroid instead of the profile master vector. Requires profileId. */
@@ -476,6 +478,8 @@ interface SimilarSearchRequest {
476
478
  }
477
479
  /** Input payload for diversity-aware search. */
478
480
  interface DiverseSearchRequest {
481
+ /** Use an anchor's embedding as the query vector */
482
+ anchorId?: string;
479
483
  /** Bucket name or ID to scope search */
480
484
  bucket?: string;
481
485
  /** Use a specific cluster centroid instead of the profile master vector. Requires profileId. */
@@ -529,6 +533,32 @@ interface SearchResultItem {
529
533
  }>;
530
534
  width?: number | null;
531
535
  }
536
+ /** A text anchor — a named semantic reference point in a bucket's vector space. */
537
+ interface Anchor {
538
+ bucketId: string;
539
+ createdAt: string;
540
+ id: string;
541
+ label: string | null;
542
+ text: string;
543
+ updatedAt: string;
544
+ }
545
+ /** Input for creating an anchor. */
546
+ interface CreateAnchorRequest {
547
+ label?: string;
548
+ text: string;
549
+ }
550
+ /** Input for updating an anchor. */
551
+ interface UpdateAnchorRequest {
552
+ label?: string | null;
553
+ text?: string;
554
+ }
555
+ /** An anchor result returned in search responses. */
556
+ interface AnchorSearchResult {
557
+ id: string;
558
+ label: string | null;
559
+ similarity: number;
560
+ text: string;
561
+ }
532
562
  /** Which filter categories were active in the request. */
533
563
  interface AppliedFilters {
534
564
  color?: string[];
@@ -547,6 +577,7 @@ interface FilteredMetadata {
547
577
  }
548
578
  /** Result payload returned by similarity/diversity search endpoints. */
549
579
  interface SimilarSearchResult {
580
+ anchors?: AnchorSearchResult[];
550
581
  filtered?: FilteredMetadata;
551
582
  results: SearchResultItem[];
552
583
  }
@@ -596,6 +627,47 @@ interface ColorSearchResultItem {
596
627
  interface ColorSearchResult {
597
628
  results: ColorSearchResultItem[];
598
629
  }
630
+ /** Input specifying the image source for search-by-image. Exactly one of url or fileKey. */
631
+ interface SearchByImageInput {
632
+ /** Key of an existing file to use as the image source */
633
+ fileKey?: string;
634
+ /** URL of an external image to download, persist, and embed */
635
+ url?: string;
636
+ }
637
+ /** Options for search-by-image. */
638
+ interface SearchByImageOptions {
639
+ /** Bucket name or ID to scope search */
640
+ bucket?: string;
641
+ /** File keys to exclude from results (e.g. already-seen items). Max 500. */
642
+ excludeKeys?: string[];
643
+ /** Structured post-filters (taxonomy, tag, color, content type, metadata) */
644
+ filters?: SearchFilters;
645
+ /** Opt-in enrichment fields to include in results */
646
+ include?: SearchIncludeField[];
647
+ /** Max results (default 10, max 50) */
648
+ limit?: number;
649
+ /** Custom metadata to attach when persisting a URL-sourced image */
650
+ metadata?: Record<string, string>;
651
+ /** Minimum similarity threshold (0–1, default 0.25) */
652
+ threshold?: number;
653
+ }
654
+ /** Source image metadata returned by search-by-image. */
655
+ interface SearchByImageSource {
656
+ embedding: {
657
+ dimensions: number;
658
+ durationMs: number;
659
+ model: string;
660
+ };
661
+ fileKey: string;
662
+ vector: number[];
663
+ }
664
+ /** Result payload returned by search-by-image. */
665
+ interface SearchByImageResult {
666
+ anchors?: AnchorSearchResult[];
667
+ filtered?: FilteredMetadata;
668
+ results: SearchResultItem[];
669
+ source: SearchByImageSource;
670
+ }
599
671
  /** A taxonomy term within a group. */
600
672
  interface TaxonomyTerm {
601
673
  name: string;
@@ -906,11 +978,13 @@ declare class StowServer {
906
978
  diverse: (params?: DiverseSearchRequest) => Promise<SimilarSearchResult>;
907
979
  text: (params: TextSearchRequest) => Promise<SimilarSearchResult>;
908
980
  color: (params: ColorSearchRequest) => Promise<ColorSearchResult>;
981
+ image: (input: SearchByImageInput, options?: SearchByImageOptions) => Promise<SearchByImageResult>;
909
982
  };
910
983
  private searchSimilar;
911
984
  private searchDiverse;
912
985
  private searchText;
913
986
  private searchColor;
987
+ private searchImage;
914
988
  /**
915
989
  * Upload a file as a drop (quick share)
916
990
  *
@@ -964,6 +1038,35 @@ declare class StowServer {
964
1038
  private getProfileClusters;
965
1039
  private reclusterProfile;
966
1040
  private renameProfileCluster;
1041
+ /**
1042
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1043
+ *
1044
+ * @example
1045
+ * ```typescript
1046
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1047
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1048
+ * ```
1049
+ */
1050
+ get anchors(): {
1051
+ create: (params: CreateAnchorRequest) => Promise<Anchor>;
1052
+ list: (options?: {
1053
+ bucket?: string;
1054
+ }) => Promise<{
1055
+ anchors: Anchor[];
1056
+ }>;
1057
+ get: (id: string, options?: {
1058
+ bucket?: string;
1059
+ }) => Promise<Anchor>;
1060
+ update: (id: string, params: UpdateAnchorRequest) => Promise<Anchor>;
1061
+ delete: (id: string, options?: {
1062
+ bucket?: string;
1063
+ }) => Promise<void>;
1064
+ };
1065
+ private createAnchor;
1066
+ private listAnchors;
1067
+ private getAnchor;
1068
+ private updateAnchor;
1069
+ private deleteAnchor;
967
1070
  }
968
1071
 
969
- export { type AppliedFilters, type BucketResult, type ColorSearchRequest, type ColorSearchResult, type ColorSearchResultItem, type ConfirmUploadRequest, type CreateBucketRequest, type DeleteProfileSignalsResult, type DiverseSearchRequest, type Drop, type DropResult, type FileColor, type FileColorProfile, type FileIncludeField, type FileResult, type FileTag, type FileTaxonomy, type FilteredMetadata, type ListBucketsResult, type ListDropsResult, type ListFilesItem, type ListFilesResult, type PresignDedupeResult, type PresignNewResult, type PresignRequest, type PresignResult, type ProfileClusterResult, type ProfileCreateRequest, type ProfileFilesResult, type ProfileResult, type ProfileSignalInput, type ProfileSignalResult, type ProfileSignalType, type ProfileSignalsResponse, type QueuedResult, type ReclusterRequest, type ReclusterResult, type RenameClusterRequest, type ReplaceResult, type SearchFilters, type SearchIncludeField, type SearchResultItem, type SimilarSearchRequest, type SimilarSearchResult, StowError, StowServer, type StowServerConfig, type TaskTriggerResult, type TaxonomyGroup, type TaxonomyListResult, type TaxonomyTerm, type TextSearchRequest, type TransformOptions, type UpdateBucketRequest, type UploadResult, type WhoamiResult };
1072
+ export { type Anchor, type AnchorSearchResult, type AppliedFilters, type BucketResult, type ColorSearchRequest, type ColorSearchResult, type ColorSearchResultItem, type ConfirmUploadRequest, type CreateAnchorRequest, type CreateBucketRequest, type DeleteProfileSignalsResult, type DiverseSearchRequest, type Drop, type DropResult, type FileColor, type FileColorProfile, type FileIncludeField, type FileResult, type FileTag, type FileTaxonomy, type FilteredMetadata, type ListBucketsResult, type ListDropsResult, type ListFilesItem, type ListFilesResult, type PresignDedupeResult, type PresignNewResult, type PresignRequest, type PresignResult, type ProfileClusterResult, type ProfileCreateRequest, type ProfileFilesResult, type ProfileResult, type ProfileSignalInput, type ProfileSignalResult, type ProfileSignalType, type ProfileSignalsResponse, type QueuedResult, type ReclusterRequest, type ReclusterResult, type RenameClusterRequest, type ReplaceResult, type SearchByImageInput, type SearchByImageOptions, type SearchByImageResult, type SearchByImageSource, type SearchFilters, type SearchIncludeField, type SearchResultItem, type SimilarSearchRequest, type SimilarSearchResult, StowError, StowServer, type StowServerConfig, type TaskTriggerResult, type TaxonomyGroup, type TaxonomyListResult, type TaxonomyTerm, type TextSearchRequest, type TransformOptions, type UpdateAnchorRequest, type UpdateBucketRequest, type UploadResult, type WhoamiResult };
package/dist/index.d.ts CHANGED
@@ -453,6 +453,8 @@ interface ConfirmUploadRequest {
453
453
  }
454
454
  /** Input payload for similarity search. */
455
455
  interface SimilarSearchRequest {
456
+ /** Use an anchor's embedding as the query vector */
457
+ anchorId?: string;
456
458
  /** Bucket name or ID to scope search */
457
459
  bucket?: string;
458
460
  /** Use a specific cluster centroid instead of the profile master vector. Requires profileId. */
@@ -476,6 +478,8 @@ interface SimilarSearchRequest {
476
478
  }
477
479
  /** Input payload for diversity-aware search. */
478
480
  interface DiverseSearchRequest {
481
+ /** Use an anchor's embedding as the query vector */
482
+ anchorId?: string;
479
483
  /** Bucket name or ID to scope search */
480
484
  bucket?: string;
481
485
  /** Use a specific cluster centroid instead of the profile master vector. Requires profileId. */
@@ -529,6 +533,32 @@ interface SearchResultItem {
529
533
  }>;
530
534
  width?: number | null;
531
535
  }
536
+ /** A text anchor — a named semantic reference point in a bucket's vector space. */
537
+ interface Anchor {
538
+ bucketId: string;
539
+ createdAt: string;
540
+ id: string;
541
+ label: string | null;
542
+ text: string;
543
+ updatedAt: string;
544
+ }
545
+ /** Input for creating an anchor. */
546
+ interface CreateAnchorRequest {
547
+ label?: string;
548
+ text: string;
549
+ }
550
+ /** Input for updating an anchor. */
551
+ interface UpdateAnchorRequest {
552
+ label?: string | null;
553
+ text?: string;
554
+ }
555
+ /** An anchor result returned in search responses. */
556
+ interface AnchorSearchResult {
557
+ id: string;
558
+ label: string | null;
559
+ similarity: number;
560
+ text: string;
561
+ }
532
562
  /** Which filter categories were active in the request. */
533
563
  interface AppliedFilters {
534
564
  color?: string[];
@@ -547,6 +577,7 @@ interface FilteredMetadata {
547
577
  }
548
578
  /** Result payload returned by similarity/diversity search endpoints. */
549
579
  interface SimilarSearchResult {
580
+ anchors?: AnchorSearchResult[];
550
581
  filtered?: FilteredMetadata;
551
582
  results: SearchResultItem[];
552
583
  }
@@ -596,6 +627,47 @@ interface ColorSearchResultItem {
596
627
  interface ColorSearchResult {
597
628
  results: ColorSearchResultItem[];
598
629
  }
630
+ /** Input specifying the image source for search-by-image. Exactly one of url or fileKey. */
631
+ interface SearchByImageInput {
632
+ /** Key of an existing file to use as the image source */
633
+ fileKey?: string;
634
+ /** URL of an external image to download, persist, and embed */
635
+ url?: string;
636
+ }
637
+ /** Options for search-by-image. */
638
+ interface SearchByImageOptions {
639
+ /** Bucket name or ID to scope search */
640
+ bucket?: string;
641
+ /** File keys to exclude from results (e.g. already-seen items). Max 500. */
642
+ excludeKeys?: string[];
643
+ /** Structured post-filters (taxonomy, tag, color, content type, metadata) */
644
+ filters?: SearchFilters;
645
+ /** Opt-in enrichment fields to include in results */
646
+ include?: SearchIncludeField[];
647
+ /** Max results (default 10, max 50) */
648
+ limit?: number;
649
+ /** Custom metadata to attach when persisting a URL-sourced image */
650
+ metadata?: Record<string, string>;
651
+ /** Minimum similarity threshold (0–1, default 0.25) */
652
+ threshold?: number;
653
+ }
654
+ /** Source image metadata returned by search-by-image. */
655
+ interface SearchByImageSource {
656
+ embedding: {
657
+ dimensions: number;
658
+ durationMs: number;
659
+ model: string;
660
+ };
661
+ fileKey: string;
662
+ vector: number[];
663
+ }
664
+ /** Result payload returned by search-by-image. */
665
+ interface SearchByImageResult {
666
+ anchors?: AnchorSearchResult[];
667
+ filtered?: FilteredMetadata;
668
+ results: SearchResultItem[];
669
+ source: SearchByImageSource;
670
+ }
599
671
  /** A taxonomy term within a group. */
600
672
  interface TaxonomyTerm {
601
673
  name: string;
@@ -906,11 +978,13 @@ declare class StowServer {
906
978
  diverse: (params?: DiverseSearchRequest) => Promise<SimilarSearchResult>;
907
979
  text: (params: TextSearchRequest) => Promise<SimilarSearchResult>;
908
980
  color: (params: ColorSearchRequest) => Promise<ColorSearchResult>;
981
+ image: (input: SearchByImageInput, options?: SearchByImageOptions) => Promise<SearchByImageResult>;
909
982
  };
910
983
  private searchSimilar;
911
984
  private searchDiverse;
912
985
  private searchText;
913
986
  private searchColor;
987
+ private searchImage;
914
988
  /**
915
989
  * Upload a file as a drop (quick share)
916
990
  *
@@ -964,6 +1038,35 @@ declare class StowServer {
964
1038
  private getProfileClusters;
965
1039
  private reclusterProfile;
966
1040
  private renameProfileCluster;
1041
+ /**
1042
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1043
+ *
1044
+ * @example
1045
+ * ```typescript
1046
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1047
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1048
+ * ```
1049
+ */
1050
+ get anchors(): {
1051
+ create: (params: CreateAnchorRequest) => Promise<Anchor>;
1052
+ list: (options?: {
1053
+ bucket?: string;
1054
+ }) => Promise<{
1055
+ anchors: Anchor[];
1056
+ }>;
1057
+ get: (id: string, options?: {
1058
+ bucket?: string;
1059
+ }) => Promise<Anchor>;
1060
+ update: (id: string, params: UpdateAnchorRequest) => Promise<Anchor>;
1061
+ delete: (id: string, options?: {
1062
+ bucket?: string;
1063
+ }) => Promise<void>;
1064
+ };
1065
+ private createAnchor;
1066
+ private listAnchors;
1067
+ private getAnchor;
1068
+ private updateAnchor;
1069
+ private deleteAnchor;
967
1070
  }
968
1071
 
969
- export { type AppliedFilters, type BucketResult, type ColorSearchRequest, type ColorSearchResult, type ColorSearchResultItem, type ConfirmUploadRequest, type CreateBucketRequest, type DeleteProfileSignalsResult, type DiverseSearchRequest, type Drop, type DropResult, type FileColor, type FileColorProfile, type FileIncludeField, type FileResult, type FileTag, type FileTaxonomy, type FilteredMetadata, type ListBucketsResult, type ListDropsResult, type ListFilesItem, type ListFilesResult, type PresignDedupeResult, type PresignNewResult, type PresignRequest, type PresignResult, type ProfileClusterResult, type ProfileCreateRequest, type ProfileFilesResult, type ProfileResult, type ProfileSignalInput, type ProfileSignalResult, type ProfileSignalType, type ProfileSignalsResponse, type QueuedResult, type ReclusterRequest, type ReclusterResult, type RenameClusterRequest, type ReplaceResult, type SearchFilters, type SearchIncludeField, type SearchResultItem, type SimilarSearchRequest, type SimilarSearchResult, StowError, StowServer, type StowServerConfig, type TaskTriggerResult, type TaxonomyGroup, type TaxonomyListResult, type TaxonomyTerm, type TextSearchRequest, type TransformOptions, type UpdateBucketRequest, type UploadResult, type WhoamiResult };
1072
+ export { type Anchor, type AnchorSearchResult, type AppliedFilters, type BucketResult, type ColorSearchRequest, type ColorSearchResult, type ColorSearchResultItem, type ConfirmUploadRequest, type CreateAnchorRequest, type CreateBucketRequest, type DeleteProfileSignalsResult, type DiverseSearchRequest, type Drop, type DropResult, type FileColor, type FileColorProfile, type FileIncludeField, type FileResult, type FileTag, type FileTaxonomy, type FilteredMetadata, type ListBucketsResult, type ListDropsResult, type ListFilesItem, type ListFilesResult, type PresignDedupeResult, type PresignNewResult, type PresignRequest, type PresignResult, type ProfileClusterResult, type ProfileCreateRequest, type ProfileFilesResult, type ProfileResult, type ProfileSignalInput, type ProfileSignalResult, type ProfileSignalType, type ProfileSignalsResponse, type QueuedResult, type ReclusterRequest, type ReclusterResult, type RenameClusterRequest, type ReplaceResult, type SearchByImageInput, type SearchByImageOptions, type SearchByImageResult, type SearchByImageSource, type SearchFilters, type SearchIncludeField, type SearchResultItem, type SimilarSearchRequest, type SimilarSearchResult, StowError, StowServer, type StowServerConfig, type TaskTriggerResult, type TaxonomyGroup, type TaxonomyListResult, type TaxonomyTerm, type TextSearchRequest, type TransformOptions, type UpdateAnchorRequest, type UpdateBucketRequest, type UploadResult, type WhoamiResult };
package/dist/index.js CHANGED
@@ -285,6 +285,17 @@ var deleteProfileSignalsResponseSchema = import_zod.z.object({
285
285
  totalSignals: import_zod.z.number(),
286
286
  vectorUpdated: import_zod.z.boolean()
287
287
  });
288
+ var anchorResponseSchema = import_zod.z.object({
289
+ id: import_zod.z.string(),
290
+ bucketId: import_zod.z.string(),
291
+ label: import_zod.z.string().nullable(),
292
+ text: import_zod.z.string(),
293
+ createdAt: import_zod.z.string(),
294
+ updatedAt: import_zod.z.string()
295
+ });
296
+ var anchorListResponseSchema = import_zod.z.object({
297
+ anchors: import_zod.z.array(anchorResponseSchema)
298
+ });
288
299
  var StowServer = class {
289
300
  apiKey;
290
301
  baseUrl;
@@ -940,7 +951,8 @@ var StowServer = class {
940
951
  similar: (params) => this.searchSimilar(params),
941
952
  diverse: (params) => this.searchDiverse(params ?? {}),
942
953
  text: (params) => this.searchText(params),
943
- color: (params) => this.searchColor(params)
954
+ color: (params) => this.searchColor(params),
955
+ image: (input, options) => this.searchImage(input, options)
944
956
  };
945
957
  }
946
958
  searchSimilar(params) {
@@ -949,6 +961,7 @@ var StowServer = class {
949
961
  method: "POST",
950
962
  headers: { "Content-Type": "application/json" },
951
963
  body: JSON.stringify({
964
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
952
965
  ...params.fileKey ? { fileKey: params.fileKey } : {},
953
966
  ...params.vector ? { vector: params.vector } : {},
954
967
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -968,6 +981,7 @@ var StowServer = class {
968
981
  method: "POST",
969
982
  headers: { "Content-Type": "application/json" },
970
983
  body: JSON.stringify({
984
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
971
985
  ...params.fileKey ? { fileKey: params.fileKey } : {},
972
986
  ...params.vector ? { vector: params.vector } : {},
973
987
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -975,7 +989,7 @@ var StowServer = class {
975
989
  ...params.clusterIds?.length ? { clusterIds: params.clusterIds } : {},
976
990
  ...bucket ? { bucket } : {},
977
991
  ...params.limit ? { limit: params.limit } : {},
978
- ...params.lambda !== void 0 ? { lambda: params.lambda } : {},
992
+ ...params.lambda === void 0 ? {} : { lambda: params.lambda },
979
993
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
980
994
  ...params.filters ? { filters: params.filters } : {},
981
995
  ...params.include?.length ? { include: params.include } : {}
@@ -1008,11 +1022,29 @@ var StowServer = class {
1008
1022
  ...bucket ? { bucket } : {},
1009
1023
  ...params.limit ? { limit: params.limit } : {},
1010
1024
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
1011
- ...params.minProportion !== void 0 ? { minProportion: params.minProportion } : {},
1025
+ ...params.minProportion === void 0 ? {} : { minProportion: params.minProportion },
1012
1026
  ...params.dominantOnly ? { dominantOnly: params.dominantOnly } : {}
1013
1027
  })
1014
1028
  });
1015
1029
  }
1030
+ searchImage(input, options) {
1031
+ const bucket = this.resolveBucket(options?.bucket);
1032
+ return this.request("/search/image", {
1033
+ method: "POST",
1034
+ headers: { "Content-Type": "application/json" },
1035
+ body: JSON.stringify({
1036
+ ...input.url ? { url: input.url } : {},
1037
+ ...input.fileKey ? { fileKey: input.fileKey } : {},
1038
+ ...bucket ? { bucket } : {},
1039
+ ...options?.limit ? { limit: options.limit } : {},
1040
+ ...options?.threshold === void 0 ? {} : { threshold: options.threshold },
1041
+ ...options?.excludeKeys?.length ? { excludeKeys: options.excludeKeys } : {},
1042
+ ...options?.filters ? { filters: options.filters } : {},
1043
+ ...options?.include?.length ? { include: options.include } : {},
1044
+ ...options?.metadata ? { metadata: options.metadata } : {}
1045
+ })
1046
+ });
1047
+ }
1016
1048
  // ============================================================
1017
1049
  // DROPS - Quick share without buckets
1018
1050
  // ============================================================
@@ -1184,7 +1216,7 @@ var StowServer = class {
1184
1216
  method: "POST",
1185
1217
  headers: { "Content-Type": "application/json" },
1186
1218
  body: JSON.stringify({
1187
- ...params?.clusterCount !== void 0 ? { clusterCount: params.clusterCount } : {}
1219
+ ...params?.clusterCount === void 0 ? {} : { clusterCount: params.clusterCount }
1188
1220
  })
1189
1221
  }
1190
1222
  );
@@ -1202,6 +1234,72 @@ var StowServer = class {
1202
1234
  }
1203
1235
  );
1204
1236
  }
1237
+ // ============================================================
1238
+ // ANCHORS - Named semantic reference points in vector space
1239
+ // ============================================================
1240
+ /**
1241
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1242
+ *
1243
+ * @example
1244
+ * ```typescript
1245
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1246
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1247
+ * ```
1248
+ */
1249
+ get anchors() {
1250
+ return {
1251
+ create: (params) => this.createAnchor(params),
1252
+ list: (options) => this.listAnchors(options),
1253
+ get: (id, options) => this.getAnchor(id, options),
1254
+ update: (id, params) => this.updateAnchor(id, params),
1255
+ delete: (id, options) => this.deleteAnchor(id, options)
1256
+ };
1257
+ }
1258
+ createAnchor(params) {
1259
+ return this.request(
1260
+ this.withBucket("/anchors"),
1261
+ {
1262
+ method: "POST",
1263
+ headers: { "Content-Type": "application/json" },
1264
+ body: JSON.stringify({
1265
+ text: params.text,
1266
+ ...params.label ? { label: params.label } : {}
1267
+ })
1268
+ },
1269
+ anchorResponseSchema
1270
+ );
1271
+ }
1272
+ listAnchors(options) {
1273
+ return this.request(
1274
+ this.withBucket("/anchors", options?.bucket),
1275
+ { method: "GET" },
1276
+ anchorListResponseSchema
1277
+ );
1278
+ }
1279
+ getAnchor(id, options) {
1280
+ return this.request(
1281
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1282
+ { method: "GET" },
1283
+ anchorResponseSchema
1284
+ );
1285
+ }
1286
+ updateAnchor(id, params) {
1287
+ return this.request(
1288
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`),
1289
+ {
1290
+ method: "PATCH",
1291
+ headers: { "Content-Type": "application/json" },
1292
+ body: JSON.stringify(params)
1293
+ },
1294
+ anchorResponseSchema
1295
+ );
1296
+ }
1297
+ async deleteAnchor(id, options) {
1298
+ await this.request(
1299
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1300
+ { method: "DELETE" }
1301
+ );
1302
+ }
1205
1303
  };
1206
1304
  // Annotate the CommonJS export names for ESM import in node:
1207
1305
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -260,6 +260,17 @@ var deleteProfileSignalsResponseSchema = z.object({
260
260
  totalSignals: z.number(),
261
261
  vectorUpdated: z.boolean()
262
262
  });
263
+ var anchorResponseSchema = z.object({
264
+ id: z.string(),
265
+ bucketId: z.string(),
266
+ label: z.string().nullable(),
267
+ text: z.string(),
268
+ createdAt: z.string(),
269
+ updatedAt: z.string()
270
+ });
271
+ var anchorListResponseSchema = z.object({
272
+ anchors: z.array(anchorResponseSchema)
273
+ });
263
274
  var StowServer = class {
264
275
  apiKey;
265
276
  baseUrl;
@@ -915,7 +926,8 @@ var StowServer = class {
915
926
  similar: (params) => this.searchSimilar(params),
916
927
  diverse: (params) => this.searchDiverse(params ?? {}),
917
928
  text: (params) => this.searchText(params),
918
- color: (params) => this.searchColor(params)
929
+ color: (params) => this.searchColor(params),
930
+ image: (input, options) => this.searchImage(input, options)
919
931
  };
920
932
  }
921
933
  searchSimilar(params) {
@@ -924,6 +936,7 @@ var StowServer = class {
924
936
  method: "POST",
925
937
  headers: { "Content-Type": "application/json" },
926
938
  body: JSON.stringify({
939
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
927
940
  ...params.fileKey ? { fileKey: params.fileKey } : {},
928
941
  ...params.vector ? { vector: params.vector } : {},
929
942
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -943,6 +956,7 @@ var StowServer = class {
943
956
  method: "POST",
944
957
  headers: { "Content-Type": "application/json" },
945
958
  body: JSON.stringify({
959
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
946
960
  ...params.fileKey ? { fileKey: params.fileKey } : {},
947
961
  ...params.vector ? { vector: params.vector } : {},
948
962
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -950,7 +964,7 @@ var StowServer = class {
950
964
  ...params.clusterIds?.length ? { clusterIds: params.clusterIds } : {},
951
965
  ...bucket ? { bucket } : {},
952
966
  ...params.limit ? { limit: params.limit } : {},
953
- ...params.lambda !== void 0 ? { lambda: params.lambda } : {},
967
+ ...params.lambda === void 0 ? {} : { lambda: params.lambda },
954
968
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
955
969
  ...params.filters ? { filters: params.filters } : {},
956
970
  ...params.include?.length ? { include: params.include } : {}
@@ -983,11 +997,29 @@ var StowServer = class {
983
997
  ...bucket ? { bucket } : {},
984
998
  ...params.limit ? { limit: params.limit } : {},
985
999
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
986
- ...params.minProportion !== void 0 ? { minProportion: params.minProportion } : {},
1000
+ ...params.minProportion === void 0 ? {} : { minProportion: params.minProportion },
987
1001
  ...params.dominantOnly ? { dominantOnly: params.dominantOnly } : {}
988
1002
  })
989
1003
  });
990
1004
  }
1005
+ searchImage(input, options) {
1006
+ const bucket = this.resolveBucket(options?.bucket);
1007
+ return this.request("/search/image", {
1008
+ method: "POST",
1009
+ headers: { "Content-Type": "application/json" },
1010
+ body: JSON.stringify({
1011
+ ...input.url ? { url: input.url } : {},
1012
+ ...input.fileKey ? { fileKey: input.fileKey } : {},
1013
+ ...bucket ? { bucket } : {},
1014
+ ...options?.limit ? { limit: options.limit } : {},
1015
+ ...options?.threshold === void 0 ? {} : { threshold: options.threshold },
1016
+ ...options?.excludeKeys?.length ? { excludeKeys: options.excludeKeys } : {},
1017
+ ...options?.filters ? { filters: options.filters } : {},
1018
+ ...options?.include?.length ? { include: options.include } : {},
1019
+ ...options?.metadata ? { metadata: options.metadata } : {}
1020
+ })
1021
+ });
1022
+ }
991
1023
  // ============================================================
992
1024
  // DROPS - Quick share without buckets
993
1025
  // ============================================================
@@ -1159,7 +1191,7 @@ var StowServer = class {
1159
1191
  method: "POST",
1160
1192
  headers: { "Content-Type": "application/json" },
1161
1193
  body: JSON.stringify({
1162
- ...params?.clusterCount !== void 0 ? { clusterCount: params.clusterCount } : {}
1194
+ ...params?.clusterCount === void 0 ? {} : { clusterCount: params.clusterCount }
1163
1195
  })
1164
1196
  }
1165
1197
  );
@@ -1177,6 +1209,72 @@ var StowServer = class {
1177
1209
  }
1178
1210
  );
1179
1211
  }
1212
+ // ============================================================
1213
+ // ANCHORS - Named semantic reference points in vector space
1214
+ // ============================================================
1215
+ /**
1216
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1217
+ *
1218
+ * @example
1219
+ * ```typescript
1220
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1221
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1222
+ * ```
1223
+ */
1224
+ get anchors() {
1225
+ return {
1226
+ create: (params) => this.createAnchor(params),
1227
+ list: (options) => this.listAnchors(options),
1228
+ get: (id, options) => this.getAnchor(id, options),
1229
+ update: (id, params) => this.updateAnchor(id, params),
1230
+ delete: (id, options) => this.deleteAnchor(id, options)
1231
+ };
1232
+ }
1233
+ createAnchor(params) {
1234
+ return this.request(
1235
+ this.withBucket("/anchors"),
1236
+ {
1237
+ method: "POST",
1238
+ headers: { "Content-Type": "application/json" },
1239
+ body: JSON.stringify({
1240
+ text: params.text,
1241
+ ...params.label ? { label: params.label } : {}
1242
+ })
1243
+ },
1244
+ anchorResponseSchema
1245
+ );
1246
+ }
1247
+ listAnchors(options) {
1248
+ return this.request(
1249
+ this.withBucket("/anchors", options?.bucket),
1250
+ { method: "GET" },
1251
+ anchorListResponseSchema
1252
+ );
1253
+ }
1254
+ getAnchor(id, options) {
1255
+ return this.request(
1256
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1257
+ { method: "GET" },
1258
+ anchorResponseSchema
1259
+ );
1260
+ }
1261
+ updateAnchor(id, params) {
1262
+ return this.request(
1263
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`),
1264
+ {
1265
+ method: "PATCH",
1266
+ headers: { "Content-Type": "application/json" },
1267
+ body: JSON.stringify(params)
1268
+ },
1269
+ anchorResponseSchema
1270
+ );
1271
+ }
1272
+ async deleteAnchor(id, options) {
1273
+ await this.request(
1274
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1275
+ { method: "DELETE" }
1276
+ );
1277
+ }
1180
1278
  };
1181
1279
  export {
1182
1280
  StowError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howells/stow-server",
3
- "version": "2.0.1",
3
+ "version": "2.2.0",
4
4
  "description": "Server-side SDK for Stow file storage",
5
5
  "license": "MIT",
6
6
  "repository": {