@maximem/synap-js-sdk 0.5.4 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -49,6 +49,7 @@ var ENDPOINTS = {
49
49
  memories_get: { method: "GET", path: "/api/v1/memories/{memory_id}", idempotent: true },
50
50
  memories_update: { method: "PATCH", path: "/api/v1/memories/{memory_id}", idempotent: false },
51
51
  memories_delete: { method: "DELETE", path: "/api/v1/memories/{memory_id}", idempotent: true },
52
+ memories_forget: { method: "POST", path: "/api/v1/memories/forget", idempotent: false },
52
53
  context_fetch_user: { method: "POST", path: "/v1/context/user/fetch", idempotent: true },
53
54
  context_fetch_customer: { method: "POST", path: "/v1/context/customer/fetch", idempotent: true },
54
55
  context_fetch_client: { method: "POST", path: "/v1/context/client/fetch", idempotent: true },
@@ -537,6 +538,7 @@ function buildFetchRequest(scope, options) {
537
538
  const maxResults = opt(options, "max_results", "maxResults") ?? 10;
538
539
  const precisionLevel = opt(options, "precision_level", "precisionLevel") ?? "high";
539
540
  const queryDate = opt(options, "query_date", "queryDate");
541
+ const perQuery = opt(options, "max_results_per_query", "maxResultsPerQuery");
540
542
  const mode = options.mode ?? "fast";
541
543
  if (searchQuery !== void 0 && !Array.isArray(searchQuery)) {
542
544
  throw new InvalidInputError("search_query must be an array when provided");
@@ -553,6 +555,7 @@ function buildFetchRequest(scope, options) {
553
555
  };
554
556
  if (precisionLevel !== "high") body["precision_level"] = precisionLevel;
555
557
  if (queryDate) body["query_date"] = queryDate;
558
+ if (perQuery) body["max_results_per_query"] = perQuery;
556
559
  if (options.include_conversation_context === false) {
557
560
  body["include_conversation_context"] = false;
558
561
  }
@@ -628,9 +631,14 @@ function pick(...values) {
628
631
  return pickDefined(...values);
629
632
  }
630
633
  var obj = (v) => v ?? {};
634
+ function matchedQueries(item = {}) {
635
+ const raw = item["matchedQueries"] ?? item.matched_queries;
636
+ return Array.isArray(raw) ? raw : [];
637
+ }
631
638
  function normalizeTemporalFields(item = {}) {
632
639
  return {
633
640
  eventDate: pick(item["eventDate"], item.event_date, null),
641
+ saidAt: pick(item["saidAt"], item.said_at, null),
634
642
  validUntil: pick(item["validUntil"], item.valid_until, null),
635
643
  temporalCategory: pick(item["temporalCategory"], item.temporal_category, null),
636
644
  temporalConfidence: pick(item["temporalConfidence"], item.temporal_confidence, 0)
@@ -644,7 +652,8 @@ function normalizeFact(item = {}) {
644
652
  source: item.source || "",
645
653
  extractedAt: pick(item["extractedAt"], item.extracted_at, null),
646
654
  metadata: obj(item.metadata),
647
- ...normalizeTemporalFields(item)
655
+ ...normalizeTemporalFields(item),
656
+ matchedQueries: matchedQueries(item)
648
657
  };
649
658
  }
650
659
  function normalizePreference(item = {}) {
@@ -656,7 +665,8 @@ function normalizePreference(item = {}) {
656
665
  source: item.source || "",
657
666
  extractedAt: pick(item["extractedAt"], item.extracted_at, null),
658
667
  metadata: obj(item.metadata),
659
- ...normalizeTemporalFields(item)
668
+ ...normalizeTemporalFields(item),
669
+ matchedQueries: matchedQueries(item)
660
670
  };
661
671
  }
662
672
  function normalizeEpisode(item = {}) {
@@ -667,7 +677,8 @@ function normalizeEpisode(item = {}) {
667
677
  significance: pick(item["significance"], item.confidence, 0),
668
678
  participants: item["participants"] || [],
669
679
  metadata: obj(item.metadata),
670
- ...normalizeTemporalFields(item)
680
+ ...normalizeTemporalFields(item),
681
+ matchedQueries: matchedQueries(item)
671
682
  };
672
683
  }
673
684
  function normalizeEmotion(item = {}) {
@@ -678,7 +689,8 @@ function normalizeEmotion(item = {}) {
678
689
  detectedAt: pick(item["detectedAt"], item["detected_at"], null),
679
690
  context: item["context"] || "",
680
691
  metadata: obj(item.metadata),
681
- ...normalizeTemporalFields(item)
692
+ ...normalizeTemporalFields(item),
693
+ matchedQueries: matchedQueries(item)
682
694
  };
683
695
  }
684
696
  function normalizeTemporalEvent(item = {}) {
@@ -686,13 +698,15 @@ function normalizeTemporalEvent(item = {}) {
686
698
  id: item.id || "",
687
699
  content: item.content || "",
688
700
  eventDate: pick(item["eventDate"], item.event_date, null),
701
+ saidAt: pick(item["saidAt"], item.said_at, null),
689
702
  validUntil: pick(item["validUntil"], item.valid_until, null),
690
703
  temporalCategory: pick(item["temporalCategory"], item.temporal_category, ""),
691
704
  temporalConfidence: pick(item["temporalConfidence"], item.temporal_confidence, 0),
692
705
  confidence: pick(item.confidence, 0),
693
706
  source: item.source || "",
694
707
  extractedAt: pick(item["extractedAt"], item.extracted_at, null),
695
- metadata: obj(item.metadata)
708
+ metadata: obj(item.metadata),
709
+ matchedQueries: matchedQueries(item)
696
710
  };
697
711
  }
698
712
  function normalizeContextMetadata(metadata = {}) {
@@ -748,6 +762,7 @@ var dt = (v) => v ? String(v) : null;
748
762
  function temporal(item) {
749
763
  return {
750
764
  event_date: dt(item["event_date"]),
765
+ said_at: dt(item["said_at"]),
751
766
  valid_until: dt(item["valid_until"]),
752
767
  temporal_category: item["temporal_category"] ?? null,
753
768
  temporal_confidence: n(item["temporal_confidence"], 0)
@@ -866,8 +881,33 @@ function buildCreateBody(options) {
866
881
  metadata: options.metadata ?? {}
867
882
  };
868
883
  }
884
+ var FORGET_MODES = ["preview", "direct"];
885
+ var FORGET_DESCRIPTION_MIN = 3;
886
+ var FORGET_DESCRIPTION_MAX = 500;
887
+ function buildForgetBody(options) {
888
+ const description = options.description;
889
+ if (typeof description !== "string" || description.length < FORGET_DESCRIPTION_MIN || description.length > FORGET_DESCRIPTION_MAX) {
890
+ throw new InvalidInputError(
891
+ `description must be between ${FORGET_DESCRIPTION_MIN} and ${FORGET_DESCRIPTION_MAX} characters`
892
+ );
893
+ }
894
+ const mode = options.mode ?? "preview";
895
+ if (!FORGET_MODES.includes(mode)) {
896
+ throw new InvalidInputError(
897
+ `Invalid mode '${mode}'. Expected one of: ${FORGET_MODES.join(", ")}`
898
+ );
899
+ }
900
+ const o2 = options;
901
+ return {
902
+ description,
903
+ user_id: either(o2, "user_id", "userId") ?? null,
904
+ customer_id: either(o2, "customer_id", "customerId") ?? null,
905
+ scope: options.scope ?? null,
906
+ mode
907
+ };
908
+ }
869
909
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "error", "cancelled"]);
870
- function createMemoriesInterface(transport) {
910
+ function createMemoriesInterface(transport, onForgotten) {
871
911
  return {
872
912
  async create(options) {
873
913
  const o2 = options;
@@ -953,6 +993,23 @@ function createMemoriesInterface(transport) {
953
993
  }
954
994
  return transport.request("memories_delete", { pathParams: { memory_id: memoryId } });
955
995
  },
996
+ async forget(options) {
997
+ const o2 = options;
998
+ transport.checkCustomerId(o2["customer_id"] ?? o2["customerId"], "memories.forget");
999
+ const body = buildForgetBody(options);
1000
+ const result = await transport.request("memories_forget", { body });
1001
+ const removed = !!result?.deleted_ids?.length || result?.status === "deleted" || result?.status === "partial";
1002
+ if (removed && onForgotten) {
1003
+ try {
1004
+ onForgotten({
1005
+ userId: body["user_id"] ?? null,
1006
+ customerId: body["customer_id"] ?? null
1007
+ });
1008
+ } catch {
1009
+ }
1010
+ }
1011
+ return result;
1012
+ },
956
1013
  async status(ingestionId) {
957
1014
  if (!ingestionId) throw new InvalidInputError("ingestion_id is required");
958
1015
  return transport.request("memories_status", {
@@ -1457,7 +1514,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
1457
1514
  if (client !== null) {
1458
1515
  throw new ListeningAlreadyActiveError("Listening is already active on this instance");
1459
1516
  }
1460
- const { GrpcStreamClient } = await import("./stream-client-5CGJNTH4.js");
1517
+ const { GrpcStreamClient } = await import("./stream-client-VWKINE47.js");
1461
1518
  const onContext = options.on_context ?? options.onContext;
1462
1519
  const onDisconnect = options.on_disconnect ?? options.onDisconnect;
1463
1520
  const onReconnect = options.on_reconnect ?? options.onReconnect;
@@ -1629,7 +1686,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
1629
1686
  }
1630
1687
 
1631
1688
  // src/version.ts
1632
- var SDK_VERSION = "0.5.4";
1689
+ var SDK_VERSION = "0.5.7";
1633
1690
 
1634
1691
  // src/registry.ts
1635
1692
  var instances = /* @__PURE__ */ new Map();
@@ -2058,6 +2115,7 @@ function normalise(item) {
2058
2115
  detected_at: pick2(item, "detected_at", "extracted_at", "created_at") ?? null,
2059
2116
  metadata: pick2(item, "metadata") ?? {},
2060
2117
  event_date: pick2(item, "event_date") ?? null,
2118
+ said_at: pick2(item, "said_at") ?? null,
2061
2119
  valid_until: pick2(item, "valid_until") ?? null,
2062
2120
  temporal_category: pick2(item, "temporal_category") ?? null,
2063
2121
  temporal_confidence: Number(pick2(item, "temporal_confidence") ?? 0)
@@ -2132,6 +2190,10 @@ function tryServeFromCache(cache, scope, params, maxItems) {
2132
2190
  return { response: null, hit: null };
2133
2191
  }
2134
2192
  }
2193
+ function distinctQueryCount(searchQuery) {
2194
+ if (!Array.isArray(searchQuery)) return 0;
2195
+ return new Set(searchQuery.filter((q) => typeof q === "string" && q.length > 0)).size;
2196
+ }
2135
2197
 
2136
2198
  // src/context/assembled.ts
2137
2199
  var COLLECTIONS2 = ["facts", "preferences", "episodes", "emotions", "temporal_events"];
@@ -2629,6 +2691,7 @@ var SynapClient = class {
2629
2691
  beforeFetch: (scope, options2) => {
2630
2692
  const o2 = options2;
2631
2693
  if (o2["query_date"] ?? o2["queryDate"]) return null;
2694
+ if (o2["max_results_per_query"] ?? o2["maxResultsPerQuery"]) return null;
2632
2695
  const attempt = tryServeFromCache(
2633
2696
  this.#anticipationCache,
2634
2697
  scope,
@@ -2699,7 +2762,11 @@ var SynapClient = class {
2699
2762
  compacted: (conversationId, format) => this.#localCompacted(conversationId, format)
2700
2763
  }
2701
2764
  );
2702
- this.memories = createMemoriesInterface(this.#transport);
2765
+ this.memories = createMemoriesInterface(this.#transport, ({ userId, customerId }) => {
2766
+ for (const id of /* @__PURE__ */ new Set([userId, customerId])) {
2767
+ if (id) this.#anticipationCache.dropEntity(id);
2768
+ }
2769
+ });
2703
2770
  this.credits = createCreditsNamespace(this.#transport);
2704
2771
  this.cache = createCacheNamespace(this.#anticipationCache);
2705
2772
  this.instance = createInstanceNamespace(
@@ -2898,6 +2965,7 @@ var SynapClient = class {
2898
2965
  mode = "fast",
2899
2966
  precision_level: precisionLevel = "high",
2900
2967
  query_date: queryDate,
2968
+ max_results_per_query: maxResultsPerQuery,
2901
2969
  include_conversation_context: includeConversationContext = true,
2902
2970
  scopes,
2903
2971
  include_scope_labels: includeScopeLabels = false,
@@ -2916,7 +2984,8 @@ var SynapClient = class {
2916
2984
  // In `shared` so it reaches all four branches at once. The Python edit
2917
2985
  // threaded three call sites by hand and missed the client branch, which
2918
2986
  // sits one indent deeper; spreading removes that whole class of miss.
2919
- query_date: queryDate
2987
+ query_date: queryDate,
2988
+ max_results_per_query: maxResultsPerQuery
2920
2989
  };
2921
2990
  const labels = [];
2922
2991
  const tasks = [];
@@ -3026,7 +3095,12 @@ var SynapClient = class {
3026
3095
  served_item_ids: served.servedItemIds,
3027
3096
  scope,
3028
3097
  source_bundle_ids: served.bundleId ? [served.bundleId] : [],
3029
- timestamp_ms: Date.now()
3098
+ timestamp_ms: Date.now(),
3099
+ // How many distinct search queries the fetch carried. A hit never
3100
+ // reaches the fetch route, so this event is how the server learns it
3101
+ // happened and what it is charged by. The count only: this event must
3102
+ // not carry the caller's words.
3103
+ query_count: distinctQueryCount(options["search_query"] ?? options["searchQuery"])
3030
3104
  });
3031
3105
  } catch {
3032
3106
  }
@@ -3165,6 +3239,7 @@ export {
3165
3239
  DEFAULT_TIMEOUTS,
3166
3240
  DOCUMENT_TYPES,
3167
3241
  ENDPOINTS,
3242
+ FORGET_MODES,
3168
3243
  HttpTransport,
3169
3244
  INGEST_MODES,
3170
3245
  ITEM_COLLECTIONS,