opencode-claude-memory 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/recall.ts DELETED
@@ -1,126 +0,0 @@
1
- import { statSync } from "fs"
2
- import { listMemories, type MemoryEntry } from "./memory.js"
3
-
4
- const encoder = new TextEncoder()
5
-
6
- export type RecalledMemory = {
7
- fileName: string
8
- name: string
9
- type: string
10
- description: string
11
- content: string
12
- ageInDays: number
13
- }
14
-
15
- const MAX_RECALLED_MEMORIES = 5
16
- const MAX_MEMORY_LINES = 200
17
- const MAX_MEMORY_BYTES = 4096
18
-
19
- function tokenizeQuery(query: string): string[] {
20
- return [...new Set(query.toLowerCase().split(/\s+/).map((token) => token.trim()).filter((token) => token.length >= 2))]
21
- }
22
-
23
- function getMemoryMtimeMs(entry: MemoryEntry): number {
24
- try {
25
- return statSync(entry.filePath).mtimeMs
26
- } catch {
27
- return 0
28
- }
29
- }
30
-
31
- function scoreMemory(entry: MemoryEntry, terms: string[]): number {
32
- if (terms.length === 0) return 0
33
- const haystack = `${entry.name}\n${entry.description}\n${entry.content}`.toLowerCase()
34
- let score = 0
35
- for (const term of terms) {
36
- if (haystack.includes(term)) score += 1
37
- }
38
- return score
39
- }
40
-
41
- function truncateMemoryContent(content: string): string {
42
- const maxLines = content.split("\n").slice(0, MAX_MEMORY_LINES)
43
- const lineTruncated = maxLines.join("\n")
44
- if (encoder.encode(lineTruncated).length <= MAX_MEMORY_BYTES) {
45
- return lineTruncated
46
- }
47
-
48
- const lines = lineTruncated.split("\n")
49
- const kept: string[] = []
50
- let usedBytes = 0
51
-
52
- for (const line of lines) {
53
- const candidate = kept.length === 0 ? line : `\n${line}`
54
- const candidateBytes = encoder.encode(candidate).length
55
- if (usedBytes + candidateBytes > MAX_MEMORY_BYTES) break
56
- kept.push(line)
57
- usedBytes += candidateBytes
58
- }
59
-
60
- return kept.join("\n")
61
- }
62
-
63
- export function recallRelevantMemories(worktree: string, query?: string): RecalledMemory[] {
64
- const memories = listMemories(worktree)
65
- if (memories.length === 0) return []
66
-
67
- const now = Date.now()
68
- const memoriesWithMeta = memories.map((entry) => {
69
- const mtimeMs = getMemoryMtimeMs(entry)
70
- return {
71
- entry,
72
- mtimeMs,
73
- }
74
- })
75
-
76
- const terms = query ? tokenizeQuery(query) : []
77
-
78
- let selected = memoriesWithMeta
79
-
80
- if (terms.length > 0) {
81
- const withScores = memoriesWithMeta
82
- .map((item) => ({
83
- ...item,
84
- score: scoreMemory(item.entry, terms),
85
- }))
86
- .sort((a, b) => b.score - a.score || b.mtimeMs - a.mtimeMs)
87
-
88
- if (withScores.some((item) => item.score > 0)) {
89
- selected = withScores
90
- }
91
- }
92
-
93
- if (selected === memoriesWithMeta) {
94
- selected = [...memoriesWithMeta].sort((a, b) => b.mtimeMs - a.mtimeMs)
95
- }
96
-
97
- return selected.slice(0, MAX_RECALLED_MEMORIES).map(({ entry, mtimeMs }) => ({
98
- fileName: entry.fileName,
99
- name: entry.name,
100
- type: entry.type,
101
- description: entry.description,
102
- content: truncateMemoryContent(entry.content),
103
- ageInDays: Math.max(0, Math.floor((now - mtimeMs) / (1000 * 60 * 60 * 24))),
104
- }))
105
- }
106
-
107
- function formatAgeWarning(ageInDays: number): string {
108
- if (ageInDays <= 1) return ""
109
- return `\n> ⚠️ This memory is ${ageInDays} days old. Memories are point-in-time observations, not live state — claims about code behavior or file:line citations may be outdated. Verify against current code before asserting as fact.\n`
110
- }
111
-
112
- export function formatRecalledMemories(memories: RecalledMemory[]): string {
113
- if (memories.length === 0) return ""
114
-
115
- const sections = memories.map((memory) => {
116
- const ageWarning = formatAgeWarning(memory.ageInDays)
117
- return `### ${memory.name} (${memory.type})${ageWarning}\n${memory.content}`
118
- })
119
- return [
120
- "## Recalled Memories",
121
- "",
122
- "The following memories were automatically selected as relevant to this conversation. They may be outdated — verify against current state before relying on them.",
123
- "",
124
- sections.join("\n\n"),
125
- ].join("\n")
126
- }