@agentmemory/agentmemory 0.8.1 → 0.8.6

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.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { getContext, init } from "iii-sdk";
3
3
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
- import { dirname, join, resolve } from "node:path";
4
+ import { dirname, join, resolve, sep } from "node:path";
5
5
  import { homedir } from "node:os";
6
6
  import Anthropic from "@anthropic-ai/sdk";
7
7
  import { createHash, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
@@ -902,7 +902,8 @@ const KV = {
902
902
  graphEdgeHistory: "mem:graph:edge-history",
903
903
  enrichedChunks: (sessionId) => `mem:enriched:${sessionId}`,
904
904
  latentEmbeddings: (obsId) => `mem:latent:${obsId}`,
905
- retentionScores: "mem:retention"
905
+ retentionScores: "mem:retention",
906
+ accessLog: "mem:access"
906
907
  };
907
908
  const STREAM = {
908
909
  name: "mem-live",
@@ -1951,9 +1952,11 @@ var IndexPersistence = class {
1951
1952
  const PRIVATE_TAG_RE = /<private>[\s\S]*?<\/private>/gi;
1952
1953
  const SECRET_PATTERN_SOURCES = [
1953
1954
  /(?:api[_-]?key|secret|token|password|credential|auth)[\s]*[=:]\s*["']?[A-Za-z0-9_\-/.+]{20,}["']?/gi,
1954
- /(?:sk|pk|rk|ak)-[A-Za-z0-9]{20,}/g,
1955
+ /Bearer\s+[A-Za-z0-9._\-+/=]{20,}/gi,
1956
+ /sk-proj-[A-Za-z0-9\-_]{20,}/g,
1957
+ /(?:sk|pk|rk|ak)-[A-Za-z0-9][A-Za-z0-9\-_]{19,}/g,
1955
1958
  /sk-ant-[A-Za-z0-9\-_]{20,}/g,
1956
- /ghp_[A-Za-z0-9]{36}/g,
1959
+ /gh[pus]_[A-Za-z0-9]{36,}/g,
1957
1960
  /github_pat_[A-Za-z0-9_]{22,}/g,
1958
1961
  /xoxb-[A-Za-z0-9\-]+/g,
1959
1962
  /AKIA[0-9A-Z]{16}/g,
@@ -2154,6 +2157,77 @@ function getXmlChildren(xml, parentTag, childTag) {
2154
2157
  return items;
2155
2158
  }
2156
2159
 
2160
+ //#endregion
2161
+ //#region src/functions/access-tracker.ts
2162
+ const RECENT_CAP = 20;
2163
+ function emptyAccessLog(memoryId) {
2164
+ return {
2165
+ memoryId,
2166
+ count: 0,
2167
+ lastAt: "",
2168
+ recent: []
2169
+ };
2170
+ }
2171
+ function normalizeAccessLog(raw) {
2172
+ const r = raw ?? {};
2173
+ const rawCount = typeof r.count === "number" && Number.isFinite(r.count) ? r.count : 0;
2174
+ const count = Math.max(0, Math.floor(rawCount));
2175
+ const rawRecent = Array.isArray(r.recent) ? r.recent.filter((x) => typeof x === "number" && Number.isFinite(x)) : [];
2176
+ const recent = rawRecent.length > RECENT_CAP ? rawRecent.slice(-RECENT_CAP) : rawRecent;
2177
+ return {
2178
+ memoryId: typeof r.memoryId === "string" ? r.memoryId : "",
2179
+ count: Math.max(count, recent.length),
2180
+ lastAt: typeof r.lastAt === "string" ? r.lastAt : "",
2181
+ recent
2182
+ };
2183
+ }
2184
+ async function getAccessLog(kv, memoryId) {
2185
+ try {
2186
+ const raw = await kv.get(KV.accessLog, memoryId);
2187
+ if (!raw) return emptyAccessLog(memoryId);
2188
+ const normalized = normalizeAccessLog(raw);
2189
+ if (!normalized.memoryId) normalized.memoryId = memoryId;
2190
+ return normalized;
2191
+ } catch {
2192
+ return emptyAccessLog(memoryId);
2193
+ }
2194
+ }
2195
+ async function recordAccess(kv, memoryId, timestampMs) {
2196
+ if (!memoryId) return;
2197
+ const ts = timestampMs ?? Date.now();
2198
+ try {
2199
+ await withKeyedLock(`mem:access:${memoryId}`, async () => {
2200
+ const existing = await getAccessLog(kv, memoryId);
2201
+ existing.count += 1;
2202
+ existing.lastAt = new Date(ts).toISOString();
2203
+ existing.recent.push(ts);
2204
+ if (existing.recent.length > RECENT_CAP) existing.recent = existing.recent.slice(-RECENT_CAP);
2205
+ await kv.set(KV.accessLog, memoryId, existing);
2206
+ });
2207
+ } catch (err) {
2208
+ try {
2209
+ getContext().logger.warn("recordAccess failed", {
2210
+ memoryId,
2211
+ error: err instanceof Error ? err.message : String(err)
2212
+ });
2213
+ } catch {}
2214
+ }
2215
+ }
2216
+ async function recordAccessBatch(kv, memoryIds, timestampMs) {
2217
+ if (!memoryIds || memoryIds.length === 0) return;
2218
+ const ts = timestampMs ?? Date.now();
2219
+ const unique = Array.from(new Set(memoryIds.filter(Boolean)));
2220
+ await Promise.allSettled(unique.map((id) => recordAccess(kv, id, ts)));
2221
+ }
2222
+ async function deleteAccessLog(kv, memoryId) {
2223
+ if (!memoryId) return;
2224
+ try {
2225
+ await withKeyedLock(`mem:access:${memoryId}`, async () => {
2226
+ await kv.delete(KV.accessLog, memoryId);
2227
+ });
2228
+ } catch {}
2229
+ }
2230
+
2157
2231
  //#endregion
2158
2232
  //#region src/functions/search.ts
2159
2233
  let index = null;
@@ -2240,6 +2314,7 @@ function registerSearchFunction(sdk, kv) {
2240
2314
  sessionId: candidates[i].sessionId
2241
2315
  });
2242
2316
  }
2317
+ recordAccessBatch(kv, enriched.map((r) => r.observation.id));
2243
2318
  ctx.logger.info("Search completed", {
2244
2319
  query,
2245
2320
  results: enriched.length,
@@ -2635,19 +2710,22 @@ function registerContextFunction(sdk, kv, tokenBudget) {
2635
2710
  const i = sessionsNeedingObs[j];
2636
2711
  const important = obsResults[j].filter((o) => o.title && o.importance >= 5);
2637
2712
  if (important.length > 0) {
2638
- const items = important.sort((a, b) => b.importance - a.importance).slice(0, 5).map((o) => `- [${o.type}] ${o.title}: ${o.narrative}`).join("\n");
2713
+ const top = important.sort((a, b) => b.importance - a.importance).slice(0, 5);
2714
+ const items = top.map((o) => `- [${o.type}] ${o.title}: ${o.narrative}`).join("\n");
2639
2715
  const content = `## Session ${sessions[i].id.slice(0, 8)} (${sessions[i].startedAt})\n${items}`;
2640
2716
  blocks.push({
2641
2717
  type: "observation",
2642
2718
  content,
2643
2719
  tokens: estimateTokens$1(content),
2644
- recency: new Date(sessions[i].startedAt).getTime()
2720
+ recency: new Date(sessions[i].startedAt).getTime(),
2721
+ sourceIds: top.map((o) => o.id)
2645
2722
  });
2646
2723
  }
2647
2724
  }
2648
2725
  blocks.sort((a, b) => b.recency - a.recency);
2649
2726
  let usedTokens = 0;
2650
2727
  const selected = [];
2728
+ const accessedIds = [];
2651
2729
  const header = `<agentmemory-context project="${escapeXmlAttr(data.project)}">`;
2652
2730
  const footer = `</agentmemory-context>`;
2653
2731
  usedTokens += estimateTokens$1(header) + estimateTokens$1(footer);
@@ -2655,7 +2733,9 @@ function registerContextFunction(sdk, kv, tokenBudget) {
2655
2733
  if (usedTokens + block.tokens > budget) break;
2656
2734
  selected.push(block.content);
2657
2735
  usedTokens += block.tokens;
2736
+ if (block.sourceIds && block.sourceIds.length > 0) accessedIds.push(...block.sourceIds);
2658
2737
  }
2738
+ if (accessedIds.length > 0) recordAccessBatch(kv, accessedIds);
2659
2739
  if (selected.length === 0) {
2660
2740
  ctx.logger.info("No context available", { project: data.project });
2661
2741
  return {
@@ -2988,6 +3068,9 @@ function registerFileIndexFunction(sdk, kv) {
2988
3068
  for (const obs of fh.observations) lines.push(`- [${obs.type}] ${obs.title}: ${obs.narrative}`);
2989
3069
  }
2990
3070
  lines.push("</agentmemory-file-context>");
3071
+ const accessedIds = [];
3072
+ for (const fh of results) for (const obs of fh.observations) accessedIds.push(obs.obsId);
3073
+ recordAccessBatch(kv, accessedIds);
2991
3074
  const context = lines.join("\n");
2992
3075
  ctx.logger.info("File context generated", {
2993
3076
  files: data.files.length,
@@ -3300,6 +3383,7 @@ function registerRememberFunction(sdk, kv) {
3300
3383
  let deleted = 0;
3301
3384
  if (data.memoryId) {
3302
3385
  await kv.delete(KV.memories, data.memoryId);
3386
+ await deleteAccessLog(kv, data.memoryId);
3303
3387
  deleted++;
3304
3388
  }
3305
3389
  if (data.sessionId && data.observationIds && data.observationIds.length > 0) for (const obsId of data.observationIds) {
@@ -3391,13 +3475,19 @@ function registerEvictFunction(sdk, kv) {
3391
3475
  if (now > new Date(mem.forgetAfter).getTime()) {
3392
3476
  stats.expiredMemories++;
3393
3477
  evictedMemIds.add(mem.id);
3394
- if (!dryRun) await kv.delete(KV.memories, mem.id).catch(() => {});
3478
+ if (!dryRun) {
3479
+ await kv.delete(KV.memories, mem.id).catch(() => {});
3480
+ await deleteAccessLog(kv, mem.id);
3481
+ }
3395
3482
  }
3396
3483
  }
3397
3484
  if (!evictedMemIds.has(mem.id) && mem.isLatest === false && mem.createdAt) {
3398
3485
  if (now - new Date(mem.createdAt).getTime() > cfg.lowImportanceMaxDays * MS_PER_DAY$1) {
3399
3486
  stats.nonLatestMemories++;
3400
- if (!dryRun) await kv.delete(KV.memories, mem.id).catch(() => {});
3487
+ if (!dryRun) {
3488
+ await kv.delete(KV.memories, mem.id).catch(() => {});
3489
+ await deleteAccessLog(kv, mem.id);
3490
+ }
3401
3491
  }
3402
3492
  }
3403
3493
  }
@@ -3562,6 +3652,7 @@ function registerRelationsFunction(sdk, kv) {
3562
3652
  });
3563
3653
  }
3564
3654
  result.sort((a, b) => b.confidence - a.confidence);
3655
+ recordAccessBatch(kv, result.map((r) => r.memory.id));
3565
3656
  ctx.logger.info("Related memories retrieved", {
3566
3657
  memoryId: data.memoryId,
3567
3658
  found: result.length
@@ -3633,6 +3724,7 @@ function registerTimelineFunction(sdk, kv) {
3633
3724
  relativePosition: i - anchorIdx
3634
3725
  });
3635
3726
  }
3727
+ recordAccessBatch(kv, entries.map((e) => e.observation.id));
3636
3728
  ctx.logger.info("Timeline retrieved", {
3637
3729
  anchor: data.anchor,
3638
3730
  entries: entries.length
@@ -3683,6 +3775,7 @@ function registerSmartSearchFunction(sdk, kv, searchFn) {
3683
3775
  observation: obs
3684
3776
  } : null)));
3685
3777
  for (const r of results) if (r) expanded.push(r);
3778
+ recordAccessBatch(kv, expanded.map((e) => e.observation.id));
3686
3779
  const truncated = data.expandIds.length > raw.length;
3687
3780
  ctx.logger.info("Smart search expanded", {
3688
3781
  requested: data.expandIds.length,
@@ -3710,6 +3803,7 @@ function registerSmartSearchFunction(sdk, kv, searchFn) {
3710
3803
  score: r.combinedScore,
3711
3804
  timestamp: r.observation.timestamp
3712
3805
  }));
3806
+ recordAccessBatch(kv, compact.map((r) => r.obsId));
3713
3807
  ctx.logger.info("Smart search compact", {
3714
3808
  query: data.query,
3715
3809
  results: compact.length
@@ -3841,7 +3935,10 @@ function registerAutoForgetFunction(sdk, kv) {
3841
3935
  if (now > new Date(mem.forgetAfter).getTime()) {
3842
3936
  result.ttlExpired.push(mem.id);
3843
3937
  deletedIds.add(mem.id);
3844
- if (!dryRun) await kv.delete(KV.memories, mem.id);
3938
+ if (!dryRun) {
3939
+ await kv.delete(KV.memories, mem.id);
3940
+ await deleteAccessLog(kv, mem.id);
3941
+ }
3845
3942
  }
3846
3943
  }
3847
3944
  const latestMemories = memories.filter((m) => m.isLatest !== false && !deletedIds.has(m.id)).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()).slice(0, 1e3);
@@ -3910,7 +4007,7 @@ function registerAutoForgetFunction(sdk, kv) {
3910
4007
 
3911
4008
  //#endregion
3912
4009
  //#region src/version.ts
3913
- const VERSION = "0.8.1";
4010
+ const VERSION = "0.8.6";
3914
4011
 
3915
4012
  //#endregion
3916
4013
  //#region src/functions/export-import.ts
@@ -3938,7 +4035,7 @@ function registerExportImportFunction(sdk, kv) {
3938
4035
  const uniqueProjects = [...new Set(paginatedSessions.map((s) => s.project))];
3939
4036
  const profileResults = await Promise.all(uniqueProjects.map((project) => kv.get(KV.profiles, project).catch(() => null)));
3940
4037
  for (const profile of profileResults) if (profile) profiles.push(profile);
3941
- const [graphNodes, graphEdges, semanticMemories, proceduralMemories, actions, actionEdges, sentinels, sketches, crystals, facets, lessons, insights, routines, signals, checkpoints] = await Promise.all([
4038
+ const [graphNodes, graphEdges, semanticMemories, proceduralMemories, actions, actionEdges, sentinels, sketches, crystals, facets, lessons, insights, routines, signals, checkpoints, accessLogs] = await Promise.all([
3942
4039
  kv.list(KV.graphNodes).catch(() => []),
3943
4040
  kv.list(KV.graphEdges).catch(() => []),
3944
4041
  kv.list(KV.semantic).catch(() => []),
@@ -3953,7 +4050,8 @@ function registerExportImportFunction(sdk, kv) {
3953
4050
  kv.list(KV.insights).catch(() => []),
3954
4051
  kv.list(KV.routines).catch(() => []),
3955
4052
  kv.list(KV.signals).catch(() => []),
3956
- kv.list(KV.checkpoints).catch(() => [])
4053
+ kv.list(KV.checkpoints).catch(() => []),
4054
+ kv.list(KV.accessLog).catch(() => [])
3957
4055
  ]);
3958
4056
  const exportData = {
3959
4057
  version: VERSION,
@@ -3977,7 +4075,8 @@ function registerExportImportFunction(sdk, kv) {
3977
4075
  insights: insights.length > 0 ? insights : void 0,
3978
4076
  routines: routines.length > 0 ? routines : void 0,
3979
4077
  signals: signals.length > 0 ? signals : void 0,
3980
- checkpoints: checkpoints.length > 0 ? checkpoints : void 0
4078
+ checkpoints: checkpoints.length > 0 ? checkpoints : void 0,
4079
+ accessLogs: accessLogs.length > 0 ? accessLogs : void 0
3981
4080
  };
3982
4081
  if (maxSessions !== void 0) exportData.pagination = {
3983
4082
  offset,
@@ -4017,7 +4116,12 @@ function registerExportImportFunction(sdk, kv) {
4017
4116
  "0.7.7",
4018
4117
  "0.7.9",
4019
4118
  "0.8.0",
4020
- "0.8.1"
4119
+ "0.8.1",
4120
+ "0.8.2",
4121
+ "0.8.3",
4122
+ "0.8.4",
4123
+ "0.8.5",
4124
+ "0.8.6"
4021
4125
  ]).has(importData.version)) return {
4022
4126
  success: false,
4023
4127
  error: `Unsupported export version: ${importData.version}`
@@ -4027,6 +4131,7 @@ function registerExportImportFunction(sdk, kv) {
4027
4131
  const MAX_SUMMARIES = 1e4;
4028
4132
  const MAX_OBS_PER_SESSION = 5e3;
4029
4133
  const MAX_TOTAL_OBSERVATIONS = 5e5;
4134
+ const MAX_ACCESS_LOGS = 5e4;
4030
4135
  if (!Array.isArray(importData.sessions)) return {
4031
4136
  success: false,
4032
4137
  error: "sessions must be an array"
@@ -4109,6 +4214,7 @@ function registerExportImportFunction(sdk, kv) {
4109
4214
  for (const e of await kv.list(KV.graphEdges).catch(() => [])) await kv.delete(KV.graphEdges, e.id);
4110
4215
  for (const s of await kv.list(KV.semantic).catch(() => [])) await kv.delete(KV.semantic, s.id);
4111
4216
  for (const p of await kv.list(KV.procedural).catch(() => [])) await kv.delete(KV.procedural, p.id);
4217
+ for (const a of await kv.list(KV.accessLog).catch(() => [])) await kv.delete(KV.accessLog, a.memoryId);
4112
4218
  }
4113
4219
  for (const session of importData.sessions) {
4114
4220
  if (strategy === "skip") {
@@ -4285,6 +4391,28 @@ function registerExportImportFunction(sdk, kv) {
4285
4391
  }
4286
4392
  await kv.set(KV.insights, insight.id, insight);
4287
4393
  }
4394
+ if (importData.accessLogs) {
4395
+ if (!Array.isArray(importData.accessLogs)) return {
4396
+ success: false,
4397
+ error: "accessLogs must be an array"
4398
+ };
4399
+ if (importData.accessLogs.length > MAX_ACCESS_LOGS) return {
4400
+ success: false,
4401
+ error: `Too many access logs (max ${MAX_ACCESS_LOGS})`
4402
+ };
4403
+ const memoryIds = new Set(importData.memories.map((m) => m.id));
4404
+ for (const raw of importData.accessLogs) {
4405
+ const log = normalizeAccessLog(raw);
4406
+ if (!log.memoryId || !memoryIds.has(log.memoryId)) continue;
4407
+ if (strategy === "skip") {
4408
+ if (await kv.get(KV.accessLog, log.memoryId).catch(() => null)) {
4409
+ stats.skipped++;
4410
+ continue;
4411
+ }
4412
+ }
4413
+ await kv.set(KV.accessLog, log.memoryId, log);
4414
+ }
4415
+ }
4288
4416
  ctx.logger.info("Import complete", {
4289
4417
  strategy,
4290
4418
  ...stats
@@ -5053,6 +5181,7 @@ function registerGovernanceFunction(sdk, kv) {
5053
5181
  let deleted = 0;
5054
5182
  for (const id of data.memoryIds) if (await kv.get(KV.memories, id)) {
5055
5183
  await kv.delete(KV.memories, id);
5184
+ await deleteAccessLog(kv, id);
5056
5185
  deleted++;
5057
5186
  }
5058
5187
  await recordAudit(kv, "delete", "mem::governance-delete", data.memoryIds, {
@@ -5100,7 +5229,10 @@ function registerGovernanceFunction(sdk, kv) {
5100
5229
  wouldDelete: candidates.length,
5101
5230
  ids: candidates.map((m) => m.id)
5102
5231
  };
5103
- for (const mem of candidates) await kv.delete(KV.memories, mem.id);
5232
+ for (const mem of candidates) {
5233
+ await kv.delete(KV.memories, mem.id);
5234
+ await deleteAccessLog(kv, mem.id);
5235
+ }
5104
5236
  await recordAudit(kv, "delete", "mem::governance-bulk", candidates.map((m) => m.id), {
5105
5237
  filter: data,
5106
5238
  deleted: candidates.length
@@ -5148,6 +5280,7 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5148
5280
  const sessions = await kv.list(KV.sessions);
5149
5281
  const memories = await kv.list(KV.memories);
5150
5282
  const graphNodes = await kv.list(KV.graphNodes);
5283
+ const accessLogs = await kv.list(KV.accessLog).catch(() => []);
5151
5284
  const observations = {};
5152
5285
  for (const session of sessions) {
5153
5286
  const obs = await kv.list(KV.observations(session.id)).catch(() => []);
@@ -5159,7 +5292,8 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5159
5292
  sessions,
5160
5293
  memories,
5161
5294
  graphNodes,
5162
- observations
5295
+ observations,
5296
+ accessLogs
5163
5297
  };
5164
5298
  writeFileSync(join(snapshotDir, "state.json"), JSON.stringify(state, null, 2), "utf-8");
5165
5299
  await gitExec(snapshotDir, ["add", "."]);
@@ -5251,6 +5385,7 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5251
5385
  if (state.memories) for (const memory of state.memories) await kv.set(KV.memories, memory.id, memory);
5252
5386
  if (state.graphNodes) for (const node of state.graphNodes) await kv.set(KV.graphNodes, node.id, node);
5253
5387
  if (state.observations) for (const [sessionId, obs] of Object.entries(state.observations)) for (const o of obs) await kv.set(KV.observations(sessionId), o.id, o);
5388
+ if (state.accessLogs) for (const log of state.accessLogs) await kv.set(KV.accessLog, log.memoryId, log);
5254
5389
  await gitExec(snapshotDir, [
5255
5390
  "checkout",
5256
5391
  "HEAD",
@@ -6418,7 +6553,7 @@ async function lwwMergeGraphNodes(kv, items) {
6418
6553
  }
6419
6554
  return count;
6420
6555
  }
6421
- function registerMeshFunction(sdk, kv) {
6556
+ function registerMeshFunction(sdk, kv, meshAuthToken) {
6422
6557
  sdk.registerFunction({ id: "mem::mesh-register" }, async (data) => {
6423
6558
  if (!data.url || !data.name) return {
6424
6559
  success: false,
@@ -6455,6 +6590,10 @@ function registerMeshFunction(sdk, kv) {
6455
6590
  };
6456
6591
  });
6457
6592
  sdk.registerFunction({ id: "mem::mesh-sync" }, async (data) => {
6593
+ if (!meshAuthToken) return {
6594
+ success: false,
6595
+ error: "mesh sync requires AGENTMEMORY_SECRET"
6596
+ };
6458
6597
  const direction = data.direction || "both";
6459
6598
  let peers;
6460
6599
  if (data.peerId) {
@@ -6490,7 +6629,10 @@ function registerMeshFunction(sdk, kv) {
6490
6629
  try {
6491
6630
  const response = await fetch(`${peer.url}/agentmemory/mesh/receive`, {
6492
6631
  method: "POST",
6493
- headers: { "Content-Type": "application/json" },
6632
+ headers: {
6633
+ "Content-Type": "application/json",
6634
+ Authorization: `Bearer ${meshAuthToken}`
6635
+ },
6494
6636
  body: JSON.stringify(pushData),
6495
6637
  signal: AbortSignal.timeout(3e4),
6496
6638
  redirect: "error"
@@ -6503,6 +6645,7 @@ function registerMeshFunction(sdk, kv) {
6503
6645
  }
6504
6646
  if (direction === "pull" || direction === "both") try {
6505
6647
  const response = await fetch(`${peer.url}/agentmemory/mesh/export?since=${peer.lastSyncAt || ""}`, {
6648
+ headers: { Authorization: `Bearer ${meshAuthToken}` },
6506
6649
  signal: AbortSignal.timeout(3e4),
6507
6650
  redirect: "error"
6508
6651
  });
@@ -8363,7 +8506,16 @@ function registerLessonsFunctions(sdk, kv) {
8363
8506
 
8364
8507
  //#endregion
8365
8508
  //#region src/functions/obsidian-export.ts
8366
- const DEFAULT_VAULT = join(homedir(), ".agentmemory", "vault");
8509
+ const DEFAULT_EXPORT_ROOT = join(homedir(), ".agentmemory");
8510
+ function getExportRoot() {
8511
+ return resolve(process.env["AGENTMEMORY_EXPORT_ROOT"] || DEFAULT_EXPORT_ROOT);
8512
+ }
8513
+ function resolveVaultDir(vaultDir) {
8514
+ const root = getExportRoot();
8515
+ const resolved = resolve(vaultDir || join(root, "vault"));
8516
+ if (resolved === root || resolved.startsWith(root + sep)) return resolved;
8517
+ return null;
8518
+ }
8367
8519
  function sanitize(name) {
8368
8520
  return name.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").slice(0, 100);
8369
8521
  }
@@ -8476,7 +8628,11 @@ function sessionToMd(s) {
8476
8628
  }
8477
8629
  function registerObsidianExportFunction(sdk, kv) {
8478
8630
  sdk.registerFunction({ id: "mem::obsidian-export" }, async (data) => {
8479
- const vaultDir = data.vaultDir || DEFAULT_VAULT;
8631
+ const vaultDir = resolveVaultDir(data.vaultDir);
8632
+ if (!vaultDir) return {
8633
+ success: false,
8634
+ error: `vaultDir must be inside ${getExportRoot()}`
8635
+ };
8480
8636
  const exportTypes = new Set(data.types || [
8481
8637
  "memories",
8482
8638
  "lessons",
@@ -9022,12 +9178,15 @@ function registerWorkingMemoryFunctions(sdk, kv, tokenBudget) {
9022
9178
  if (Math.abs(strengthDiff) > .2) return strengthDiff;
9023
9179
  return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
9024
9180
  });
9181
+ const archivalIds = [];
9025
9182
  for (const mem of active) {
9026
9183
  const tokens = estimateTokens(mem.content);
9027
9184
  if (usedTokens + tokens > budget) continue;
9028
9185
  archivalLines.push(`- [${mem.type}] ${mem.title}: ${mem.content}`);
9186
+ archivalIds.push(mem.id);
9029
9187
  usedTokens += tokens;
9030
9188
  }
9189
+ recordAccessBatch(kv, archivalIds);
9031
9190
  const pagedOut = active.length - archivalLines.length;
9032
9191
  const sections = [];
9033
9192
  if (coreLines.length > 0) sections.push(`## Core Memory\n${coreLines.join("\n")}`);
@@ -9781,17 +9940,15 @@ const DEFAULT_DECAY = {
9781
9940
  cold: .15
9782
9941
  }
9783
9942
  };
9784
- function computeRetention(salience, createdAt, accessTimestamps, config) {
9943
+ function computeReinforcementBoost(accessTimestamps, sigma) {
9785
9944
  const now = Date.now();
9786
- const deltaT = (now - new Date(createdAt).getTime()) / (1e3 * 60 * 60 * 24);
9787
- const temporalDecay = Math.exp(-config.lambda * deltaT);
9788
- let reinforcementBoost = 0;
9945
+ let boost = 0;
9789
9946
  for (const tAccess of accessTimestamps) {
9947
+ if (!Number.isFinite(tAccess)) continue;
9790
9948
  const daysSinceAccess = (now - tAccess) / (1e3 * 60 * 60 * 24);
9791
- if (daysSinceAccess > 0) reinforcementBoost += 1 / daysSinceAccess;
9949
+ if (daysSinceAccess > 0) boost += 1 / daysSinceAccess;
9792
9950
  }
9793
- reinforcementBoost *= config.sigma;
9794
- return Math.min(1, salience * temporalDecay + reinforcementBoost);
9951
+ return boost * sigma;
9795
9952
  }
9796
9953
  function computeSalience(memory, accessCount) {
9797
9954
  let baseSalience = .5;
@@ -9817,37 +9974,64 @@ function registerRetentionFunctions(sdk, kv) {
9817
9974
  ...DEFAULT_DECAY,
9818
9975
  ...data.config
9819
9976
  };
9820
- const memories = await kv.list(KV.memories);
9821
- const semanticMems = await kv.list(KV.semantic);
9977
+ const [memories, semanticMems, allLogs] = await Promise.all([
9978
+ kv.list(KV.memories),
9979
+ kv.list(KV.semantic),
9980
+ kv.list(KV.accessLog).catch(() => [])
9981
+ ]);
9982
+ const logsById = /* @__PURE__ */ new Map();
9983
+ for (const raw of allLogs) {
9984
+ const log = normalizeAccessLog(raw);
9985
+ if (log.memoryId) logsById.set(log.memoryId, log);
9986
+ }
9822
9987
  const scores = [];
9988
+ const computeDecay = (createdAt) => Math.exp(-config.lambda * ((Date.now() - new Date(createdAt).getTime()) / (1e3 * 60 * 60 * 24)));
9823
9989
  for (const mem of memories) {
9824
9990
  if (!mem.isLatest) continue;
9825
- const salience = computeSalience(mem, 0);
9826
- const score = computeRetention(salience, mem.createdAt, [], config);
9991
+ const log = logsById.get(mem.id) ?? emptyAccessLog(mem.id);
9992
+ const salience = computeSalience(mem, log.count);
9993
+ const temporalDecay = computeDecay(mem.createdAt);
9994
+ const reinforcementBoost = computeReinforcementBoost(log.recent, config.sigma);
9995
+ const score = Math.min(1, salience * temporalDecay + reinforcementBoost);
9827
9996
  const entry = {
9828
9997
  memoryId: mem.id,
9829
9998
  score,
9830
9999
  salience,
9831
- temporalDecay: Math.exp(-config.lambda * ((Date.now() - new Date(mem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9832
- reinforcementBoost: 0,
9833
- lastAccessed: mem.updatedAt,
9834
- accessCount: 0
10000
+ temporalDecay,
10001
+ reinforcementBoost,
10002
+ lastAccessed: log.lastAt || mem.updatedAt,
10003
+ accessCount: log.count
9835
10004
  };
9836
10005
  scores.push(entry);
9837
10006
  await kv.set(KV.retentionScores, mem.id, entry);
9838
10007
  }
9839
10008
  for (const sem of semanticMems) {
9840
- const accessTimestamps = sem.lastAccessedAt ? [new Date(sem.lastAccessedAt).getTime()] : [];
9841
- const salience = computeSalience(sem, sem.accessCount);
9842
- const score = computeRetention(salience, sem.createdAt, accessTimestamps, config);
10009
+ const log = logsById.get(sem.id) ?? emptyAccessLog(sem.id);
10010
+ let accessTimestamps;
10011
+ let effectiveCount;
10012
+ if (log.recent.length > 0 || log.count > 0) {
10013
+ accessTimestamps = log.recent;
10014
+ effectiveCount = log.count;
10015
+ } else if (sem.lastAccessedAt) {
10016
+ const legacyTs = Date.parse(sem.lastAccessedAt);
10017
+ accessTimestamps = Number.isFinite(legacyTs) ? [legacyTs] : [];
10018
+ effectiveCount = sem.accessCount;
10019
+ } else {
10020
+ accessTimestamps = [];
10021
+ effectiveCount = sem.accessCount;
10022
+ }
10023
+ const salience = computeSalience(sem, effectiveCount);
10024
+ const temporalDecay = computeDecay(sem.createdAt);
10025
+ const reinforcementBoost = computeReinforcementBoost(accessTimestamps, config.sigma);
10026
+ const score = Math.min(1, salience * temporalDecay + reinforcementBoost);
9843
10027
  const entry = {
9844
10028
  memoryId: sem.id,
9845
10029
  score,
9846
10030
  salience,
9847
- temporalDecay: Math.exp(-config.lambda * ((Date.now() - new Date(sem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9848
- reinforcementBoost: score - salience * Math.exp(-config.lambda * ((Date.now() - new Date(sem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9849
- lastAccessed: sem.lastAccessedAt,
9850
- accessCount: sem.accessCount
10031
+ temporalDecay,
10032
+ reinforcementBoost,
10033
+ lastAccessed: log.lastAt || sem.lastAccessedAt,
10034
+ accessCount: effectiveCount
9851
10035
  };
9852
10036
  scores.push(entry);
9853
10037
  await kv.set(KV.retentionScores, sem.id, entry);
@@ -9891,6 +10075,7 @@ function registerRetentionFunctions(sdk, kv) {
9891
10075
  for (const candidate of candidates) try {
9892
10076
  await kv.delete(KV.memories, candidate.memoryId);
9893
10077
  await kv.delete(KV.retentionScores, candidate.memoryId);
10078
+ await deleteAccessLog(kv, candidate.memoryId);
9894
10079
  evicted++;
9895
10080
  } catch {
9896
10081
  continue;
@@ -10046,14 +10231,57 @@ async function getLatestHealth(kv) {
10046
10231
  //#endregion
10047
10232
  //#region src/auth.ts
10048
10233
  const hmacKey = randomBytes(32);
10234
+ const VIEWER_NONCE_PLACEHOLDER = "__AGENTMEMORY_VIEWER_NONCE__";
10049
10235
  function timingSafeCompare(a, b) {
10050
10236
  return timingSafeEqual(createHmac("sha256", hmacKey).update(a).digest(), createHmac("sha256", hmacKey).update(b).digest());
10051
10237
  }
10052
- const VIEWER_CSP = "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self' ws://localhost:* wss://localhost:*; img-src 'self'; font-src 'self'";
10238
+ function createViewerNonce() {
10239
+ return randomBytes(16).toString("base64url");
10240
+ }
10241
+ function buildViewerCsp(nonce) {
10242
+ return [
10243
+ "default-src 'none'",
10244
+ "base-uri 'none'",
10245
+ "frame-ancestors 'none'",
10246
+ "object-src 'none'",
10247
+ "form-action 'none'",
10248
+ `script-src 'nonce-${nonce}'`,
10249
+ "script-src-attr 'none'",
10250
+ "style-src 'unsafe-inline'",
10251
+ "connect-src 'self' http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:* wss://localhost:* wss://127.0.0.1:*",
10252
+ "img-src 'self'",
10253
+ "font-src 'self'"
10254
+ ].join("; ");
10255
+ }
10256
+
10257
+ //#endregion
10258
+ //#region src/viewer/document.ts
10259
+ function loadViewerTemplate() {
10260
+ const base = dirname(fileURLToPath(import.meta.url));
10261
+ const candidates = [
10262
+ join(base, "..", "src", "viewer", "index.html"),
10263
+ join(base, "..", "viewer", "index.html"),
10264
+ join(base, "viewer", "index.html")
10265
+ ];
10266
+ for (const path of candidates) try {
10267
+ return readFileSync(path, "utf-8");
10268
+ } catch {}
10269
+ return null;
10270
+ }
10271
+ function renderViewerDocument() {
10272
+ const template = loadViewerTemplate();
10273
+ if (!template) return { found: false };
10274
+ const nonce = createViewerNonce();
10275
+ return {
10276
+ found: true,
10277
+ html: template.replaceAll(VIEWER_NONCE_PLACEHOLDER, nonce),
10278
+ csp: buildViewerCsp(nonce)
10279
+ };
10280
+ }
10053
10281
 
10054
10282
  //#endregion
10055
10283
  //#region src/triggers/api.ts
10056
- function checkAuth$1(req, secret) {
10284
+ function checkAuth(req, secret) {
10057
10285
  if (!secret) return null;
10058
10286
  const auth = req.headers?.["authorization"] || req.headers?.["Authorization"];
10059
10287
  if (typeof auth !== "string" || !timingSafeCompare(auth, `Bearer ${secret}`)) return {
@@ -10062,6 +10290,13 @@ function checkAuth$1(req, secret) {
10062
10290
  };
10063
10291
  return null;
10064
10292
  }
10293
+ function requireConfiguredSecret(secret, feature) {
10294
+ if (secret) return null;
10295
+ return {
10296
+ status_code: 503,
10297
+ body: { error: `${feature} requires AGENTMEMORY_SECRET` }
10298
+ };
10299
+ }
10065
10300
  function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10066
10301
  sdk.registerFunction({ id: "api::liveness" }, async () => ({
10067
10302
  status_code: 200,
@@ -10079,7 +10314,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10079
10314
  }
10080
10315
  });
10081
10316
  sdk.registerFunction({ id: "api::health" }, async (req) => {
10082
- const authErr = checkAuth$1(req, secret);
10317
+ const authErr = checkAuth(req, secret);
10083
10318
  if (authErr) return authErr;
10084
10319
  const health = await getLatestHealth(kv);
10085
10320
  const functionMetrics = metricsStore ? await metricsStore.getAll() : [];
@@ -10106,7 +10341,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10106
10341
  }
10107
10342
  });
10108
10343
  sdk.registerFunction({ id: "api::observe" }, async (req) => {
10109
- const authErr = checkAuth$1(req, secret);
10344
+ const authErr = checkAuth(req, secret);
10110
10345
  if (authErr) return authErr;
10111
10346
  return {
10112
10347
  status_code: 201,
@@ -10122,7 +10357,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10122
10357
  }
10123
10358
  });
10124
10359
  sdk.registerFunction({ id: "api::context" }, async (req) => {
10125
- const authErr = checkAuth$1(req, secret);
10360
+ const authErr = checkAuth(req, secret);
10126
10361
  if (authErr) return authErr;
10127
10362
  return {
10128
10363
  status_code: 200,
@@ -10138,7 +10373,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10138
10373
  }
10139
10374
  });
10140
10375
  sdk.registerFunction({ id: "api::search" }, async (req) => {
10141
- const authErr = checkAuth$1(req, secret);
10376
+ const authErr = checkAuth(req, secret);
10142
10377
  if (authErr) return authErr;
10143
10378
  const body = req.body ?? {};
10144
10379
  if (typeof body.query !== "string" || !body.query.trim()) return {
@@ -10177,7 +10412,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10177
10412
  }
10178
10413
  });
10179
10414
  sdk.registerFunction({ id: "api::session::start" }, async (req) => {
10180
- const authErr = checkAuth$1(req, secret);
10415
+ const authErr = checkAuth(req, secret);
10181
10416
  if (authErr) return authErr;
10182
10417
  const { sessionId, project, cwd } = req.body;
10183
10418
  const session = {
@@ -10209,7 +10444,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10209
10444
  }
10210
10445
  });
10211
10446
  sdk.registerFunction({ id: "api::session::end" }, async (req) => {
10212
- const authErr = checkAuth$1(req, secret);
10447
+ const authErr = checkAuth(req, secret);
10213
10448
  if (authErr) return authErr;
10214
10449
  const session = await kv.get(KV.sessions, req.body.sessionId);
10215
10450
  if (session) await kv.set(KV.sessions, req.body.sessionId, {
@@ -10231,7 +10466,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10231
10466
  }
10232
10467
  });
10233
10468
  sdk.registerFunction({ id: "api::summarize" }, async (req) => {
10234
- const authErr = checkAuth$1(req, secret);
10469
+ const authErr = checkAuth(req, secret);
10235
10470
  if (authErr) return authErr;
10236
10471
  return {
10237
10472
  status_code: 200,
@@ -10247,7 +10482,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10247
10482
  }
10248
10483
  });
10249
10484
  sdk.registerFunction({ id: "api::sessions" }, async (req) => {
10250
- const authErr = checkAuth$1(req, secret);
10485
+ const authErr = checkAuth(req, secret);
10251
10486
  if (authErr) return authErr;
10252
10487
  return {
10253
10488
  status_code: 200,
@@ -10263,7 +10498,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10263
10498
  }
10264
10499
  });
10265
10500
  sdk.registerFunction({ id: "api::observations" }, async (req) => {
10266
- const authErr = checkAuth$1(req, secret);
10501
+ const authErr = checkAuth(req, secret);
10267
10502
  if (authErr) return authErr;
10268
10503
  const sessionId = req.query_params["sessionId"];
10269
10504
  if (!sessionId) return {
@@ -10284,7 +10519,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10284
10519
  }
10285
10520
  });
10286
10521
  sdk.registerFunction({ id: "api::file-context" }, async (req) => {
10287
- const authErr = checkAuth$1(req, secret);
10522
+ const authErr = checkAuth(req, secret);
10288
10523
  if (authErr) return authErr;
10289
10524
  return {
10290
10525
  status_code: 200,
@@ -10300,7 +10535,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10300
10535
  }
10301
10536
  });
10302
10537
  sdk.registerFunction({ id: "api::enrich" }, async (req) => {
10303
- const authErr = checkAuth$1(req, secret);
10538
+ const authErr = checkAuth(req, secret);
10304
10539
  if (authErr) return authErr;
10305
10540
  if (!req.body?.sessionId || typeof req.body.sessionId !== "string" || !Array.isArray(req.body?.files) || req.body.files.length === 0 || !req.body.files.every((f) => typeof f === "string")) return {
10306
10541
  status_code: 400,
@@ -10324,7 +10559,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10324
10559
  }
10325
10560
  });
10326
10561
  sdk.registerFunction({ id: "api::remember" }, async (req) => {
10327
- const authErr = checkAuth$1(req, secret);
10562
+ const authErr = checkAuth(req, secret);
10328
10563
  if (authErr) return authErr;
10329
10564
  if (!req.body?.content || typeof req.body.content !== "string" || !req.body.content.trim()) return {
10330
10565
  status_code: 400,
@@ -10344,7 +10579,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10344
10579
  }
10345
10580
  });
10346
10581
  sdk.registerFunction({ id: "api::forget" }, async (req) => {
10347
- const authErr = checkAuth$1(req, secret);
10582
+ const authErr = checkAuth(req, secret);
10348
10583
  if (authErr) return authErr;
10349
10584
  if (!req.body?.sessionId && !req.body?.memoryId) return {
10350
10585
  status_code: 400,
@@ -10364,7 +10599,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10364
10599
  }
10365
10600
  });
10366
10601
  sdk.registerFunction({ id: "api::consolidate" }, async (req) => {
10367
- const authErr = checkAuth$1(req, secret);
10602
+ const authErr = checkAuth(req, secret);
10368
10603
  if (authErr) return authErr;
10369
10604
  return {
10370
10605
  status_code: 200,
@@ -10380,7 +10615,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10380
10615
  }
10381
10616
  });
10382
10617
  sdk.registerFunction({ id: "api::patterns" }, async (req) => {
10383
- const authErr = checkAuth$1(req, secret);
10618
+ const authErr = checkAuth(req, secret);
10384
10619
  if (authErr) return authErr;
10385
10620
  return {
10386
10621
  status_code: 200,
@@ -10396,7 +10631,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10396
10631
  }
10397
10632
  });
10398
10633
  sdk.registerFunction({ id: "api::generate-rules" }, async (req) => {
10399
- const authErr = checkAuth$1(req, secret);
10634
+ const authErr = checkAuth(req, secret);
10400
10635
  if (authErr) return authErr;
10401
10636
  return {
10402
10637
  status_code: 200,
@@ -10412,7 +10647,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10412
10647
  }
10413
10648
  });
10414
10649
  sdk.registerFunction({ id: "api::migrate" }, async (req) => {
10415
- const authErr = checkAuth$1(req, secret);
10650
+ const authErr = checkAuth(req, secret);
10416
10651
  if (authErr) return authErr;
10417
10652
  if (!req.body?.dbPath || typeof req.body.dbPath !== "string") return {
10418
10653
  status_code: 400,
@@ -10432,7 +10667,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10432
10667
  }
10433
10668
  });
10434
10669
  sdk.registerFunction({ id: "api::evict" }, async (req) => {
10435
- const authErr = checkAuth$1(req, secret);
10670
+ const authErr = checkAuth(req, secret);
10436
10671
  if (authErr) return authErr;
10437
10672
  const dryRun = req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
10438
10673
  return {
@@ -10449,7 +10684,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10449
10684
  }
10450
10685
  });
10451
10686
  sdk.registerFunction({ id: "api::smart-search" }, async (req) => {
10452
- const authErr = checkAuth$1(req, secret);
10687
+ const authErr = checkAuth(req, secret);
10453
10688
  if (authErr) return authErr;
10454
10689
  if (!req.body?.query && (!req.body?.expandIds || req.body.expandIds.length === 0)) return {
10455
10690
  status_code: 400,
@@ -10469,7 +10704,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10469
10704
  }
10470
10705
  });
10471
10706
  sdk.registerFunction({ id: "api::timeline" }, async (req) => {
10472
- const authErr = checkAuth$1(req, secret);
10707
+ const authErr = checkAuth(req, secret);
10473
10708
  if (authErr) return authErr;
10474
10709
  if (!req.body?.anchor) return {
10475
10710
  status_code: 400,
@@ -10489,7 +10724,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10489
10724
  }
10490
10725
  });
10491
10726
  sdk.registerFunction({ id: "api::profile" }, async (req) => {
10492
- const authErr = checkAuth$1(req, secret);
10727
+ const authErr = checkAuth(req, secret);
10493
10728
  if (authErr) return authErr;
10494
10729
  const project = req.query_params["project"];
10495
10730
  if (!project) return {
@@ -10510,7 +10745,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10510
10745
  }
10511
10746
  });
10512
10747
  sdk.registerFunction({ id: "api::export" }, async (req) => {
10513
- const authErr = checkAuth$1(req, secret);
10748
+ const authErr = checkAuth(req, secret);
10514
10749
  if (authErr) return authErr;
10515
10750
  return {
10516
10751
  status_code: 200,
@@ -10526,7 +10761,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10526
10761
  }
10527
10762
  });
10528
10763
  sdk.registerFunction({ id: "api::import" }, async (req) => {
10529
- const authErr = checkAuth$1(req, secret);
10764
+ const authErr = checkAuth(req, secret);
10530
10765
  if (authErr) return authErr;
10531
10766
  if (!req.body?.exportData) return {
10532
10767
  status_code: 400,
@@ -10546,7 +10781,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10546
10781
  }
10547
10782
  });
10548
10783
  sdk.registerFunction({ id: "api::relations" }, async (req) => {
10549
- const authErr = checkAuth$1(req, secret);
10784
+ const authErr = checkAuth(req, secret);
10550
10785
  if (authErr) return authErr;
10551
10786
  if (!req.body?.sourceId || !req.body?.targetId || !req.body?.type) return {
10552
10787
  status_code: 400,
@@ -10566,7 +10801,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10566
10801
  }
10567
10802
  });
10568
10803
  sdk.registerFunction({ id: "api::evolve" }, async (req) => {
10569
- const authErr = checkAuth$1(req, secret);
10804
+ const authErr = checkAuth(req, secret);
10570
10805
  if (authErr) return authErr;
10571
10806
  if (!req.body?.memoryId || !req.body?.newContent) return {
10572
10807
  status_code: 400,
@@ -10586,7 +10821,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10586
10821
  }
10587
10822
  });
10588
10823
  sdk.registerFunction({ id: "api::auto-forget" }, async (req) => {
10589
- const authErr = checkAuth$1(req, secret);
10824
+ const authErr = checkAuth(req, secret);
10590
10825
  if (authErr) return authErr;
10591
10826
  const dryRun = req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
10592
10827
  return {
@@ -10603,7 +10838,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10603
10838
  }
10604
10839
  });
10605
10840
  sdk.registerFunction({ id: "api::claude-bridge-read" }, async (req) => {
10606
- const authErr = checkAuth$1(req, secret);
10841
+ const authErr = checkAuth(req, secret);
10607
10842
  if (authErr) return authErr;
10608
10843
  try {
10609
10844
  return {
@@ -10626,7 +10861,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10626
10861
  }
10627
10862
  });
10628
10863
  sdk.registerFunction({ id: "api::claude-bridge-sync" }, async (req) => {
10629
- const authErr = checkAuth$1(req, secret);
10864
+ const authErr = checkAuth(req, secret);
10630
10865
  if (authErr) return authErr;
10631
10866
  try {
10632
10867
  return {
@@ -10649,7 +10884,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10649
10884
  }
10650
10885
  });
10651
10886
  sdk.registerFunction({ id: "api::graph-query" }, async (req) => {
10652
- const authErr = checkAuth$1(req, secret);
10887
+ const authErr = checkAuth(req, secret);
10653
10888
  if (authErr) return authErr;
10654
10889
  try {
10655
10890
  return {
@@ -10672,7 +10907,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10672
10907
  }
10673
10908
  });
10674
10909
  sdk.registerFunction({ id: "api::graph-stats" }, async (req) => {
10675
- const authErr = checkAuth$1(req, secret);
10910
+ const authErr = checkAuth(req, secret);
10676
10911
  if (authErr) return authErr;
10677
10912
  try {
10678
10913
  return {
@@ -10695,7 +10930,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10695
10930
  }
10696
10931
  });
10697
10932
  sdk.registerFunction({ id: "api::graph-extract" }, async (req) => {
10698
- const authErr = checkAuth$1(req, secret);
10933
+ const authErr = checkAuth(req, secret);
10699
10934
  if (authErr) return authErr;
10700
10935
  if (!Array.isArray(req.body?.observations) || req.body.observations.length === 0) return {
10701
10936
  status_code: 400,
@@ -10722,7 +10957,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10722
10957
  }
10723
10958
  });
10724
10959
  sdk.registerFunction({ id: "api::consolidate-pipeline" }, async (req) => {
10725
- const authErr = checkAuth$1(req, secret);
10960
+ const authErr = checkAuth(req, secret);
10726
10961
  if (authErr) return authErr;
10727
10962
  try {
10728
10963
  return {
@@ -10745,7 +10980,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10745
10980
  }
10746
10981
  });
10747
10982
  sdk.registerFunction({ id: "api::team-share" }, async (req) => {
10748
- const authErr = checkAuth$1(req, secret);
10983
+ const authErr = checkAuth(req, secret);
10749
10984
  if (authErr) return authErr;
10750
10985
  if (!req.body?.itemId || !req.body?.itemType) return {
10751
10986
  status_code: 400,
@@ -10772,7 +11007,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10772
11007
  }
10773
11008
  });
10774
11009
  sdk.registerFunction({ id: "api::team-feed" }, async (req) => {
10775
- const authErr = checkAuth$1(req, secret);
11010
+ const authErr = checkAuth(req, secret);
10776
11011
  if (authErr) return authErr;
10777
11012
  try {
10778
11013
  const limit = parseInt(req.query_params?.["limit"]) || 20;
@@ -10796,7 +11031,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10796
11031
  }
10797
11032
  });
10798
11033
  sdk.registerFunction({ id: "api::team-profile" }, async (req) => {
10799
- const authErr = checkAuth$1(req, secret);
11034
+ const authErr = checkAuth(req, secret);
10800
11035
  if (authErr) return authErr;
10801
11036
  try {
10802
11037
  return {
@@ -10819,7 +11054,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10819
11054
  }
10820
11055
  });
10821
11056
  sdk.registerFunction({ id: "api::audit" }, async (req) => {
10822
- const authErr = checkAuth$1(req, secret);
11057
+ const authErr = checkAuth(req, secret);
10823
11058
  if (authErr) return authErr;
10824
11059
  return {
10825
11060
  status_code: 200,
@@ -10838,7 +11073,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10838
11073
  }
10839
11074
  });
10840
11075
  sdk.registerFunction({ id: "api::governance-delete" }, async (req) => {
10841
- const authErr = checkAuth$1(req, secret);
11076
+ const authErr = checkAuth(req, secret);
10842
11077
  if (authErr) return authErr;
10843
11078
  if (!req.body?.memoryIds || !Array.isArray(req.body.memoryIds)) return {
10844
11079
  status_code: 400,
@@ -10858,7 +11093,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10858
11093
  }
10859
11094
  });
10860
11095
  sdk.registerFunction({ id: "api::governance-bulk" }, async (req) => {
10861
- const authErr = checkAuth$1(req, secret);
11096
+ const authErr = checkAuth(req, secret);
10862
11097
  if (authErr) return authErr;
10863
11098
  return {
10864
11099
  status_code: 200,
@@ -10874,7 +11109,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10874
11109
  }
10875
11110
  });
10876
11111
  sdk.registerFunction({ id: "api::snapshots" }, async (req) => {
10877
- const authErr = checkAuth$1(req, secret);
11112
+ const authErr = checkAuth(req, secret);
10878
11113
  if (authErr) return authErr;
10879
11114
  try {
10880
11115
  return {
@@ -10897,7 +11132,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10897
11132
  }
10898
11133
  });
10899
11134
  sdk.registerFunction({ id: "api::snapshot-create" }, async (req) => {
10900
- const authErr = checkAuth$1(req, secret);
11135
+ const authErr = checkAuth(req, secret);
10901
11136
  if (authErr) return authErr;
10902
11137
  try {
10903
11138
  return {
@@ -10920,7 +11155,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10920
11155
  }
10921
11156
  });
10922
11157
  sdk.registerFunction({ id: "api::snapshot-restore" }, async (req) => {
10923
- const authErr = checkAuth$1(req, secret);
11158
+ const authErr = checkAuth(req, secret);
10924
11159
  if (authErr) return authErr;
10925
11160
  if (!req.body?.commitHash) return {
10926
11161
  status_code: 400,
@@ -10947,7 +11182,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10947
11182
  }
10948
11183
  });
10949
11184
  sdk.registerFunction({ id: "api::memories" }, async (req) => {
10950
- const authErr = checkAuth$1(req, secret);
11185
+ const authErr = checkAuth(req, secret);
10951
11186
  if (authErr) return authErr;
10952
11187
  const memories = await kv.list(KV.memories);
10953
11188
  return {
@@ -10964,7 +11199,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10964
11199
  }
10965
11200
  });
10966
11201
  sdk.registerFunction({ id: "api::action-create" }, async (req) => {
10967
- const authErr = checkAuth$1(req, secret);
11202
+ const authErr = checkAuth(req, secret);
10968
11203
  if (authErr) return authErr;
10969
11204
  if (!req.body?.title) return {
10970
11205
  status_code: 400,
@@ -10984,7 +11219,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10984
11219
  }
10985
11220
  });
10986
11221
  sdk.registerFunction({ id: "api::action-update" }, async (req) => {
10987
- const authErr = checkAuth$1(req, secret);
11222
+ const authErr = checkAuth(req, secret);
10988
11223
  if (authErr) return authErr;
10989
11224
  if (!req.body?.actionId) return {
10990
11225
  status_code: 400,
@@ -11004,7 +11239,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11004
11239
  }
11005
11240
  });
11006
11241
  sdk.registerFunction({ id: "api::action-list" }, async (req) => {
11007
- const authErr = checkAuth$1(req, secret);
11242
+ const authErr = checkAuth(req, secret);
11008
11243
  if (authErr) return authErr;
11009
11244
  return {
11010
11245
  status_code: 200,
@@ -11024,7 +11259,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11024
11259
  }
11025
11260
  });
11026
11261
  sdk.registerFunction({ id: "api::action-get" }, async (req) => {
11027
- const authErr = checkAuth$1(req, secret);
11262
+ const authErr = checkAuth(req, secret);
11028
11263
  if (authErr) return authErr;
11029
11264
  const actionId = req.query_params?.["actionId"];
11030
11265
  if (!actionId) return {
@@ -11045,7 +11280,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11045
11280
  }
11046
11281
  });
11047
11282
  sdk.registerFunction({ id: "api::action-edge" }, async (req) => {
11048
- const authErr = checkAuth$1(req, secret);
11283
+ const authErr = checkAuth(req, secret);
11049
11284
  if (authErr) return authErr;
11050
11285
  if (!req.body?.sourceActionId || !req.body?.targetActionId || !req.body?.type) return {
11051
11286
  status_code: 400,
@@ -11065,7 +11300,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11065
11300
  }
11066
11301
  });
11067
11302
  sdk.registerFunction({ id: "api::frontier" }, async (req) => {
11068
- const authErr = checkAuth$1(req, secret);
11303
+ const authErr = checkAuth(req, secret);
11069
11304
  if (authErr) return authErr;
11070
11305
  return {
11071
11306
  status_code: 200,
@@ -11085,7 +11320,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11085
11320
  }
11086
11321
  });
11087
11322
  sdk.registerFunction({ id: "api::next" }, async (req) => {
11088
- const authErr = checkAuth$1(req, secret);
11323
+ const authErr = checkAuth(req, secret);
11089
11324
  if (authErr) return authErr;
11090
11325
  return {
11091
11326
  status_code: 200,
@@ -11104,7 +11339,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11104
11339
  }
11105
11340
  });
11106
11341
  sdk.registerFunction({ id: "api::lease-acquire" }, async (req) => {
11107
- const authErr = checkAuth$1(req, secret);
11342
+ const authErr = checkAuth(req, secret);
11108
11343
  if (authErr) return authErr;
11109
11344
  if (!req.body?.actionId || !req.body?.agentId) return {
11110
11345
  status_code: 400,
@@ -11124,7 +11359,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11124
11359
  }
11125
11360
  });
11126
11361
  sdk.registerFunction({ id: "api::lease-release" }, async (req) => {
11127
- const authErr = checkAuth$1(req, secret);
11362
+ const authErr = checkAuth(req, secret);
11128
11363
  if (authErr) return authErr;
11129
11364
  if (!req.body?.actionId || !req.body?.agentId) return {
11130
11365
  status_code: 400,
@@ -11144,7 +11379,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11144
11379
  }
11145
11380
  });
11146
11381
  sdk.registerFunction({ id: "api::lease-renew" }, async (req) => {
11147
- const authErr = checkAuth$1(req, secret);
11382
+ const authErr = checkAuth(req, secret);
11148
11383
  if (authErr) return authErr;
11149
11384
  if (!req.body?.actionId || !req.body?.agentId) return {
11150
11385
  status_code: 400,
@@ -11164,7 +11399,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11164
11399
  }
11165
11400
  });
11166
11401
  sdk.registerFunction({ id: "api::routine-create" }, async (req) => {
11167
- const authErr = checkAuth$1(req, secret);
11402
+ const authErr = checkAuth(req, secret);
11168
11403
  if (authErr) return authErr;
11169
11404
  if (!req.body?.name) return {
11170
11405
  status_code: 400,
@@ -11184,7 +11419,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11184
11419
  }
11185
11420
  });
11186
11421
  sdk.registerFunction({ id: "api::routine-list" }, async (req) => {
11187
- const authErr = checkAuth$1(req, secret);
11422
+ const authErr = checkAuth(req, secret);
11188
11423
  if (authErr) return authErr;
11189
11424
  return {
11190
11425
  status_code: 200,
@@ -11200,7 +11435,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11200
11435
  }
11201
11436
  });
11202
11437
  sdk.registerFunction({ id: "api::routine-run" }, async (req) => {
11203
- const authErr = checkAuth$1(req, secret);
11438
+ const authErr = checkAuth(req, secret);
11204
11439
  if (authErr) return authErr;
11205
11440
  if (!req.body?.routineId) return {
11206
11441
  status_code: 400,
@@ -11220,7 +11455,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11220
11455
  }
11221
11456
  });
11222
11457
  sdk.registerFunction({ id: "api::routine-status" }, async (req) => {
11223
- const authErr = checkAuth$1(req, secret);
11458
+ const authErr = checkAuth(req, secret);
11224
11459
  if (authErr) return authErr;
11225
11460
  const runId = req.query_params?.["runId"];
11226
11461
  if (!runId) return {
@@ -11241,7 +11476,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11241
11476
  }
11242
11477
  });
11243
11478
  sdk.registerFunction({ id: "api::signal-send" }, async (req) => {
11244
- const authErr = checkAuth$1(req, secret);
11479
+ const authErr = checkAuth(req, secret);
11245
11480
  if (authErr) return authErr;
11246
11481
  if (!req.body?.from || !req.body?.content) return {
11247
11482
  status_code: 400,
@@ -11261,7 +11496,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11261
11496
  }
11262
11497
  });
11263
11498
  sdk.registerFunction({ id: "api::signal-read" }, async (req) => {
11264
- const authErr = checkAuth$1(req, secret);
11499
+ const authErr = checkAuth(req, secret);
11265
11500
  if (authErr) return authErr;
11266
11501
  const agentId = req.query_params?.["agentId"];
11267
11502
  if (!agentId) return {
@@ -11287,7 +11522,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11287
11522
  }
11288
11523
  });
11289
11524
  sdk.registerFunction({ id: "api::checkpoint-create" }, async (req) => {
11290
- const authErr = checkAuth$1(req, secret);
11525
+ const authErr = checkAuth(req, secret);
11291
11526
  if (authErr) return authErr;
11292
11527
  if (!req.body?.name) return {
11293
11528
  status_code: 400,
@@ -11307,7 +11542,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11307
11542
  }
11308
11543
  });
11309
11544
  sdk.registerFunction({ id: "api::checkpoint-resolve" }, async (req) => {
11310
- const authErr = checkAuth$1(req, secret);
11545
+ const authErr = checkAuth(req, secret);
11311
11546
  if (authErr) return authErr;
11312
11547
  if (!req.body?.checkpointId || !req.body?.status) return {
11313
11548
  status_code: 400,
@@ -11327,7 +11562,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11327
11562
  }
11328
11563
  });
11329
11564
  sdk.registerFunction({ id: "api::checkpoint-list" }, async (req) => {
11330
- const authErr = checkAuth$1(req, secret);
11565
+ const authErr = checkAuth(req, secret);
11331
11566
  if (authErr) return authErr;
11332
11567
  return {
11333
11568
  status_code: 200,
@@ -11346,7 +11581,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11346
11581
  }
11347
11582
  });
11348
11583
  sdk.registerFunction({ id: "api::mesh-register" }, async (req) => {
11349
- const authErr = checkAuth$1(req, secret);
11584
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11585
+ if (secretErr) return secretErr;
11586
+ const authErr = checkAuth(req, secret);
11350
11587
  if (authErr) return authErr;
11351
11588
  if (!req.body?.url || !req.body?.name) return {
11352
11589
  status_code: 400,
@@ -11366,7 +11603,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11366
11603
  }
11367
11604
  });
11368
11605
  sdk.registerFunction({ id: "api::mesh-list" }, async (req) => {
11369
- const authErr = checkAuth$1(req, secret);
11606
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11607
+ if (secretErr) return secretErr;
11608
+ const authErr = checkAuth(req, secret);
11370
11609
  if (authErr) return authErr;
11371
11610
  return {
11372
11611
  status_code: 200,
@@ -11382,7 +11621,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11382
11621
  }
11383
11622
  });
11384
11623
  sdk.registerFunction({ id: "api::mesh-sync" }, async (req) => {
11385
- const authErr = checkAuth$1(req, secret);
11624
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11625
+ if (secretErr) return secretErr;
11626
+ const authErr = checkAuth(req, secret);
11386
11627
  if (authErr) return authErr;
11387
11628
  return {
11388
11629
  status_code: 200,
@@ -11398,7 +11639,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11398
11639
  }
11399
11640
  });
11400
11641
  sdk.registerFunction({ id: "api::mesh-receive" }, async (req) => {
11401
- const authErr = checkAuth$1(req, secret);
11642
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11643
+ if (secretErr) return secretErr;
11644
+ const authErr = checkAuth(req, secret);
11402
11645
  if (authErr) return authErr;
11403
11646
  return {
11404
11647
  status_code: 200,
@@ -11414,7 +11657,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11414
11657
  }
11415
11658
  });
11416
11659
  sdk.registerFunction({ id: "api::mesh-export" }, async (req) => {
11417
- const authErr = checkAuth$1(req, secret);
11660
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11661
+ if (secretErr) return secretErr;
11662
+ const authErr = checkAuth(req, secret);
11418
11663
  if (authErr) return authErr;
11419
11664
  const since = req.query_params?.["since"];
11420
11665
  if (since) {
@@ -11460,7 +11705,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11460
11705
  }
11461
11706
  });
11462
11707
  sdk.registerFunction({ id: "api::flow-compress" }, async (req) => {
11463
- const authErr = checkAuth$1(req, secret);
11708
+ const authErr = checkAuth(req, secret);
11464
11709
  if (authErr) return authErr;
11465
11710
  try {
11466
11711
  return {
@@ -11483,7 +11728,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11483
11728
  }
11484
11729
  });
11485
11730
  sdk.registerFunction({ id: "api::branch-detect" }, async (req) => {
11486
- const authErr = checkAuth$1(req, secret);
11731
+ const authErr = checkAuth(req, secret);
11487
11732
  if (authErr) return authErr;
11488
11733
  const cwd = req.query_params?.["cwd"] || process.cwd();
11489
11734
  return {
@@ -11500,7 +11745,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11500
11745
  }
11501
11746
  });
11502
11747
  sdk.registerFunction({ id: "api::branch-worktrees" }, async (req) => {
11503
- const authErr = checkAuth$1(req, secret);
11748
+ const authErr = checkAuth(req, secret);
11504
11749
  if (authErr) return authErr;
11505
11750
  const cwd = req.query_params?.["cwd"] || process.cwd();
11506
11751
  return {
@@ -11517,7 +11762,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11517
11762
  }
11518
11763
  });
11519
11764
  sdk.registerFunction({ id: "api::branch-sessions" }, async (req) => {
11520
- const authErr = checkAuth$1(req, secret);
11765
+ const authErr = checkAuth(req, secret);
11521
11766
  if (authErr) return authErr;
11522
11767
  const cwd = req.query_params?.["cwd"] || process.cwd();
11523
11768
  return {
@@ -11533,27 +11778,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11533
11778
  http_method: "GET"
11534
11779
  }
11535
11780
  });
11536
- sdk.registerFunction({ id: "api::viewer" }, async () => {
11537
- const headers = {
11538
- "Content-Type": "text/html",
11539
- "Content-Security-Policy": VIEWER_CSP
11781
+ sdk.registerFunction({ id: "api::viewer" }, async (req) => {
11782
+ const denied = checkAuth(req, secret);
11783
+ if (denied) return denied;
11784
+ const rendered = renderViewerDocument();
11785
+ if (rendered.found) return {
11786
+ status_code: 200,
11787
+ headers: {
11788
+ "Content-Type": "text/html",
11789
+ "Content-Security-Policy": rendered.csp
11790
+ },
11791
+ body: rendered.html
11540
11792
  };
11541
- const base = dirname(fileURLToPath(import.meta.url));
11542
- const candidates = [
11543
- join(base, "..", "viewer", "index.html"),
11544
- join(base, "..", "src", "viewer", "index.html"),
11545
- join(base, "viewer", "index.html")
11546
- ];
11547
- for (const p of candidates) try {
11548
- return {
11549
- status_code: 200,
11550
- headers,
11551
- body: readFileSync(p, "utf-8")
11552
- };
11553
- } catch {}
11554
11793
  return {
11555
11794
  status_code: 404,
11556
- headers,
11795
+ headers: { "Content-Type": "text/html" },
11557
11796
  body: "<!DOCTYPE html><html><body><h1>agentmemory</h1><p>viewer not found</p></body></html>"
11558
11797
  };
11559
11798
  });
@@ -11566,7 +11805,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11566
11805
  }
11567
11806
  });
11568
11807
  sdk.registerFunction({ id: "api::sentinel-create" }, async (req) => {
11569
- const denied = checkAuth$1(req, secret);
11808
+ const denied = checkAuth(req, secret);
11570
11809
  if (denied) return denied;
11571
11810
  const body = req.body;
11572
11811
  if (!body?.name) return {
@@ -11587,7 +11826,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11587
11826
  }
11588
11827
  });
11589
11828
  sdk.registerFunction({ id: "api::sentinel-trigger" }, async (req) => {
11590
- const denied = checkAuth$1(req, secret);
11829
+ const denied = checkAuth(req, secret);
11591
11830
  if (denied) return denied;
11592
11831
  const body = req.body;
11593
11832
  if (!body?.sentinelId) return {
@@ -11608,7 +11847,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11608
11847
  }
11609
11848
  });
11610
11849
  sdk.registerFunction({ id: "api::sentinel-check" }, async (req) => {
11611
- const denied = checkAuth$1(req, secret);
11850
+ const denied = checkAuth(req, secret);
11612
11851
  if (denied) return denied;
11613
11852
  return {
11614
11853
  status_code: 200,
@@ -11624,7 +11863,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11624
11863
  }
11625
11864
  });
11626
11865
  sdk.registerFunction({ id: "api::sentinel-cancel" }, async (req) => {
11627
- const denied = checkAuth$1(req, secret);
11866
+ const denied = checkAuth(req, secret);
11628
11867
  if (denied) return denied;
11629
11868
  const body = req.body;
11630
11869
  if (!body?.sentinelId) return {
@@ -11645,7 +11884,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11645
11884
  }
11646
11885
  });
11647
11886
  sdk.registerFunction({ id: "api::sentinel-list" }, async (req) => {
11648
- const denied = checkAuth$1(req, secret);
11887
+ const denied = checkAuth(req, secret);
11649
11888
  if (denied) return denied;
11650
11889
  const params = req.query_params || {};
11651
11890
  return {
@@ -11665,7 +11904,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11665
11904
  }
11666
11905
  });
11667
11906
  sdk.registerFunction({ id: "api::sketch-create" }, async (req) => {
11668
- const denied = checkAuth$1(req, secret);
11907
+ const denied = checkAuth(req, secret);
11669
11908
  if (denied) return denied;
11670
11909
  const body = req.body;
11671
11910
  if (!body?.title) return {
@@ -11686,7 +11925,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11686
11925
  }
11687
11926
  });
11688
11927
  sdk.registerFunction({ id: "api::sketch-add" }, async (req) => {
11689
- const denied = checkAuth$1(req, secret);
11928
+ const denied = checkAuth(req, secret);
11690
11929
  if (denied) return denied;
11691
11930
  const body = req.body;
11692
11931
  if (!body?.sketchId || !body?.title) return {
@@ -11707,7 +11946,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11707
11946
  }
11708
11947
  });
11709
11948
  sdk.registerFunction({ id: "api::sketch-promote" }, async (req) => {
11710
- const denied = checkAuth$1(req, secret);
11949
+ const denied = checkAuth(req, secret);
11711
11950
  if (denied) return denied;
11712
11951
  const body = req.body;
11713
11952
  if (!body?.sketchId) return {
@@ -11728,7 +11967,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11728
11967
  }
11729
11968
  });
11730
11969
  sdk.registerFunction({ id: "api::sketch-discard" }, async (req) => {
11731
- const denied = checkAuth$1(req, secret);
11970
+ const denied = checkAuth(req, secret);
11732
11971
  if (denied) return denied;
11733
11972
  const body = req.body;
11734
11973
  if (!body?.sketchId) return {
@@ -11749,7 +11988,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11749
11988
  }
11750
11989
  });
11751
11990
  sdk.registerFunction({ id: "api::sketch-list" }, async (req) => {
11752
- const denied = checkAuth$1(req, secret);
11991
+ const denied = checkAuth(req, secret);
11753
11992
  if (denied) return denied;
11754
11993
  const params = req.query_params || {};
11755
11994
  return {
@@ -11769,7 +12008,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11769
12008
  }
11770
12009
  });
11771
12010
  sdk.registerFunction({ id: "api::sketch-gc" }, async (req) => {
11772
- const denied = checkAuth$1(req, secret);
12011
+ const denied = checkAuth(req, secret);
11773
12012
  if (denied) return denied;
11774
12013
  return {
11775
12014
  status_code: 200,
@@ -11785,7 +12024,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11785
12024
  }
11786
12025
  });
11787
12026
  sdk.registerFunction({ id: "api::crystallize" }, async (req) => {
11788
- const denied = checkAuth$1(req, secret);
12027
+ const denied = checkAuth(req, secret);
11789
12028
  if (denied) return denied;
11790
12029
  const body = req.body;
11791
12030
  if (!body?.actionIds) return {
@@ -11806,7 +12045,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11806
12045
  }
11807
12046
  });
11808
12047
  sdk.registerFunction({ id: "api::crystal-list" }, async (req) => {
11809
- const denied = checkAuth$1(req, secret);
12048
+ const denied = checkAuth(req, secret);
11810
12049
  if (denied) return denied;
11811
12050
  const params = req.query_params || {};
11812
12051
  return {
@@ -11827,7 +12066,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11827
12066
  }
11828
12067
  });
11829
12068
  sdk.registerFunction({ id: "api::auto-crystallize" }, async (req) => {
11830
- const denied = checkAuth$1(req, secret);
12069
+ const denied = checkAuth(req, secret);
11831
12070
  if (denied) return denied;
11832
12071
  const body = req.body;
11833
12072
  return {
@@ -11844,7 +12083,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11844
12083
  }
11845
12084
  });
11846
12085
  sdk.registerFunction({ id: "api::diagnose" }, async (req) => {
11847
- const denied = checkAuth$1(req, secret);
12086
+ const denied = checkAuth(req, secret);
11848
12087
  if (denied) return denied;
11849
12088
  const body = req.body;
11850
12089
  return {
@@ -11861,7 +12100,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11861
12100
  }
11862
12101
  });
11863
12102
  sdk.registerFunction({ id: "api::heal" }, async (req) => {
11864
- const denied = checkAuth$1(req, secret);
12103
+ const denied = checkAuth(req, secret);
11865
12104
  if (denied) return denied;
11866
12105
  const body = req.body;
11867
12106
  return {
@@ -11878,7 +12117,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11878
12117
  }
11879
12118
  });
11880
12119
  sdk.registerFunction({ id: "api::facet-tag" }, async (req) => {
11881
- const denied = checkAuth$1(req, secret);
12120
+ const denied = checkAuth(req, secret);
11882
12121
  if (denied) return denied;
11883
12122
  const body = req.body;
11884
12123
  if (!body?.targetId || !body?.dimension || !body?.value) return {
@@ -11899,7 +12138,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11899
12138
  }
11900
12139
  });
11901
12140
  sdk.registerFunction({ id: "api::facet-untag" }, async (req) => {
11902
- const denied = checkAuth$1(req, secret);
12141
+ const denied = checkAuth(req, secret);
11903
12142
  if (denied) return denied;
11904
12143
  const body = req.body;
11905
12144
  if (!body?.targetId || !body?.dimension) return {
@@ -11920,7 +12159,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11920
12159
  }
11921
12160
  });
11922
12161
  sdk.registerFunction({ id: "api::facet-query" }, async (req) => {
11923
- const denied = checkAuth$1(req, secret);
12162
+ const denied = checkAuth(req, secret);
11924
12163
  if (denied) return denied;
11925
12164
  const body = req.body;
11926
12165
  return {
@@ -11937,7 +12176,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11937
12176
  }
11938
12177
  });
11939
12178
  sdk.registerFunction({ id: "api::facet-get" }, async (req) => {
11940
- const denied = checkAuth$1(req, secret);
12179
+ const denied = checkAuth(req, secret);
11941
12180
  if (denied) return denied;
11942
12181
  const params = req.query_params || {};
11943
12182
  if (!params.targetId) return {
@@ -11958,7 +12197,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11958
12197
  }
11959
12198
  });
11960
12199
  sdk.registerFunction({ id: "api::facet-stats" }, async (req) => {
11961
- const denied = checkAuth$1(req, secret);
12200
+ const denied = checkAuth(req, secret);
11962
12201
  if (denied) return denied;
11963
12202
  const params = req.query_params || {};
11964
12203
  return {
@@ -11975,7 +12214,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11975
12214
  }
11976
12215
  });
11977
12216
  sdk.registerFunction({ id: "api::verify" }, async (req) => {
11978
- const denied = checkAuth$1(req, secret);
12217
+ const denied = checkAuth(req, secret);
11979
12218
  if (denied) return denied;
11980
12219
  const body = req.body;
11981
12220
  if (!body?.id || typeof body.id !== "string") return {
@@ -11996,7 +12235,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11996
12235
  }
11997
12236
  });
11998
12237
  sdk.registerFunction({ id: "api::cascade-update" }, async (req) => {
11999
- const denied = checkAuth$1(req, secret);
12238
+ const denied = checkAuth(req, secret);
12000
12239
  if (denied) return denied;
12001
12240
  const body = req.body;
12002
12241
  if (!body?.supersededMemoryId || typeof body.supersededMemoryId !== "string") return {
@@ -12017,7 +12256,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12017
12256
  }
12018
12257
  });
12019
12258
  sdk.registerFunction({ id: "api::lesson-save" }, async (req) => {
12020
- const denied = checkAuth$1(req, secret);
12259
+ const denied = checkAuth(req, secret);
12021
12260
  if (denied) return denied;
12022
12261
  const body = req.body;
12023
12262
  if (!body?.content || typeof body.content !== "string") return {
@@ -12047,7 +12286,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12047
12286
  }
12048
12287
  });
12049
12288
  sdk.registerFunction({ id: "api::lesson-list" }, async (req) => {
12050
- const denied = checkAuth$1(req, secret);
12289
+ const denied = checkAuth(req, secret);
12051
12290
  if (denied) return denied;
12052
12291
  const params = req.query_params || {};
12053
12292
  return {
@@ -12069,7 +12308,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12069
12308
  }
12070
12309
  });
12071
12310
  sdk.registerFunction({ id: "api::lesson-search" }, async (req) => {
12072
- const denied = checkAuth$1(req, secret);
12311
+ const denied = checkAuth(req, secret);
12073
12312
  if (denied) return denied;
12074
12313
  const body = req.body;
12075
12314
  if (!body?.query || typeof body.query !== "string") return {
@@ -12090,7 +12329,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12090
12329
  }
12091
12330
  });
12092
12331
  sdk.registerFunction({ id: "api::lesson-strengthen" }, async (req) => {
12093
- const denied = checkAuth$1(req, secret);
12332
+ const denied = checkAuth(req, secret);
12094
12333
  if (denied) return denied;
12095
12334
  const body = req.body;
12096
12335
  if (!body?.lessonId || typeof body.lessonId !== "string") return {
@@ -12111,7 +12350,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12111
12350
  }
12112
12351
  });
12113
12352
  sdk.registerFunction({ id: "api::obsidian-export" }, async (req) => {
12114
- const denied = checkAuth$1(req, secret);
12353
+ const denied = checkAuth(req, secret);
12115
12354
  if (denied) return denied;
12116
12355
  const body = req.body || {};
12117
12356
  const types = typeof body.types === "string" ? body.types.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
@@ -12132,7 +12371,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12132
12371
  }
12133
12372
  });
12134
12373
  sdk.registerFunction({ id: "api::reflect" }, async (req) => {
12135
- const denied = checkAuth$1(req, secret);
12374
+ const denied = checkAuth(req, secret);
12136
12375
  if (denied) return denied;
12137
12376
  const body = req.body || {};
12138
12377
  return {
@@ -12152,7 +12391,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12152
12391
  }
12153
12392
  });
12154
12393
  sdk.registerFunction({ id: "api::insight-list" }, async (req) => {
12155
- const denied = checkAuth$1(req, secret);
12394
+ const denied = checkAuth(req, secret);
12156
12395
  if (denied) return denied;
12157
12396
  const params = req.query_params || {};
12158
12397
  return {
@@ -12173,7 +12412,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12173
12412
  }
12174
12413
  });
12175
12414
  sdk.registerFunction({ id: "api::insight-search" }, async (req) => {
12176
- const denied = checkAuth$1(req, secret);
12415
+ const denied = checkAuth(req, secret);
12177
12416
  if (denied) return denied;
12178
12417
  const body = req.body;
12179
12418
  if (!body?.query || typeof body.query !== "string") return {
@@ -14442,11 +14681,6 @@ function readBody(req) {
14442
14681
  req.on("error", reject);
14443
14682
  });
14444
14683
  }
14445
- function checkAuth(req, secret) {
14446
- if (!secret) return true;
14447
- const auth = req.headers["authorization"] || "";
14448
- return typeof auth === "string" && timingSafeCompare(auth, `Bearer ${secret}`);
14449
- }
14450
14684
  function startViewerServer(port, _kv, _sdk, secret, restPort) {
14451
14685
  const resolvedRestPort = restPort ?? port - 2;
14452
14686
  const server = createServer(async (req, res) => {
@@ -14464,32 +14698,20 @@ function startViewerServer(port, _kv, _sdk, secret, restPort) {
14464
14698
  return;
14465
14699
  }
14466
14700
  if (method === "GET" && (pathname === "/" || pathname === "/viewer" || pathname === "/agentmemory/viewer")) {
14467
- const base = dirname(fileURLToPath(import.meta.url));
14468
- const candidates = [
14469
- join(base, "index.html"),
14470
- join(base, "viewer", "index.html"),
14471
- join(base, "..", "viewer", "index.html"),
14472
- join(base, "..", "src", "viewer", "index.html"),
14473
- join(base, "..", "dist", "viewer", "index.html")
14474
- ];
14475
- for (const p of candidates) try {
14476
- const html = readFileSync(p, "utf-8");
14701
+ const rendered = renderViewerDocument();
14702
+ if (rendered.found) {
14477
14703
  res.writeHead(200, {
14478
14704
  "Content-Type": "text/html; charset=utf-8",
14479
- "Content-Security-Policy": VIEWER_CSP,
14705
+ "Content-Security-Policy": rendered.csp,
14480
14706
  "Cache-Control": "no-cache"
14481
14707
  });
14482
- res.end(html);
14708
+ res.end(rendered.html);
14483
14709
  return;
14484
- } catch {}
14710
+ }
14485
14711
  res.writeHead(404, { "Content-Type": "text/plain" });
14486
14712
  res.end("viewer not found");
14487
14713
  return;
14488
14714
  }
14489
- if (!checkAuth(req, secret)) {
14490
- json(res, 401, { error: "unauthorized" }, req);
14491
- return;
14492
- }
14493
14715
  try {
14494
14716
  await proxyToRestApi(resolvedRestPort, pathname, qs, method, req, res, secret);
14495
14717
  } catch (err) {
@@ -14747,7 +14969,7 @@ async function main() {
14747
14969
  registerRoutinesFunction(sdk, kv);
14748
14970
  registerSignalsFunction(sdk, kv);
14749
14971
  registerCheckpointsFunction(sdk, kv);
14750
- registerMeshFunction(sdk, kv);
14972
+ registerMeshFunction(sdk, kv, secret);
14751
14973
  registerBranchAwareFunction(sdk, kv);
14752
14974
  registerFlowCompressFunction(sdk, kv, provider);
14753
14975
  registerSentinelsFunction(sdk, kv);