@agentmemory/agentmemory 0.8.0 → 0.8.5

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.0";
4010
+ const VERSION = "0.8.5";
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,
@@ -4016,7 +4115,12 @@ function registerExportImportFunction(sdk, kv) {
4016
4115
  "0.7.6",
4017
4116
  "0.7.7",
4018
4117
  "0.7.9",
4019
- "0.8.0"
4118
+ "0.8.0",
4119
+ "0.8.1",
4120
+ "0.8.2",
4121
+ "0.8.3",
4122
+ "0.8.4",
4123
+ "0.8.5"
4020
4124
  ]).has(importData.version)) return {
4021
4125
  success: false,
4022
4126
  error: `Unsupported export version: ${importData.version}`
@@ -4026,6 +4130,7 @@ function registerExportImportFunction(sdk, kv) {
4026
4130
  const MAX_SUMMARIES = 1e4;
4027
4131
  const MAX_OBS_PER_SESSION = 5e3;
4028
4132
  const MAX_TOTAL_OBSERVATIONS = 5e5;
4133
+ const MAX_ACCESS_LOGS = 5e4;
4029
4134
  if (!Array.isArray(importData.sessions)) return {
4030
4135
  success: false,
4031
4136
  error: "sessions must be an array"
@@ -4108,6 +4213,7 @@ function registerExportImportFunction(sdk, kv) {
4108
4213
  for (const e of await kv.list(KV.graphEdges).catch(() => [])) await kv.delete(KV.graphEdges, e.id);
4109
4214
  for (const s of await kv.list(KV.semantic).catch(() => [])) await kv.delete(KV.semantic, s.id);
4110
4215
  for (const p of await kv.list(KV.procedural).catch(() => [])) await kv.delete(KV.procedural, p.id);
4216
+ for (const a of await kv.list(KV.accessLog).catch(() => [])) await kv.delete(KV.accessLog, a.memoryId);
4111
4217
  }
4112
4218
  for (const session of importData.sessions) {
4113
4219
  if (strategy === "skip") {
@@ -4284,6 +4390,28 @@ function registerExportImportFunction(sdk, kv) {
4284
4390
  }
4285
4391
  await kv.set(KV.insights, insight.id, insight);
4286
4392
  }
4393
+ if (importData.accessLogs) {
4394
+ if (!Array.isArray(importData.accessLogs)) return {
4395
+ success: false,
4396
+ error: "accessLogs must be an array"
4397
+ };
4398
+ if (importData.accessLogs.length > MAX_ACCESS_LOGS) return {
4399
+ success: false,
4400
+ error: `Too many access logs (max ${MAX_ACCESS_LOGS})`
4401
+ };
4402
+ const memoryIds = new Set(importData.memories.map((m) => m.id));
4403
+ for (const raw of importData.accessLogs) {
4404
+ const log = normalizeAccessLog(raw);
4405
+ if (!log.memoryId || !memoryIds.has(log.memoryId)) continue;
4406
+ if (strategy === "skip") {
4407
+ if (await kv.get(KV.accessLog, log.memoryId).catch(() => null)) {
4408
+ stats.skipped++;
4409
+ continue;
4410
+ }
4411
+ }
4412
+ await kv.set(KV.accessLog, log.memoryId, log);
4413
+ }
4414
+ }
4287
4415
  ctx.logger.info("Import complete", {
4288
4416
  strategy,
4289
4417
  ...stats
@@ -5052,6 +5180,7 @@ function registerGovernanceFunction(sdk, kv) {
5052
5180
  let deleted = 0;
5053
5181
  for (const id of data.memoryIds) if (await kv.get(KV.memories, id)) {
5054
5182
  await kv.delete(KV.memories, id);
5183
+ await deleteAccessLog(kv, id);
5055
5184
  deleted++;
5056
5185
  }
5057
5186
  await recordAudit(kv, "delete", "mem::governance-delete", data.memoryIds, {
@@ -5099,7 +5228,10 @@ function registerGovernanceFunction(sdk, kv) {
5099
5228
  wouldDelete: candidates.length,
5100
5229
  ids: candidates.map((m) => m.id)
5101
5230
  };
5102
- for (const mem of candidates) await kv.delete(KV.memories, mem.id);
5231
+ for (const mem of candidates) {
5232
+ await kv.delete(KV.memories, mem.id);
5233
+ await deleteAccessLog(kv, mem.id);
5234
+ }
5103
5235
  await recordAudit(kv, "delete", "mem::governance-bulk", candidates.map((m) => m.id), {
5104
5236
  filter: data,
5105
5237
  deleted: candidates.length
@@ -5147,6 +5279,7 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5147
5279
  const sessions = await kv.list(KV.sessions);
5148
5280
  const memories = await kv.list(KV.memories);
5149
5281
  const graphNodes = await kv.list(KV.graphNodes);
5282
+ const accessLogs = await kv.list(KV.accessLog).catch(() => []);
5150
5283
  const observations = {};
5151
5284
  for (const session of sessions) {
5152
5285
  const obs = await kv.list(KV.observations(session.id)).catch(() => []);
@@ -5158,7 +5291,8 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5158
5291
  sessions,
5159
5292
  memories,
5160
5293
  graphNodes,
5161
- observations
5294
+ observations,
5295
+ accessLogs
5162
5296
  };
5163
5297
  writeFileSync(join(snapshotDir, "state.json"), JSON.stringify(state, null, 2), "utf-8");
5164
5298
  await gitExec(snapshotDir, ["add", "."]);
@@ -5250,6 +5384,7 @@ function registerSnapshotFunction(sdk, kv, snapshotDir) {
5250
5384
  if (state.memories) for (const memory of state.memories) await kv.set(KV.memories, memory.id, memory);
5251
5385
  if (state.graphNodes) for (const node of state.graphNodes) await kv.set(KV.graphNodes, node.id, node);
5252
5386
  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);
5387
+ if (state.accessLogs) for (const log of state.accessLogs) await kv.set(KV.accessLog, log.memoryId, log);
5253
5388
  await gitExec(snapshotDir, [
5254
5389
  "checkout",
5255
5390
  "HEAD",
@@ -6417,7 +6552,7 @@ async function lwwMergeGraphNodes(kv, items) {
6417
6552
  }
6418
6553
  return count;
6419
6554
  }
6420
- function registerMeshFunction(sdk, kv) {
6555
+ function registerMeshFunction(sdk, kv, meshAuthToken) {
6421
6556
  sdk.registerFunction({ id: "mem::mesh-register" }, async (data) => {
6422
6557
  if (!data.url || !data.name) return {
6423
6558
  success: false,
@@ -6454,6 +6589,10 @@ function registerMeshFunction(sdk, kv) {
6454
6589
  };
6455
6590
  });
6456
6591
  sdk.registerFunction({ id: "mem::mesh-sync" }, async (data) => {
6592
+ if (!meshAuthToken) return {
6593
+ success: false,
6594
+ error: "mesh sync requires AGENTMEMORY_SECRET"
6595
+ };
6457
6596
  const direction = data.direction || "both";
6458
6597
  let peers;
6459
6598
  if (data.peerId) {
@@ -6489,7 +6628,10 @@ function registerMeshFunction(sdk, kv) {
6489
6628
  try {
6490
6629
  const response = await fetch(`${peer.url}/agentmemory/mesh/receive`, {
6491
6630
  method: "POST",
6492
- headers: { "Content-Type": "application/json" },
6631
+ headers: {
6632
+ "Content-Type": "application/json",
6633
+ Authorization: `Bearer ${meshAuthToken}`
6634
+ },
6493
6635
  body: JSON.stringify(pushData),
6494
6636
  signal: AbortSignal.timeout(3e4),
6495
6637
  redirect: "error"
@@ -6502,6 +6644,7 @@ function registerMeshFunction(sdk, kv) {
6502
6644
  }
6503
6645
  if (direction === "pull" || direction === "both") try {
6504
6646
  const response = await fetch(`${peer.url}/agentmemory/mesh/export?since=${peer.lastSyncAt || ""}`, {
6647
+ headers: { Authorization: `Bearer ${meshAuthToken}` },
6505
6648
  signal: AbortSignal.timeout(3e4),
6506
6649
  redirect: "error"
6507
6650
  });
@@ -8362,7 +8505,16 @@ function registerLessonsFunctions(sdk, kv) {
8362
8505
 
8363
8506
  //#endregion
8364
8507
  //#region src/functions/obsidian-export.ts
8365
- const DEFAULT_VAULT = join(homedir(), ".agentmemory", "vault");
8508
+ const DEFAULT_EXPORT_ROOT = join(homedir(), ".agentmemory");
8509
+ function getExportRoot() {
8510
+ return resolve(process.env["AGENTMEMORY_EXPORT_ROOT"] || DEFAULT_EXPORT_ROOT);
8511
+ }
8512
+ function resolveVaultDir(vaultDir) {
8513
+ const root = getExportRoot();
8514
+ const resolved = resolve(vaultDir || join(root, "vault"));
8515
+ if (resolved === root || resolved.startsWith(root + sep)) return resolved;
8516
+ return null;
8517
+ }
8366
8518
  function sanitize(name) {
8367
8519
  return name.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").slice(0, 100);
8368
8520
  }
@@ -8475,7 +8627,11 @@ function sessionToMd(s) {
8475
8627
  }
8476
8628
  function registerObsidianExportFunction(sdk, kv) {
8477
8629
  sdk.registerFunction({ id: "mem::obsidian-export" }, async (data) => {
8478
- const vaultDir = data.vaultDir || DEFAULT_VAULT;
8630
+ const vaultDir = resolveVaultDir(data.vaultDir);
8631
+ if (!vaultDir) return {
8632
+ success: false,
8633
+ error: `vaultDir must be inside ${getExportRoot()}`
8634
+ };
8479
8635
  const exportTypes = new Set(data.types || [
8480
8636
  "memories",
8481
8637
  "lessons",
@@ -9021,12 +9177,15 @@ function registerWorkingMemoryFunctions(sdk, kv, tokenBudget) {
9021
9177
  if (Math.abs(strengthDiff) > .2) return strengthDiff;
9022
9178
  return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
9023
9179
  });
9180
+ const archivalIds = [];
9024
9181
  for (const mem of active) {
9025
9182
  const tokens = estimateTokens(mem.content);
9026
9183
  if (usedTokens + tokens > budget) continue;
9027
9184
  archivalLines.push(`- [${mem.type}] ${mem.title}: ${mem.content}`);
9185
+ archivalIds.push(mem.id);
9028
9186
  usedTokens += tokens;
9029
9187
  }
9188
+ recordAccessBatch(kv, archivalIds);
9030
9189
  const pagedOut = active.length - archivalLines.length;
9031
9190
  const sections = [];
9032
9191
  if (coreLines.length > 0) sections.push(`## Core Memory\n${coreLines.join("\n")}`);
@@ -9780,17 +9939,15 @@ const DEFAULT_DECAY = {
9780
9939
  cold: .15
9781
9940
  }
9782
9941
  };
9783
- function computeRetention(salience, createdAt, accessTimestamps, config) {
9942
+ function computeReinforcementBoost(accessTimestamps, sigma) {
9784
9943
  const now = Date.now();
9785
- const deltaT = (now - new Date(createdAt).getTime()) / (1e3 * 60 * 60 * 24);
9786
- const temporalDecay = Math.exp(-config.lambda * deltaT);
9787
- let reinforcementBoost = 0;
9944
+ let boost = 0;
9788
9945
  for (const tAccess of accessTimestamps) {
9946
+ if (!Number.isFinite(tAccess)) continue;
9789
9947
  const daysSinceAccess = (now - tAccess) / (1e3 * 60 * 60 * 24);
9790
- if (daysSinceAccess > 0) reinforcementBoost += 1 / daysSinceAccess;
9948
+ if (daysSinceAccess > 0) boost += 1 / daysSinceAccess;
9791
9949
  }
9792
- reinforcementBoost *= config.sigma;
9793
- return Math.min(1, salience * temporalDecay + reinforcementBoost);
9950
+ return boost * sigma;
9794
9951
  }
9795
9952
  function computeSalience(memory, accessCount) {
9796
9953
  let baseSalience = .5;
@@ -9816,37 +9973,64 @@ function registerRetentionFunctions(sdk, kv) {
9816
9973
  ...DEFAULT_DECAY,
9817
9974
  ...data.config
9818
9975
  };
9819
- const memories = await kv.list(KV.memories);
9820
- const semanticMems = await kv.list(KV.semantic);
9976
+ const [memories, semanticMems, allLogs] = await Promise.all([
9977
+ kv.list(KV.memories),
9978
+ kv.list(KV.semantic),
9979
+ kv.list(KV.accessLog).catch(() => [])
9980
+ ]);
9981
+ const logsById = /* @__PURE__ */ new Map();
9982
+ for (const raw of allLogs) {
9983
+ const log = normalizeAccessLog(raw);
9984
+ if (log.memoryId) logsById.set(log.memoryId, log);
9985
+ }
9821
9986
  const scores = [];
9987
+ const computeDecay = (createdAt) => Math.exp(-config.lambda * ((Date.now() - new Date(createdAt).getTime()) / (1e3 * 60 * 60 * 24)));
9822
9988
  for (const mem of memories) {
9823
9989
  if (!mem.isLatest) continue;
9824
- const salience = computeSalience(mem, 0);
9825
- const score = computeRetention(salience, mem.createdAt, [], config);
9990
+ const log = logsById.get(mem.id) ?? emptyAccessLog(mem.id);
9991
+ const salience = computeSalience(mem, log.count);
9992
+ const temporalDecay = computeDecay(mem.createdAt);
9993
+ const reinforcementBoost = computeReinforcementBoost(log.recent, config.sigma);
9994
+ const score = Math.min(1, salience * temporalDecay + reinforcementBoost);
9826
9995
  const entry = {
9827
9996
  memoryId: mem.id,
9828
9997
  score,
9829
9998
  salience,
9830
- temporalDecay: Math.exp(-config.lambda * ((Date.now() - new Date(mem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9831
- reinforcementBoost: 0,
9832
- lastAccessed: mem.updatedAt,
9833
- accessCount: 0
9999
+ temporalDecay,
10000
+ reinforcementBoost,
10001
+ lastAccessed: log.lastAt || mem.updatedAt,
10002
+ accessCount: log.count
9834
10003
  };
9835
10004
  scores.push(entry);
9836
10005
  await kv.set(KV.retentionScores, mem.id, entry);
9837
10006
  }
9838
10007
  for (const sem of semanticMems) {
9839
- const accessTimestamps = sem.lastAccessedAt ? [new Date(sem.lastAccessedAt).getTime()] : [];
9840
- const salience = computeSalience(sem, sem.accessCount);
9841
- const score = computeRetention(salience, sem.createdAt, accessTimestamps, config);
10008
+ const log = logsById.get(sem.id) ?? emptyAccessLog(sem.id);
10009
+ let accessTimestamps;
10010
+ let effectiveCount;
10011
+ if (log.recent.length > 0 || log.count > 0) {
10012
+ accessTimestamps = log.recent;
10013
+ effectiveCount = log.count;
10014
+ } else if (sem.lastAccessedAt) {
10015
+ const legacyTs = Date.parse(sem.lastAccessedAt);
10016
+ accessTimestamps = Number.isFinite(legacyTs) ? [legacyTs] : [];
10017
+ effectiveCount = sem.accessCount;
10018
+ } else {
10019
+ accessTimestamps = [];
10020
+ effectiveCount = sem.accessCount;
10021
+ }
10022
+ const salience = computeSalience(sem, effectiveCount);
10023
+ const temporalDecay = computeDecay(sem.createdAt);
10024
+ const reinforcementBoost = computeReinforcementBoost(accessTimestamps, config.sigma);
10025
+ const score = Math.min(1, salience * temporalDecay + reinforcementBoost);
9842
10026
  const entry = {
9843
10027
  memoryId: sem.id,
9844
10028
  score,
9845
10029
  salience,
9846
- temporalDecay: Math.exp(-config.lambda * ((Date.now() - new Date(sem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9847
- reinforcementBoost: score - salience * Math.exp(-config.lambda * ((Date.now() - new Date(sem.createdAt).getTime()) / (1e3 * 60 * 60 * 24))),
9848
- lastAccessed: sem.lastAccessedAt,
9849
- accessCount: sem.accessCount
10030
+ temporalDecay,
10031
+ reinforcementBoost,
10032
+ lastAccessed: log.lastAt || sem.lastAccessedAt,
10033
+ accessCount: effectiveCount
9850
10034
  };
9851
10035
  scores.push(entry);
9852
10036
  await kv.set(KV.retentionScores, sem.id, entry);
@@ -9890,6 +10074,7 @@ function registerRetentionFunctions(sdk, kv) {
9890
10074
  for (const candidate of candidates) try {
9891
10075
  await kv.delete(KV.memories, candidate.memoryId);
9892
10076
  await kv.delete(KV.retentionScores, candidate.memoryId);
10077
+ await deleteAccessLog(kv, candidate.memoryId);
9893
10078
  evicted++;
9894
10079
  } catch {
9895
10080
  continue;
@@ -10045,14 +10230,57 @@ async function getLatestHealth(kv) {
10045
10230
  //#endregion
10046
10231
  //#region src/auth.ts
10047
10232
  const hmacKey = randomBytes(32);
10233
+ const VIEWER_NONCE_PLACEHOLDER = "__AGENTMEMORY_VIEWER_NONCE__";
10048
10234
  function timingSafeCompare(a, b) {
10049
10235
  return timingSafeEqual(createHmac("sha256", hmacKey).update(a).digest(), createHmac("sha256", hmacKey).update(b).digest());
10050
10236
  }
10051
- 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'";
10237
+ function createViewerNonce() {
10238
+ return randomBytes(16).toString("base64url");
10239
+ }
10240
+ function buildViewerCsp(nonce) {
10241
+ return [
10242
+ "default-src 'none'",
10243
+ "base-uri 'none'",
10244
+ "frame-ancestors 'none'",
10245
+ "object-src 'none'",
10246
+ "form-action 'none'",
10247
+ `script-src 'nonce-${nonce}'`,
10248
+ "script-src-attr 'none'",
10249
+ "style-src 'unsafe-inline'",
10250
+ "connect-src 'self' http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:* wss://localhost:* wss://127.0.0.1:*",
10251
+ "img-src 'self'",
10252
+ "font-src 'self'"
10253
+ ].join("; ");
10254
+ }
10255
+
10256
+ //#endregion
10257
+ //#region src/viewer/document.ts
10258
+ function loadViewerTemplate() {
10259
+ const base = dirname(fileURLToPath(import.meta.url));
10260
+ const candidates = [
10261
+ join(base, "..", "src", "viewer", "index.html"),
10262
+ join(base, "..", "viewer", "index.html"),
10263
+ join(base, "viewer", "index.html")
10264
+ ];
10265
+ for (const path of candidates) try {
10266
+ return readFileSync(path, "utf-8");
10267
+ } catch {}
10268
+ return null;
10269
+ }
10270
+ function renderViewerDocument() {
10271
+ const template = loadViewerTemplate();
10272
+ if (!template) return { found: false };
10273
+ const nonce = createViewerNonce();
10274
+ return {
10275
+ found: true,
10276
+ html: template.replaceAll(VIEWER_NONCE_PLACEHOLDER, nonce),
10277
+ csp: buildViewerCsp(nonce)
10278
+ };
10279
+ }
10052
10280
 
10053
10281
  //#endregion
10054
10282
  //#region src/triggers/api.ts
10055
- function checkAuth$1(req, secret) {
10283
+ function checkAuth(req, secret) {
10056
10284
  if (!secret) return null;
10057
10285
  const auth = req.headers?.["authorization"] || req.headers?.["Authorization"];
10058
10286
  if (typeof auth !== "string" || !timingSafeCompare(auth, `Bearer ${secret}`)) return {
@@ -10061,6 +10289,13 @@ function checkAuth$1(req, secret) {
10061
10289
  };
10062
10290
  return null;
10063
10291
  }
10292
+ function requireConfiguredSecret(secret, feature) {
10293
+ if (secret) return null;
10294
+ return {
10295
+ status_code: 503,
10296
+ body: { error: `${feature} requires AGENTMEMORY_SECRET` }
10297
+ };
10298
+ }
10064
10299
  function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10065
10300
  sdk.registerFunction({ id: "api::liveness" }, async () => ({
10066
10301
  status_code: 200,
@@ -10078,7 +10313,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10078
10313
  }
10079
10314
  });
10080
10315
  sdk.registerFunction({ id: "api::health" }, async (req) => {
10081
- const authErr = checkAuth$1(req, secret);
10316
+ const authErr = checkAuth(req, secret);
10082
10317
  if (authErr) return authErr;
10083
10318
  const health = await getLatestHealth(kv);
10084
10319
  const functionMetrics = metricsStore ? await metricsStore.getAll() : [];
@@ -10105,7 +10340,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10105
10340
  }
10106
10341
  });
10107
10342
  sdk.registerFunction({ id: "api::observe" }, async (req) => {
10108
- const authErr = checkAuth$1(req, secret);
10343
+ const authErr = checkAuth(req, secret);
10109
10344
  if (authErr) return authErr;
10110
10345
  return {
10111
10346
  status_code: 201,
@@ -10121,7 +10356,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10121
10356
  }
10122
10357
  });
10123
10358
  sdk.registerFunction({ id: "api::context" }, async (req) => {
10124
- const authErr = checkAuth$1(req, secret);
10359
+ const authErr = checkAuth(req, secret);
10125
10360
  if (authErr) return authErr;
10126
10361
  return {
10127
10362
  status_code: 200,
@@ -10137,7 +10372,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10137
10372
  }
10138
10373
  });
10139
10374
  sdk.registerFunction({ id: "api::search" }, async (req) => {
10140
- const authErr = checkAuth$1(req, secret);
10375
+ const authErr = checkAuth(req, secret);
10141
10376
  if (authErr) return authErr;
10142
10377
  const body = req.body ?? {};
10143
10378
  if (typeof body.query !== "string" || !body.query.trim()) return {
@@ -10176,7 +10411,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10176
10411
  }
10177
10412
  });
10178
10413
  sdk.registerFunction({ id: "api::session::start" }, async (req) => {
10179
- const authErr = checkAuth$1(req, secret);
10414
+ const authErr = checkAuth(req, secret);
10180
10415
  if (authErr) return authErr;
10181
10416
  const { sessionId, project, cwd } = req.body;
10182
10417
  const session = {
@@ -10208,7 +10443,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10208
10443
  }
10209
10444
  });
10210
10445
  sdk.registerFunction({ id: "api::session::end" }, async (req) => {
10211
- const authErr = checkAuth$1(req, secret);
10446
+ const authErr = checkAuth(req, secret);
10212
10447
  if (authErr) return authErr;
10213
10448
  const session = await kv.get(KV.sessions, req.body.sessionId);
10214
10449
  if (session) await kv.set(KV.sessions, req.body.sessionId, {
@@ -10230,7 +10465,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10230
10465
  }
10231
10466
  });
10232
10467
  sdk.registerFunction({ id: "api::summarize" }, async (req) => {
10233
- const authErr = checkAuth$1(req, secret);
10468
+ const authErr = checkAuth(req, secret);
10234
10469
  if (authErr) return authErr;
10235
10470
  return {
10236
10471
  status_code: 200,
@@ -10246,7 +10481,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10246
10481
  }
10247
10482
  });
10248
10483
  sdk.registerFunction({ id: "api::sessions" }, async (req) => {
10249
- const authErr = checkAuth$1(req, secret);
10484
+ const authErr = checkAuth(req, secret);
10250
10485
  if (authErr) return authErr;
10251
10486
  return {
10252
10487
  status_code: 200,
@@ -10262,7 +10497,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10262
10497
  }
10263
10498
  });
10264
10499
  sdk.registerFunction({ id: "api::observations" }, async (req) => {
10265
- const authErr = checkAuth$1(req, secret);
10500
+ const authErr = checkAuth(req, secret);
10266
10501
  if (authErr) return authErr;
10267
10502
  const sessionId = req.query_params["sessionId"];
10268
10503
  if (!sessionId) return {
@@ -10283,7 +10518,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10283
10518
  }
10284
10519
  });
10285
10520
  sdk.registerFunction({ id: "api::file-context" }, async (req) => {
10286
- const authErr = checkAuth$1(req, secret);
10521
+ const authErr = checkAuth(req, secret);
10287
10522
  if (authErr) return authErr;
10288
10523
  return {
10289
10524
  status_code: 200,
@@ -10299,7 +10534,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10299
10534
  }
10300
10535
  });
10301
10536
  sdk.registerFunction({ id: "api::enrich" }, async (req) => {
10302
- const authErr = checkAuth$1(req, secret);
10537
+ const authErr = checkAuth(req, secret);
10303
10538
  if (authErr) return authErr;
10304
10539
  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 {
10305
10540
  status_code: 400,
@@ -10323,7 +10558,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10323
10558
  }
10324
10559
  });
10325
10560
  sdk.registerFunction({ id: "api::remember" }, async (req) => {
10326
- const authErr = checkAuth$1(req, secret);
10561
+ const authErr = checkAuth(req, secret);
10327
10562
  if (authErr) return authErr;
10328
10563
  if (!req.body?.content || typeof req.body.content !== "string" || !req.body.content.trim()) return {
10329
10564
  status_code: 400,
@@ -10343,7 +10578,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10343
10578
  }
10344
10579
  });
10345
10580
  sdk.registerFunction({ id: "api::forget" }, async (req) => {
10346
- const authErr = checkAuth$1(req, secret);
10581
+ const authErr = checkAuth(req, secret);
10347
10582
  if (authErr) return authErr;
10348
10583
  if (!req.body?.sessionId && !req.body?.memoryId) return {
10349
10584
  status_code: 400,
@@ -10363,7 +10598,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10363
10598
  }
10364
10599
  });
10365
10600
  sdk.registerFunction({ id: "api::consolidate" }, async (req) => {
10366
- const authErr = checkAuth$1(req, secret);
10601
+ const authErr = checkAuth(req, secret);
10367
10602
  if (authErr) return authErr;
10368
10603
  return {
10369
10604
  status_code: 200,
@@ -10379,7 +10614,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10379
10614
  }
10380
10615
  });
10381
10616
  sdk.registerFunction({ id: "api::patterns" }, async (req) => {
10382
- const authErr = checkAuth$1(req, secret);
10617
+ const authErr = checkAuth(req, secret);
10383
10618
  if (authErr) return authErr;
10384
10619
  return {
10385
10620
  status_code: 200,
@@ -10395,7 +10630,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10395
10630
  }
10396
10631
  });
10397
10632
  sdk.registerFunction({ id: "api::generate-rules" }, async (req) => {
10398
- const authErr = checkAuth$1(req, secret);
10633
+ const authErr = checkAuth(req, secret);
10399
10634
  if (authErr) return authErr;
10400
10635
  return {
10401
10636
  status_code: 200,
@@ -10411,7 +10646,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10411
10646
  }
10412
10647
  });
10413
10648
  sdk.registerFunction({ id: "api::migrate" }, async (req) => {
10414
- const authErr = checkAuth$1(req, secret);
10649
+ const authErr = checkAuth(req, secret);
10415
10650
  if (authErr) return authErr;
10416
10651
  if (!req.body?.dbPath || typeof req.body.dbPath !== "string") return {
10417
10652
  status_code: 400,
@@ -10431,7 +10666,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10431
10666
  }
10432
10667
  });
10433
10668
  sdk.registerFunction({ id: "api::evict" }, async (req) => {
10434
- const authErr = checkAuth$1(req, secret);
10669
+ const authErr = checkAuth(req, secret);
10435
10670
  if (authErr) return authErr;
10436
10671
  const dryRun = req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
10437
10672
  return {
@@ -10448,7 +10683,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10448
10683
  }
10449
10684
  });
10450
10685
  sdk.registerFunction({ id: "api::smart-search" }, async (req) => {
10451
- const authErr = checkAuth$1(req, secret);
10686
+ const authErr = checkAuth(req, secret);
10452
10687
  if (authErr) return authErr;
10453
10688
  if (!req.body?.query && (!req.body?.expandIds || req.body.expandIds.length === 0)) return {
10454
10689
  status_code: 400,
@@ -10468,7 +10703,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10468
10703
  }
10469
10704
  });
10470
10705
  sdk.registerFunction({ id: "api::timeline" }, async (req) => {
10471
- const authErr = checkAuth$1(req, secret);
10706
+ const authErr = checkAuth(req, secret);
10472
10707
  if (authErr) return authErr;
10473
10708
  if (!req.body?.anchor) return {
10474
10709
  status_code: 400,
@@ -10488,7 +10723,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10488
10723
  }
10489
10724
  });
10490
10725
  sdk.registerFunction({ id: "api::profile" }, async (req) => {
10491
- const authErr = checkAuth$1(req, secret);
10726
+ const authErr = checkAuth(req, secret);
10492
10727
  if (authErr) return authErr;
10493
10728
  const project = req.query_params["project"];
10494
10729
  if (!project) return {
@@ -10509,7 +10744,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10509
10744
  }
10510
10745
  });
10511
10746
  sdk.registerFunction({ id: "api::export" }, async (req) => {
10512
- const authErr = checkAuth$1(req, secret);
10747
+ const authErr = checkAuth(req, secret);
10513
10748
  if (authErr) return authErr;
10514
10749
  return {
10515
10750
  status_code: 200,
@@ -10525,7 +10760,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10525
10760
  }
10526
10761
  });
10527
10762
  sdk.registerFunction({ id: "api::import" }, async (req) => {
10528
- const authErr = checkAuth$1(req, secret);
10763
+ const authErr = checkAuth(req, secret);
10529
10764
  if (authErr) return authErr;
10530
10765
  if (!req.body?.exportData) return {
10531
10766
  status_code: 400,
@@ -10545,7 +10780,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10545
10780
  }
10546
10781
  });
10547
10782
  sdk.registerFunction({ id: "api::relations" }, async (req) => {
10548
- const authErr = checkAuth$1(req, secret);
10783
+ const authErr = checkAuth(req, secret);
10549
10784
  if (authErr) return authErr;
10550
10785
  if (!req.body?.sourceId || !req.body?.targetId || !req.body?.type) return {
10551
10786
  status_code: 400,
@@ -10565,7 +10800,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10565
10800
  }
10566
10801
  });
10567
10802
  sdk.registerFunction({ id: "api::evolve" }, async (req) => {
10568
- const authErr = checkAuth$1(req, secret);
10803
+ const authErr = checkAuth(req, secret);
10569
10804
  if (authErr) return authErr;
10570
10805
  if (!req.body?.memoryId || !req.body?.newContent) return {
10571
10806
  status_code: 400,
@@ -10585,7 +10820,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10585
10820
  }
10586
10821
  });
10587
10822
  sdk.registerFunction({ id: "api::auto-forget" }, async (req) => {
10588
- const authErr = checkAuth$1(req, secret);
10823
+ const authErr = checkAuth(req, secret);
10589
10824
  if (authErr) return authErr;
10590
10825
  const dryRun = req.query_params?.["dryRun"] === "true" || req.body?.dryRun === true;
10591
10826
  return {
@@ -10602,7 +10837,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10602
10837
  }
10603
10838
  });
10604
10839
  sdk.registerFunction({ id: "api::claude-bridge-read" }, async (req) => {
10605
- const authErr = checkAuth$1(req, secret);
10840
+ const authErr = checkAuth(req, secret);
10606
10841
  if (authErr) return authErr;
10607
10842
  try {
10608
10843
  return {
@@ -10625,7 +10860,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10625
10860
  }
10626
10861
  });
10627
10862
  sdk.registerFunction({ id: "api::claude-bridge-sync" }, async (req) => {
10628
- const authErr = checkAuth$1(req, secret);
10863
+ const authErr = checkAuth(req, secret);
10629
10864
  if (authErr) return authErr;
10630
10865
  try {
10631
10866
  return {
@@ -10648,7 +10883,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10648
10883
  }
10649
10884
  });
10650
10885
  sdk.registerFunction({ id: "api::graph-query" }, async (req) => {
10651
- const authErr = checkAuth$1(req, secret);
10886
+ const authErr = checkAuth(req, secret);
10652
10887
  if (authErr) return authErr;
10653
10888
  try {
10654
10889
  return {
@@ -10671,7 +10906,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10671
10906
  }
10672
10907
  });
10673
10908
  sdk.registerFunction({ id: "api::graph-stats" }, async (req) => {
10674
- const authErr = checkAuth$1(req, secret);
10909
+ const authErr = checkAuth(req, secret);
10675
10910
  if (authErr) return authErr;
10676
10911
  try {
10677
10912
  return {
@@ -10694,7 +10929,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10694
10929
  }
10695
10930
  });
10696
10931
  sdk.registerFunction({ id: "api::graph-extract" }, async (req) => {
10697
- const authErr = checkAuth$1(req, secret);
10932
+ const authErr = checkAuth(req, secret);
10698
10933
  if (authErr) return authErr;
10699
10934
  if (!Array.isArray(req.body?.observations) || req.body.observations.length === 0) return {
10700
10935
  status_code: 400,
@@ -10721,7 +10956,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10721
10956
  }
10722
10957
  });
10723
10958
  sdk.registerFunction({ id: "api::consolidate-pipeline" }, async (req) => {
10724
- const authErr = checkAuth$1(req, secret);
10959
+ const authErr = checkAuth(req, secret);
10725
10960
  if (authErr) return authErr;
10726
10961
  try {
10727
10962
  return {
@@ -10744,7 +10979,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10744
10979
  }
10745
10980
  });
10746
10981
  sdk.registerFunction({ id: "api::team-share" }, async (req) => {
10747
- const authErr = checkAuth$1(req, secret);
10982
+ const authErr = checkAuth(req, secret);
10748
10983
  if (authErr) return authErr;
10749
10984
  if (!req.body?.itemId || !req.body?.itemType) return {
10750
10985
  status_code: 400,
@@ -10771,7 +11006,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10771
11006
  }
10772
11007
  });
10773
11008
  sdk.registerFunction({ id: "api::team-feed" }, async (req) => {
10774
- const authErr = checkAuth$1(req, secret);
11009
+ const authErr = checkAuth(req, secret);
10775
11010
  if (authErr) return authErr;
10776
11011
  try {
10777
11012
  const limit = parseInt(req.query_params?.["limit"]) || 20;
@@ -10795,7 +11030,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10795
11030
  }
10796
11031
  });
10797
11032
  sdk.registerFunction({ id: "api::team-profile" }, async (req) => {
10798
- const authErr = checkAuth$1(req, secret);
11033
+ const authErr = checkAuth(req, secret);
10799
11034
  if (authErr) return authErr;
10800
11035
  try {
10801
11036
  return {
@@ -10818,7 +11053,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10818
11053
  }
10819
11054
  });
10820
11055
  sdk.registerFunction({ id: "api::audit" }, async (req) => {
10821
- const authErr = checkAuth$1(req, secret);
11056
+ const authErr = checkAuth(req, secret);
10822
11057
  if (authErr) return authErr;
10823
11058
  return {
10824
11059
  status_code: 200,
@@ -10837,7 +11072,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10837
11072
  }
10838
11073
  });
10839
11074
  sdk.registerFunction({ id: "api::governance-delete" }, async (req) => {
10840
- const authErr = checkAuth$1(req, secret);
11075
+ const authErr = checkAuth(req, secret);
10841
11076
  if (authErr) return authErr;
10842
11077
  if (!req.body?.memoryIds || !Array.isArray(req.body.memoryIds)) return {
10843
11078
  status_code: 400,
@@ -10857,7 +11092,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10857
11092
  }
10858
11093
  });
10859
11094
  sdk.registerFunction({ id: "api::governance-bulk" }, async (req) => {
10860
- const authErr = checkAuth$1(req, secret);
11095
+ const authErr = checkAuth(req, secret);
10861
11096
  if (authErr) return authErr;
10862
11097
  return {
10863
11098
  status_code: 200,
@@ -10873,7 +11108,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10873
11108
  }
10874
11109
  });
10875
11110
  sdk.registerFunction({ id: "api::snapshots" }, async (req) => {
10876
- const authErr = checkAuth$1(req, secret);
11111
+ const authErr = checkAuth(req, secret);
10877
11112
  if (authErr) return authErr;
10878
11113
  try {
10879
11114
  return {
@@ -10896,7 +11131,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10896
11131
  }
10897
11132
  });
10898
11133
  sdk.registerFunction({ id: "api::snapshot-create" }, async (req) => {
10899
- const authErr = checkAuth$1(req, secret);
11134
+ const authErr = checkAuth(req, secret);
10900
11135
  if (authErr) return authErr;
10901
11136
  try {
10902
11137
  return {
@@ -10919,7 +11154,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10919
11154
  }
10920
11155
  });
10921
11156
  sdk.registerFunction({ id: "api::snapshot-restore" }, async (req) => {
10922
- const authErr = checkAuth$1(req, secret);
11157
+ const authErr = checkAuth(req, secret);
10923
11158
  if (authErr) return authErr;
10924
11159
  if (!req.body?.commitHash) return {
10925
11160
  status_code: 400,
@@ -10946,7 +11181,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10946
11181
  }
10947
11182
  });
10948
11183
  sdk.registerFunction({ id: "api::memories" }, async (req) => {
10949
- const authErr = checkAuth$1(req, secret);
11184
+ const authErr = checkAuth(req, secret);
10950
11185
  if (authErr) return authErr;
10951
11186
  const memories = await kv.list(KV.memories);
10952
11187
  return {
@@ -10963,7 +11198,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10963
11198
  }
10964
11199
  });
10965
11200
  sdk.registerFunction({ id: "api::action-create" }, async (req) => {
10966
- const authErr = checkAuth$1(req, secret);
11201
+ const authErr = checkAuth(req, secret);
10967
11202
  if (authErr) return authErr;
10968
11203
  if (!req.body?.title) return {
10969
11204
  status_code: 400,
@@ -10983,7 +11218,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
10983
11218
  }
10984
11219
  });
10985
11220
  sdk.registerFunction({ id: "api::action-update" }, async (req) => {
10986
- const authErr = checkAuth$1(req, secret);
11221
+ const authErr = checkAuth(req, secret);
10987
11222
  if (authErr) return authErr;
10988
11223
  if (!req.body?.actionId) return {
10989
11224
  status_code: 400,
@@ -11003,7 +11238,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11003
11238
  }
11004
11239
  });
11005
11240
  sdk.registerFunction({ id: "api::action-list" }, async (req) => {
11006
- const authErr = checkAuth$1(req, secret);
11241
+ const authErr = checkAuth(req, secret);
11007
11242
  if (authErr) return authErr;
11008
11243
  return {
11009
11244
  status_code: 200,
@@ -11023,7 +11258,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11023
11258
  }
11024
11259
  });
11025
11260
  sdk.registerFunction({ id: "api::action-get" }, async (req) => {
11026
- const authErr = checkAuth$1(req, secret);
11261
+ const authErr = checkAuth(req, secret);
11027
11262
  if (authErr) return authErr;
11028
11263
  const actionId = req.query_params?.["actionId"];
11029
11264
  if (!actionId) return {
@@ -11044,7 +11279,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11044
11279
  }
11045
11280
  });
11046
11281
  sdk.registerFunction({ id: "api::action-edge" }, async (req) => {
11047
- const authErr = checkAuth$1(req, secret);
11282
+ const authErr = checkAuth(req, secret);
11048
11283
  if (authErr) return authErr;
11049
11284
  if (!req.body?.sourceActionId || !req.body?.targetActionId || !req.body?.type) return {
11050
11285
  status_code: 400,
@@ -11064,7 +11299,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11064
11299
  }
11065
11300
  });
11066
11301
  sdk.registerFunction({ id: "api::frontier" }, async (req) => {
11067
- const authErr = checkAuth$1(req, secret);
11302
+ const authErr = checkAuth(req, secret);
11068
11303
  if (authErr) return authErr;
11069
11304
  return {
11070
11305
  status_code: 200,
@@ -11084,7 +11319,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11084
11319
  }
11085
11320
  });
11086
11321
  sdk.registerFunction({ id: "api::next" }, async (req) => {
11087
- const authErr = checkAuth$1(req, secret);
11322
+ const authErr = checkAuth(req, secret);
11088
11323
  if (authErr) return authErr;
11089
11324
  return {
11090
11325
  status_code: 200,
@@ -11103,7 +11338,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11103
11338
  }
11104
11339
  });
11105
11340
  sdk.registerFunction({ id: "api::lease-acquire" }, async (req) => {
11106
- const authErr = checkAuth$1(req, secret);
11341
+ const authErr = checkAuth(req, secret);
11107
11342
  if (authErr) return authErr;
11108
11343
  if (!req.body?.actionId || !req.body?.agentId) return {
11109
11344
  status_code: 400,
@@ -11123,7 +11358,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11123
11358
  }
11124
11359
  });
11125
11360
  sdk.registerFunction({ id: "api::lease-release" }, async (req) => {
11126
- const authErr = checkAuth$1(req, secret);
11361
+ const authErr = checkAuth(req, secret);
11127
11362
  if (authErr) return authErr;
11128
11363
  if (!req.body?.actionId || !req.body?.agentId) return {
11129
11364
  status_code: 400,
@@ -11143,7 +11378,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11143
11378
  }
11144
11379
  });
11145
11380
  sdk.registerFunction({ id: "api::lease-renew" }, async (req) => {
11146
- const authErr = checkAuth$1(req, secret);
11381
+ const authErr = checkAuth(req, secret);
11147
11382
  if (authErr) return authErr;
11148
11383
  if (!req.body?.actionId || !req.body?.agentId) return {
11149
11384
  status_code: 400,
@@ -11163,7 +11398,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11163
11398
  }
11164
11399
  });
11165
11400
  sdk.registerFunction({ id: "api::routine-create" }, async (req) => {
11166
- const authErr = checkAuth$1(req, secret);
11401
+ const authErr = checkAuth(req, secret);
11167
11402
  if (authErr) return authErr;
11168
11403
  if (!req.body?.name) return {
11169
11404
  status_code: 400,
@@ -11183,7 +11418,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11183
11418
  }
11184
11419
  });
11185
11420
  sdk.registerFunction({ id: "api::routine-list" }, async (req) => {
11186
- const authErr = checkAuth$1(req, secret);
11421
+ const authErr = checkAuth(req, secret);
11187
11422
  if (authErr) return authErr;
11188
11423
  return {
11189
11424
  status_code: 200,
@@ -11199,7 +11434,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11199
11434
  }
11200
11435
  });
11201
11436
  sdk.registerFunction({ id: "api::routine-run" }, async (req) => {
11202
- const authErr = checkAuth$1(req, secret);
11437
+ const authErr = checkAuth(req, secret);
11203
11438
  if (authErr) return authErr;
11204
11439
  if (!req.body?.routineId) return {
11205
11440
  status_code: 400,
@@ -11219,7 +11454,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11219
11454
  }
11220
11455
  });
11221
11456
  sdk.registerFunction({ id: "api::routine-status" }, async (req) => {
11222
- const authErr = checkAuth$1(req, secret);
11457
+ const authErr = checkAuth(req, secret);
11223
11458
  if (authErr) return authErr;
11224
11459
  const runId = req.query_params?.["runId"];
11225
11460
  if (!runId) return {
@@ -11240,7 +11475,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11240
11475
  }
11241
11476
  });
11242
11477
  sdk.registerFunction({ id: "api::signal-send" }, async (req) => {
11243
- const authErr = checkAuth$1(req, secret);
11478
+ const authErr = checkAuth(req, secret);
11244
11479
  if (authErr) return authErr;
11245
11480
  if (!req.body?.from || !req.body?.content) return {
11246
11481
  status_code: 400,
@@ -11260,7 +11495,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11260
11495
  }
11261
11496
  });
11262
11497
  sdk.registerFunction({ id: "api::signal-read" }, async (req) => {
11263
- const authErr = checkAuth$1(req, secret);
11498
+ const authErr = checkAuth(req, secret);
11264
11499
  if (authErr) return authErr;
11265
11500
  const agentId = req.query_params?.["agentId"];
11266
11501
  if (!agentId) return {
@@ -11286,7 +11521,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11286
11521
  }
11287
11522
  });
11288
11523
  sdk.registerFunction({ id: "api::checkpoint-create" }, async (req) => {
11289
- const authErr = checkAuth$1(req, secret);
11524
+ const authErr = checkAuth(req, secret);
11290
11525
  if (authErr) return authErr;
11291
11526
  if (!req.body?.name) return {
11292
11527
  status_code: 400,
@@ -11306,7 +11541,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11306
11541
  }
11307
11542
  });
11308
11543
  sdk.registerFunction({ id: "api::checkpoint-resolve" }, async (req) => {
11309
- const authErr = checkAuth$1(req, secret);
11544
+ const authErr = checkAuth(req, secret);
11310
11545
  if (authErr) return authErr;
11311
11546
  if (!req.body?.checkpointId || !req.body?.status) return {
11312
11547
  status_code: 400,
@@ -11326,7 +11561,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11326
11561
  }
11327
11562
  });
11328
11563
  sdk.registerFunction({ id: "api::checkpoint-list" }, async (req) => {
11329
- const authErr = checkAuth$1(req, secret);
11564
+ const authErr = checkAuth(req, secret);
11330
11565
  if (authErr) return authErr;
11331
11566
  return {
11332
11567
  status_code: 200,
@@ -11345,7 +11580,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11345
11580
  }
11346
11581
  });
11347
11582
  sdk.registerFunction({ id: "api::mesh-register" }, async (req) => {
11348
- const authErr = checkAuth$1(req, secret);
11583
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11584
+ if (secretErr) return secretErr;
11585
+ const authErr = checkAuth(req, secret);
11349
11586
  if (authErr) return authErr;
11350
11587
  if (!req.body?.url || !req.body?.name) return {
11351
11588
  status_code: 400,
@@ -11365,7 +11602,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11365
11602
  }
11366
11603
  });
11367
11604
  sdk.registerFunction({ id: "api::mesh-list" }, async (req) => {
11368
- const authErr = checkAuth$1(req, secret);
11605
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11606
+ if (secretErr) return secretErr;
11607
+ const authErr = checkAuth(req, secret);
11369
11608
  if (authErr) return authErr;
11370
11609
  return {
11371
11610
  status_code: 200,
@@ -11381,7 +11620,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11381
11620
  }
11382
11621
  });
11383
11622
  sdk.registerFunction({ id: "api::mesh-sync" }, async (req) => {
11384
- const authErr = checkAuth$1(req, secret);
11623
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11624
+ if (secretErr) return secretErr;
11625
+ const authErr = checkAuth(req, secret);
11385
11626
  if (authErr) return authErr;
11386
11627
  return {
11387
11628
  status_code: 200,
@@ -11397,7 +11638,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11397
11638
  }
11398
11639
  });
11399
11640
  sdk.registerFunction({ id: "api::mesh-receive" }, async (req) => {
11400
- const authErr = checkAuth$1(req, secret);
11641
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11642
+ if (secretErr) return secretErr;
11643
+ const authErr = checkAuth(req, secret);
11401
11644
  if (authErr) return authErr;
11402
11645
  return {
11403
11646
  status_code: 200,
@@ -11413,7 +11656,9 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11413
11656
  }
11414
11657
  });
11415
11658
  sdk.registerFunction({ id: "api::mesh-export" }, async (req) => {
11416
- const authErr = checkAuth$1(req, secret);
11659
+ const secretErr = requireConfiguredSecret(secret, "mesh");
11660
+ if (secretErr) return secretErr;
11661
+ const authErr = checkAuth(req, secret);
11417
11662
  if (authErr) return authErr;
11418
11663
  const since = req.query_params?.["since"];
11419
11664
  if (since) {
@@ -11459,7 +11704,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11459
11704
  }
11460
11705
  });
11461
11706
  sdk.registerFunction({ id: "api::flow-compress" }, async (req) => {
11462
- const authErr = checkAuth$1(req, secret);
11707
+ const authErr = checkAuth(req, secret);
11463
11708
  if (authErr) return authErr;
11464
11709
  try {
11465
11710
  return {
@@ -11482,7 +11727,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11482
11727
  }
11483
11728
  });
11484
11729
  sdk.registerFunction({ id: "api::branch-detect" }, async (req) => {
11485
- const authErr = checkAuth$1(req, secret);
11730
+ const authErr = checkAuth(req, secret);
11486
11731
  if (authErr) return authErr;
11487
11732
  const cwd = req.query_params?.["cwd"] || process.cwd();
11488
11733
  return {
@@ -11499,7 +11744,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11499
11744
  }
11500
11745
  });
11501
11746
  sdk.registerFunction({ id: "api::branch-worktrees" }, async (req) => {
11502
- const authErr = checkAuth$1(req, secret);
11747
+ const authErr = checkAuth(req, secret);
11503
11748
  if (authErr) return authErr;
11504
11749
  const cwd = req.query_params?.["cwd"] || process.cwd();
11505
11750
  return {
@@ -11516,7 +11761,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11516
11761
  }
11517
11762
  });
11518
11763
  sdk.registerFunction({ id: "api::branch-sessions" }, async (req) => {
11519
- const authErr = checkAuth$1(req, secret);
11764
+ const authErr = checkAuth(req, secret);
11520
11765
  if (authErr) return authErr;
11521
11766
  const cwd = req.query_params?.["cwd"] || process.cwd();
11522
11767
  return {
@@ -11532,27 +11777,21 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11532
11777
  http_method: "GET"
11533
11778
  }
11534
11779
  });
11535
- sdk.registerFunction({ id: "api::viewer" }, async () => {
11536
- const headers = {
11537
- "Content-Type": "text/html",
11538
- "Content-Security-Policy": VIEWER_CSP
11780
+ sdk.registerFunction({ id: "api::viewer" }, async (req) => {
11781
+ const denied = checkAuth(req, secret);
11782
+ if (denied) return denied;
11783
+ const rendered = renderViewerDocument();
11784
+ if (rendered.found) return {
11785
+ status_code: 200,
11786
+ headers: {
11787
+ "Content-Type": "text/html",
11788
+ "Content-Security-Policy": rendered.csp
11789
+ },
11790
+ body: rendered.html
11539
11791
  };
11540
- const base = dirname(fileURLToPath(import.meta.url));
11541
- const candidates = [
11542
- join(base, "..", "viewer", "index.html"),
11543
- join(base, "..", "src", "viewer", "index.html"),
11544
- join(base, "viewer", "index.html")
11545
- ];
11546
- for (const p of candidates) try {
11547
- return {
11548
- status_code: 200,
11549
- headers,
11550
- body: readFileSync(p, "utf-8")
11551
- };
11552
- } catch {}
11553
11792
  return {
11554
11793
  status_code: 404,
11555
- headers,
11794
+ headers: { "Content-Type": "text/html" },
11556
11795
  body: "<!DOCTYPE html><html><body><h1>agentmemory</h1><p>viewer not found</p></body></html>"
11557
11796
  };
11558
11797
  });
@@ -11565,7 +11804,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11565
11804
  }
11566
11805
  });
11567
11806
  sdk.registerFunction({ id: "api::sentinel-create" }, async (req) => {
11568
- const denied = checkAuth$1(req, secret);
11807
+ const denied = checkAuth(req, secret);
11569
11808
  if (denied) return denied;
11570
11809
  const body = req.body;
11571
11810
  if (!body?.name) return {
@@ -11586,7 +11825,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11586
11825
  }
11587
11826
  });
11588
11827
  sdk.registerFunction({ id: "api::sentinel-trigger" }, async (req) => {
11589
- const denied = checkAuth$1(req, secret);
11828
+ const denied = checkAuth(req, secret);
11590
11829
  if (denied) return denied;
11591
11830
  const body = req.body;
11592
11831
  if (!body?.sentinelId) return {
@@ -11607,7 +11846,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11607
11846
  }
11608
11847
  });
11609
11848
  sdk.registerFunction({ id: "api::sentinel-check" }, async (req) => {
11610
- const denied = checkAuth$1(req, secret);
11849
+ const denied = checkAuth(req, secret);
11611
11850
  if (denied) return denied;
11612
11851
  return {
11613
11852
  status_code: 200,
@@ -11623,7 +11862,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11623
11862
  }
11624
11863
  });
11625
11864
  sdk.registerFunction({ id: "api::sentinel-cancel" }, async (req) => {
11626
- const denied = checkAuth$1(req, secret);
11865
+ const denied = checkAuth(req, secret);
11627
11866
  if (denied) return denied;
11628
11867
  const body = req.body;
11629
11868
  if (!body?.sentinelId) return {
@@ -11644,7 +11883,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11644
11883
  }
11645
11884
  });
11646
11885
  sdk.registerFunction({ id: "api::sentinel-list" }, async (req) => {
11647
- const denied = checkAuth$1(req, secret);
11886
+ const denied = checkAuth(req, secret);
11648
11887
  if (denied) return denied;
11649
11888
  const params = req.query_params || {};
11650
11889
  return {
@@ -11664,7 +11903,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11664
11903
  }
11665
11904
  });
11666
11905
  sdk.registerFunction({ id: "api::sketch-create" }, async (req) => {
11667
- const denied = checkAuth$1(req, secret);
11906
+ const denied = checkAuth(req, secret);
11668
11907
  if (denied) return denied;
11669
11908
  const body = req.body;
11670
11909
  if (!body?.title) return {
@@ -11685,7 +11924,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11685
11924
  }
11686
11925
  });
11687
11926
  sdk.registerFunction({ id: "api::sketch-add" }, async (req) => {
11688
- const denied = checkAuth$1(req, secret);
11927
+ const denied = checkAuth(req, secret);
11689
11928
  if (denied) return denied;
11690
11929
  const body = req.body;
11691
11930
  if (!body?.sketchId || !body?.title) return {
@@ -11706,7 +11945,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11706
11945
  }
11707
11946
  });
11708
11947
  sdk.registerFunction({ id: "api::sketch-promote" }, async (req) => {
11709
- const denied = checkAuth$1(req, secret);
11948
+ const denied = checkAuth(req, secret);
11710
11949
  if (denied) return denied;
11711
11950
  const body = req.body;
11712
11951
  if (!body?.sketchId) return {
@@ -11727,7 +11966,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11727
11966
  }
11728
11967
  });
11729
11968
  sdk.registerFunction({ id: "api::sketch-discard" }, async (req) => {
11730
- const denied = checkAuth$1(req, secret);
11969
+ const denied = checkAuth(req, secret);
11731
11970
  if (denied) return denied;
11732
11971
  const body = req.body;
11733
11972
  if (!body?.sketchId) return {
@@ -11748,7 +11987,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11748
11987
  }
11749
11988
  });
11750
11989
  sdk.registerFunction({ id: "api::sketch-list" }, async (req) => {
11751
- const denied = checkAuth$1(req, secret);
11990
+ const denied = checkAuth(req, secret);
11752
11991
  if (denied) return denied;
11753
11992
  const params = req.query_params || {};
11754
11993
  return {
@@ -11768,7 +12007,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11768
12007
  }
11769
12008
  });
11770
12009
  sdk.registerFunction({ id: "api::sketch-gc" }, async (req) => {
11771
- const denied = checkAuth$1(req, secret);
12010
+ const denied = checkAuth(req, secret);
11772
12011
  if (denied) return denied;
11773
12012
  return {
11774
12013
  status_code: 200,
@@ -11784,7 +12023,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11784
12023
  }
11785
12024
  });
11786
12025
  sdk.registerFunction({ id: "api::crystallize" }, async (req) => {
11787
- const denied = checkAuth$1(req, secret);
12026
+ const denied = checkAuth(req, secret);
11788
12027
  if (denied) return denied;
11789
12028
  const body = req.body;
11790
12029
  if (!body?.actionIds) return {
@@ -11805,7 +12044,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11805
12044
  }
11806
12045
  });
11807
12046
  sdk.registerFunction({ id: "api::crystal-list" }, async (req) => {
11808
- const denied = checkAuth$1(req, secret);
12047
+ const denied = checkAuth(req, secret);
11809
12048
  if (denied) return denied;
11810
12049
  const params = req.query_params || {};
11811
12050
  return {
@@ -11826,7 +12065,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11826
12065
  }
11827
12066
  });
11828
12067
  sdk.registerFunction({ id: "api::auto-crystallize" }, async (req) => {
11829
- const denied = checkAuth$1(req, secret);
12068
+ const denied = checkAuth(req, secret);
11830
12069
  if (denied) return denied;
11831
12070
  const body = req.body;
11832
12071
  return {
@@ -11843,7 +12082,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11843
12082
  }
11844
12083
  });
11845
12084
  sdk.registerFunction({ id: "api::diagnose" }, async (req) => {
11846
- const denied = checkAuth$1(req, secret);
12085
+ const denied = checkAuth(req, secret);
11847
12086
  if (denied) return denied;
11848
12087
  const body = req.body;
11849
12088
  return {
@@ -11860,7 +12099,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11860
12099
  }
11861
12100
  });
11862
12101
  sdk.registerFunction({ id: "api::heal" }, async (req) => {
11863
- const denied = checkAuth$1(req, secret);
12102
+ const denied = checkAuth(req, secret);
11864
12103
  if (denied) return denied;
11865
12104
  const body = req.body;
11866
12105
  return {
@@ -11877,7 +12116,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11877
12116
  }
11878
12117
  });
11879
12118
  sdk.registerFunction({ id: "api::facet-tag" }, async (req) => {
11880
- const denied = checkAuth$1(req, secret);
12119
+ const denied = checkAuth(req, secret);
11881
12120
  if (denied) return denied;
11882
12121
  const body = req.body;
11883
12122
  if (!body?.targetId || !body?.dimension || !body?.value) return {
@@ -11898,7 +12137,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11898
12137
  }
11899
12138
  });
11900
12139
  sdk.registerFunction({ id: "api::facet-untag" }, async (req) => {
11901
- const denied = checkAuth$1(req, secret);
12140
+ const denied = checkAuth(req, secret);
11902
12141
  if (denied) return denied;
11903
12142
  const body = req.body;
11904
12143
  if (!body?.targetId || !body?.dimension) return {
@@ -11919,7 +12158,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11919
12158
  }
11920
12159
  });
11921
12160
  sdk.registerFunction({ id: "api::facet-query" }, async (req) => {
11922
- const denied = checkAuth$1(req, secret);
12161
+ const denied = checkAuth(req, secret);
11923
12162
  if (denied) return denied;
11924
12163
  const body = req.body;
11925
12164
  return {
@@ -11936,7 +12175,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11936
12175
  }
11937
12176
  });
11938
12177
  sdk.registerFunction({ id: "api::facet-get" }, async (req) => {
11939
- const denied = checkAuth$1(req, secret);
12178
+ const denied = checkAuth(req, secret);
11940
12179
  if (denied) return denied;
11941
12180
  const params = req.query_params || {};
11942
12181
  if (!params.targetId) return {
@@ -11957,7 +12196,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11957
12196
  }
11958
12197
  });
11959
12198
  sdk.registerFunction({ id: "api::facet-stats" }, async (req) => {
11960
- const denied = checkAuth$1(req, secret);
12199
+ const denied = checkAuth(req, secret);
11961
12200
  if (denied) return denied;
11962
12201
  const params = req.query_params || {};
11963
12202
  return {
@@ -11974,7 +12213,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11974
12213
  }
11975
12214
  });
11976
12215
  sdk.registerFunction({ id: "api::verify" }, async (req) => {
11977
- const denied = checkAuth$1(req, secret);
12216
+ const denied = checkAuth(req, secret);
11978
12217
  if (denied) return denied;
11979
12218
  const body = req.body;
11980
12219
  if (!body?.id || typeof body.id !== "string") return {
@@ -11995,7 +12234,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
11995
12234
  }
11996
12235
  });
11997
12236
  sdk.registerFunction({ id: "api::cascade-update" }, async (req) => {
11998
- const denied = checkAuth$1(req, secret);
12237
+ const denied = checkAuth(req, secret);
11999
12238
  if (denied) return denied;
12000
12239
  const body = req.body;
12001
12240
  if (!body?.supersededMemoryId || typeof body.supersededMemoryId !== "string") return {
@@ -12016,7 +12255,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12016
12255
  }
12017
12256
  });
12018
12257
  sdk.registerFunction({ id: "api::lesson-save" }, async (req) => {
12019
- const denied = checkAuth$1(req, secret);
12258
+ const denied = checkAuth(req, secret);
12020
12259
  if (denied) return denied;
12021
12260
  const body = req.body;
12022
12261
  if (!body?.content || typeof body.content !== "string") return {
@@ -12046,7 +12285,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12046
12285
  }
12047
12286
  });
12048
12287
  sdk.registerFunction({ id: "api::lesson-list" }, async (req) => {
12049
- const denied = checkAuth$1(req, secret);
12288
+ const denied = checkAuth(req, secret);
12050
12289
  if (denied) return denied;
12051
12290
  const params = req.query_params || {};
12052
12291
  return {
@@ -12068,7 +12307,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12068
12307
  }
12069
12308
  });
12070
12309
  sdk.registerFunction({ id: "api::lesson-search" }, async (req) => {
12071
- const denied = checkAuth$1(req, secret);
12310
+ const denied = checkAuth(req, secret);
12072
12311
  if (denied) return denied;
12073
12312
  const body = req.body;
12074
12313
  if (!body?.query || typeof body.query !== "string") return {
@@ -12089,7 +12328,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12089
12328
  }
12090
12329
  });
12091
12330
  sdk.registerFunction({ id: "api::lesson-strengthen" }, async (req) => {
12092
- const denied = checkAuth$1(req, secret);
12331
+ const denied = checkAuth(req, secret);
12093
12332
  if (denied) return denied;
12094
12333
  const body = req.body;
12095
12334
  if (!body?.lessonId || typeof body.lessonId !== "string") return {
@@ -12110,7 +12349,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12110
12349
  }
12111
12350
  });
12112
12351
  sdk.registerFunction({ id: "api::obsidian-export" }, async (req) => {
12113
- const denied = checkAuth$1(req, secret);
12352
+ const denied = checkAuth(req, secret);
12114
12353
  if (denied) return denied;
12115
12354
  const body = req.body || {};
12116
12355
  const types = typeof body.types === "string" ? body.types.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
@@ -12131,7 +12370,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12131
12370
  }
12132
12371
  });
12133
12372
  sdk.registerFunction({ id: "api::reflect" }, async (req) => {
12134
- const denied = checkAuth$1(req, secret);
12373
+ const denied = checkAuth(req, secret);
12135
12374
  if (denied) return denied;
12136
12375
  const body = req.body || {};
12137
12376
  return {
@@ -12151,7 +12390,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12151
12390
  }
12152
12391
  });
12153
12392
  sdk.registerFunction({ id: "api::insight-list" }, async (req) => {
12154
- const denied = checkAuth$1(req, secret);
12393
+ const denied = checkAuth(req, secret);
12155
12394
  if (denied) return denied;
12156
12395
  const params = req.query_params || {};
12157
12396
  return {
@@ -12172,7 +12411,7 @@ function registerApiTriggers(sdk, kv, secret, metricsStore, provider) {
12172
12411
  }
12173
12412
  });
12174
12413
  sdk.registerFunction({ id: "api::insight-search" }, async (req) => {
12175
- const denied = checkAuth$1(req, secret);
12414
+ const denied = checkAuth(req, secret);
12176
12415
  if (denied) return denied;
12177
12416
  const body = req.body;
12178
12417
  if (!body?.query || typeof body.query !== "string") return {
@@ -14441,11 +14680,6 @@ function readBody(req) {
14441
14680
  req.on("error", reject);
14442
14681
  });
14443
14682
  }
14444
- function checkAuth(req, secret) {
14445
- if (!secret) return true;
14446
- const auth = req.headers["authorization"] || "";
14447
- return typeof auth === "string" && timingSafeCompare(auth, `Bearer ${secret}`);
14448
- }
14449
14683
  function startViewerServer(port, _kv, _sdk, secret, restPort) {
14450
14684
  const resolvedRestPort = restPort ?? port - 2;
14451
14685
  const server = createServer(async (req, res) => {
@@ -14463,30 +14697,20 @@ function startViewerServer(port, _kv, _sdk, secret, restPort) {
14463
14697
  return;
14464
14698
  }
14465
14699
  if (method === "GET" && (pathname === "/" || pathname === "/viewer" || pathname === "/agentmemory/viewer")) {
14466
- const base = dirname(fileURLToPath(import.meta.url));
14467
- const candidates = [
14468
- join(base, "..", "src", "viewer", "index.html"),
14469
- join(base, "..", "viewer", "index.html"),
14470
- join(base, "viewer", "index.html")
14471
- ];
14472
- for (const p of candidates) try {
14473
- const html = readFileSync(p, "utf-8");
14700
+ const rendered = renderViewerDocument();
14701
+ if (rendered.found) {
14474
14702
  res.writeHead(200, {
14475
14703
  "Content-Type": "text/html; charset=utf-8",
14476
- "Content-Security-Policy": VIEWER_CSP,
14704
+ "Content-Security-Policy": rendered.csp,
14477
14705
  "Cache-Control": "no-cache"
14478
14706
  });
14479
- res.end(html);
14707
+ res.end(rendered.html);
14480
14708
  return;
14481
- } catch {}
14709
+ }
14482
14710
  res.writeHead(404, { "Content-Type": "text/plain" });
14483
14711
  res.end("viewer not found");
14484
14712
  return;
14485
14713
  }
14486
- if (!checkAuth(req, secret)) {
14487
- json(res, 401, { error: "unauthorized" }, req);
14488
- return;
14489
- }
14490
14714
  try {
14491
14715
  await proxyToRestApi(resolvedRestPort, pathname, qs, method, req, res, secret);
14492
14716
  } catch (err) {
@@ -14744,7 +14968,7 @@ async function main() {
14744
14968
  registerRoutinesFunction(sdk, kv);
14745
14969
  registerSignalsFunction(sdk, kv);
14746
14970
  registerCheckpointsFunction(sdk, kv);
14747
- registerMeshFunction(sdk, kv);
14971
+ registerMeshFunction(sdk, kv, secret);
14748
14972
  registerBranchAwareFunction(sdk, kv);
14749
14973
  registerFlowCompressFunction(sdk, kv, provider);
14750
14974
  registerSentinelsFunction(sdk, kv);