@pentatonic-ai/ai-agent-sdk 0.9.5 → 0.10.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.
Files changed (131) hide show
  1. package/README.md +3 -3
  2. package/bin/cli.js +1 -1
  3. package/bin/commands/config.js +1 -1
  4. package/dist/index.cjs +39 -72
  5. package/dist/index.js +36 -69
  6. package/package.json +10 -3
  7. package/packages/doctor/src/checks/local-memory.js +2 -2
  8. package/packages/memory/README.md +2 -2
  9. package/packages/memory/openclaw-plugin/README.md +2 -2
  10. package/packages/memory/openclaw-plugin/openclaw.plugin.json +1 -1
  11. package/packages/memory/package-lock.json +49 -33
  12. package/packages/memory/package.json +4 -1
  13. package/packages/memory/src/__tests__/engine.test.js +40 -5
  14. package/packages/memory/src/engine.js +38 -3
  15. package/packages/memory/src/server.js +2 -2
  16. package/packages/memory-engine-v2/.env.example +30 -0
  17. package/packages/memory-engine-v2/README.md +125 -0
  18. package/packages/memory-engine-v2/compat/Dockerfile +11 -0
  19. package/packages/memory-engine-v2/compat/requirements.txt +6 -0
  20. package/packages/memory-engine-v2/compat/server.py +1047 -0
  21. package/packages/memory-engine-v2/docker-compose.aws.yml +78 -0
  22. package/packages/memory-engine-v2/docker-compose.yml +206 -0
  23. package/packages/memory-engine-v2/extractor-async/Dockerfile +14 -0
  24. package/packages/memory-engine-v2/extractor-async/confidence.py +62 -0
  25. package/packages/memory-engine-v2/extractor-async/noise_filter.py +144 -0
  26. package/packages/memory-engine-v2/extractor-async/requirements.txt +2 -0
  27. package/packages/memory-engine-v2/extractor-async/test_confidence.py +76 -0
  28. package/packages/memory-engine-v2/extractor-async/test_noise_filter.py +177 -0
  29. package/packages/memory-engine-v2/extractor-async/worker.py +797 -0
  30. package/packages/memory-engine-v2/extractor-sync/Dockerfile +11 -0
  31. package/packages/memory-engine-v2/extractor-sync/requirements.txt +4 -0
  32. package/packages/memory-engine-v2/extractor-sync/server.py +424 -0
  33. package/packages/memory-engine-v2/org-model/migrations/001_init.sql +390 -0
  34. package/packages/memory-engine-v2/tests/e2e_smoke.py +356 -0
  35. package/packages/memory-engine-v2/tests/fixtures/generate_synthetic_corpus.py +758 -0
  36. package/packages/memory-engine/.env.example +0 -13
  37. package/packages/memory-engine/MIGRATION.md +0 -219
  38. package/packages/memory-engine/README.md +0 -145
  39. package/packages/memory-engine/bench/README.md +0 -99
  40. package/packages/memory-engine/bench/scorecards-engine/agent-coding__pentatonic-baseline__20260427-142523.json +0 -1115
  41. package/packages/memory-engine/bench/scorecards-engine/chat-recall__pentatonic-baseline__20260427-142648.json +0 -819
  42. package/packages/memory-engine/bench/scorecards-engine/circular-economy__pentatonic-baseline__20260427-142757.json +0 -1278
  43. package/packages/memory-engine/bench/scorecards-engine/customer-support__pentatonic-baseline__20260427-142900.json +0 -1018
  44. package/packages/memory-engine/bench/scorecards-engine/marketplace-ops__pentatonic-baseline__20260427-142957.json +0 -1038
  45. package/packages/memory-engine/bench/scorecards-engine/product-catalogue__pentatonic-baseline__20260427-143122.json +0 -961
  46. package/packages/memory-engine/bench/scorecards-engine-via-docker/agent-coding__pentatonic-memory__20260427-161812.json +0 -1115
  47. package/packages/memory-engine/bench/scorecards-engine-via-docker/chat-recall__pentatonic-memory__20260427-161701.json +0 -819
  48. package/packages/memory-engine/bench/scorecards-engine-via-docker/circular-economy__pentatonic-memory__20260427-161713.json +0 -1278
  49. package/packages/memory-engine/bench/scorecards-engine-via-docker/customer-support__pentatonic-memory__20260427-161723.json +0 -1018
  50. package/packages/memory-engine/bench/scorecards-engine-via-docker/marketplace-ops__pentatonic-memory__20260427-161732.json +0 -1038
  51. package/packages/memory-engine/bench/scorecards-engine-via-docker/product-catalogue__pentatonic-memory__20260427-161741.json +0 -937
  52. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/agent-coding__pentatonic-memory__20260427-184718.json +0 -1115
  53. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/chat-recall__pentatonic-memory__20260427-184614.json +0 -819
  54. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/circular-economy__pentatonic-memory__20260427-184809.json +0 -1278
  55. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/customer-support__pentatonic-memory__20260427-184854.json +0 -1018
  56. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/marketplace-ops__pentatonic-memory__20260427-184929.json +0 -1038
  57. package/packages/memory-engine/bench/scorecards-engine-via-l2-7-layer-populated/product-catalogue__pentatonic-memory__20260427-185015.json +0 -961
  58. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/agent-coding__pentatonic-memory__20260427-175252.json +0 -1115
  59. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/chat-recall__pentatonic-memory__20260427-175312.json +0 -819
  60. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/circular-economy__pentatonic-memory__20260427-175335.json +0 -1278
  61. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/customer-support__pentatonic-memory__20260427-175355.json +0 -1018
  62. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/marketplace-ops__pentatonic-memory__20260427-175413.json +0 -1038
  63. package/packages/memory-engine/bench/scorecards-engine-via-l2-empty-layers/product-catalogue__pentatonic-memory__20260427-175430.json +0 -883
  64. package/packages/memory-engine/bench/scorecards-engine-via-shim/agent-coding__pentatonic-memory__20260427-155409.json +0 -1115
  65. package/packages/memory-engine/bench/scorecards-engine-via-shim/chat-recall__pentatonic-memory__20260427-155421.json +0 -819
  66. package/packages/memory-engine/bench/scorecards-engine-via-shim/circular-economy__pentatonic-memory__20260427-155433.json +0 -1278
  67. package/packages/memory-engine/bench/scorecards-engine-via-shim/customer-support__pentatonic-memory__20260427-155443.json +0 -1018
  68. package/packages/memory-engine/bench/scorecards-engine-via-shim/marketplace-ops__pentatonic-memory__20260427-155453.json +0 -1038
  69. package/packages/memory-engine/bench/scorecards-engine-via-shim/product-catalogue__pentatonic-memory__20260427-155503.json +0 -937
  70. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory-latest__20260427-145103.json +0 -1115
  71. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/agent-coding__pentatonic-memory__20260427-144909.json +0 -1115
  72. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory-latest__20260427-145153.json +0 -819
  73. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/chat-recall__pentatonic-memory__20260427-145120.json +0 -542
  74. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory-latest__20260427-145313.json +0 -1278
  75. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/circular-economy__pentatonic-memory__20260427-145207.json +0 -894
  76. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory-latest__20260427-145412.json +0 -1018
  77. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/customer-support__pentatonic-memory__20260427-145327.json +0 -680
  78. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory-latest__20260427-145517.json +0 -1038
  79. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/marketplace-ops__pentatonic-memory__20260427-145422.json +0 -693
  80. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory-latest__20260427-145616.json +0 -961
  81. package/packages/memory-engine/bench/scorecards-pentatonic-baseline/product-catalogue__pentatonic-memory__20260427-145528.json +0 -727
  82. package/packages/memory-engine/compat/Dockerfile +0 -22
  83. package/packages/memory-engine/compat/server.py +0 -1255
  84. package/packages/memory-engine/docker-compose.test.yml +0 -59
  85. package/packages/memory-engine/docker-compose.yml +0 -240
  86. package/packages/memory-engine/engine/README.md +0 -52
  87. package/packages/memory-engine/engine/l2-hybridrag-proxy.py +0 -1543
  88. package/packages/memory-engine/engine/l5-comms-layer.py +0 -663
  89. package/packages/memory-engine/engine/l6-document-store.py +0 -1018
  90. package/packages/memory-engine/engine/services/_shared/__init__.py +0 -1
  91. package/packages/memory-engine/engine/services/_shared/embed_provider.py +0 -468
  92. package/packages/memory-engine/engine/services/l2/Dockerfile +0 -50
  93. package/packages/memory-engine/engine/services/l2/init_databases.py +0 -81
  94. package/packages/memory-engine/engine/services/l2/l2-hybridrag-proxy.py +0 -2721
  95. package/packages/memory-engine/engine/services/l5/Dockerfile +0 -11
  96. package/packages/memory-engine/engine/services/l5/l5-comms-layer.py +0 -808
  97. package/packages/memory-engine/engine/services/l6/Dockerfile +0 -30
  98. package/packages/memory-engine/engine/services/l6/l6-document-store.py +0 -1221
  99. package/packages/memory-engine/engine/services/nv-embed/Dockerfile +0 -28
  100. package/packages/memory-engine/engine/services/nv-embed/server.py +0 -152
  101. package/packages/memory-engine/pme_memory/__init__.py +0 -0
  102. package/packages/memory-engine/pme_memory/__main__.py +0 -129
  103. package/packages/memory-engine/pme_memory/artifacts.py +0 -95
  104. package/packages/memory-engine/pme_memory/embed.py +0 -74
  105. package/packages/memory-engine/pme_memory/health.py +0 -36
  106. package/packages/memory-engine/pme_memory/hygiene.py +0 -159
  107. package/packages/memory-engine/pme_memory/indexer.py +0 -200
  108. package/packages/memory-engine/pme_memory/needs.py +0 -55
  109. package/packages/memory-engine/pme_memory/provenance.py +0 -80
  110. package/packages/memory-engine/pme_memory/scoring.py +0 -168
  111. package/packages/memory-engine/pme_memory/search.py +0 -52
  112. package/packages/memory-engine/pme_memory/store.py +0 -86
  113. package/packages/memory-engine/pme_memory/synthesis.py +0 -114
  114. package/packages/memory-engine/pyproject.toml +0 -65
  115. package/packages/memory-engine/scripts/kg-extractor.py +0 -557
  116. package/packages/memory-engine/scripts/kg-preflexor-v2.py +0 -738
  117. package/packages/memory-engine/scripts/wipe-legacy-l3-entities.py +0 -128
  118. package/packages/memory-engine/tests/e2e_arena.sh +0 -259
  119. package/packages/memory-engine/tests/embed_stub/Dockerfile +0 -13
  120. package/packages/memory-engine/tests/embed_stub/server.py +0 -80
  121. package/packages/memory-engine/tests/test_aggregate.py +0 -333
  122. package/packages/memory-engine/tests/test_api_contract.sh +0 -57
  123. package/packages/memory-engine/tests/test_arena_safety.py +0 -232
  124. package/packages/memory-engine/tests/test_channel_stat_reader.py +0 -437
  125. package/packages/memory-engine/tests/test_channel_stat_rollups.py +0 -308
  126. package/packages/memory-engine/tests/test_compat_nv_embed_probe.py +0 -48
  127. package/packages/memory-engine/tests/test_embed_provider.py +0 -492
  128. package/packages/memory-engine/tests/test_l2_qmd_vec_search.py +0 -280
  129. package/packages/memory-engine/tests/test_l3_arena_isolation.py +0 -412
  130. package/packages/memory-engine/tests/test_l6_module_load.py +0 -84
  131. package/packages/memory-engine/tests/test_people_list_reader.py +0 -432
package/README.md CHANGED
@@ -114,7 +114,7 @@ sudo systemctl restart ollama
114
114
 
115
115
  ```bash
116
116
  git clone https://github.com/Pentatonic-Ltd/ai-agent-sdk.git
117
- cd ai-agent-sdk/packages/memory-engine
117
+ cd ai-agent-sdk/packages/memory-engine-v2
118
118
 
119
119
  # Default .env points at Ollama on the host. Edit if your Ollama is
120
120
  # elsewhere or you want to use a higher-quality model (e.g. mxbai-embed-large
@@ -238,7 +238,7 @@ await adapter.init();
238
238
  await adapter.ingestChunk('User prefers dark mode', { kind: 'note' });
239
239
  ```
240
240
 
241
- For raw `/search` and `/store`, just `fetch()` against `${engineUrl}/search` etc. The wire format is documented in `packages/memory-engine/MIGRATION.md`.
241
+ For raw `/search` and `/store`, just `fetch()` against `${engineUrl}/search` etc. The wire format is documented in `packages/memory-engine-v2/MIGRATION.md`.
242
242
 
243
243
  ---
244
244
 
@@ -504,7 +504,7 @@ const { content, model, usage, toolCalls } = normalizeResponse(openaiResponse);
504
504
 
505
505
  Thin HTTP client for the memory engine. `config = { engineUrl, arena, apiKey? }`. Returns `{ ingestChunk(content, metadata), deleteByCorpusFile(repoAbs, relPath), init() }`. See [Use as a library](#use-as-a-library).
506
506
 
507
- For raw `/store` / `/search` calls, just `fetch()` against `${engineUrl}` directly — the wire format is documented in `packages/memory-engine/MIGRATION.md`.
507
+ For raw `/store` / `/search` calls, just `fetch()` against `${engineUrl}` directly — the wire format is documented in `packages/memory-engine-v2/MIGRATION.md`.
508
508
 
509
509
  ---
510
510
 
package/bin/cli.js CHANGED
@@ -78,7 +78,7 @@ function ask(question) {
78
78
  // in favour of:
79
79
  // - `tes config local` → writes the plugin config + prints engine
80
80
  // bring-up instructions
81
- // - `cd packages/memory-engine && docker compose up -d` → runs the
81
+ // - `cd packages/memory-engine-v2 && docker compose up -d` → runs the
82
82
  // actual engine
83
83
  // `ask` is kept for any future interactive prompts.
84
84
 
@@ -131,7 +131,7 @@ async function runConfigLocal(opts) {
131
131
  log("");
132
132
  log(" 2. Bring up the engine docker stack:");
133
133
  log("");
134
- log(" cd packages/memory-engine");
134
+ log(" cd packages/memory-engine-v2");
135
135
  log(" cp .env.example .env # if no .env yet");
136
136
  log(" # edit .env if you want a different embedding model/dim");
137
137
  log(" docker compose up -d --scale nv-embed=0");
package/dist/index.cjs CHANGED
@@ -17,8 +17,8 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/index.js
20
- var src_exports = {};
21
- __export(src_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  Session: () => Session,
23
23
  TESClient: () => TESClient,
24
24
  buildTrackUrl: () => buildTrackUrl,
@@ -27,7 +27,7 @@ __export(src_exports, {
27
27
  signPayload: () => signPayload,
28
28
  verifyPayload: () => verifyPayload
29
29
  });
30
- module.exports = __toCommonJS(src_exports);
30
+ module.exports = __toCommonJS(index_exports);
31
31
 
32
32
  // src/normalizer.js
33
33
  function normalizeResponse(raw) {
@@ -189,8 +189,7 @@ var encoder = new TextEncoder();
189
189
  function toBase64Url(buffer) {
190
190
  const bytes = new Uint8Array(buffer);
191
191
  let binary = "";
192
- for (let i = 0; i < bytes.length; i++)
193
- binary += String.fromCharCode(bytes[i]);
192
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
194
193
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
195
194
  }
196
195
  async function signPayload(secret, payload) {
@@ -211,27 +210,22 @@ async function verifyPayload(secret, payload, signature) {
211
210
  }
212
211
  async function buildTrackUrl(endpoint, apiKey, payload) {
213
212
  const p = { ...payload };
214
- if (!p.e)
215
- p.e = "LINK_CLICK";
213
+ if (!p.e) p.e = "LINK_CLICK";
216
214
  const encoded = toBase64Url(encoder.encode(JSON.stringify(p)));
217
215
  const sig = await signPayload(apiKey, p);
218
216
  return `${endpoint}/r/${encoded}?sig=${sig}`;
219
217
  }
220
218
  var URL_RE = /https?:\/\/[^\s"'<>)\]]+/g;
221
219
  async function rewriteUrls(text, config, sessionId, metadata) {
222
- if (!text)
223
- return text;
220
+ if (!text) return text;
224
221
  const redirectPrefix = `${config.endpoint}/r/`;
225
222
  const matches = [...text.matchAll(URL_RE)];
226
- if (matches.length === 0)
227
- return text;
223
+ if (matches.length === 0) return text;
228
224
  const replacements = /* @__PURE__ */ new Map();
229
225
  for (const m of matches) {
230
226
  const originalUrl = m[0];
231
- if (originalUrl.startsWith(redirectPrefix))
232
- continue;
233
- if (replacements.has(originalUrl))
234
- continue;
227
+ if (originalUrl.startsWith(redirectPrefix)) continue;
228
+ if (replacements.has(originalUrl)) continue;
235
229
  const payload = {
236
230
  u: originalUrl,
237
231
  s: sessionId,
@@ -254,10 +248,8 @@ async function rewriteUrls(text, config, sessionId, metadata) {
254
248
 
255
249
  // src/session.js
256
250
  function truncate(value, maxLen) {
257
- if (!value || !maxLen || typeof value !== "string")
258
- return value;
259
- if (value.length <= maxLen)
260
- return value;
251
+ if (!value || !maxLen || typeof value !== "string") return value;
252
+ if (value.length <= maxLen) return value;
261
253
  return value.slice(0, maxLen) + "...[truncated]";
262
254
  }
263
255
  var Session = class {
@@ -420,8 +412,7 @@ var Session = class {
420
412
  // packages/memory/src/inject.js
421
413
  var MAX_CHARS_PER_MEMORY = 1200;
422
414
  function injectMemories(body, memories, provider) {
423
- if (!memories || memories.length === 0)
424
- return body;
415
+ if (!memories || memories.length === 0) return body;
425
416
  const preamble = formatPreamble(memories);
426
417
  if (provider === "anthropic") {
427
418
  return injectAnthropic(body, preamble);
@@ -482,8 +473,7 @@ var DEFAULT_SEARCH_TIMEOUT_MS = 5e3;
482
473
  var DEFAULT_SEARCH_LIMIT = 6;
483
474
  var DEFAULT_SEARCH_MIN_SCORE = 0.55;
484
475
  function normalizeConfig(config) {
485
- if (!config)
486
- throw new Error("hosted: config is required");
476
+ if (!config) throw new Error("hosted: config is required");
487
477
  const endpoint = config.endpoint || config.tes_endpoint;
488
478
  const clientId = config.clientId || config.tes_client_id;
489
479
  const apiKey = config.apiKey || config.tes_api_key;
@@ -508,8 +498,7 @@ function buildHostedHeaders(config) {
508
498
  return headers;
509
499
  }
510
500
  async function hostedSearch(config, query, opts = {}) {
511
- if (!query)
512
- return { memories: [], skipped: "no_query" };
501
+ if (!query) return { memories: [], skipped: "no_query" };
513
502
  let cfg;
514
503
  try {
515
504
  cfg = normalizeConfig(config);
@@ -556,8 +545,7 @@ async function hostedSearch(config, query, opts = {}) {
556
545
  return { memories: payload.data?.semanticSearchMemories || [] };
557
546
  }
558
547
  function shortenReason(msg) {
559
- if (typeof msg !== "string")
560
- return "unknown";
548
+ if (typeof msg !== "string") return "unknown";
561
549
  return msg.toLowerCase().replace(/[^a-z0-9]+/g, "_").slice(0, 60);
562
550
  }
563
551
 
@@ -568,23 +556,19 @@ var MEMORY_DEFAULTS = {
568
556
  timeoutMs: 800
569
557
  };
570
558
  function detectClientType(client) {
571
- if (client?.chat?.completions?.create)
572
- return "openai";
573
- if (client?.messages?.create)
574
- return "anthropic";
575
- if (typeof client?.run === "function")
576
- return "workers-ai";
559
+ if (client?.chat?.completions?.create) return "openai";
560
+ if (client?.messages?.create) return "anthropic";
561
+ if (typeof client?.run === "function") return "workers-ai";
577
562
  return "unknown";
578
563
  }
579
564
  function extractLastUserMessage(params, provider) {
565
+ void provider;
580
566
  const msgs = Array.isArray(params?.messages) ? params.messages : null;
581
- if (!msgs)
582
- return null;
567
+ if (!msgs) return null;
583
568
  for (let i = msgs.length - 1; i >= 0; i--) {
584
569
  if (msgs[i].role === "user") {
585
570
  const c = msgs[i].content;
586
- if (typeof c === "string")
587
- return c;
571
+ if (typeof c === "string") return c;
588
572
  if (Array.isArray(c)) {
589
573
  return c.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("\n");
590
574
  }
@@ -634,8 +618,7 @@ function wrapClient(clientConfig, client, sessionOpts = {}) {
634
618
  metadata: sessionOpts.metadata
635
619
  });
636
620
  const type = detectClientType(client);
637
- if (type === "openai")
638
- return wrapOpenAI(clientConfig, client, sessionOpts);
621
+ if (type === "openai") return wrapOpenAI(clientConfig, client, sessionOpts);
639
622
  if (type === "anthropic")
640
623
  return wrapAnthropic(clientConfig, client, sessionOpts);
641
624
  if (type === "workers-ai")
@@ -649,10 +632,8 @@ function wrapOpenAI(clientConfig, client, sessionOpts) {
649
632
  get(target, prop) {
650
633
  if (prop === "chat")
651
634
  return wrapOpenAIChat(clientConfig, target.chat, target, sessionOpts);
652
- if (prop === "sessionId")
653
- return sessionOpts._resolvedSessionId;
654
- if (prop === "tesSession")
655
- return sessionOpts._session;
635
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
636
+ if (prop === "tesSession") return sessionOpts._session;
656
637
  if (prop === "session")
657
638
  return (opts) => new OpenAISession(clientConfig, target, opts);
658
639
  return target[prop];
@@ -729,10 +710,8 @@ function wrapAnthropic(clientConfig, client, sessionOpts) {
729
710
  target,
730
711
  sessionOpts
731
712
  );
732
- if (prop === "sessionId")
733
- return sessionOpts._resolvedSessionId;
734
- if (prop === "tesSession")
735
- return sessionOpts._session;
713
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
714
+ if (prop === "tesSession") return sessionOpts._session;
736
715
  if (prop === "session")
737
716
  return (opts) => new AnthropicSession(clientConfig, target, opts);
738
717
  return target[prop];
@@ -819,10 +798,8 @@ function wrapWorkersAI(clientConfig, aiBinding, sessionOpts) {
819
798
  return result;
820
799
  };
821
800
  }
822
- if (prop === "sessionId")
823
- return sessionOpts._resolvedSessionId;
824
- if (prop === "tesSession")
825
- return sessionOpts._session;
801
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
802
+ if (prop === "tesSession") return sessionOpts._session;
826
803
  if (prop === "session")
827
804
  return (opts) => new WorkersAISession(clientConfig, target, opts);
828
805
  return target[prop];
@@ -841,29 +818,24 @@ var WorkersAISession = class extends Session {
841
818
  }
842
819
  };
843
820
  function extractToolResults(session, messages) {
844
- if (!messages?.length || !session._toolCalls.length)
845
- return;
821
+ if (!messages?.length || !session._toolCalls.length) return;
846
822
  const idToName = /* @__PURE__ */ new Map();
847
823
  for (const msg of messages) {
848
824
  if (msg.role === "assistant" && msg.tool_calls) {
849
825
  for (const tc of msg.tool_calls) {
850
826
  const id = tc.id || tc.tool_call_id;
851
827
  const name = tc.function?.name || tc.name;
852
- if (id && name)
853
- idToName.set(id, name);
828
+ if (id && name) idToName.set(id, name);
854
829
  }
855
830
  }
856
831
  }
857
832
  for (const msg of messages) {
858
- if (msg.role !== "tool" || !msg.content)
859
- continue;
833
+ if (msg.role !== "tool" || !msg.content) continue;
860
834
  const callId = msg.tool_call_id;
861
835
  const toolName = callId ? idToName.get(callId) : null;
862
836
  for (const tc of session._toolCalls) {
863
- if (tc.result)
864
- continue;
865
- if (toolName && tc.tool !== toolName)
866
- continue;
837
+ if (tc.result) continue;
838
+ if (toolName && tc.tool !== toolName) continue;
867
839
  try {
868
840
  const parsed = JSON.parse(msg.content);
869
841
  if (Array.isArray(parsed)) {
@@ -906,7 +878,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
906
878
  }
907
879
 
908
880
  // src/telemetry.js
909
- var VERSION = "0.9.5";
881
+ var VERSION = "0.10.0";
910
882
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
911
883
  function machineId() {
912
884
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
@@ -917,11 +889,9 @@ function machineId() {
917
889
  return (hash >>> 0).toString(16).padStart(8, "0");
918
890
  }
919
891
  function emitTelemetry(mode) {
920
- if (typeof process !== "undefined" && process.env?.PENTATONIC_TELEMETRY === "0")
921
- return;
892
+ if (typeof process !== "undefined" && process.env?.PENTATONIC_TELEMETRY === "0") return;
922
893
  const f = globalThis.fetch;
923
- if (!f)
924
- return;
894
+ if (!f) return;
925
895
  f(TELEMETRY_URL, {
926
896
  method: "POST",
927
897
  headers: { "Content-Type": "application/json" },
@@ -941,12 +911,9 @@ function emitTelemetry(mode) {
941
911
  // src/client.js
942
912
  var TESClient = class {
943
913
  constructor({ clientId, apiKey, endpoint, headers, userId, captureContent = true, maxContentLength = 4096 }) {
944
- if (!clientId)
945
- throw new Error("clientId is required");
946
- if (!apiKey)
947
- throw new Error("apiKey is required");
948
- if (!endpoint)
949
- throw new Error("endpoint is required");
914
+ if (!clientId) throw new Error("clientId is required");
915
+ if (!apiKey) throw new Error("apiKey is required");
916
+ if (!endpoint) throw new Error("endpoint is required");
950
917
  const cleanEndpoint = endpoint.replace(/\/$/, "");
951
918
  const isLocalDev = /^http:\/\/localhost(:\d+)?(\/|$)/.test(cleanEndpoint) || /^http:\/\/127\.0\.0\.1(:\d+)?(\/|$)/.test(cleanEndpoint);
952
919
  if (!cleanEndpoint.startsWith("https://") && !isLocalDev) {
package/dist/index.js CHANGED
@@ -158,8 +158,7 @@ var encoder = new TextEncoder();
158
158
  function toBase64Url(buffer) {
159
159
  const bytes = new Uint8Array(buffer);
160
160
  let binary = "";
161
- for (let i = 0; i < bytes.length; i++)
162
- binary += String.fromCharCode(bytes[i]);
161
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
163
162
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
164
163
  }
165
164
  async function signPayload(secret, payload) {
@@ -180,27 +179,22 @@ async function verifyPayload(secret, payload, signature) {
180
179
  }
181
180
  async function buildTrackUrl(endpoint, apiKey, payload) {
182
181
  const p = { ...payload };
183
- if (!p.e)
184
- p.e = "LINK_CLICK";
182
+ if (!p.e) p.e = "LINK_CLICK";
185
183
  const encoded = toBase64Url(encoder.encode(JSON.stringify(p)));
186
184
  const sig = await signPayload(apiKey, p);
187
185
  return `${endpoint}/r/${encoded}?sig=${sig}`;
188
186
  }
189
187
  var URL_RE = /https?:\/\/[^\s"'<>)\]]+/g;
190
188
  async function rewriteUrls(text, config, sessionId, metadata) {
191
- if (!text)
192
- return text;
189
+ if (!text) return text;
193
190
  const redirectPrefix = `${config.endpoint}/r/`;
194
191
  const matches = [...text.matchAll(URL_RE)];
195
- if (matches.length === 0)
196
- return text;
192
+ if (matches.length === 0) return text;
197
193
  const replacements = /* @__PURE__ */ new Map();
198
194
  for (const m of matches) {
199
195
  const originalUrl = m[0];
200
- if (originalUrl.startsWith(redirectPrefix))
201
- continue;
202
- if (replacements.has(originalUrl))
203
- continue;
196
+ if (originalUrl.startsWith(redirectPrefix)) continue;
197
+ if (replacements.has(originalUrl)) continue;
204
198
  const payload = {
205
199
  u: originalUrl,
206
200
  s: sessionId,
@@ -223,10 +217,8 @@ async function rewriteUrls(text, config, sessionId, metadata) {
223
217
 
224
218
  // src/session.js
225
219
  function truncate(value, maxLen) {
226
- if (!value || !maxLen || typeof value !== "string")
227
- return value;
228
- if (value.length <= maxLen)
229
- return value;
220
+ if (!value || !maxLen || typeof value !== "string") return value;
221
+ if (value.length <= maxLen) return value;
230
222
  return value.slice(0, maxLen) + "...[truncated]";
231
223
  }
232
224
  var Session = class {
@@ -389,8 +381,7 @@ var Session = class {
389
381
  // packages/memory/src/inject.js
390
382
  var MAX_CHARS_PER_MEMORY = 1200;
391
383
  function injectMemories(body, memories, provider) {
392
- if (!memories || memories.length === 0)
393
- return body;
384
+ if (!memories || memories.length === 0) return body;
394
385
  const preamble = formatPreamble(memories);
395
386
  if (provider === "anthropic") {
396
387
  return injectAnthropic(body, preamble);
@@ -451,8 +442,7 @@ var DEFAULT_SEARCH_TIMEOUT_MS = 5e3;
451
442
  var DEFAULT_SEARCH_LIMIT = 6;
452
443
  var DEFAULT_SEARCH_MIN_SCORE = 0.55;
453
444
  function normalizeConfig(config) {
454
- if (!config)
455
- throw new Error("hosted: config is required");
445
+ if (!config) throw new Error("hosted: config is required");
456
446
  const endpoint = config.endpoint || config.tes_endpoint;
457
447
  const clientId = config.clientId || config.tes_client_id;
458
448
  const apiKey = config.apiKey || config.tes_api_key;
@@ -477,8 +467,7 @@ function buildHostedHeaders(config) {
477
467
  return headers;
478
468
  }
479
469
  async function hostedSearch(config, query, opts = {}) {
480
- if (!query)
481
- return { memories: [], skipped: "no_query" };
470
+ if (!query) return { memories: [], skipped: "no_query" };
482
471
  let cfg;
483
472
  try {
484
473
  cfg = normalizeConfig(config);
@@ -525,8 +514,7 @@ async function hostedSearch(config, query, opts = {}) {
525
514
  return { memories: payload.data?.semanticSearchMemories || [] };
526
515
  }
527
516
  function shortenReason(msg) {
528
- if (typeof msg !== "string")
529
- return "unknown";
517
+ if (typeof msg !== "string") return "unknown";
530
518
  return msg.toLowerCase().replace(/[^a-z0-9]+/g, "_").slice(0, 60);
531
519
  }
532
520
 
@@ -537,23 +525,19 @@ var MEMORY_DEFAULTS = {
537
525
  timeoutMs: 800
538
526
  };
539
527
  function detectClientType(client) {
540
- if (client?.chat?.completions?.create)
541
- return "openai";
542
- if (client?.messages?.create)
543
- return "anthropic";
544
- if (typeof client?.run === "function")
545
- return "workers-ai";
528
+ if (client?.chat?.completions?.create) return "openai";
529
+ if (client?.messages?.create) return "anthropic";
530
+ if (typeof client?.run === "function") return "workers-ai";
546
531
  return "unknown";
547
532
  }
548
533
  function extractLastUserMessage(params, provider) {
534
+ void provider;
549
535
  const msgs = Array.isArray(params?.messages) ? params.messages : null;
550
- if (!msgs)
551
- return null;
536
+ if (!msgs) return null;
552
537
  for (let i = msgs.length - 1; i >= 0; i--) {
553
538
  if (msgs[i].role === "user") {
554
539
  const c = msgs[i].content;
555
- if (typeof c === "string")
556
- return c;
540
+ if (typeof c === "string") return c;
557
541
  if (Array.isArray(c)) {
558
542
  return c.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("\n");
559
543
  }
@@ -603,8 +587,7 @@ function wrapClient(clientConfig, client, sessionOpts = {}) {
603
587
  metadata: sessionOpts.metadata
604
588
  });
605
589
  const type = detectClientType(client);
606
- if (type === "openai")
607
- return wrapOpenAI(clientConfig, client, sessionOpts);
590
+ if (type === "openai") return wrapOpenAI(clientConfig, client, sessionOpts);
608
591
  if (type === "anthropic")
609
592
  return wrapAnthropic(clientConfig, client, sessionOpts);
610
593
  if (type === "workers-ai")
@@ -618,10 +601,8 @@ function wrapOpenAI(clientConfig, client, sessionOpts) {
618
601
  get(target, prop) {
619
602
  if (prop === "chat")
620
603
  return wrapOpenAIChat(clientConfig, target.chat, target, sessionOpts);
621
- if (prop === "sessionId")
622
- return sessionOpts._resolvedSessionId;
623
- if (prop === "tesSession")
624
- return sessionOpts._session;
604
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
605
+ if (prop === "tesSession") return sessionOpts._session;
625
606
  if (prop === "session")
626
607
  return (opts) => new OpenAISession(clientConfig, target, opts);
627
608
  return target[prop];
@@ -698,10 +679,8 @@ function wrapAnthropic(clientConfig, client, sessionOpts) {
698
679
  target,
699
680
  sessionOpts
700
681
  );
701
- if (prop === "sessionId")
702
- return sessionOpts._resolvedSessionId;
703
- if (prop === "tesSession")
704
- return sessionOpts._session;
682
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
683
+ if (prop === "tesSession") return sessionOpts._session;
705
684
  if (prop === "session")
706
685
  return (opts) => new AnthropicSession(clientConfig, target, opts);
707
686
  return target[prop];
@@ -788,10 +767,8 @@ function wrapWorkersAI(clientConfig, aiBinding, sessionOpts) {
788
767
  return result;
789
768
  };
790
769
  }
791
- if (prop === "sessionId")
792
- return sessionOpts._resolvedSessionId;
793
- if (prop === "tesSession")
794
- return sessionOpts._session;
770
+ if (prop === "sessionId") return sessionOpts._resolvedSessionId;
771
+ if (prop === "tesSession") return sessionOpts._session;
795
772
  if (prop === "session")
796
773
  return (opts) => new WorkersAISession(clientConfig, target, opts);
797
774
  return target[prop];
@@ -810,29 +787,24 @@ var WorkersAISession = class extends Session {
810
787
  }
811
788
  };
812
789
  function extractToolResults(session, messages) {
813
- if (!messages?.length || !session._toolCalls.length)
814
- return;
790
+ if (!messages?.length || !session._toolCalls.length) return;
815
791
  const idToName = /* @__PURE__ */ new Map();
816
792
  for (const msg of messages) {
817
793
  if (msg.role === "assistant" && msg.tool_calls) {
818
794
  for (const tc of msg.tool_calls) {
819
795
  const id = tc.id || tc.tool_call_id;
820
796
  const name = tc.function?.name || tc.name;
821
- if (id && name)
822
- idToName.set(id, name);
797
+ if (id && name) idToName.set(id, name);
823
798
  }
824
799
  }
825
800
  }
826
801
  for (const msg of messages) {
827
- if (msg.role !== "tool" || !msg.content)
828
- continue;
802
+ if (msg.role !== "tool" || !msg.content) continue;
829
803
  const callId = msg.tool_call_id;
830
804
  const toolName = callId ? idToName.get(callId) : null;
831
805
  for (const tc of session._toolCalls) {
832
- if (tc.result)
833
- continue;
834
- if (toolName && tc.tool !== toolName)
835
- continue;
806
+ if (tc.result) continue;
807
+ if (toolName && tc.tool !== toolName) continue;
836
808
  try {
837
809
  const parsed = JSON.parse(msg.content);
838
810
  if (Array.isArray(parsed)) {
@@ -875,7 +847,7 @@ function fireAndForgetEmit(clientConfig, sessionOpts, messages, result, model) {
875
847
  }
876
848
 
877
849
  // src/telemetry.js
878
- var VERSION = "0.9.5";
850
+ var VERSION = "0.10.0";
879
851
  var TELEMETRY_URL = "https://sdk-telemetry.philip-134.workers.dev";
880
852
  function machineId() {
881
853
  const raw = typeof process !== "undefined" ? `${process.env?.USER || process.env?.USERNAME || "u"}:${process.platform || "x"}:${process.arch || "x"}` : "browser";
@@ -886,11 +858,9 @@ function machineId() {
886
858
  return (hash >>> 0).toString(16).padStart(8, "0");
887
859
  }
888
860
  function emitTelemetry(mode) {
889
- if (typeof process !== "undefined" && process.env?.PENTATONIC_TELEMETRY === "0")
890
- return;
861
+ if (typeof process !== "undefined" && process.env?.PENTATONIC_TELEMETRY === "0") return;
891
862
  const f = globalThis.fetch;
892
- if (!f)
893
- return;
863
+ if (!f) return;
894
864
  f(TELEMETRY_URL, {
895
865
  method: "POST",
896
866
  headers: { "Content-Type": "application/json" },
@@ -910,12 +880,9 @@ function emitTelemetry(mode) {
910
880
  // src/client.js
911
881
  var TESClient = class {
912
882
  constructor({ clientId, apiKey, endpoint, headers, userId, captureContent = true, maxContentLength = 4096 }) {
913
- if (!clientId)
914
- throw new Error("clientId is required");
915
- if (!apiKey)
916
- throw new Error("apiKey is required");
917
- if (!endpoint)
918
- throw new Error("endpoint is required");
883
+ if (!clientId) throw new Error("clientId is required");
884
+ if (!apiKey) throw new Error("apiKey is required");
885
+ if (!endpoint) throw new Error("endpoint is required");
919
886
  const cleanEndpoint = endpoint.replace(/\/$/, "");
920
887
  const isLocalDev = /^http:\/\/localhost(:\d+)?(\/|$)/.test(cleanEndpoint) || /^http:\/\/127\.0\.0\.1(:\d+)?(\/|$)/.test(cleanEndpoint);
921
888
  if (!cleanEndpoint.startsWith("https://") && !isLocalDev) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pentatonic-ai/ai-agent-sdk",
3
- "version": "0.9.5",
3
+ "version": "0.10.0",
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",
@@ -27,7 +27,7 @@
27
27
  "src",
28
28
  "bin",
29
29
  "packages/memory",
30
- "packages/memory-engine",
30
+ "packages/memory-engine-v2",
31
31
  "packages/doctor",
32
32
  "build.js",
33
33
  "README.md",
@@ -73,11 +73,18 @@
73
73
  "dependencies": {
74
74
  "@modelcontextprotocol/sdk": "^1.27.1",
75
75
  "@pentatonic-ai/ai-agent-sdk": "^0.4.0",
76
- "esbuild": "^0.20.0"
76
+ "esbuild": "^0.25.0"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@jest/globals": "^29.7.0",
80
80
  "jest": "^29.7.0",
81
81
  "pg": "^8.20.0"
82
+ },
83
+ "overrides": {
84
+ "path-to-regexp": "^8.4.0",
85
+ "ip-address": "^10.1.1",
86
+ "@hono/node-server": "^1.19.13",
87
+ "picomatch": "^4.0.4",
88
+ "esbuild": "^0.25.0"
82
89
  }
83
90
  }
@@ -2,7 +2,7 @@
2
2
  * Local memory engine checks.
3
3
  *
4
4
  * Targets the engine stack started by:
5
- * cd packages/memory-engine && docker compose up -d
5
+ * cd packages/memory-engine-v2 && docker compose up -d
6
6
  *
7
7
  * The engine exposes a compat HTTP shim on port 8099 (or whatever
8
8
  * memory_url is set to in the user's plugin config). All checks are
@@ -202,7 +202,7 @@ function checkEmbeddingPath() {
202
202
  }
203
203
  return {
204
204
  ok: false,
205
- msg: `nv_embed=${nv} — L4/L5/L6 indexing will fail. Check NV_EMBED_URL in packages/memory-engine/.env`,
205
+ msg: `nv_embed=${nv} — L4/L5/L6 indexing will fail. Check NV_EMBED_URL in packages/memory-engine-v2/.env`,
206
206
  detail: { nv_embed: nv },
207
207
  };
208
208
  } catch (err) {
@@ -4,11 +4,11 @@
4
4
  >
5
5
  > This package is the **legacy** single-process MCP server backed by
6
6
  > PostgreSQL + pgvector + Ollama. It's superseded by the **7-layer
7
- > memory engine** at [`packages/memory-engine/`](../memory-engine/),
7
+ > memory engine** at [`packages/memory-engine-v2/`](../memory-engine/),
8
8
  > which is what the top-level SDK README walks users into and what
9
9
  > TES production runs.
10
10
  >
11
- > | | This package (legacy) | `packages/memory-engine/` (current) |
11
+ > | | This package (legacy) | `packages/memory-engine-v2/` (current) |
12
12
  > |---|---|---|
13
13
  > | Wire | MCP over stdio | HTTP (`/store`, `/search`, ...) |
14
14
  > | Storage | One Postgres table, one embedding | 7 layers fused via RRF |
@@ -7,7 +7,7 @@ Persistent, searchable memory for OpenClaw. Local (Docker + Ollama) or hosted (P
7
7
  > The `database_url` / `embedding_url` / `llm_url` config fields shown
8
8
  > in this README configure the **legacy** `packages/memory/` Postgres+
9
9
  > Ollama+pgvector MCP server, which is being retired in favour of the
10
- > 7-layer memory engine at `packages/memory-engine/`. Both backends
10
+ > 7-layer memory engine at `packages/memory-engine-v2/`. Both backends
11
11
  > still work; the legacy one will be removed in v1.0.
12
12
  >
13
13
  > **For new installs, prefer:**
@@ -23,7 +23,7 @@ Persistent, searchable memory for OpenClaw. Local (Docker + Ollama) or hosted (P
23
23
  > ```
24
24
  >
25
25
  > …with the engine brought up via `docker compose up -d` from
26
- > `packages/memory-engine/`. See the
26
+ > `packages/memory-engine-v2/`. See the
27
27
  > [top-level SDK README](../../../README.md#local-self-hosted) for the
28
28
  > walkthrough.
29
29
 
@@ -17,7 +17,7 @@
17
17
  "memory_url": {
18
18
  "type": "string",
19
19
  "default": "http://localhost:8099",
20
- "description": "Memory engine HTTP URL (local mode). Default 8099 = packages/memory-engine compat shim. (3333 was the legacy single-process MCP server port — deprecated.)"
20
+ "description": "Memory engine HTTP URL (local mode). Default 8099 = packages/memory-engine-v2 compat shim. (3333 was the legacy single-process MCP server port — deprecated.)"
21
21
  },
22
22
  "database_url": {
23
23
  "type": "string",