@howells/stow-server 2.0.0 → 2.1.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. */
@@ -520,13 +524,41 @@ interface SearchResultItem {
520
524
  name: string;
521
525
  }>;
522
526
  taxonomies?: Array<{
523
- slug: string;
524
- name: string;
527
+ externalUri: string | null;
525
528
  group: string;
529
+ name: string;
526
530
  similarity: number;
531
+ slug: string;
532
+ source: string;
527
533
  }>;
528
534
  width?: number | null;
529
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
+ }
530
562
  /** Which filter categories were active in the request. */
531
563
  interface AppliedFilters {
532
564
  color?: string[];
@@ -545,6 +577,7 @@ interface FilteredMetadata {
545
577
  }
546
578
  /** Result payload returned by similarity/diversity search endpoints. */
547
579
  interface SimilarSearchResult {
580
+ anchors?: AnchorSearchResult[];
548
581
  filtered?: FilteredMetadata;
549
582
  results: SearchResultItem[];
550
583
  }
@@ -938,19 +971,19 @@ declare class StowServer {
938
971
  */
939
972
  get profiles(): {
940
973
  create: (params?: ProfileCreateRequest) => Promise<ProfileResult>;
941
- get: (id: string) => Promise<ProfileResult>;
942
- delete: (id: string) => Promise<void>;
974
+ get: (id: string, bucket?: string) => Promise<ProfileResult>;
975
+ delete: (id: string, bucket?: string) => Promise<void>;
943
976
  addFiles: (id: string, fileKeys: string[], bucket?: string) => Promise<ProfileFilesResult>;
944
977
  removeFiles: (id: string, fileKeys: string[], bucket?: string) => Promise<ProfileFilesResult>;
945
978
  signal: (id: string, signals: ProfileSignalInput[], bucket?: string) => Promise<ProfileSignalsResponse>;
946
- deleteSignals: (id: string, signalIds: string[]) => Promise<DeleteProfileSignalsResult>;
947
- clusters: (id: string) => Promise<{
979
+ deleteSignals: (id: string, signalIds: string[], bucket?: string) => Promise<DeleteProfileSignalsResult>;
980
+ clusters: (id: string, bucket?: string) => Promise<{
948
981
  profileId: string;
949
982
  signalCount: number;
950
983
  clusters: ProfileClusterResult[];
951
984
  }>;
952
- recluster: (id: string, params?: ReclusterRequest) => Promise<ReclusterResult>;
953
- renameCluster: (profileId: string, clusterId: string, params: RenameClusterRequest) => Promise<ProfileClusterResult>;
985
+ recluster: (id: string, params?: ReclusterRequest, bucket?: string) => Promise<ReclusterResult>;
986
+ renameCluster: (profileId: string, clusterId: string, params: RenameClusterRequest, bucket?: string) => Promise<ProfileClusterResult>;
954
987
  };
955
988
  private createProfile;
956
989
  private getProfile;
@@ -962,6 +995,35 @@ declare class StowServer {
962
995
  private getProfileClusters;
963
996
  private reclusterProfile;
964
997
  private renameProfileCluster;
998
+ /**
999
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1000
+ *
1001
+ * @example
1002
+ * ```typescript
1003
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1004
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1005
+ * ```
1006
+ */
1007
+ get anchors(): {
1008
+ create: (params: CreateAnchorRequest) => Promise<Anchor>;
1009
+ list: (options?: {
1010
+ bucket?: string;
1011
+ }) => Promise<{
1012
+ anchors: Anchor[];
1013
+ }>;
1014
+ get: (id: string, options?: {
1015
+ bucket?: string;
1016
+ }) => Promise<Anchor>;
1017
+ update: (id: string, params: UpdateAnchorRequest) => Promise<Anchor>;
1018
+ delete: (id: string, options?: {
1019
+ bucket?: string;
1020
+ }) => Promise<void>;
1021
+ };
1022
+ private createAnchor;
1023
+ private listAnchors;
1024
+ private getAnchor;
1025
+ private updateAnchor;
1026
+ private deleteAnchor;
965
1027
  }
966
1028
 
967
- 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 };
1029
+ 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 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. */
@@ -520,13 +524,41 @@ interface SearchResultItem {
520
524
  name: string;
521
525
  }>;
522
526
  taxonomies?: Array<{
523
- slug: string;
524
- name: string;
527
+ externalUri: string | null;
525
528
  group: string;
529
+ name: string;
526
530
  similarity: number;
531
+ slug: string;
532
+ source: string;
527
533
  }>;
528
534
  width?: number | null;
529
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
+ }
530
562
  /** Which filter categories were active in the request. */
531
563
  interface AppliedFilters {
532
564
  color?: string[];
@@ -545,6 +577,7 @@ interface FilteredMetadata {
545
577
  }
546
578
  /** Result payload returned by similarity/diversity search endpoints. */
547
579
  interface SimilarSearchResult {
580
+ anchors?: AnchorSearchResult[];
548
581
  filtered?: FilteredMetadata;
549
582
  results: SearchResultItem[];
550
583
  }
@@ -938,19 +971,19 @@ declare class StowServer {
938
971
  */
939
972
  get profiles(): {
940
973
  create: (params?: ProfileCreateRequest) => Promise<ProfileResult>;
941
- get: (id: string) => Promise<ProfileResult>;
942
- delete: (id: string) => Promise<void>;
974
+ get: (id: string, bucket?: string) => Promise<ProfileResult>;
975
+ delete: (id: string, bucket?: string) => Promise<void>;
943
976
  addFiles: (id: string, fileKeys: string[], bucket?: string) => Promise<ProfileFilesResult>;
944
977
  removeFiles: (id: string, fileKeys: string[], bucket?: string) => Promise<ProfileFilesResult>;
945
978
  signal: (id: string, signals: ProfileSignalInput[], bucket?: string) => Promise<ProfileSignalsResponse>;
946
- deleteSignals: (id: string, signalIds: string[]) => Promise<DeleteProfileSignalsResult>;
947
- clusters: (id: string) => Promise<{
979
+ deleteSignals: (id: string, signalIds: string[], bucket?: string) => Promise<DeleteProfileSignalsResult>;
980
+ clusters: (id: string, bucket?: string) => Promise<{
948
981
  profileId: string;
949
982
  signalCount: number;
950
983
  clusters: ProfileClusterResult[];
951
984
  }>;
952
- recluster: (id: string, params?: ReclusterRequest) => Promise<ReclusterResult>;
953
- renameCluster: (profileId: string, clusterId: string, params: RenameClusterRequest) => Promise<ProfileClusterResult>;
985
+ recluster: (id: string, params?: ReclusterRequest, bucket?: string) => Promise<ReclusterResult>;
986
+ renameCluster: (profileId: string, clusterId: string, params: RenameClusterRequest, bucket?: string) => Promise<ProfileClusterResult>;
954
987
  };
955
988
  private createProfile;
956
989
  private getProfile;
@@ -962,6 +995,35 @@ declare class StowServer {
962
995
  private getProfileClusters;
963
996
  private reclusterProfile;
964
997
  private renameProfileCluster;
998
+ /**
999
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1000
+ *
1001
+ * @example
1002
+ * ```typescript
1003
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1004
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1005
+ * ```
1006
+ */
1007
+ get anchors(): {
1008
+ create: (params: CreateAnchorRequest) => Promise<Anchor>;
1009
+ list: (options?: {
1010
+ bucket?: string;
1011
+ }) => Promise<{
1012
+ anchors: Anchor[];
1013
+ }>;
1014
+ get: (id: string, options?: {
1015
+ bucket?: string;
1016
+ }) => Promise<Anchor>;
1017
+ update: (id: string, params: UpdateAnchorRequest) => Promise<Anchor>;
1018
+ delete: (id: string, options?: {
1019
+ bucket?: string;
1020
+ }) => Promise<void>;
1021
+ };
1022
+ private createAnchor;
1023
+ private listAnchors;
1024
+ private getAnchor;
1025
+ private updateAnchor;
1026
+ private deleteAnchor;
965
1027
  }
966
1028
 
967
- 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 };
1029
+ 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 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;
@@ -949,6 +960,7 @@ var StowServer = class {
949
960
  method: "POST",
950
961
  headers: { "Content-Type": "application/json" },
951
962
  body: JSON.stringify({
963
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
952
964
  ...params.fileKey ? { fileKey: params.fileKey } : {},
953
965
  ...params.vector ? { vector: params.vector } : {},
954
966
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -968,6 +980,7 @@ var StowServer = class {
968
980
  method: "POST",
969
981
  headers: { "Content-Type": "application/json" },
970
982
  body: JSON.stringify({
983
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
971
984
  ...params.fileKey ? { fileKey: params.fileKey } : {},
972
985
  ...params.vector ? { vector: params.vector } : {},
973
986
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -975,7 +988,7 @@ var StowServer = class {
975
988
  ...params.clusterIds?.length ? { clusterIds: params.clusterIds } : {},
976
989
  ...bucket ? { bucket } : {},
977
990
  ...params.limit ? { limit: params.limit } : {},
978
- ...params.lambda !== void 0 ? { lambda: params.lambda } : {},
991
+ ...params.lambda === void 0 ? {} : { lambda: params.lambda },
979
992
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
980
993
  ...params.filters ? { filters: params.filters } : {},
981
994
  ...params.include?.length ? { include: params.include } : {}
@@ -1008,7 +1021,7 @@ var StowServer = class {
1008
1021
  ...bucket ? { bucket } : {},
1009
1022
  ...params.limit ? { limit: params.limit } : {},
1010
1023
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
1011
- ...params.minProportion !== void 0 ? { minProportion: params.minProportion } : {},
1024
+ ...params.minProportion === void 0 ? {} : { minProportion: params.minProportion },
1012
1025
  ...params.dominantOnly ? { dominantOnly: params.dominantOnly } : {}
1013
1026
  })
1014
1027
  });
@@ -1089,89 +1102,80 @@ var StowServer = class {
1089
1102
  get profiles() {
1090
1103
  return {
1091
1104
  create: (params) => this.createProfile(params),
1092
- get: (id) => this.getProfile(id),
1093
- delete: (id) => this.deleteProfile(id),
1105
+ get: (id, bucket) => this.getProfile(id, bucket),
1106
+ delete: (id, bucket) => this.deleteProfile(id, bucket),
1094
1107
  addFiles: (id, fileKeys, bucket) => this.addProfileFiles(id, fileKeys, bucket),
1095
1108
  removeFiles: (id, fileKeys, bucket) => this.removeProfileFiles(id, fileKeys, bucket),
1096
1109
  signal: (id, signals, bucket) => this.signalProfile(id, signals, bucket),
1097
- deleteSignals: (id, signalIds) => this.deleteProfileSignals(id, signalIds),
1098
- clusters: (id) => this.getProfileClusters(id),
1099
- recluster: (id, params) => this.reclusterProfile(id, params),
1100
- renameCluster: (profileId, clusterId, params) => this.renameProfileCluster(profileId, clusterId, params)
1110
+ deleteSignals: (id, signalIds, bucket) => this.deleteProfileSignals(id, signalIds, bucket),
1111
+ clusters: (id, bucket) => this.getProfileClusters(id, bucket),
1112
+ recluster: (id, params, bucket) => this.reclusterProfile(id, params, bucket),
1113
+ renameCluster: (profileId, clusterId, params, bucket) => this.renameProfileCluster(profileId, clusterId, params, bucket)
1101
1114
  };
1102
1115
  }
1103
1116
  createProfile(params) {
1104
1117
  return this.request(
1105
- "/profiles",
1118
+ this.withBucket("/profiles", params?.bucket),
1106
1119
  {
1107
1120
  method: "POST",
1108
1121
  headers: { "Content-Type": "application/json" },
1109
1122
  body: JSON.stringify({
1110
1123
  ...params?.name ? { name: params.name } : {},
1111
- ...params?.fileKeys ? { fileKeys: params.fileKeys } : {},
1112
- ...params?.bucket ? { bucket: params.bucket } : {}
1124
+ ...params?.fileKeys ? { fileKeys: params.fileKeys } : {}
1113
1125
  })
1114
1126
  },
1115
1127
  profileResultSchema
1116
1128
  );
1117
1129
  }
1118
- getProfile(id) {
1130
+ getProfile(id, bucket) {
1119
1131
  return this.request(
1120
- `/profiles/${encodeURIComponent(id)}`,
1132
+ this.withBucket(`/profiles/${encodeURIComponent(id)}`, bucket),
1121
1133
  { method: "GET" },
1122
1134
  profileResultSchema
1123
1135
  );
1124
1136
  }
1125
- async deleteProfile(id) {
1126
- await this.request(`/profiles/${encodeURIComponent(id)}`, {
1127
- method: "DELETE"
1128
- });
1137
+ async deleteProfile(id, bucket) {
1138
+ await this.request(
1139
+ this.withBucket(`/profiles/${encodeURIComponent(id)}`, bucket),
1140
+ { method: "DELETE" }
1141
+ );
1129
1142
  }
1130
1143
  addProfileFiles(id, fileKeys, bucket) {
1131
1144
  return this.request(
1132
- `/profiles/${encodeURIComponent(id)}/files`,
1145
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/files`, bucket),
1133
1146
  {
1134
1147
  method: "POST",
1135
1148
  headers: { "Content-Type": "application/json" },
1136
- body: JSON.stringify({
1137
- fileKeys,
1138
- ...bucket ? { bucket } : {}
1139
- })
1149
+ body: JSON.stringify({ fileKeys })
1140
1150
  },
1141
1151
  profileFilesResultSchema
1142
1152
  );
1143
1153
  }
1144
1154
  removeProfileFiles(id, fileKeys, bucket) {
1145
1155
  return this.request(
1146
- `/profiles/${encodeURIComponent(id)}/files`,
1156
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/files`, bucket),
1147
1157
  {
1148
1158
  method: "DELETE",
1149
1159
  headers: { "Content-Type": "application/json" },
1150
- body: JSON.stringify({
1151
- fileKeys,
1152
- ...bucket ? { bucket } : {}
1153
- })
1160
+ body: JSON.stringify({ fileKeys })
1154
1161
  },
1155
1162
  profileFilesResultSchema
1156
1163
  );
1157
1164
  }
1158
1165
  signalProfile(id, signals, bucket) {
1159
1166
  return this.request(
1160
- `/profiles/${encodeURIComponent(id)}/signals`,
1167
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/signals`, bucket),
1161
1168
  {
1162
1169
  method: "POST",
1163
1170
  headers: { "Content-Type": "application/json" },
1164
- body: JSON.stringify({
1165
- signals,
1166
- ...bucket ? { bucket } : {}
1167
- })
1171
+ body: JSON.stringify({ signals })
1168
1172
  },
1169
1173
  profileSignalsResponseSchema
1170
1174
  );
1171
1175
  }
1172
- deleteProfileSignals(id, signalIds) {
1176
+ deleteProfileSignals(id, signalIds, bucket) {
1173
1177
  return this.request(
1174
- `/profiles/${encodeURIComponent(id)}/signals`,
1178
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/signals`, bucket),
1175
1179
  {
1176
1180
  method: "DELETE",
1177
1181
  headers: { "Content-Type": "application/json" },
@@ -1180,23 +1184,30 @@ var StowServer = class {
1180
1184
  deleteProfileSignalsResponseSchema
1181
1185
  );
1182
1186
  }
1183
- getProfileClusters(id) {
1184
- return this.request(`/profiles/${encodeURIComponent(id)}/clusters`, {
1185
- method: "GET"
1186
- });
1187
+ getProfileClusters(id, bucket) {
1188
+ return this.request(
1189
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/clusters`, bucket),
1190
+ { method: "GET" }
1191
+ );
1187
1192
  }
1188
- reclusterProfile(id, params) {
1189
- return this.request(`/profiles/${encodeURIComponent(id)}/clusters`, {
1190
- method: "POST",
1191
- headers: { "Content-Type": "application/json" },
1192
- body: JSON.stringify({
1193
- ...params?.clusterCount !== void 0 ? { clusterCount: params.clusterCount } : {}
1194
- })
1195
- });
1193
+ reclusterProfile(id, params, bucket) {
1194
+ return this.request(
1195
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/clusters`, bucket),
1196
+ {
1197
+ method: "POST",
1198
+ headers: { "Content-Type": "application/json" },
1199
+ body: JSON.stringify({
1200
+ ...params?.clusterCount === void 0 ? {} : { clusterCount: params.clusterCount }
1201
+ })
1202
+ }
1203
+ );
1196
1204
  }
1197
- renameProfileCluster(profileId, clusterId, params) {
1205
+ renameProfileCluster(profileId, clusterId, params, bucket) {
1198
1206
  return this.request(
1199
- `/profiles/${encodeURIComponent(profileId)}/clusters/${encodeURIComponent(clusterId)}`,
1207
+ this.withBucket(
1208
+ `/profiles/${encodeURIComponent(profileId)}/clusters/${encodeURIComponent(clusterId)}`,
1209
+ bucket
1210
+ ),
1200
1211
  {
1201
1212
  method: "PUT",
1202
1213
  headers: { "Content-Type": "application/json" },
@@ -1204,6 +1215,72 @@ var StowServer = class {
1204
1215
  }
1205
1216
  );
1206
1217
  }
1218
+ // ============================================================
1219
+ // ANCHORS - Named semantic reference points in vector space
1220
+ // ============================================================
1221
+ /**
1222
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1223
+ *
1224
+ * @example
1225
+ * ```typescript
1226
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1227
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1228
+ * ```
1229
+ */
1230
+ get anchors() {
1231
+ return {
1232
+ create: (params) => this.createAnchor(params),
1233
+ list: (options) => this.listAnchors(options),
1234
+ get: (id, options) => this.getAnchor(id, options),
1235
+ update: (id, params) => this.updateAnchor(id, params),
1236
+ delete: (id, options) => this.deleteAnchor(id, options)
1237
+ };
1238
+ }
1239
+ createAnchor(params) {
1240
+ return this.request(
1241
+ this.withBucket("/anchors"),
1242
+ {
1243
+ method: "POST",
1244
+ headers: { "Content-Type": "application/json" },
1245
+ body: JSON.stringify({
1246
+ text: params.text,
1247
+ ...params.label ? { label: params.label } : {}
1248
+ })
1249
+ },
1250
+ anchorResponseSchema
1251
+ );
1252
+ }
1253
+ listAnchors(options) {
1254
+ return this.request(
1255
+ this.withBucket("/anchors", options?.bucket),
1256
+ { method: "GET" },
1257
+ anchorListResponseSchema
1258
+ );
1259
+ }
1260
+ getAnchor(id, options) {
1261
+ return this.request(
1262
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1263
+ { method: "GET" },
1264
+ anchorResponseSchema
1265
+ );
1266
+ }
1267
+ updateAnchor(id, params) {
1268
+ return this.request(
1269
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`),
1270
+ {
1271
+ method: "PATCH",
1272
+ headers: { "Content-Type": "application/json" },
1273
+ body: JSON.stringify(params)
1274
+ },
1275
+ anchorResponseSchema
1276
+ );
1277
+ }
1278
+ async deleteAnchor(id, options) {
1279
+ await this.request(
1280
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1281
+ { method: "DELETE" }
1282
+ );
1283
+ }
1207
1284
  };
1208
1285
  // Annotate the CommonJS export names for ESM import in node:
1209
1286
  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;
@@ -924,6 +935,7 @@ var StowServer = class {
924
935
  method: "POST",
925
936
  headers: { "Content-Type": "application/json" },
926
937
  body: JSON.stringify({
938
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
927
939
  ...params.fileKey ? { fileKey: params.fileKey } : {},
928
940
  ...params.vector ? { vector: params.vector } : {},
929
941
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -943,6 +955,7 @@ var StowServer = class {
943
955
  method: "POST",
944
956
  headers: { "Content-Type": "application/json" },
945
957
  body: JSON.stringify({
958
+ ...params.anchorId ? { anchorId: params.anchorId } : {},
946
959
  ...params.fileKey ? { fileKey: params.fileKey } : {},
947
960
  ...params.vector ? { vector: params.vector } : {},
948
961
  ...params.profileId ? { profileId: params.profileId } : {},
@@ -950,7 +963,7 @@ var StowServer = class {
950
963
  ...params.clusterIds?.length ? { clusterIds: params.clusterIds } : {},
951
964
  ...bucket ? { bucket } : {},
952
965
  ...params.limit ? { limit: params.limit } : {},
953
- ...params.lambda !== void 0 ? { lambda: params.lambda } : {},
966
+ ...params.lambda === void 0 ? {} : { lambda: params.lambda },
954
967
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
955
968
  ...params.filters ? { filters: params.filters } : {},
956
969
  ...params.include?.length ? { include: params.include } : {}
@@ -983,7 +996,7 @@ var StowServer = class {
983
996
  ...bucket ? { bucket } : {},
984
997
  ...params.limit ? { limit: params.limit } : {},
985
998
  ...params.excludeKeys?.length ? { excludeKeys: params.excludeKeys } : {},
986
- ...params.minProportion !== void 0 ? { minProportion: params.minProportion } : {},
999
+ ...params.minProportion === void 0 ? {} : { minProportion: params.minProportion },
987
1000
  ...params.dominantOnly ? { dominantOnly: params.dominantOnly } : {}
988
1001
  })
989
1002
  });
@@ -1064,89 +1077,80 @@ var StowServer = class {
1064
1077
  get profiles() {
1065
1078
  return {
1066
1079
  create: (params) => this.createProfile(params),
1067
- get: (id) => this.getProfile(id),
1068
- delete: (id) => this.deleteProfile(id),
1080
+ get: (id, bucket) => this.getProfile(id, bucket),
1081
+ delete: (id, bucket) => this.deleteProfile(id, bucket),
1069
1082
  addFiles: (id, fileKeys, bucket) => this.addProfileFiles(id, fileKeys, bucket),
1070
1083
  removeFiles: (id, fileKeys, bucket) => this.removeProfileFiles(id, fileKeys, bucket),
1071
1084
  signal: (id, signals, bucket) => this.signalProfile(id, signals, bucket),
1072
- deleteSignals: (id, signalIds) => this.deleteProfileSignals(id, signalIds),
1073
- clusters: (id) => this.getProfileClusters(id),
1074
- recluster: (id, params) => this.reclusterProfile(id, params),
1075
- renameCluster: (profileId, clusterId, params) => this.renameProfileCluster(profileId, clusterId, params)
1085
+ deleteSignals: (id, signalIds, bucket) => this.deleteProfileSignals(id, signalIds, bucket),
1086
+ clusters: (id, bucket) => this.getProfileClusters(id, bucket),
1087
+ recluster: (id, params, bucket) => this.reclusterProfile(id, params, bucket),
1088
+ renameCluster: (profileId, clusterId, params, bucket) => this.renameProfileCluster(profileId, clusterId, params, bucket)
1076
1089
  };
1077
1090
  }
1078
1091
  createProfile(params) {
1079
1092
  return this.request(
1080
- "/profiles",
1093
+ this.withBucket("/profiles", params?.bucket),
1081
1094
  {
1082
1095
  method: "POST",
1083
1096
  headers: { "Content-Type": "application/json" },
1084
1097
  body: JSON.stringify({
1085
1098
  ...params?.name ? { name: params.name } : {},
1086
- ...params?.fileKeys ? { fileKeys: params.fileKeys } : {},
1087
- ...params?.bucket ? { bucket: params.bucket } : {}
1099
+ ...params?.fileKeys ? { fileKeys: params.fileKeys } : {}
1088
1100
  })
1089
1101
  },
1090
1102
  profileResultSchema
1091
1103
  );
1092
1104
  }
1093
- getProfile(id) {
1105
+ getProfile(id, bucket) {
1094
1106
  return this.request(
1095
- `/profiles/${encodeURIComponent(id)}`,
1107
+ this.withBucket(`/profiles/${encodeURIComponent(id)}`, bucket),
1096
1108
  { method: "GET" },
1097
1109
  profileResultSchema
1098
1110
  );
1099
1111
  }
1100
- async deleteProfile(id) {
1101
- await this.request(`/profiles/${encodeURIComponent(id)}`, {
1102
- method: "DELETE"
1103
- });
1112
+ async deleteProfile(id, bucket) {
1113
+ await this.request(
1114
+ this.withBucket(`/profiles/${encodeURIComponent(id)}`, bucket),
1115
+ { method: "DELETE" }
1116
+ );
1104
1117
  }
1105
1118
  addProfileFiles(id, fileKeys, bucket) {
1106
1119
  return this.request(
1107
- `/profiles/${encodeURIComponent(id)}/files`,
1120
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/files`, bucket),
1108
1121
  {
1109
1122
  method: "POST",
1110
1123
  headers: { "Content-Type": "application/json" },
1111
- body: JSON.stringify({
1112
- fileKeys,
1113
- ...bucket ? { bucket } : {}
1114
- })
1124
+ body: JSON.stringify({ fileKeys })
1115
1125
  },
1116
1126
  profileFilesResultSchema
1117
1127
  );
1118
1128
  }
1119
1129
  removeProfileFiles(id, fileKeys, bucket) {
1120
1130
  return this.request(
1121
- `/profiles/${encodeURIComponent(id)}/files`,
1131
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/files`, bucket),
1122
1132
  {
1123
1133
  method: "DELETE",
1124
1134
  headers: { "Content-Type": "application/json" },
1125
- body: JSON.stringify({
1126
- fileKeys,
1127
- ...bucket ? { bucket } : {}
1128
- })
1135
+ body: JSON.stringify({ fileKeys })
1129
1136
  },
1130
1137
  profileFilesResultSchema
1131
1138
  );
1132
1139
  }
1133
1140
  signalProfile(id, signals, bucket) {
1134
1141
  return this.request(
1135
- `/profiles/${encodeURIComponent(id)}/signals`,
1142
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/signals`, bucket),
1136
1143
  {
1137
1144
  method: "POST",
1138
1145
  headers: { "Content-Type": "application/json" },
1139
- body: JSON.stringify({
1140
- signals,
1141
- ...bucket ? { bucket } : {}
1142
- })
1146
+ body: JSON.stringify({ signals })
1143
1147
  },
1144
1148
  profileSignalsResponseSchema
1145
1149
  );
1146
1150
  }
1147
- deleteProfileSignals(id, signalIds) {
1151
+ deleteProfileSignals(id, signalIds, bucket) {
1148
1152
  return this.request(
1149
- `/profiles/${encodeURIComponent(id)}/signals`,
1153
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/signals`, bucket),
1150
1154
  {
1151
1155
  method: "DELETE",
1152
1156
  headers: { "Content-Type": "application/json" },
@@ -1155,23 +1159,30 @@ var StowServer = class {
1155
1159
  deleteProfileSignalsResponseSchema
1156
1160
  );
1157
1161
  }
1158
- getProfileClusters(id) {
1159
- return this.request(`/profiles/${encodeURIComponent(id)}/clusters`, {
1160
- method: "GET"
1161
- });
1162
+ getProfileClusters(id, bucket) {
1163
+ return this.request(
1164
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/clusters`, bucket),
1165
+ { method: "GET" }
1166
+ );
1162
1167
  }
1163
- reclusterProfile(id, params) {
1164
- return this.request(`/profiles/${encodeURIComponent(id)}/clusters`, {
1165
- method: "POST",
1166
- headers: { "Content-Type": "application/json" },
1167
- body: JSON.stringify({
1168
- ...params?.clusterCount !== void 0 ? { clusterCount: params.clusterCount } : {}
1169
- })
1170
- });
1168
+ reclusterProfile(id, params, bucket) {
1169
+ return this.request(
1170
+ this.withBucket(`/profiles/${encodeURIComponent(id)}/clusters`, bucket),
1171
+ {
1172
+ method: "POST",
1173
+ headers: { "Content-Type": "application/json" },
1174
+ body: JSON.stringify({
1175
+ ...params?.clusterCount === void 0 ? {} : { clusterCount: params.clusterCount }
1176
+ })
1177
+ }
1178
+ );
1171
1179
  }
1172
- renameProfileCluster(profileId, clusterId, params) {
1180
+ renameProfileCluster(profileId, clusterId, params, bucket) {
1173
1181
  return this.request(
1174
- `/profiles/${encodeURIComponent(profileId)}/clusters/${encodeURIComponent(clusterId)}`,
1182
+ this.withBucket(
1183
+ `/profiles/${encodeURIComponent(profileId)}/clusters/${encodeURIComponent(clusterId)}`,
1184
+ bucket
1185
+ ),
1175
1186
  {
1176
1187
  method: "PUT",
1177
1188
  headers: { "Content-Type": "application/json" },
@@ -1179,6 +1190,72 @@ var StowServer = class {
1179
1190
  }
1180
1191
  );
1181
1192
  }
1193
+ // ============================================================
1194
+ // ANCHORS - Named semantic reference points in vector space
1195
+ // ============================================================
1196
+ /**
1197
+ * Anchors namespace for creating, listing, updating, and deleting text anchors.
1198
+ *
1199
+ * @example
1200
+ * ```typescript
1201
+ * const anchor = await stow.anchors.create({ text: "minimalist architecture", label: "minimal" });
1202
+ * const results = await stow.search.similar({ anchorId: anchor.id });
1203
+ * ```
1204
+ */
1205
+ get anchors() {
1206
+ return {
1207
+ create: (params) => this.createAnchor(params),
1208
+ list: (options) => this.listAnchors(options),
1209
+ get: (id, options) => this.getAnchor(id, options),
1210
+ update: (id, params) => this.updateAnchor(id, params),
1211
+ delete: (id, options) => this.deleteAnchor(id, options)
1212
+ };
1213
+ }
1214
+ createAnchor(params) {
1215
+ return this.request(
1216
+ this.withBucket("/anchors"),
1217
+ {
1218
+ method: "POST",
1219
+ headers: { "Content-Type": "application/json" },
1220
+ body: JSON.stringify({
1221
+ text: params.text,
1222
+ ...params.label ? { label: params.label } : {}
1223
+ })
1224
+ },
1225
+ anchorResponseSchema
1226
+ );
1227
+ }
1228
+ listAnchors(options) {
1229
+ return this.request(
1230
+ this.withBucket("/anchors", options?.bucket),
1231
+ { method: "GET" },
1232
+ anchorListResponseSchema
1233
+ );
1234
+ }
1235
+ getAnchor(id, options) {
1236
+ return this.request(
1237
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1238
+ { method: "GET" },
1239
+ anchorResponseSchema
1240
+ );
1241
+ }
1242
+ updateAnchor(id, params) {
1243
+ return this.request(
1244
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`),
1245
+ {
1246
+ method: "PATCH",
1247
+ headers: { "Content-Type": "application/json" },
1248
+ body: JSON.stringify(params)
1249
+ },
1250
+ anchorResponseSchema
1251
+ );
1252
+ }
1253
+ async deleteAnchor(id, options) {
1254
+ await this.request(
1255
+ this.withBucket(`/anchors/${encodeURIComponent(id)}`, options?.bucket),
1256
+ { method: "DELETE" }
1257
+ );
1258
+ }
1182
1259
  };
1183
1260
  export {
1184
1261
  StowError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howells/stow-server",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Server-side SDK for Stow file storage",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,10 +33,10 @@
33
33
  "zod": "^3.0.0 || ^4.0.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@types/node": "^25.3.0",
36
+ "@types/node": "^25.5.0",
37
37
  "tsup": "^8.5.1",
38
38
  "typescript": "^5.9.3",
39
- "vitest": "^4.0.18",
39
+ "vitest": "^4.1.0",
40
40
  "zod": "^4.3.6",
41
41
  "@stow/typescript-config": "0.0.0"
42
42
  },