@pentatonic-ai/ai-agent-sdk 0.10.20 → 0.10.21

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.cjs CHANGED
@@ -878,7 +878,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
878
878
  }
879
879
 
880
880
  // src/telemetry.js
881
- var VERSION = "0.10.20";
881
+ var VERSION = "0.10.21";
882
882
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
883
883
  function machineId() {
884
884
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
package/dist/index.js CHANGED
@@ -847,7 +847,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
847
847
  }
848
848
 
849
849
  // src/telemetry.js
850
- var VERSION = "0.10.20";
850
+ var VERSION = "0.10.21";
851
851
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
852
852
  function machineId() {
853
853
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pentatonic-ai/ai-agent-sdk",
3
- "version": "0.10.20",
3
+ "version": "0.10.21",
4
4
  "description": "TES SDK — LLM observability and lifecycle tracking via Pentatonic Thing Event System. Track token usage, tool calls, and conversations. Manage things through event-sourced lifecycle stages with AI enrichment and vector search.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -913,6 +913,34 @@ def _resolve_arenas(req: GraphQueryRequest) -> list[str]:
913
913
  return arenas
914
914
 
915
915
 
916
+ # Decay access signal (RFC-decay-and-fusion Part B1): the Fusion Drive decay pass
917
+ # ages salience by the most recent of (last_accessed, last_seen/asserted_at), so
918
+ # without an access bump a frequently-retrieved memory still decays and can be
919
+ # evicted. Bump last_accessed on the nodes a read returns so retrieval keeps them
920
+ # alive. THROTTLED to once / _ACCESS_BUMP_THROTTLE per node (the UPDATE no-ops for
921
+ # nodes touched recently) to bound write amplification on these hot read paths,
922
+ # and BEST-EFFORT — a bump failure must never fail the read. `table` is always a
923
+ # trusted literal (never user input).
924
+ _ACCESS_BUMP_THROTTLE = "6 hours"
925
+
926
+
927
+ async def _bump_last_accessed(conn, cur, table: str, ids: list[str]) -> None:
928
+ ids = [i for i in ids if i]
929
+ if not ids:
930
+ return
931
+ try:
932
+ await cur.execute(
933
+ f"UPDATE {table} SET last_accessed = NOW() "
934
+ f"WHERE id = ANY(%s) AND (last_accessed IS NULL "
935
+ f"OR last_accessed < NOW() - interval '{_ACCESS_BUMP_THROTTLE}')",
936
+ (ids,),
937
+ )
938
+ await conn.commit()
939
+ except Exception as e: # noqa: BLE001 — never let the access bump break a read
940
+ await conn.rollback()
941
+ log.warning("last_accessed bump failed on %s: %s", table, e)
942
+
943
+
916
944
  @app.post("/entities")
917
945
  async def list_entities(req: GraphQueryRequest):
918
946
  """Filter entities by arena + optional type + optional name pattern.
@@ -930,10 +958,10 @@ async def list_entities(req: GraphQueryRequest):
930
958
  params.extend([pattern, pattern])
931
959
  sql = f"""
932
960
  SELECT id, arena, entity_type, canonical_name, aliases,
933
- provenance_event_ids, attributes, last_seen
961
+ provenance_event_ids, attributes, salience, last_seen
934
962
  FROM entities
935
963
  WHERE {' AND '.join(conditions)}
936
- ORDER BY last_seen DESC
964
+ ORDER BY salience DESC, last_seen DESC
937
965
  LIMIT %s
938
966
  """
939
967
  params.append(req.limit)
@@ -941,6 +969,7 @@ async def list_entities(req: GraphQueryRequest):
941
969
  async with conn.cursor() as cur:
942
970
  await cur.execute(sql, params)
943
971
  rows = await cur.fetchall()
972
+ await _bump_last_accessed(conn, cur, "entities", [r["id"] for r in rows])
944
973
  return {"results": [dict(r) for r in rows]}
945
974
 
946
975
 
@@ -977,10 +1006,10 @@ async def list_facts(req: GraphQueryRequest):
977
1006
  SELECT f.id, f.arena, f.category, f.predicate, f.statement,
978
1007
  f.subject_entity_id, f.object_entity_id,
979
1008
  f.confidence, f.stage, f.asserted_at,
980
- f.provenance_event_ids
1009
+ f.salience, f.provenance_event_ids
981
1010
  FROM facts f
982
1011
  WHERE {' AND '.join(conditions)}
983
- ORDER BY f.asserted_at DESC
1012
+ ORDER BY f.salience DESC, f.asserted_at DESC
984
1013
  LIMIT %s
985
1014
  """
986
1015
  params.append(req.limit)
@@ -988,6 +1017,7 @@ async def list_facts(req: GraphQueryRequest):
988
1017
  async with conn.cursor() as cur:
989
1018
  await cur.execute(sql, params)
990
1019
  rows = await cur.fetchall()
1020
+ await _bump_last_accessed(conn, cur, "facts", [r["id"] for r in rows])
991
1021
  return {"results": [dict(r) for r in rows]}
992
1022
 
993
1023
 
@@ -1013,13 +1043,13 @@ async def list_relationships(req: GraphQueryRequest):
1013
1043
  r.from_entity_id, r.to_entity_id,
1014
1044
  ef.canonical_name AS from_name,
1015
1045
  et.canonical_name AS to_name,
1016
- r.first_seen, r.last_seen,
1046
+ r.first_seen, r.last_seen, r.salience,
1017
1047
  r.provenance_event_ids
1018
1048
  FROM relationships r
1019
1049
  JOIN entities ef ON ef.id = r.from_entity_id
1020
1050
  JOIN entities et ON et.id = r.to_entity_id
1021
1051
  WHERE {' AND '.join(conditions)}
1022
- ORDER BY r.last_seen DESC
1052
+ ORDER BY r.salience DESC, r.last_seen DESC
1023
1053
  LIMIT %s
1024
1054
  """
1025
1055
  params.append(req.limit)
@@ -1027,6 +1057,7 @@ async def list_relationships(req: GraphQueryRequest):
1027
1057
  async with conn.cursor() as cur:
1028
1058
  await cur.execute(sql, params)
1029
1059
  rows = await cur.fetchall()
1060
+ await _bump_last_accessed(conn, cur, "relationships", [r["id"] for r in rows])
1030
1061
  return {"results": [dict(r) for r in rows]}
1031
1062
 
1032
1063