claude-memory-layer 1.0.45 → 1.0.47
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/README.md +4 -2
- package/dist/cli/index.js +126 -12
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +1209 -24
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +125 -11
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +125 -11
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +125 -11
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +125 -11
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +125 -11
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +125 -11
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +1215 -30
- package/dist/index.js.map +4 -4
- package/dist/mcp/index.js +305 -45
- package/dist/mcp/index.js.map +2 -2
- package/dist/server/api/index.js +125 -11
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +125 -11
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +125 -11
- package/dist/services/memory-service.js.map +2 -2
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ Claude Memory Layer는 AI 에이전트의 대화와 작업 이벤트를 프로
|
|
|
21
21
|
- **Vector Outbox V2**: SQLite source write와 vector enqueue를 같은 트랜잭션으로 묶고, versioned LanceDB upsert와 stuck-job recovery를 지원합니다.
|
|
22
22
|
- **Dashboard 운영성 강화**: local-only 기본 bind, 선택적 password gate, Vector Health 카드, Perspective Memory aggregate 카드, retrieval trace/score breakdown을 제공합니다.
|
|
23
23
|
- **Codex/Hermes history ingest**: 원본 세션은 read-only validate/replay로 먼저 확인하고, 명시적 import로만 프로젝트 메모리에 반영합니다.
|
|
24
|
+
- **Hermes/CML/Headroom 운영 모델**: Hermes built-in memory, `session_search`, CML context-pack, read-only Hermes provider, Headroom reference stance는 [`docs/HERMES_CML_HEADROOM_OPERATING_MODEL.md`](docs/HERMES_CML_HEADROOM_OPERATING_MODEL.md)에 정리되어 있습니다.
|
|
24
25
|
- **npm 설치 안정화**: `@huggingface/transformers`는 optional dependency + postinstall repair로 설치하며, CUDA 11 환경에서는 CPU-only ONNX Runtime으로 자동 복구합니다.
|
|
25
26
|
|
|
26
27
|
## 빠른 시작 (신규 프로젝트 기준)
|
|
@@ -311,6 +312,7 @@ MCP client가 환경에 따라 PATH를 못 찾으면 `command -v claude-memory-l
|
|
|
311
312
|
### Advanced Features
|
|
312
313
|
|
|
313
314
|
- **Citations System**: 검색 결과를 `[mem:abc123]` 형태로 추적하고 `source`/`mem-source-ref`로 근거 확인
|
|
315
|
+
- **Source Neighbor Expansion**: `mem-source-ref(includeNeighbors=true, neighborWindow=1..5)`로 MemPalace식 hit 주변 세션 이벤트를 privacy-safe preview로 함께 확인
|
|
314
316
|
- **Progressive Disclosure**: index → timeline → details 순서로 필요한 만큼만 확장해 토큰 비용 절감
|
|
315
317
|
- **Codex/Hermes Importers**: read-only validate/replay 후 explicit import로만 mutation 수행
|
|
316
318
|
- **Perspective Query Agent**: 관점별 observation + raw memory를 읽기 전용으로 조합하고 source refs를 유지
|
|
@@ -680,7 +682,7 @@ node dist/mcp/index.js
|
|
|
680
682
|
| Context | `mem-context-pack` | 작업 시작용 relevant memory + recent timeline + follow-up refs |
|
|
681
683
|
| Context | `mem-import-latest` | 최신 Claude/Codex/Hermes 세션을 bounded import 후 context-pack freshness 확보 |
|
|
682
684
|
| Context | `mem-project-timeline` | 최근 프로젝트 메모리를 session/source/count/safe-preview로 요약 |
|
|
683
|
-
| Context | `mem-source-ref` | `mem:`/`event:` ref를 redacted preview와 safe metadata로
|
|
685
|
+
| Context | `mem-source-ref` | `mem:`/`event:` ref를 redacted preview와 safe metadata로 해석; `includeNeighbors` + `neighborWindow`로 같은 세션의 전후 이벤트를 bounded/privacy-safe preview로 확장 |
|
|
684
686
|
| Operations | `mem-facet-query` / `mem-facet-tag` | project-scoped facet 조회/태깅 |
|
|
685
687
|
| Operations | `mem-action-list` / `mem-action-update` | 다음 작업/action 상태 조회·갱신 |
|
|
686
688
|
| Operations | `mem-frontier` | blocked/next action frontier와 safe resume hints |
|
|
@@ -702,7 +704,7 @@ node dist/mcp/index.js
|
|
|
702
704
|
```text
|
|
703
705
|
1. 새 작업 시작: mem-context-pack(projectPath, query)
|
|
704
706
|
2. 최근 흐름 확인: mem-project-timeline(projectPath)
|
|
705
|
-
3. 근거가 더 필요할 때: mem-source-ref(projectPath, ids=["mem:abc123"])
|
|
707
|
+
3. 근거가 더 필요할 때: mem-source-ref(projectPath, ids=["mem:abc123"], includeNeighbors=true, neighborWindow=1)
|
|
706
708
|
```
|
|
707
709
|
|
|
708
710
|
이 workflow는 Hermes/Codex/Claude Code가 같은 project-scoped memory backend를 공유할 때 특히 유용합니다. `mem-source-ref`는 raw transcript를 그대로 덤프하지 않고 allowlisted metadata와 privacy-filtered preview만 반환합니다.
|
package/dist/cli/index.js
CHANGED
|
@@ -2574,6 +2574,7 @@ var VectorOutbox = class {
|
|
|
2574
2574
|
// src/core/retrieval-debug-lanes.ts
|
|
2575
2575
|
var RETRIEVAL_DEBUG_LANE_NAMES = [
|
|
2576
2576
|
"raw_event",
|
|
2577
|
+
"session_event",
|
|
2577
2578
|
"session_summary",
|
|
2578
2579
|
"graph_path",
|
|
2579
2580
|
"facet_match"
|
|
@@ -9926,6 +9927,18 @@ var COMMAND_ARTIFACT_PATTERNS = [
|
|
|
9926
9927
|
/<local-command-stdout>[\s\S]*?<\/local-command-stdout>/i,
|
|
9927
9928
|
/<local-command-stderr>[\s\S]*?<\/local-command-stderr>/i
|
|
9928
9929
|
];
|
|
9930
|
+
var LOW_SIGNAL_CONTEXT_PATTERNS = [
|
|
9931
|
+
/<environment_context\b[\s\S]*<\/environment_context>/i,
|
|
9932
|
+
/<turn_aborted>/i,
|
|
9933
|
+
/^#\s*AGENTS\.md\s+instructions\b[\s\S]*<INSTRUCTIONS>/i,
|
|
9934
|
+
/^\s*(?:understood[,\s.]*)?(?:stopping|stopped|pausing|paused)\s+here\b[\s\S]{0,180}\blet\s+me\s+know\s+when\s+you(?:'d|\s+would)?\s+like\s+to\s+continue\b/i,
|
|
9935
|
+
/^\s*\[?CONTEXT\s+COMPACTION\s*[—-]\s*REFERENCE\s+ONLY\]?\b[\s\S]{0,600}\b(?:earlier\s+turns\s+were\s+compacted|handoff\s+from\s+a\s+previous\s+context\s+window|active\s+task)\b/i,
|
|
9936
|
+
/^\s*Summary\s+generation\s+was\s+unavailable\.\s*\d+\s+message\(s\)\s+were\s+removed\s+to\s+free\s+context\s+space\b/i,
|
|
9937
|
+
/^\s*---\s*END\s+OF\s+CONTEXT\s+SUMMARY\b/i,
|
|
9938
|
+
/^\s*\[Your\s+active\s+task\s+list\s+was\s+preserved\s+across\s+context\s+compression\]/i,
|
|
9939
|
+
/^➜\s+\S+\s+git:\([^)]*\)\s+/i,
|
|
9940
|
+
/^\$\s+\S+/i
|
|
9941
|
+
];
|
|
9929
9942
|
var CONTINUATION_QUERY_PATTERNS = [
|
|
9930
9943
|
/^\s*(?:continue|resume|next|what(?:'s| is)? next|next\s+(?:step|task|action)|recommended\s+(?:next\s+)?(?:step|task|action)|what should (?:we|i) do next)\??\s*$/i,
|
|
9931
9944
|
/^\s*(?:응\s*)?(?:이어서(?:\s*진행(?:해줘)?)?|계속(?:\s*해줘)?|다음\s*(?:단계|작업|추천\s*작업|추천|할\s*일)?(?:은|는)?(?:\s*(?:뭐야|진행(?:해줘)?))?\??|남은\s*(?:추가(?:로)?\s*)?(?:(?:할\s*만한\s*)?(?:작업|일)|할\s*일)?(?:은|는)?\s*(?:있어|있나|있나요|뭐야)\??|추천\s*작업(?:은|는)?(?:\s*뭐야)?\??|진행해줘)\s*$/i
|
|
@@ -9937,7 +9950,7 @@ var SHORT_REPAIR_FOLLOW_UP_PATTERNS = [
|
|
|
9937
9950
|
var CURRENT_STATE_QUERY_PATTERNS = [
|
|
9938
9951
|
/\bcurrent\b.*\b(?:state|status|deployment|blocker|pr|pull request)\b/i,
|
|
9939
9952
|
/\b(?:still|as current|current)\b.*\b(?:unresolved|open|pending|not completed)\b/i,
|
|
9940
|
-
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|
|
|
9953
|
+
/\b(?:old|obsolete|stale|resolved|already resolved)\b.*\b(?:current|still|unresolved|open|status)\b/i,
|
|
9941
9954
|
/(?:현재|아직|이전|오래된|해결된).*(?:상태|미해결|열린|블로커|PR|풀리퀘스트)/i
|
|
9942
9955
|
];
|
|
9943
9956
|
var STALE_CONTENT_PATTERNS = [
|
|
@@ -10083,6 +10096,21 @@ function isCommandArtifactQuery(query) {
|
|
|
10083
10096
|
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
10084
10097
|
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
10085
10098
|
}
|
|
10099
|
+
function isCommandArtifactContent(content) {
|
|
10100
|
+
const trimmed = content.trim();
|
|
10101
|
+
if (!trimmed) return false;
|
|
10102
|
+
const normalized = trimmed.toLowerCase();
|
|
10103
|
+
if (normalized.includes("local-command-stdout") || normalized.includes("local-command-stderr")) return true;
|
|
10104
|
+
if (normalized.includes("command-name") || normalized.includes("command-message")) return true;
|
|
10105
|
+
return COMMAND_ARTIFACT_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
10106
|
+
}
|
|
10107
|
+
function isLowSignalContextContent(content) {
|
|
10108
|
+
const trimmed = content.trim();
|
|
10109
|
+
if (!trimmed) return true;
|
|
10110
|
+
if (isCommandArtifactContent(trimmed)) return true;
|
|
10111
|
+
if (LOW_SIGNAL_CONTEXT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
10112
|
+
return false;
|
|
10113
|
+
}
|
|
10086
10114
|
function isGenericContinuationQuery(query) {
|
|
10087
10115
|
const trimmed = query.trim();
|
|
10088
10116
|
if (!trimmed) return false;
|
|
@@ -10100,6 +10128,16 @@ function isShortRepairFollowUpQuery(query) {
|
|
|
10100
10128
|
if (tokens.length > 8) return false;
|
|
10101
10129
|
return SHORT_REPAIR_FOLLOW_UP_PATTERNS.some((pattern) => pattern.test(trimmed));
|
|
10102
10130
|
}
|
|
10131
|
+
function isLowConfidenceContextFallbackQuery(query) {
|
|
10132
|
+
const trimmed = query.trim();
|
|
10133
|
+
if (!trimmed) return false;
|
|
10134
|
+
if (isGenericContinuationQuery(trimmed) || isShortRepairFollowUpQuery(trimmed)) return true;
|
|
10135
|
+
const terms = new Set(tokenizeQualityText(trimmed));
|
|
10136
|
+
if ((terms.has("compacted") || terms.has("compaction")) && terms.has("handoff")) return false;
|
|
10137
|
+
const hasContinuationRecall = /^(?:continue|resume)\b/i.test(trimmed) && (terms.has("work") || terms.has("step") || terms.has("task") || terms.has("last") || terms.has("completed"));
|
|
10138
|
+
const hasValidationGateRecall = terms.has("validation") && (terms.has("gate") || terms.has("check")) && (terms.has("run") || terms.has("before") || terms.has("commit") || terms.has("committing") || terms.has("change"));
|
|
10139
|
+
return hasContinuationRecall || hasValidationGateRecall;
|
|
10140
|
+
}
|
|
10103
10141
|
function isCurrentStateQuery(query) {
|
|
10104
10142
|
const trimmed = query.trim();
|
|
10105
10143
|
if (!trimmed) return false;
|
|
@@ -10273,6 +10311,7 @@ var Retriever = class {
|
|
|
10273
10311
|
}
|
|
10274
10312
|
async retrieve(query, options = {}) {
|
|
10275
10313
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
10314
|
+
const retrievalMode = options.retrievalMode ?? ((options.strategy ?? DEFAULT_OPTIONS.strategy) === "auto" ? "session-event-hybrid" : "event");
|
|
10276
10315
|
const sessionFilter = opts.scope?.sessionId ?? opts.sessionId;
|
|
10277
10316
|
const fallbackTrace = [];
|
|
10278
10317
|
const qualityQuery = buildRetrievalQualityQuery(query);
|
|
@@ -10303,6 +10342,7 @@ var Retriever = class {
|
|
|
10303
10342
|
decayPolicy: opts.decayPolicy,
|
|
10304
10343
|
intentRewrite: opts.intentRewrite === true,
|
|
10305
10344
|
graphHop: opts.graphHop,
|
|
10345
|
+
retrievalMode,
|
|
10306
10346
|
projectScopeMode: opts.projectScopeMode,
|
|
10307
10347
|
projectHash: opts.projectHash,
|
|
10308
10348
|
allowedProjectHashes: opts.allowedProjectHashes,
|
|
@@ -10321,6 +10361,7 @@ var Retriever = class {
|
|
|
10321
10361
|
rerankWeights: opts.rerankWeights,
|
|
10322
10362
|
decayPolicy: opts.decayPolicy,
|
|
10323
10363
|
graphHop: opts.graphHop,
|
|
10364
|
+
retrievalMode,
|
|
10324
10365
|
projectScopeMode: opts.projectScopeMode,
|
|
10325
10366
|
projectHash: opts.projectHash,
|
|
10326
10367
|
allowedProjectHashes: opts.allowedProjectHashes,
|
|
@@ -10340,6 +10381,7 @@ var Retriever = class {
|
|
|
10340
10381
|
rerankWeights: opts.rerankWeights,
|
|
10341
10382
|
decayPolicy: opts.decayPolicy,
|
|
10342
10383
|
graphHop: opts.graphHop,
|
|
10384
|
+
retrievalMode,
|
|
10343
10385
|
projectScopeMode: opts.projectScopeMode,
|
|
10344
10386
|
projectHash: opts.projectHash,
|
|
10345
10387
|
allowedProjectHashes: opts.allowedProjectHashes,
|
|
@@ -10360,14 +10402,37 @@ var Retriever = class {
|
|
|
10360
10402
|
query,
|
|
10361
10403
|
minScore: opts.minScore
|
|
10362
10404
|
});
|
|
10405
|
+
const expandedSummary = retrievalMode === "session-event-hybrid" ? await this.expandSessionEventHybrid(filteredSummary, {
|
|
10406
|
+
query: qualityQuery,
|
|
10407
|
+
currentStateQuery: query,
|
|
10408
|
+
limit: opts.topK * 4
|
|
10409
|
+
}) : filteredSummary;
|
|
10410
|
+
const scopedExpandedSummary = retrievalMode === "session-event-hybrid" ? await this.applyScopeFilters(expandedSummary, {
|
|
10411
|
+
scope: opts.scope,
|
|
10412
|
+
projectScopeMode: opts.projectScopeMode,
|
|
10413
|
+
projectHash: opts.projectHash,
|
|
10414
|
+
allowedProjectHashes: opts.allowedProjectHashes,
|
|
10415
|
+
facets: opts.facets
|
|
10416
|
+
}) : expandedSummary;
|
|
10417
|
+
const finalSummary = retrievalMode === "session-event-hybrid" ? this.applyQualityFilters(scopedExpandedSummary, {
|
|
10418
|
+
query,
|
|
10419
|
+
minScore: opts.minScore
|
|
10420
|
+
}) : scopedExpandedSummary;
|
|
10363
10421
|
current = {
|
|
10364
|
-
results:
|
|
10365
|
-
candidateResults:
|
|
10366
|
-
matchResult: this.matcher.matchSearchResults(
|
|
10422
|
+
results: finalSummary,
|
|
10423
|
+
candidateResults: finalSummary,
|
|
10424
|
+
matchResult: this.matcher.matchSearchResults(finalSummary, () => 0)
|
|
10367
10425
|
};
|
|
10368
10426
|
fallbackTrace.push("fallback:summary");
|
|
10369
10427
|
}
|
|
10370
|
-
const
|
|
10428
|
+
const selectedResults = current.results.slice(0, opts.topK).filter((result) => {
|
|
10429
|
+
if (current.matchResult.confidence !== "none") return true;
|
|
10430
|
+
if (isLowConfidenceContextFallbackQuery(query)) {
|
|
10431
|
+
return (result.semanticScore ?? result.score) >= 0.5 || result.score >= 0.5;
|
|
10432
|
+
}
|
|
10433
|
+
return (result.semanticScore ?? result.score) >= 0.62 || result.score >= 0.62;
|
|
10434
|
+
});
|
|
10435
|
+
const memories = await this.enrichResults(selectedResults, opts, query);
|
|
10371
10436
|
const context = this.buildContext(memories, opts.maxTokens);
|
|
10372
10437
|
return {
|
|
10373
10438
|
memories,
|
|
@@ -10375,7 +10440,7 @@ var Retriever = class {
|
|
|
10375
10440
|
totalTokens: this.estimateTokens(context),
|
|
10376
10441
|
context,
|
|
10377
10442
|
fallbackTrace,
|
|
10378
|
-
selectedDebug:
|
|
10443
|
+
selectedDebug: selectedResults.map((r) => this.debugDetailForResult(r)),
|
|
10379
10444
|
candidateDebug: (current.candidateResults || []).slice(0, Math.max(opts.topK * 3, 20)).map((r) => this.debugDetailForResult(r)),
|
|
10380
10445
|
rawQueryText: current.queryRewriteKind ? query : void 0,
|
|
10381
10446
|
effectiveQueryText: current.effectiveQueryText,
|
|
@@ -10442,13 +10507,18 @@ var Retriever = class {
|
|
|
10442
10507
|
initialResults = this.mergeResults(initialResults, rewrittenResults, input.topK * 3);
|
|
10443
10508
|
}
|
|
10444
10509
|
}
|
|
10445
|
-
const
|
|
10510
|
+
const graphExpandedResults = input.graphHop?.enabled === false ? initialResults : await this.expandGraphHops(initialResults, {
|
|
10446
10511
|
query,
|
|
10447
10512
|
queryGraphEnabled: this.queryGraphExpansionEnabled,
|
|
10448
10513
|
maxHops: clampGraphHops(input.graphHop?.maxHops ?? 1),
|
|
10449
10514
|
hopPenalty: Math.max(0, input.graphHop?.hopPenalty ?? 0.08),
|
|
10450
10515
|
limit: input.topK * 4
|
|
10451
10516
|
});
|
|
10517
|
+
const expandedResults = input.retrievalMode === "session-event-hybrid" ? await this.expandSessionEventHybrid(graphExpandedResults, {
|
|
10518
|
+
query: rerankQuery,
|
|
10519
|
+
currentStateQuery: query,
|
|
10520
|
+
limit: input.topK * 4
|
|
10521
|
+
}) : graphExpandedResults;
|
|
10452
10522
|
const rerankedResults = input.rerankWithKeyword ? this.rerankByKeywordOverlap(expandedResults, rerankQuery, input.rerankWeights, input.decayPolicy) : expandedResults;
|
|
10453
10523
|
const filtered = await this.applyScopeFilters(rerankedResults, {
|
|
10454
10524
|
scope: input.scope,
|
|
@@ -10470,6 +10540,7 @@ var Retriever = class {
|
|
|
10470
10540
|
if (isCurrentStateQuery(options.query)) {
|
|
10471
10541
|
filtered = filtered.filter((result) => !isStaleOrSupersededContent(result.content));
|
|
10472
10542
|
}
|
|
10543
|
+
filtered = filtered.filter((result) => !isLowSignalContextContent(result.content));
|
|
10473
10544
|
filtered = filtered.filter(
|
|
10474
10545
|
(result) => this.isGraphPathResult(result) || hasDiscriminativeTermOverlap(options.query, result.content)
|
|
10475
10546
|
);
|
|
@@ -10495,6 +10566,47 @@ var Retriever = class {
|
|
|
10495
10566
|
}
|
|
10496
10567
|
return [...byId.values()].sort((a, b) => b.score - a.score).slice(0, limit);
|
|
10497
10568
|
}
|
|
10569
|
+
async expandSessionEventHybrid(seeds, opts) {
|
|
10570
|
+
if (seeds.length === 0 || opts.limit <= seeds.length) return seeds;
|
|
10571
|
+
const queryTokens = this.tokenize(opts.query);
|
|
10572
|
+
if (queryTokens.length === 0) return seeds;
|
|
10573
|
+
const byId = /* @__PURE__ */ new Map();
|
|
10574
|
+
for (const seed of seeds) byId.set(seed.eventId, seed);
|
|
10575
|
+
const bestSeedBySession = /* @__PURE__ */ new Map();
|
|
10576
|
+
for (const seed of [...seeds].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId))) {
|
|
10577
|
+
if (!seed.sessionId || bestSeedBySession.has(seed.sessionId)) continue;
|
|
10578
|
+
bestSeedBySession.set(seed.sessionId, seed);
|
|
10579
|
+
}
|
|
10580
|
+
const suppressStaleState = isCurrentStateQuery(opts.currentStateQuery);
|
|
10581
|
+
for (const [sessionId, seed] of bestSeedBySession) {
|
|
10582
|
+
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
10583
|
+
for (const event of [...sessionEvents].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime())) {
|
|
10584
|
+
if (byId.has(event.id)) continue;
|
|
10585
|
+
if (isLowSignalContextContent(event.content)) continue;
|
|
10586
|
+
if (suppressStaleState && isStaleOrSupersededContent(event.content)) continue;
|
|
10587
|
+
const lexicalScore = this.keywordOverlap(queryTokens, this.tokenize(event.content));
|
|
10588
|
+
if (lexicalScore <= 0) continue;
|
|
10589
|
+
if (shouldApplyTechnicalGuard(opts.query) && !hasTechnicalTermOverlap(opts.query, event.content)) continue;
|
|
10590
|
+
const score = Math.min(0.95, Math.max(0.35, seed.score * 0.72 + lexicalScore * 0.28));
|
|
10591
|
+
const row = withRetrievalLane({
|
|
10592
|
+
id: `session-event-${seed.eventId}-${event.id}`,
|
|
10593
|
+
eventId: event.id,
|
|
10594
|
+
content: event.content,
|
|
10595
|
+
score,
|
|
10596
|
+
sessionId: event.sessionId,
|
|
10597
|
+
eventType: event.eventType,
|
|
10598
|
+
timestamp: event.timestamp.toISOString(),
|
|
10599
|
+
semanticScore: seed.semanticScore ?? seed.score,
|
|
10600
|
+
lexicalScore,
|
|
10601
|
+
recencyScore: seed.recencyScore
|
|
10602
|
+
}, { lane: "session_event", reason: `same_session:${seed.eventId}`, score });
|
|
10603
|
+
byId.set(row.eventId, row);
|
|
10604
|
+
if (byId.size >= opts.limit) break;
|
|
10605
|
+
}
|
|
10606
|
+
if (byId.size >= opts.limit) break;
|
|
10607
|
+
}
|
|
10608
|
+
return [...byId.values()].sort((a, b) => b.score - a.score || compareStable(a.eventId, b.eventId)).slice(0, opts.limit);
|
|
10609
|
+
}
|
|
10498
10610
|
async expandGraphHops(seeds, opts) {
|
|
10499
10611
|
const byId = /* @__PURE__ */ new Map();
|
|
10500
10612
|
for (const s of seeds) byId.set(s.eventId, s);
|
|
@@ -10810,7 +10922,7 @@ var Retriever = class {
|
|
|
10810
10922
|
async retrieveRecent(limit = 100) {
|
|
10811
10923
|
return this.eventStore.getRecentEvents(limit);
|
|
10812
10924
|
}
|
|
10813
|
-
async enrichResults(results, options) {
|
|
10925
|
+
async enrichResults(results, options, query) {
|
|
10814
10926
|
const memories = [];
|
|
10815
10927
|
for (const result of results) {
|
|
10816
10928
|
const event = await this.eventStore.getEvent(result.eventId);
|
|
@@ -10820,13 +10932,13 @@ var Retriever = class {
|
|
|
10820
10932
|
}
|
|
10821
10933
|
let sessionContext;
|
|
10822
10934
|
if (options.includeSessionContext) {
|
|
10823
|
-
sessionContext = await this.getSessionContext(event.sessionId, event.id);
|
|
10935
|
+
sessionContext = await this.getSessionContext(event.sessionId, event.id, query);
|
|
10824
10936
|
}
|
|
10825
10937
|
memories.push({ event, score: result.score, sessionContext });
|
|
10826
10938
|
}
|
|
10827
10939
|
return memories;
|
|
10828
10940
|
}
|
|
10829
|
-
async getSessionContext(sessionId, eventId) {
|
|
10941
|
+
async getSessionContext(sessionId, eventId, query) {
|
|
10830
10942
|
const sessionEvents = await this.eventStore.getSessionEvents(sessionId);
|
|
10831
10943
|
const eventIndex = sessionEvents.findIndex((e) => e.id === eventId);
|
|
10832
10944
|
if (eventIndex === -1) return void 0;
|
|
@@ -10834,7 +10946,9 @@ var Retriever = class {
|
|
|
10834
10946
|
const end = Math.min(sessionEvents.length, eventIndex + 2);
|
|
10835
10947
|
const contextEvents = sessionEvents.slice(start, end);
|
|
10836
10948
|
if (contextEvents.length <= 1) return void 0;
|
|
10837
|
-
|
|
10949
|
+
const suppressStaleState = isCurrentStateQuery(query);
|
|
10950
|
+
const contextLines = contextEvents.filter((e) => e.id !== eventId).filter((e) => !isLowSignalContextContent(e.content)).filter((e) => !(suppressStaleState && isStaleOrSupersededContent(e.content))).map((e) => `[${e.eventType}]: ${e.content.slice(0, 200)}...`);
|
|
10951
|
+
return contextLines.length > 0 ? contextLines.join("\n") : void 0;
|
|
10838
10952
|
}
|
|
10839
10953
|
buildUnifiedContext(projectResult, sharedMemories) {
|
|
10840
10954
|
let context = projectResult.context;
|
|
@@ -20990,7 +21104,7 @@ async function runOperationCli(action, label) {
|
|
|
20990
21104
|
}
|
|
20991
21105
|
}
|
|
20992
21106
|
var program = new Command();
|
|
20993
|
-
program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.
|
|
21107
|
+
program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.47");
|
|
20994
21108
|
program.command("market-context").description("Fetch read-only DART/FRED/Finnhub context with structured MarketContextSnapshot bull/bear/risk/catalyst analysis").option("--company <name>", "Company name for DART fallback search and report subject").option("--dart-corp-code <code>", "Exact DART corp_code for issuer-specific filings").option("--symbol <ticker>", "Listed ticker for Finnhub company profile").option("--providers <list>", "Comma-separated providers: dart,fred,finnhub").option("--fred-series <list>", "Comma-separated FRED series IDs").option("--json", "Print structured JSON including analysis.marketSnapshot").option("--no-snapshot", "Disable MarketContextSnapshot and DART company snapshot analysis").action(async (options) => {
|
|
20995
21109
|
try {
|
|
20996
21110
|
await runMarketContextCommand(options);
|