@smartmemory/sdk-js 1.4.52 → 1.4.57

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/README.md CHANGED
@@ -79,6 +79,40 @@ function Dashboard() {
79
79
  }
80
80
  ```
81
81
 
82
+ ### Browser analytics (optional)
83
+
84
+ The analytics entry point is browser-only and intentionally separate from the core and React bindings. Install its optional `posthog-js` peer only in apps that use analytics:
85
+
86
+ ```bash
87
+ npm install posthog-js
88
+ ```
89
+
90
+ ```jsx
91
+ import { PostHogProvider } from 'posthog-js/react';
92
+ import {
93
+ AnalyticsIdentity,
94
+ createAnalyticsConfig,
95
+ } from '@smartmemory/sdk-js/react/analytics';
96
+
97
+ const analytics = createAnalyticsConfig({
98
+ app: 'web',
99
+ apiKey: import.meta.env.VITE_PUBLIC_POSTHOG_KEY,
100
+ apiHost: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
101
+ });
102
+
103
+ // Keep the existing child passthrough when analytics.apiKey is null.
104
+ const root = analytics.apiKey
105
+ ? <PostHogProvider apiKey={analytics.apiKey} options={analytics.options}><App /></PostHogProvider>
106
+ : <App />;
107
+
108
+ function IdentityAdapter() {
109
+ const { user, isAuthenticated, workspaceId } = useAuth();
110
+ return <AnalyticsIdentity {...{ user, isAuthenticated, workspaceId }} />;
111
+ }
112
+ ```
113
+
114
+ This subpath also exports `captureProductEvent`, `captureException`, and `resetAnalytics`. It is not re-exported from `@smartmemory/sdk-js/react`, so non-browser consumers never load PostHog.
115
+
82
116
  ## Entry Points
83
117
 
84
118
  | Import | Contents |
@@ -86,6 +120,7 @@ function Dashboard() {
86
120
  | `@smartmemory/sdk-js` | SmartMemoryClient, AuthCore, TokenManager, all domain APIs, APIError |
87
121
  | `@smartmemory/sdk-js/core` | Everything above + BaseAPI, RefreshManager, SSOManager (internal access) |
88
122
  | `@smartmemory/sdk-js/react` | SmartMemoryProvider, useAuth, useAuthState, useAuthActions, useSmartMemory, AuthWrapper |
123
+ | `@smartmemory/sdk-js/react/analytics` | Browser-only strict PostHog config, identity, product-event, exception, and reset helpers (optional `posthog-js` peer) |
89
124
  | `@smartmemory/sdk-js/fetch` | createAuthFetch, installInterceptor |
90
125
 
91
126
  ## Configuration
@@ -3,7 +3,7 @@ var R = (a) => {
3
3
  };
4
4
  var k = (a, e, t) => e.has(a) || R("Cannot " + t);
5
5
  var g = (a, e, t) => (k(a, e, "read from private field"), t ? t.call(a) : e.get(a)), w = (a, e, t) => e.has(a) ? R("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(a) : e.set(a, t), b = (a, e, t, s) => (k(a, e, "write to private field"), s ? s.call(a, t) : e.set(a, t), t), S = (a, e, t) => (k(a, e, "access private method"), t);
6
- const U = {
6
+ const A = {
7
7
  access: "smart_memory_auth_token",
8
8
  refresh: "smart_memory_refresh_token",
9
9
  user: "smart_memory_user",
@@ -23,7 +23,7 @@ class C {
23
23
  * @param {Object} [options.keys] - Custom storage key names
24
24
  */
25
25
  constructor({ storage: e = "localStorage", keys: t = {} } = {}) {
26
- this.storageType = e, this.keys = { ...U, ...t }, this._memory = { access: null, refresh: null, user: null, tenant: null, team: null };
26
+ this.storageType = e, this.keys = { ...A, ...t }, this._memory = { access: null, refresh: null, user: null, tenant: null, team: null };
27
27
  }
28
28
  getAccessToken() {
29
29
  return this.storageType === "memory" ? this._memory.access : this._getFromStorage(this.keys.access, y.access);
@@ -191,7 +191,7 @@ l = new WeakMap(), f = new WeakSet(), v = async function() {
191
191
  return this.tokenManager.setAccessToken(r.access_token), r.refresh_token && this.tokenManager.setRefreshToken(r.refresh_token), this.onTokenRefreshed(r.access_token), r.access_token;
192
192
  };
193
193
  const I = "smart_memory_sso_redirect";
194
- class q {
194
+ class L {
195
195
  /**
196
196
  * @param {Object} options
197
197
  * @param {string} options.webAppUrl - Web app URL for login redirect
@@ -230,7 +230,7 @@ class q {
230
230
  }
231
231
  }
232
232
  }
233
- class L {
233
+ class q {
234
234
  constructor(e) {
235
235
  this.mode = e.mode, this.apiBaseUrl = e.apiBaseUrl, this.endpoints = e.endpoints || {}, this.listeners = /* @__PURE__ */ new Set(), this.useCookieAuth = e.useCookieAuth ?? this.mode === "sso", this.apiKey = e.apiKey || null, this.apiKey && (this.mode = "apiKey"), this.tokenManager = new C({
236
236
  storage: e.storage || "localStorage",
@@ -247,7 +247,7 @@ class L {
247
247
  onRefreshFailed: () => {
248
248
  this.clearLocalAuth();
249
249
  }
250
- }) : this.refreshManager = null, this.mode === "sso" && (this.ssoManager = new q({
250
+ }) : this.refreshManager = null, this.mode === "sso" && (this.ssoManager = new L({
251
251
  webAppUrl: e.webAppUrl,
252
252
  allowedHosts: e.allowedRedirectHosts || [],
253
253
  tokenManager: this.tokenManager
@@ -286,7 +286,8 @@ class L {
286
286
  isAuthenticated: this.isAuthenticated(),
287
287
  user: this.currentUser,
288
288
  token: this.currentToken,
289
- tenantId: this.tokenManager.getTenantId()
289
+ tenantId: this.tokenManager.getTenantId(),
290
+ workspaceId: this.tokenManager.getTeamId()
290
291
  };
291
292
  this.listeners.forEach((t) => {
292
293
  try {
@@ -530,6 +531,21 @@ class z {
530
531
  constructor(e) {
531
532
  this.api = e;
532
533
  }
534
+ /**
535
+ * Create a memory item.
536
+ *
537
+ * Provenance like `retrieved_context_ids` travels inside `metadata` — the storage
538
+ * layer lifts it onto the server-side MemoryItem; no dedicated option exists
539
+ * (GRAPH-API-1i wire field added then removed 2026-08-02).
540
+ *
541
+ * @param {Object} options
542
+ * @param {string} options.content - Memory content
543
+ * @param {string} [options.memoryType='semantic'] - Memory type
544
+ * @param {Object} [options.metadata] - Additional metadata
545
+ * @param {boolean} [options.usePipeline=true] - Run the full extraction pipeline
546
+ * @param {string} [options.profileName] - Pipeline profile, routed server-side
547
+ * @param {Object} [options.conversationContext] - Conversation-aware extraction context
548
+ */
533
549
  async create({
534
550
  content: e,
535
551
  memoryType: t = "semantic",
@@ -578,9 +594,31 @@ class z {
578
594
  async delete(e) {
579
595
  return this.api.delete(`/memory/${e}`);
580
596
  }
581
- async list({ limit: e = 50, offset: t = 0, type: s = null } = {}) {
582
- let r = `/memory/list?limit=${e}&offset=${t}`;
583
- return s && (r += `&memory_type=${s}`), this.api.get(r);
597
+ /**
598
+ * List memory items, optionally filtered by an exact metadata match.
599
+ *
600
+ * @param {object} [options]
601
+ * @param {number} [options.limit=50]
602
+ * @param {number} [options.offset=0]
603
+ * @param {string|null} [options.type=null] - NOTE: sent as `memory_type`, which the
604
+ * `/memory/list` route does not declare and therefore ignores. Pre-existing; kept as-is
605
+ * so nothing silently changes behaviour for callers already passing it.
606
+ * @param {string|null} [options.metadataKey=null] - GRAPH-API-1l. Metadata key to filter
607
+ * on. Nested keys use dot syntax (`profile.tier`). Must be paired with `metadataValue`;
608
+ * sending only one half is a 422.
609
+ * @param {string|null} [options.metadataValue=null] - Value the key must equal.
610
+ * @returns {Promise<{items: object[], total: number, limit: number, offset: number}>}
611
+ * `total` counts the filtered set, so it drives pagination directly.
612
+ */
613
+ async list({
614
+ limit: e = 50,
615
+ offset: t = 0,
616
+ type: s = null,
617
+ metadataKey: r = null,
618
+ metadataValue: n = null
619
+ } = {}) {
620
+ const i = new URLSearchParams({ limit: e, offset: t });
621
+ return s && i.append("memory_type", s), r != null && i.append("metadata_key", r), n != null && i.append("metadata_value", n), this.api.get(`/memory/list?${i}`);
584
622
  }
585
623
  /**
586
624
  * Search for memory items.
@@ -611,9 +649,9 @@ class z {
611
649
  * present only under `cite: true`. Pre-LINEAGE-1 callers who indexed into a
612
650
  * bare array must read `response.results` instead.
613
651
  */
614
- async search(e, { topK: t = 5, enableHybrid: s = !0, memoryType: r = null, expertise: n = !1, cite: i = !1, decompose: o = !1, multiHop: c = !1, maxHops: u = 3, budgetMs: p = 1500, semanticHops: _ = !1, includeReference: $ = !1, includeConsolidated: T = !1, consolidationFirst: A = !1 } = {}) {
652
+ async search(e, { topK: t = 5, enableHybrid: s = !0, memoryType: r = null, expertise: n = !1, cite: i = !1, decompose: o = !1, multiHop: c = !1, maxHops: u = 3, budgetMs: p = 1500, semanticHops: _ = !1, includeReference: $ = !1, includeConsolidated: T = !1, consolidationFirst: U = !1 } = {}) {
615
653
  const m = { query: e, top_k: t, enable_hybrid: s };
616
- return r && (m.memory_type = r), n && (m.expertise = !0), i && (m.cite = !0), o && (m.decompose = !0), c && (m.multi_hop = !0), c && u !== 3 && (m.max_hops = u), c && p !== 1500 && (m.budget_ms = p), c && _ && (m.semantic_hops = !0), $ && (m.include_reference = !0), T && (m.include_consolidated = !0), A && (m.consolidation_first = !0), this.api.post("/memory/search", m);
654
+ return r && (m.memory_type = r), n && (m.expertise = !0), i && (m.cite = !0), o && (m.decompose = !0), c && (m.multi_hop = !0), c && u !== 3 && (m.max_hops = u), c && p !== 1500 && (m.budget_ms = p), c && _ && (m.semantic_hops = !0), $ && (m.include_reference = !0), T && (m.include_consolidated = !0), U && (m.consolidation_first = !0), this.api.post("/memory/search", m);
617
655
  }
618
656
  async getWorkingContext(e, t, { k: s = 20, maxTokens: r = null, strategy: n = null } = {}) {
619
657
  const i = {
@@ -645,9 +683,22 @@ class z {
645
683
  async getLinks(e) {
646
684
  return this.api.get(`/memory/${e}/links`);
647
685
  }
648
- async searchByMetadata(e, t, { memoryType: s = null } = {}) {
649
- const r = new URLSearchParams({ metadata_key: e, metadata_value: t });
650
- return s && r.append("memory_type", s), this.api.get(`/memory/by-metadata?${r}`);
686
+ /**
687
+ * Find memory items by exact metadata match.
688
+ *
689
+ * @deprecated GRAPH-API-1l — use {@link MemoryAPI#list} with `metadataKey` /
690
+ * `metadataValue` instead. It applies the same filter but adds pagination and an
691
+ * exact `total`. This method still works and its behaviour is unchanged; the two
692
+ * endpoints return slightly different item shapes, so migrate deliberately rather
693
+ * than by find-and-replace.
694
+ */
695
+ async searchByMetadata(e, t, { memoryType: s = null, limit: r = 25 } = {}) {
696
+ const n = new URLSearchParams({
697
+ metadata_key: e,
698
+ metadata_value: t,
699
+ limit: r
700
+ });
701
+ return s && n.append("memory_type", s), this.api.get(`/memory/by-metadata?${n}`);
651
702
  }
652
703
  async getNeighbors(e) {
653
704
  return this.api.get(`/memory/${e}/neighbors`);
@@ -965,9 +1016,12 @@ class E {
965
1016
  /**
966
1017
  * Find existing decisions that may conflict with this one.
967
1018
  * @param {string} decisionId
1019
+ * @param {number} [minContest=0] - Minimum pairwise contest severity (0..1).
968
1020
  */
969
- async findConflicts(e) {
970
- return this.api.post(`/memory/decisions/${e}/conflicts`);
1021
+ async findConflicts(e, t = 0) {
1022
+ return this.api.post(
1023
+ `/memory/decisions/${e}/conflicts?min_contest=${encodeURIComponent(t)}`
1024
+ );
971
1025
  }
972
1026
  // --- Legacy reasoning proxies (kept for backward compatibility) ---
973
1027
  /**
@@ -1059,8 +1113,20 @@ class O {
1059
1113
  * Fetch edges for multiple node IDs in bulk.
1060
1114
  * @param {string[]} nodeIds
1061
1115
  */
1062
- async getEdgesBulk(e) {
1063
- return this.api.post("/memory/graph/edges", { node_ids: e });
1116
+ async getEdgesBulk(e, { includeProperties: t = !1 } = {}) {
1117
+ const s = t ? "?include_properties=true" : "";
1118
+ return this.api.post(`/memory/graph/edges${s}`, { node_ids: e });
1119
+ }
1120
+ /**
1121
+ * Bulk upsert graph nodes and edges, optionally replacing a node-ID prefix.
1122
+ * @param {Object} [params]
1123
+ * @param {Array<Object>} [params.nodes=[]] - Nodes with item_id, label, and properties.
1124
+ * @param {Array<Object>} [params.edges=[]] - Edges with source_id, target_id, edge_type, and properties.
1125
+ * @param {string|null} [params.deletePrefix=null] - Scoped node-ID prefix to delete before writing.
1126
+ */
1127
+ async bulkUpsert({ nodes: e = [], edges: t = [], deletePrefix: s = null } = {}) {
1128
+ const r = { nodes: e, edges: t };
1129
+ return s !== null && (r.delete_prefix = s), this.api.post("/memory/graph/bulk", r);
1064
1130
  }
1065
1131
  /**
1066
1132
  * Get Wikipedia grounding status for an entity node.
@@ -1506,7 +1572,7 @@ class J {
1506
1572
  return this.api.get(`/memory/temporal/relationships/${e}/valid-periods`);
1507
1573
  }
1508
1574
  }
1509
- class V {
1575
+ class W {
1510
1576
  constructor(e) {
1511
1577
  this.api = e;
1512
1578
  }
@@ -1575,7 +1641,7 @@ class V {
1575
1641
  return this.api.get("/memory/governance/summary");
1576
1642
  }
1577
1643
  }
1578
- class W {
1644
+ class V {
1579
1645
  constructor(e) {
1580
1646
  this.api = e;
1581
1647
  }
@@ -2918,9 +2984,9 @@ class oe {
2918
2984
  }
2919
2985
  class me {
2920
2986
  constructor(e) {
2921
- this.auth = new L(e);
2987
+ this.auth = new q(e);
2922
2988
  const t = new M(this.auth, { fetchFn: e.fetchFn });
2923
- this._api = t, this.memories = new z(t), this.decisions = new E(t), this.opinions = new x(t), this.graph = new O(t), this.teams = new F(t), this.profiles = new j(t), this.subscriptions = new H(t), this.authAPI = new B(t), this.agents = new K(t), this.usage = new G(t), this.insights = new D(t), this.tokenUsage = new N(t), this.temporal = new J(t), this.governance = new V(t), this.evolution = new W(t), this.reasoning = new Y(t), this.reasoningTraces = new Z(t), this.ontology = new Q(t), this.analytics = new X(t), this.validation = new ee(t), this.pipeline = new te(t), this.archive = new se(t), this.zettelkasten = new re(t), this.procedureMatches = new ne(t), this.procedureCandidates = new ie(t), this.procedureDrift = new ae(t), this.summaries = new oe(t);
2989
+ this._api = t, this.memories = new z(t), this.decisions = new E(t), this.opinions = new x(t), this.graph = new O(t), this.teams = new F(t), this.profiles = new j(t), this.subscriptions = new H(t), this.authAPI = new B(t), this.agents = new K(t), this.usage = new G(t), this.insights = new D(t), this.tokenUsage = new N(t), this.temporal = new J(t), this.governance = new W(t), this.evolution = new V(t), this.reasoning = new Y(t), this.reasoningTraces = new Z(t), this.ontology = new Q(t), this.analytics = new X(t), this.validation = new ee(t), this.pipeline = new te(t), this.archive = new se(t), this.zettelkasten = new re(t), this.procedureMatches = new ne(t), this.procedureCandidates = new ie(t), this.procedureDrift = new ae(t), this.summaries = new oe(t);
2924
2990
  }
2925
2991
  setTeamId(e) {
2926
2992
  this.auth.tokenManager.setTeamId(e), this.auth.notifyListeners();
@@ -2949,8 +3015,8 @@ export {
2949
3015
  h as A,
2950
3016
  M as B,
2951
3017
  E as D,
2952
- W as E,
2953
- V as G,
3018
+ V as E,
3019
+ W as G,
2954
3020
  D as I,
2955
3021
  z as M,
2956
3022
  Q as O,
@@ -2965,7 +3031,7 @@ export {
2965
3031
  X as b,
2966
3032
  se as c,
2967
3033
  B as d,
2968
- L as e,
3034
+ q as e,
2969
3035
  O as f,
2970
3036
  x as g,
2971
3037
  ie as h,
@@ -2977,5 +3043,5 @@ export {
2977
3043
  C as n,
2978
3044
  N as o,
2979
3045
  P as p,
2980
- q
3046
+ L as q
2981
3047
  };
package/dist/core.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as e, a as r, d as A, e as I, B as P, D as n, f as o, I as t, M as i, j as g, p as M, q as h, S as m, l as S, T as f, n as p, U as l } from "./core-D1Y88paM.js";
1
+ import { A as e, a as r, d as A, e as I, B as P, D as n, f as o, I as t, M as i, j as g, p as M, q as h, S as m, l as S, T as f, n as p, U as l } from "./core-D1O9gOZK.js";
2
2
  export {
3
3
  e as APIError,
4
4
  r as AgentAPI,
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as f, a as u, b as A, c as b, d as P, e as h, D as I, E as g, G as x, f as p, I as w, M as m, O as k, g as v, P as T, h as B, i as y, j as C, R as E, k as S, S as R, l as F, T as M, m as L, n as O, o as G, U, V as $, Z as D } from "./core-D1Y88paM.js";
1
+ import { A as f, a as u, b as A, c as b, d as P, e as h, D as I, E as g, G as x, f as p, I as w, M as m, O as k, g as v, P as T, h as B, i as y, j as C, R as E, k as S, S as R, l as F, T as M, m as L, n as O, o as G, U, V as $, Z as D } from "./core-D1O9gOZK.js";
2
2
  const i = {
3
3
  variables: {
4
4
  colorBackground: "transparent",
@@ -0,0 +1,228 @@
1
+ import { useEffect as m } from "react";
2
+ import u from "posthog-js";
3
+ function y() {
4
+ var e;
5
+ if (typeof import.meta < "u")
6
+ return "production";
7
+ if (typeof process < "u")
8
+ return (e = process.env) == null ? void 0 : e.NODE_ENV;
9
+ }
10
+ function E(e) {
11
+ return e === "production" || e === "test" ? e : "development";
12
+ }
13
+ const g = /(url|referrer|href)/i;
14
+ function b(e) {
15
+ if (typeof e != "string" || !/^https?:\/\//i.test(e))
16
+ return e;
17
+ try {
18
+ const t = new URL(e);
19
+ return `${t.origin}${t.pathname}`;
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+ function p(e) {
25
+ if (!e || typeof e != "object")
26
+ return e;
27
+ const t = Array.isArray(e) ? [...e] : { ...e };
28
+ for (const [r, n] of Object.entries(t))
29
+ n && typeof n == "object" ? t[r] = p(n) : g.test(r) && (t[r] = b(n));
30
+ return t;
31
+ }
32
+ function h(e) {
33
+ return !e || typeof e != "object" ? e : { ...e, properties: p(e.properties) };
34
+ }
35
+ function U({ app: e, apiKey: t, apiHost: r }) {
36
+ const n = typeof t == "string" && t.trim() ? t.trim() : null, c = E(y());
37
+ return {
38
+ apiKey: n,
39
+ options: {
40
+ api_host: r,
41
+ autocapture: !1,
42
+ // PostHog's exception autocapture hooks window.onerror / unhandledrejection
43
+ // and ships the raw message, stack, and filenames — it never passes through
44
+ // our sanitized captureException seam, so an error string built from a search
45
+ // query or memory content would be sent verbatim. Explicit capture only.
46
+ capture_exceptions: !1,
47
+ capture_pageview: "history_change",
48
+ cross_subdomain_cookie: !0,
49
+ defaults: "2025-05-24",
50
+ // Session replay is ON but fully masked (D3 revision 2026-07-22):
51
+ // layout/navigation are visible, memory content, search queries, and
52
+ // chat text are not.
53
+ //
54
+ // maskTextSelector: '*' is the load-bearing flag. The top-level
55
+ // mask_all_text / mask_all_element_attributes options do NOT reach the
56
+ // recorder — posthog-js reads them only in autocapture.js and
57
+ // dead-clicks-autocapture.js (see their `maskAllText:` usage). The replay
58
+ // recorder resolves masking solely from session_recording.{maskAllInputs,
59
+ // maskTextSelector, blockSelector}. They are kept here as defense in depth
60
+ // for the autocapture surfaces, which remote config can switch on.
61
+ disable_session_recording: !1,
62
+ mask_all_text: !0,
63
+ mask_all_element_attributes: !0,
64
+ session_recording: {
65
+ maskAllInputs: !0,
66
+ maskTextSelector: "*"
67
+ },
68
+ // The PostHog project has consoleLogRecordingEnabled: true server-side, which
69
+ // pipes console output into the replay. Apps log raw payloads while debugging
70
+ // (Maya logs recalled memory content), so that is a content channel masking
71
+ // does not cover. Pin it off from the client, which takes precedence.
72
+ enable_recording_console_log: !1,
73
+ // $current_url / $referrer and their $initial_* variants are attached by
74
+ // PostHog to every event, replay snapshot, and identify — outside the
75
+ // product-event allowlist. Strip query strings and fragments so record
76
+ // identifiers cannot ride along.
77
+ before_send: h,
78
+ loaded: (i) => {
79
+ if (!(!n || typeof (i == null ? void 0 : i.register) != "function"))
80
+ try {
81
+ i.register({ app: e, environment: c });
82
+ } catch {
83
+ }
84
+ }
85
+ }
86
+ };
87
+ }
88
+ function v() {
89
+ return !u || u.__loaded !== !0 ? null : u;
90
+ }
91
+ function x({ user: e, isAuthenticated: t, workspaceId: r }) {
92
+ const n = e == null ? void 0 : e.id, c = e == null ? void 0 : e.email, i = e == null ? void 0 : e.subscription_tier, s = e == null ? void 0 : e.tenant_id;
93
+ return m(() => {
94
+ var f, _, l, d;
95
+ const o = v();
96
+ if (o)
97
+ try {
98
+ if (!t || !n) {
99
+ (f = o.unregister) == null || f.call(o, "workspace_id");
100
+ return;
101
+ }
102
+ r ? (_ = o.register) == null || _.call(o, { workspace_id: r }) : (l = o.unregister) == null || l.call(o, "workspace_id"), (d = o.identify) == null || d.call(o, n, {
103
+ email: c,
104
+ plan: i,
105
+ tenant_id: s
106
+ });
107
+ } catch {
108
+ }
109
+ }, [c, t, i, s, n, r]), null;
110
+ }
111
+ const z = Object.freeze({
112
+ evolution_triggered: Object.freeze(["error_count", "evolver_count", "evolver_keys", "executed_count", "profile_present", "skipped_count", "stop_on_error"]),
113
+ memories_cleared: Object.freeze(["deleted_count", "nuclear"]),
114
+ memory_created: Object.freeze(["created_count", "failed_count", "has_collection", "memory_type", "profile_present", "source", "tag_count", "use_pipeline"]),
115
+ memory_deleted: Object.freeze(["memory_type", "operation", "source"]),
116
+ memory_edited: Object.freeze(["changed_fields", "has_collection", "memory_type", "tag_count", "write_mode"]),
117
+ search_performed: Object.freeze(["budget_bucket", "cite", "decompose", "hybrid", "max_hops", "memory_type", "min_score_bucket", "multi_hop", "result_count", "semantic_hops", "surface", "top_k"]),
118
+ studio_pipeline_saved: Object.freeze(["enricher_count", "evolver_count", "grounder_count", "override_key_count", "save_surface", "stage_count", "storage"])
119
+ }), O = Object.freeze({
120
+ memory_deleted: Object.freeze({
121
+ source: Object.freeze(["user", "cli", "api", "import", "signup", "managed", "mcp", "pipeline", "hook", "lifecycle", "observe", "evolver", "code", "enricher", "conversation", "structured", "version", "snapshot", "unknown"])
122
+ }),
123
+ search_performed: Object.freeze({
124
+ min_score_bucket: Object.freeze(["lt50", "lt80", "gte80"])
125
+ })
126
+ }), j = /* @__PURE__ */ new Set([
127
+ "body",
128
+ "content",
129
+ "context",
130
+ "error",
131
+ "message",
132
+ "query",
133
+ "response",
134
+ "result",
135
+ "tag_values",
136
+ "tags",
137
+ "url"
138
+ ]), k = /* @__PURE__ */ new Set([
139
+ "AggregateError",
140
+ "Error",
141
+ "EvalError",
142
+ "RangeError",
143
+ "ReferenceError",
144
+ "SyntaxError",
145
+ "TypeError",
146
+ "URIError"
147
+ ]), R = ["source", "component", "operation", "method"];
148
+ function a() {
149
+ return !u || u.__loaded !== !0 ? null : u;
150
+ }
151
+ function A(e) {
152
+ return j.has(e) ? !0 : /(^|_)(id|ids|name|names|tag|tags)$/.test(e);
153
+ }
154
+ function S(e, t, r) {
155
+ var c;
156
+ const n = (c = O[e]) == null ? void 0 : c[t];
157
+ return !n || n.includes(r);
158
+ }
159
+ function w(e) {
160
+ try {
161
+ return k.has(e == null ? void 0 : e.name) ? e.name : "Error";
162
+ } catch {
163
+ return "Error";
164
+ }
165
+ }
166
+ function N(e) {
167
+ const t = new Error();
168
+ return delete t.message, delete t.stack, Object.defineProperty(t, "name", {
169
+ configurable: !0,
170
+ enumerable: !0,
171
+ value: w(e)
172
+ }), t;
173
+ }
174
+ function T(e) {
175
+ const t = {};
176
+ if (!e || typeof e != "object")
177
+ return t;
178
+ for (const r of R)
179
+ typeof e[r] == "string" && (t[r] = e[r]);
180
+ return typeof e.status == "number" && Number.isFinite(e.status) && (t.status = e.status), t;
181
+ }
182
+ function I(e, t = {}) {
183
+ const r = z[e], n = a();
184
+ if (!r || !n || typeof n.capture != "function")
185
+ return !1;
186
+ try {
187
+ const c = {};
188
+ for (const i of r) {
189
+ if (A(i))
190
+ continue;
191
+ const s = t == null ? void 0 : t[i];
192
+ s === void 0 || !S(e, i, s) || (c[i] = s);
193
+ }
194
+ return n.capture(e, c), !0;
195
+ } catch {
196
+ return !1;
197
+ }
198
+ }
199
+ function D(e, t = {}) {
200
+ const r = a();
201
+ if (!r || typeof r.captureException != "function")
202
+ return !1;
203
+ try {
204
+ return r.captureException(
205
+ N(e),
206
+ T(t)
207
+ ), !0;
208
+ } catch {
209
+ return !1;
210
+ }
211
+ }
212
+ function K() {
213
+ const e = a();
214
+ if (!e || typeof e.reset != "function")
215
+ return !1;
216
+ try {
217
+ return e.reset(), !0;
218
+ } catch {
219
+ return !1;
220
+ }
221
+ }
222
+ export {
223
+ x as AnalyticsIdentity,
224
+ D as captureException,
225
+ I as captureProductEvent,
226
+ U as createAnalyticsConfig,
227
+ K as resetAnalytics
228
+ };
package/dist/react.js CHANGED
@@ -1,64 +1,66 @@
1
- import h, { createContext as d, useRef as y, useState as v, useEffect as b, useCallback as c, useContext as f } from "react";
2
- import { S as x } from "./core-D1Y88paM.js";
3
- const m = d(null), g = d(null);
4
- function U({ children: e, ...r }) {
5
- const n = y(null);
6
- n.current || (n.current = new x(r));
7
- const t = n.current, [u, o] = v({
1
+ import h, { createContext as d, useRef as I, useState as p, useEffect as C, useCallback as c, useContext as g } from "react";
2
+ import { S as y } from "./core-D1O9gOZK.js";
3
+ const m = d(null), f = d(null);
4
+ function b({ children: e, ...r }) {
5
+ const n = I(null);
6
+ n.current || (n.current = new y(r));
7
+ const t = n.current, [o, u] = p({
8
8
  isAuthenticated: t.auth.isAuthenticated(),
9
9
  user: t.auth.getCurrentUser(),
10
10
  token: t.auth.getCurrentToken(),
11
11
  tenantId: t.auth.getTenantId(),
12
+ workspaceId: t.auth.tokenManager.getTeamId(),
12
13
  loading: !1,
13
14
  error: null
14
15
  });
15
- b(() => t.auth.addListener((a) => {
16
- o((C) => ({
17
- ...C,
18
- isAuthenticated: a.isAuthenticated,
19
- user: a.user,
20
- token: a.token,
21
- tenantId: a.tenantId
16
+ C(() => t.auth.addListener((i) => {
17
+ u((k) => ({
18
+ ...k,
19
+ isAuthenticated: i.isAuthenticated,
20
+ user: i.user,
21
+ token: i.token,
22
+ tenantId: i.tenantId,
23
+ workspaceId: i.workspaceId
22
24
  }));
23
25
  }), [t]);
24
- const s = c(async () => {
26
+ const a = c(async () => {
25
27
  await t.auth.logout();
26
- }, [t]), A = c((i) => t.auth.hasRole(i), [t]), S = c((i) => t.auth.getLoginUrl(i), [t]), w = {
27
- ...u,
28
- logout: s,
29
- hasRole: A,
30
- getLoginUrl: S
28
+ }, [t]), w = c((s) => t.auth.hasRole(s), [t]), A = c((s) => t.auth.getLoginUrl(s), [t]), S = {
29
+ ...o,
30
+ logout: a,
31
+ hasRole: w,
32
+ getLoginUrl: A
31
33
  };
32
- return /* @__PURE__ */ h.createElement(m.Provider, { value: w }, /* @__PURE__ */ h.createElement(g.Provider, { value: t }, e));
34
+ return /* @__PURE__ */ h.createElement(m.Provider, { value: S }, /* @__PURE__ */ h.createElement(f.Provider, { value: t }, e));
33
35
  }
34
36
  function l() {
35
- const e = f(m);
37
+ const e = g(m);
36
38
  if (!e)
37
39
  throw new Error("useAuth must be used within a SmartMemoryProvider");
38
40
  return e;
39
41
  }
40
- function k() {
41
- const { isAuthenticated: e, user: r, token: n, tenantId: t, loading: u, error: o } = l();
42
- return { isAuthenticated: e, user: r, token: n, tenantId: t, loading: u, error: o };
42
+ function x() {
43
+ const { isAuthenticated: e, user: r, token: n, tenantId: t, workspaceId: o, loading: u, error: a } = l();
44
+ return { isAuthenticated: e, user: r, token: n, tenantId: t, workspaceId: o, loading: u, error: a };
43
45
  }
44
- function p() {
46
+ function R() {
45
47
  const { login: e, logout: r, hasRole: n, getLoginUrl: t } = l();
46
48
  return { login: e, logout: r, hasRole: n, getLoginUrl: t };
47
49
  }
48
- function E() {
49
- const e = f(g);
50
+ function U() {
51
+ const e = g(f);
50
52
  if (!e)
51
53
  throw new Error("useSmartMemory must be used within a SmartMemoryProvider");
52
54
  return e;
53
55
  }
54
- function I({ children: e, fallback: r = null, redirectToLogin: n = !1 }) {
55
- const { isAuthenticated: t, loading: u, getLoginUrl: o } = l();
56
- if (u) return r;
56
+ function E({ children: e, fallback: r = null, redirectToLogin: n = !1 }) {
57
+ const { isAuthenticated: t, loading: o, getLoginUrl: u } = l();
58
+ if (o) return r;
57
59
  if (!t) {
58
60
  if (n)
59
61
  try {
60
- const s = o();
61
- window.location.href = s;
62
+ const a = u();
63
+ window.location.href = a;
62
64
  } catch {
63
65
  }
64
66
  return r;
@@ -67,11 +69,11 @@ function I({ children: e, fallback: r = null, redirectToLogin: n = !1 }) {
67
69
  }
68
70
  export {
69
71
  m as AuthContext,
70
- I as AuthWrapper,
71
- g as ClientContext,
72
- U as SmartMemoryProvider,
72
+ E as AuthWrapper,
73
+ f as ClientContext,
74
+ b as SmartMemoryProvider,
73
75
  l as useAuth,
74
- p as useAuthActions,
75
- k as useAuthState,
76
- E as useSmartMemory
76
+ R as useAuthActions,
77
+ x as useAuthState,
78
+ U as useSmartMemory
77
79
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@smartmemory/sdk-js",
3
- "version": "1.4.52",
4
- "description": "Unified JavaScript SDK for SmartMemory API — auth + API client for all frontends",
3
+ "version": "1.4.57",
4
+ "description": "Unified JavaScript SDK for SmartMemory API \u2014 auth + API client for all frontends",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -18,6 +18,10 @@
18
18
  "development": "./src/react/index.js",
19
19
  "default": "./dist/react.js"
20
20
  },
21
+ "./react/analytics": {
22
+ "development": "./src/react/analytics/index.js",
23
+ "default": "./dist/react/analytics.js"
24
+ },
21
25
  "./fetch": {
22
26
  "development": "./src/fetch/index.js",
23
27
  "default": "./dist/fetch.js"
@@ -35,13 +39,17 @@
35
39
  "test": "vitest run",
36
40
  "test:watch": "vitest",
37
41
  "test:coverage": "vitest run --coverage",
38
- "lint": "eslint src/ tests/"
42
+ "lint": "eslint src/ tests/ scripts/"
39
43
  },
40
44
  "peerDependencies": {
45
+ "posthog-js": "^1.313.0",
41
46
  "react": ">=18.0.0",
42
47
  "react-dom": ">=18.0.0"
43
48
  },
44
49
  "peerDependenciesMeta": {
50
+ "posthog-js": {
51
+ "optional": true
52
+ },
45
53
  "react": {
46
54
  "optional": true
47
55
  },
@@ -57,6 +65,7 @@
57
65
  "eslint": "^9.0.0",
58
66
  "globals": "^16.0.0",
59
67
  "jsdom": "^25.0.0",
68
+ "posthog-js": "^1.313.0",
60
69
  "react": "^18.3.0",
61
70
  "react-dom": "^18.3.0",
62
71
  "vite": "^6.0.0",