@subcortex-ai/sdk 0.3.8 → 0.3.9

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
@@ -242,6 +242,27 @@ const subcortex = new SubCortexClient({
242
242
  })
243
243
  ```
244
244
 
245
+ ## Framework Integration
246
+
247
+ ### Next.js (App Router)
248
+
249
+ Next.js patches `globalThis.fetch` with aggressive caching. GET requests — including assertion queries, user identification, and signal snapshots — will return stale data unless you bypass the cache. **This is critical for cognitive data that changes between sessions.**
250
+
251
+ ```typescript
252
+ // app/api/my-agent/route.ts
253
+ const noCacheFetch: typeof fetch = (input, init) =>
254
+ fetch(input, { ...init, cache: 'no-store' })
255
+
256
+ const subcortex = new SubCortexClient({
257
+ endpoint: process.env.SUBCORTEX_ENDPOINT!,
258
+ tenantId: process.env.SUBCORTEX_TENANT_ID!,
259
+ apiKey: process.env.SUBCORTEX_API_KEY,
260
+ fetch: noCacheFetch, // ← Required in Next.js
261
+ })
262
+ ```
263
+
264
+ Without this, `users.identify()`, `assertions.query()`, and `signals.query()` may return cached results — meaning new assertions added between sessions (by other agents, users, or the SubCortex console) will be invisible until a hard page refresh.
265
+
245
266
  ## What is SubCortex?
246
267
 
247
268
  SubCortex is a purpose-built cognitive engine for AI agents — persistent memory, identity, emotional signals, and knowledge graph in one system.
package/dist/index.cjs CHANGED
@@ -2058,16 +2058,25 @@ function toContextXml(user, options = {}) {
2058
2058
  if (knowledge.length > 0) {
2059
2059
  lines.push(` <knowledge count="${knowledge.length}">`);
2060
2060
  for (const mem of knowledge) {
2061
+ if (mem.predicate.startsWith("signal:")) {
2062
+ const sigType = mem.predicate.slice(7);
2063
+ const val = mem.value;
2064
+ const content = typeof val === "object" && val?.content ? String(val.content) : formatValue(mem.value);
2065
+ const intensity = typeof val === "object" && val?.intensity ? Number(val.intensity) : mem.confidence;
2066
+ const about = typeof val === "object" && val?.aboutSubject ? ` about="${esc(String(val.aboutSubject))}"` : "";
2067
+ lines.push(` <signal type="${esc(sigType)}" intensity="${fmtConf(intensity)}"${about}>${esc(content)}</signal>`);
2068
+ continue;
2069
+ }
2061
2070
  const memSignals = findSignalsForFact(mem, signalsByAbout);
2062
2071
  if (memSignals.length > 0) {
2063
2072
  lines.push(` <fact predicate="${esc(mem.predicate)}" confidence="${fmtConf(mem.confidence)}">`);
2064
- lines.push(` ${esc(String(mem.value))}`);
2073
+ lines.push(` ${esc(formatValue(mem.value))}`);
2065
2074
  for (const sig of memSignals) {
2066
2075
  lines.push(` ${renderSignal(sig)}`);
2067
2076
  }
2068
2077
  lines.push(` </fact>`);
2069
2078
  } else {
2070
- lines.push(` <fact predicate="${esc(mem.predicate)}" confidence="${fmtConf(mem.confidence)}">${esc(String(mem.value))}</fact>`);
2079
+ lines.push(` <fact predicate="${esc(mem.predicate)}" confidence="${fmtConf(mem.confidence)}">${esc(formatValue(mem.value))}</fact>`);
2071
2080
  }
2072
2081
  }
2073
2082
  lines.push(` </knowledge>`);
@@ -2109,6 +2118,12 @@ function findSignalsForFact(fact, signalsByAbout) {
2109
2118
  }
2110
2119
  return results;
2111
2120
  }
2121
+ function formatValue(v) {
2122
+ if (v === null || v === void 0) return "";
2123
+ if (typeof v === "string") return v;
2124
+ if (typeof v === "object" && "content" in v) return String(v.content);
2125
+ return JSON.stringify(v);
2126
+ }
2112
2127
  function fmtConf(n) {
2113
2128
  return n.toFixed(2);
2114
2129
  }