@anuma/sdk 6.38.0 → 6.39.1

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.
@@ -20430,15 +20430,17 @@ Build ONLY when the user gives an explicit instruction to build, create, generat
20430
20430
 
20431
20431
  Once the user HAS given an explicit build instruction, you are in App Builder mode: you produce polished, production-quality React apps that feel designed \u2014 not generic.
20432
20432
 
20433
- DESIGN: on the initial build, before writing code, briefly state (2-3 sentences) what you want this app to feel like \u2014 name the specific fonts, the palette in hex, and one signature detail. Be concrete: "Fraunces display + Inter body + JetBrains Mono metadata, terracotta #b75432 accent on bone #f3efe6, paper-grain texture via inline SVG noise" is the kind of specificity that anchors the build. Default to nothing: don't pick "safe modern productivity" unless the brief literally asks for utilitarian. On later turns, state a design brief only when the change is visual (a restyle, new theme, or new UI); for a logic, data, or behavior-only change, skip the brief and just make the change.
20433
+ DESIGN: on the initial build, before writing code, briefly state (2-3 sentences) what you want this app to feel like \u2014 name the specific fonts, the palette in hex, and one signature detail. Be concrete: "Fraunces display + Inter body + JetBrains Mono metadata, terracotta #b75432 accent on bone #f3efe6, paper-grain texture via inline SVG noise" is the kind of specificity that anchors the build. Default to nothing: don't pick "safe modern productivity" unless the brief literally asks for utilitarian. On later turns, state a design brief only when the change is visual (a restyle, new theme, or new UI); for a text, logic, data, or behavior-only change, skip the brief and just make the change.
20434
+
20435
+ EDIT SCOPE: Change only the files and lines required by the current user request. A title rename is a text edit, not a design change. Preserve styles, dependencies, and unrelated logic on text edits. Design feedback does not authorize unrelated edits.
20434
20436
 
20435
20437
  WORKFLOW:
20436
20438
  1. NEVER output code as text or markdown. ALWAYS use tools.
20437
20439
  2. Initial build: state your design brief, then create_file with a "files" array writing ALL files in one call. The preview renders automatically.
20438
20440
  3. patch_file requires read_file for that path earlier in the conversation (or create_file in the same conversation, which counts). read_file output is numbered "42: <text>" \u2014 the prefix is display-only; never copy it into "find". Each "find" must match exactly one location \u2014 include 2-3 lines of surrounding context. Pass multiple patches per call to change distinct locations.
20439
20441
  4. Prefer patch_file for changes to existing files \u2014 surgical, reviewable, preserves surrounding code. Reserve create_file overwrites for substantial restructuring. Inserts: find the line before, replace with that line + the new line. Deletes: empty replace.
20440
- 5. After substantial changes, call critique_design first (taste, hierarchy, distinctiveness, weakest decision) and then audit_design (mechanical: tokens, focus states, aria-labels, alt, heading order). Patch what each surfaces. critique catches taste issues no checklist would; audit catches mechanics you'd miss. Run both; act on both.
20441
- 6. Before declaring done, call verify_app. The host's preview runtime reports whether your app actually mounted and surfaces any errors it captured \u2014 hallucinated imports, syntax the bundler rejected, undefined components, runtime crashes. If \`rendered\` is false or \`errors\` is non-empty, fix every error before the next message. If the response includes a \`note\` that verify_app isn't wired in this host, skip \u2014 audit + critique are your feedback in that case.
20442
+ 5. On the initial build, when adding new UI, or after user-requested design changes, call critique_design first and then audit_design. Critique checks taste, hierarchy, and distinctiveness. Audit checks tokens, focus states, aria-labels, alt text, and heading order. Patch only issues within the current user request. For text, logic, or data edits, skip both design tools.
20443
+ 6. Before declaring done, call verify_app. The host's preview runtime reports whether your app actually mounted and surfaces any errors it captured \u2014 hallucinated imports, syntax the bundler rejected, undefined components, runtime crashes. If \`rendered\` is false or \`errors\` is non-empty, fix every error before the next message. If the response includes a \`note\` that verify_app isn't wired in this host, skip runtime verification. An unavailable runtime verifier does not authorize design changes. Use audit_design and critique_design only for the initial build, adding new UI, or user-requested design changes.
20442
20444
  7. Keep responses to a sentence or two. Exception: when responding to critique_design, write a substantive paragraph per rubric question.
20443
20445
 
20444
20446
  STRUCTURE:
@@ -20584,12 +20586,13 @@ function isCacheExpired(cache, expirationMs = DEFAULT_CACHE_EXPIRATION_MS) {
20584
20586
  if (!cache) return true;
20585
20587
  return Date.now() - cache.timestamp > expirationMs;
20586
20588
  }
20587
- function buildCacheEntry(tools, checksum) {
20589
+ function buildCacheEntry(tools, checksum, etag) {
20588
20590
  return {
20589
20591
  tools,
20590
20592
  timestamp: Date.now(),
20591
20593
  version: CACHE_VERSION,
20592
- ...checksum && { checksum }
20594
+ ...checksum && { checksum },
20595
+ ...etag && { etag }
20593
20596
  };
20594
20597
  }
20595
20598
  function writeLocalStorageCache(entry) {
@@ -20624,19 +20627,36 @@ function shouldRefreshTools(responseChecksum, cache = localStorageToolsCache) {
20624
20627
  const cachedChecksum = getToolsChecksum(cache);
20625
20628
  return cachedChecksum instanceof Promise ? cachedChecksum.then(decide) : decide(cachedChecksum);
20626
20629
  }
20627
- async function fetchServerToolsFromApi(baseUrl, token) {
20628
- const response = await fetch(`${baseUrl}/api/v1/tools`, {
20630
+ async function fetchServerToolsFromApi(baseUrl, authHeaders, etag) {
20631
+ const request = (validator) => fetch(`${baseUrl}/api/v1/tools`, {
20629
20632
  method: "GET",
20630
20633
  headers: {
20631
- Authorization: `Bearer ${token}`,
20632
- "Content-Type": "application/json"
20634
+ ...authHeaders,
20635
+ "Content-Type": "application/json",
20636
+ ...validator && { "If-None-Match": validator }
20633
20637
  }
20634
20638
  });
20639
+ let response;
20640
+ try {
20641
+ response = await request(etag);
20642
+ } catch (error) {
20643
+ if (!etag || !(error instanceof TypeError)) throw error;
20644
+ etag = void 0;
20645
+ response = await request();
20646
+ }
20647
+ if (etag && response.status === 304) {
20648
+ return { notModified: true };
20649
+ }
20635
20650
  if (!response.ok) {
20636
20651
  throw new Error(`Failed to fetch server tools: ${response.status}`);
20637
20652
  }
20638
20653
  const data = await response.json();
20639
- return convertServerToolsResponse(data);
20654
+ const responseEtag = response.headers?.get("ETag") ?? void 0;
20655
+ return {
20656
+ notModified: false,
20657
+ ...convertServerToolsResponse(data),
20658
+ ...responseEtag && { etag: responseEtag }
20659
+ };
20640
20660
  }
20641
20661
  async function getServerTools(options) {
20642
20662
  const {
@@ -20668,34 +20688,30 @@ async function getServerTools(options) {
20668
20688
  try {
20669
20689
  const { BASE_URL: BASE_URL2 } = await Promise.resolve().then(() => (init_clientConfig(), clientConfig_exports));
20670
20690
  const effectiveBaseUrl = baseUrl ?? BASE_URL2;
20691
+ const validator = cached && !forceRefresh ? cached.etag : void 0;
20692
+ let authHeaders;
20671
20693
  if (apiKey) {
20672
- const response = await fetch(`${effectiveBaseUrl}/api/v1/tools`, {
20673
- method: "GET",
20674
- headers: {
20675
- "X-API-Key": apiKey,
20676
- "Content-Type": "application/json"
20677
- }
20678
- });
20679
- if (!response.ok) {
20680
- throw new Error(`Failed to fetch server tools: ${response.status}`);
20694
+ authHeaders = { "X-API-Key": apiKey };
20695
+ } else {
20696
+ if (!getToken) {
20697
+ getLogger().warn("[serverTools] No auth method available for fetching tools");
20698
+ return cached?.tools ?? [];
20681
20699
  }
20682
- const data = await response.json();
20683
- const { tools: tools2, checksum: checksum2 } = convertServerToolsResponse(data);
20684
- await persistCache(buildCacheEntry(tools2, checksum2));
20685
- return tools2;
20686
- }
20687
- if (!getToken) {
20688
- getLogger().warn("[serverTools] No auth method available for fetching tools");
20689
- return cached?.tools ?? [];
20700
+ const token = await getToken();
20701
+ if (!token) {
20702
+ getLogger().warn("[serverTools] No auth token available for fetching tools");
20703
+ return cached?.tools ?? [];
20704
+ }
20705
+ authHeaders = { Authorization: `Bearer ${token}` };
20690
20706
  }
20691
- const token = await getToken();
20692
- if (!token) {
20693
- getLogger().warn("[serverTools] No auth token available for fetching tools");
20694
- return cached?.tools ?? [];
20707
+ const result = await fetchServerToolsFromApi(effectiveBaseUrl, authHeaders, validator);
20708
+ if (result.notModified) {
20709
+ const confirmed = cached;
20710
+ await persistCache({ ...confirmed, timestamp: Date.now() });
20711
+ return confirmed.tools;
20695
20712
  }
20696
- const { tools, checksum } = await fetchServerToolsFromApi(effectiveBaseUrl, token);
20697
- await persistCache(buildCacheEntry(tools, checksum));
20698
- return tools;
20713
+ await persistCache(buildCacheEntry(result.tools, result.checksum, result.etag));
20714
+ return result.tools;
20699
20715
  } catch (error) {
20700
20716
  getLogger().error("[serverTools] Failed to fetch server tools:", error);
20701
20717
  if (cached?.tools) {
@@ -33957,7 +33973,6 @@ async function recall(query, ctx, options = {}) {
33957
33973
  }
33958
33974
  const needsChunkEmbedding = types.includes("chunk") && ctx.storageCtx;
33959
33975
  const wantsTemporal = types.includes("fact") && (ctx.factSource || ctx.vaultCtx);
33960
- const graphRefiner = flags.traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
33961
33976
  const queryEmbedTotalTimeoutMs = options.queryEmbedTotalTimeoutMs ?? DEFAULT_QUERY_EMBED_TOTAL_TIMEOUT_MS;
33962
33977
  const prepStart = nowMs2();
33963
33978
  let sharedEmbedMs = 0;
@@ -33986,13 +34001,12 @@ async function recall(query, ctx, options = {}) {
33986
34001
  safeLane(
33987
34002
  "graph",
33988
34003
  () => graphLaneFailed = true,
33989
- () => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(query, ctx, flags.traverse, {
33990
- ...options.maxHops !== void 0 && { maxHops: options.maxHops },
33991
- ...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
33992
- ...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
33993
- ...options.rrfK !== void 0 && { rrfK: options.rrfK },
33994
- ...graphRefiner && { refineNeighbors: graphRefiner }
33995
- })
34004
+ () => ctx.factSource ? ctx.factSource.graphRanking(query, flags.traverse, options) : buildGraphLaneRanking(
34005
+ query,
34006
+ ctx,
34007
+ flags.traverse,
34008
+ graphTraversalOptions(options, flags.traverse)
34009
+ )
33996
34010
  ),
33997
34011
  wantsTemporal ? safeLane(
33998
34012
  "temporal",
@@ -34211,6 +34225,16 @@ function toFactMemory(r, now) {
34211
34225
  updatedAt: r.updatedAt ?? /* @__PURE__ */ new Date(0)
34212
34226
  };
34213
34227
  }
34228
+ function graphTraversalOptions(options, traverse) {
34229
+ const refineNeighbors = traverse && options.graphRefine && options.decomposeOptions ? createLlmNeighborRefiner(options.decomposeOptions) : void 0;
34230
+ return {
34231
+ ...options.maxHops !== void 0 && { maxHops: options.maxHops },
34232
+ ...options.entityFanout !== void 0 && { entityFanout: options.entityFanout },
34233
+ ...options.nodeBudget !== void 0 && { nodeBudget: options.nodeBudget },
34234
+ ...options.rrfK !== void 0 && { rrfK: options.rrfK },
34235
+ ...refineNeighbors && { refineNeighbors }
34236
+ };
34237
+ }
34214
34238
  async function buildGraphLaneRanking(query, ctx, traverse = false, traversalOptions = {}) {
34215
34239
  const entityCtx = ctx.entityCtx ?? ctx.vaultCtx?.entityCtx;
34216
34240
  if (!entityCtx) return [];
@@ -34376,24 +34400,33 @@ function isDumpQuery(query) {
34376
34400
  return false;
34377
34401
  }
34378
34402
  async function listRecentFacts(ctx, limit, toolOptions) {
34403
+ const store = toolOptions?.memoryStore;
34379
34404
  const vaultCtx = ctx.vaultCtx;
34380
- if (!vaultCtx) return [];
34381
- const ordered = await getVaultRankingProjectionsOp(vaultCtx, {
34405
+ if (!vaultCtx && !store) return [];
34406
+ const read = (ids) => store ? store.list({ memoryIds: ids }) : getVaultMemoriesByIdsOp(vaultCtx, ids);
34407
+ const filters = {
34382
34408
  ...toolOptions?.scopes && { scopes: toolOptions.scopes },
34383
- ...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds },
34409
+ ...toolOptions?.memoryIds !== void 0 && { memoryIds: toolOptions.memoryIds }
34410
+ };
34411
+ const project = (size) => store ? store.listProjections({ ...filters, limit: size }) : getVaultRankingProjectionsOp(vaultCtx, {
34412
+ ...filters,
34384
34413
  ...toolOptions?.folderId !== void 0 && { folderId: toolOptions.folderId }
34385
34414
  });
34386
34415
  const readable = [];
34387
- for (let i = 0; i < ordered.length && readable.length < limit; i += limit) {
34388
- const batch = ordered.slice(i, i + limit).map((p) => p.uniqueId);
34389
- const byId = new Map(
34390
- (await getVaultMemoriesByIdsOp(vaultCtx, batch)).map((m) => [m.uniqueId, m])
34391
- );
34392
- for (const id of batch) {
34393
- const m = byId.get(id);
34394
- if (m && !isEncrypted(m.content)) readable.push(m);
34395
- if (readable.length >= limit) break;
34416
+ let start = 0;
34417
+ for (let size = limit; readable.length < limit; size *= 2) {
34418
+ const ordered = await project(size);
34419
+ for (let i = start; i < ordered.length && readable.length < limit; i += limit) {
34420
+ const batch = ordered.slice(i, i + limit).map((p) => p.uniqueId);
34421
+ const byId = new Map((await read(batch)).map((m) => [m.uniqueId, m]));
34422
+ for (const id of batch) {
34423
+ const m = byId.get(id);
34424
+ if (m && !isEncrypted(m.content)) readable.push(m);
34425
+ if (readable.length >= limit) break;
34426
+ }
34396
34427
  }
34428
+ if (!store || ordered.length < size) break;
34429
+ start = ordered.length;
34397
34430
  }
34398
34431
  return readable.map((m) => ({
34399
34432
  id: m.uniqueId,
@@ -34410,6 +34443,8 @@ async function listRecentFacts(ctx, limit, toolOptions) {
34410
34443
  }));
34411
34444
  }
34412
34445
  function createRecallTool(ctx, toolOptions, callbacks) {
34446
+ if (toolOptions?.memoryStore && toolOptions.folderId !== void 0)
34447
+ throw new Error("Folders are not supported with a memoryStore");
34413
34448
  const defaultTypes = toolOptions?.types ?? ["fact", "chunk"];
34414
34449
  const defaultLimit = toolOptions?.limit ?? DEFAULT_LIMIT2;
34415
34450
  const defaultBudget = toolOptions?.budget ?? DEFAULT_BUDGET2;
@@ -34481,7 +34516,7 @@ function createRecallTool(ctx, toolOptions, callbacks) {
34481
34516
  let surfaced = 0;
34482
34517
  try {
34483
34518
  let recallDegraded = [];
34484
- const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && ctx.vaultCtx !== void 0;
34519
+ const wantsRecent = args.sort === "recent" && defaultTypes.includes("fact") && (ctx.vaultCtx !== void 0 || toolOptions?.memoryStore !== void 0);
34485
34520
  let result;
34486
34521
  if (wantsRecent) {
34487
34522
  result = { memories: await listRecentFacts(ctx, effectiveLimit, toolOptions) };
@@ -34991,6 +35026,7 @@ function createLocalMemoryStore(options) {
34991
35026
  });
34992
35027
  };
34993
35028
  return {
35029
+ masksEmbeddingInput: options.embeddingOptions.maskInput !== void 0,
34994
35030
  list: (listOptions) => getAllVaultMemoriesOp(vaultCtx, listOptions),
34995
35031
  get: (id) => getVaultMemoryOp(vaultCtx, id),
34996
35032
  listArchived: async () => {
@@ -35072,6 +35108,22 @@ function createLocalMemoryStore(options) {
35072
35108
  { vaultCtx, embeddingOptions: options.embeddingOptions, vaultCache },
35073
35109
  retainOptions
35074
35110
  ),
35111
+ factSource: {
35112
+ search: (query, searchOptions) => searchVaultMemoriesWithSize(
35113
+ query,
35114
+ vaultCtx,
35115
+ options.embeddingOptions,
35116
+ vaultCache,
35117
+ searchOptions
35118
+ ),
35119
+ graphRanking: (query, traverse, recallOptions) => buildGraphLaneRanking(
35120
+ query,
35121
+ { vaultCtx, entityCtx, embeddingOptions: options.embeddingOptions },
35122
+ traverse,
35123
+ graphTraversalOptions(recallOptions, traverse)
35124
+ ),
35125
+ temporalRanking: (query, now) => buildTemporalLaneRanking(query, vaultCtx, now)
35126
+ },
35075
35127
  subscribe: (onChange, subscribeOptions) => {
35076
35128
  const afterFirst = () => {
35077
35129
  let first = true;
@@ -36767,19 +36819,20 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
36767
36819
  const budget = wantsDecompose ? "high" : searchOptions?.rerank ? "mid" : "low";
36768
36820
  const folderId = searchOptions?.folderId ?? argFolderId;
36769
36821
  if (searchOptions?.useFusion === false) {
36770
- const { results: legacy, embeddingsUnavailable } = await searchVaultMemoriesWithSize(
36822
+ const legacyOptions = {
36823
+ limit: requestLimit,
36824
+ minSimilarity,
36825
+ useFusion: false,
36826
+ ...tuningForward,
36827
+ ...folderId !== void 0 && { folderId },
36828
+ ...searchOptions?.scopes && { scopes: searchOptions.scopes }
36829
+ };
36830
+ const { results: legacy, embeddingsUnavailable } = "retain" in vaultCtx ? await vaultCtx.factSource.search(query, legacyOptions) : await searchVaultMemoriesWithSize(
36771
36831
  query,
36772
36832
  vaultCtx,
36773
36833
  embeddingOptions,
36774
36834
  cache,
36775
- {
36776
- limit: requestLimit,
36777
- minSimilarity,
36778
- useFusion: false,
36779
- ...tuningForward,
36780
- ...folderId !== void 0 && { folderId },
36781
- ...searchOptions?.scopes && { scopes: searchOptions.scopes }
36782
- }
36835
+ legacyOptions
36783
36836
  );
36784
36837
  if (legacy.length === 0) {
36785
36838
  return embeddingsUnavailable ? EMBEDDINGS_DEGRADED_EMPTY_NO_LEXICAL : "No relevant memories found in the vault.";
@@ -36798,7 +36851,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
36798
36851
  let recallDegraded = [];
36799
36852
  const result = await recall(
36800
36853
  query,
36801
- { vaultCtx, embeddingOptions, vaultCache: cache },
36854
+ "retain" in vaultCtx ? { factSource: vaultCtx.factSource, embeddingOptions } : { vaultCtx, embeddingOptions, vaultCache: cache },
36802
36855
  {
36803
36856
  onDiagnostics: (d) => {
36804
36857
  recallDegraded = d.degraded;
@@ -36878,8 +36931,10 @@ function describeWriteOutcome(outcome) {
36878
36931
  }
36879
36932
  }
36880
36933
  function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
36934
+ const store = "retain" in vaultCtx ? vaultCtx : void 0;
36935
+ const ctx = "retain" in vaultCtx ? void 0 : vaultCtx;
36881
36936
  const hasOnSave = !!options?.onSave;
36882
- const folderNames = options?.folderMap ? Array.from(options.folderMap.keys()) : [];
36937
+ const folderNames = !store && options?.folderMap ? Array.from(options.folderMap.keys()) : [];
36883
36938
  return {
36884
36939
  type: "function",
36885
36940
  function: {
@@ -36924,7 +36979,7 @@ function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
36924
36979
  let previousContent;
36925
36980
  const scope = options?.scope ?? "private";
36926
36981
  if (isUpdate) {
36927
- const existing = await getVaultMemoryOp(vaultCtx, id);
36982
+ const existing = store ? await store.get(id) : await getVaultMemoryOp(ctx, id);
36928
36983
  if (!existing) {
36929
36984
  return `Error: Memory with ID "${id}" not found. Creating a new memory instead would require a separate call without an ID.`;
36930
36985
  }
@@ -36945,9 +37000,18 @@ function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
36945
37000
  return isUpdate ? `Memory update was cancelled by the user. The memory "${id}" was not modified.` : "Memory save was cancelled by the user. No memory was created.";
36946
37001
  }
36947
37002
  }
36948
- if (isUpdate) {
37003
+ if (isUpdate && store) {
37004
+ const updated = await store.update(id, {
37005
+ content,
37006
+ ...factType !== void 0 && { factType }
37007
+ });
37008
+ if (!updated) {
37009
+ return `Error: Failed to update memory "${id}".`;
37010
+ }
37011
+ return `Memory updated successfully (ID: ${updated.uniqueId}).`;
37012
+ } else if (isUpdate) {
36949
37013
  const folderId = folderName ? options?.folderMap?.get(folderName) : void 0;
36950
- const updated = await updateVaultMemoryOp(vaultCtx, id, {
37014
+ const updated = await updateVaultMemoryOp(ctx, id, {
36951
37015
  content,
36952
37016
  embedding: null,
36953
37017
  folderId,
@@ -36962,7 +37026,7 @@ function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
36962
37026
  content,
36963
37027
  embeddingOptions,
36964
37028
  cache,
36965
- vaultCtx,
37029
+ ctx,
36966
37030
  id,
36967
37031
  updated.updatedAt
36968
37032
  ).catch(() => {
@@ -36982,18 +37046,22 @@ function createMemoryVaultTool(vaultCtx, options, embeddingOptions, cache) {
36982
37046
  await notifyWritten(options, input, outcome);
36983
37047
  return describeWriteOutcome(outcome);
36984
37048
  }
36985
- const created = await createVaultMemoryOp(vaultCtx, {
37049
+ const created = store ? await store.create({
37050
+ content,
37051
+ scope,
37052
+ ...factType !== void 0 && { factType }
37053
+ }) : await createVaultMemoryOp(ctx, {
36986
37054
  content,
36987
37055
  scope,
36988
37056
  folderId,
36989
37057
  ...factType !== void 0 && { factType }
36990
37058
  });
36991
- if (embeddingOptions && cache) {
37059
+ if (ctx && embeddingOptions && cache) {
36992
37060
  eagerEmbedContent(
36993
37061
  content,
36994
37062
  embeddingOptions,
36995
37063
  cache,
36996
- vaultCtx,
37064
+ ctx,
36997
37065
  created.uniqueId,
36998
37066
  created.updatedAt
36999
37067
  ).catch(() => {