studiograph 1.0.0

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.
Files changed (101) hide show
  1. package/README.md +18 -0
  2. package/dist/agent/orchestrator.d.ts +69 -0
  3. package/dist/agent/orchestrator.js +211 -0
  4. package/dist/agent/orchestrator.js.map +1 -0
  5. package/dist/agent/tools/graph-tools.d.ts +30 -0
  6. package/dist/agent/tools/graph-tools.js +536 -0
  7. package/dist/agent/tools/graph-tools.js.map +1 -0
  8. package/dist/auth/github.d.ts +53 -0
  9. package/dist/auth/github.js +180 -0
  10. package/dist/auth/github.js.map +1 -0
  11. package/dist/cli/commands/auth.d.ts +10 -0
  12. package/dist/cli/commands/auth.js +63 -0
  13. package/dist/cli/commands/auth.js.map +1 -0
  14. package/dist/cli/commands/init.d.ts +7 -0
  15. package/dist/cli/commands/init.js +299 -0
  16. package/dist/cli/commands/init.js.map +1 -0
  17. package/dist/cli/commands/join.d.ts +14 -0
  18. package/dist/cli/commands/join.js +230 -0
  19. package/dist/cli/commands/join.js.map +1 -0
  20. package/dist/cli/commands/members.d.ts +11 -0
  21. package/dist/cli/commands/members.js +230 -0
  22. package/dist/cli/commands/members.js.map +1 -0
  23. package/dist/cli/commands/serve.d.ts +17 -0
  24. package/dist/cli/commands/serve.js +90 -0
  25. package/dist/cli/commands/serve.js.map +1 -0
  26. package/dist/cli/commands/start.d.ts +7 -0
  27. package/dist/cli/commands/start.js +381 -0
  28. package/dist/cli/commands/start.js.map +1 -0
  29. package/dist/cli/commands/sync.d.ts +10 -0
  30. package/dist/cli/commands/sync.js +121 -0
  31. package/dist/cli/commands/sync.js.map +1 -0
  32. package/dist/cli/index.d.ts +7 -0
  33. package/dist/cli/index.js +31 -0
  34. package/dist/cli/index.js.map +1 -0
  35. package/dist/core/graph.d.ts +169 -0
  36. package/dist/core/graph.js +558 -0
  37. package/dist/core/graph.js.map +1 -0
  38. package/dist/core/types.d.ts +216 -0
  39. package/dist/core/types.js +71 -0
  40. package/dist/core/types.js.map +1 -0
  41. package/dist/core/user-config.d.ts +31 -0
  42. package/dist/core/user-config.js +50 -0
  43. package/dist/core/user-config.js.map +1 -0
  44. package/dist/core/validation.d.ts +2371 -0
  45. package/dist/core/validation.js +432 -0
  46. package/dist/core/validation.js.map +1 -0
  47. package/dist/core/workspace-manager.d.ts +104 -0
  48. package/dist/core/workspace-manager.js +432 -0
  49. package/dist/core/workspace-manager.js.map +1 -0
  50. package/dist/core/workspace.d.ts +103 -0
  51. package/dist/core/workspace.js +306 -0
  52. package/dist/core/workspace.js.map +1 -0
  53. package/dist/server/index.d.ts +25 -0
  54. package/dist/server/index.js +84 -0
  55. package/dist/server/index.js.map +1 -0
  56. package/dist/server/plugin-loader.d.ts +31 -0
  57. package/dist/server/plugin-loader.js +81 -0
  58. package/dist/server/plugin-loader.js.map +1 -0
  59. package/dist/server/routes/chat.d.ts +11 -0
  60. package/dist/server/routes/chat.js +66 -0
  61. package/dist/server/routes/chat.js.map +1 -0
  62. package/dist/server/routes/graph-api.d.ts +9 -0
  63. package/dist/server/routes/graph-api.js +72 -0
  64. package/dist/server/routes/graph-api.js.map +1 -0
  65. package/dist/server/routes/webhook.d.ts +14 -0
  66. package/dist/server/routes/webhook.js +69 -0
  67. package/dist/server/routes/webhook.js.map +1 -0
  68. package/dist/services/assets/base.d.ts +69 -0
  69. package/dist/services/assets/base.js +113 -0
  70. package/dist/services/assets/base.js.map +1 -0
  71. package/dist/services/assets/index.d.ts +36 -0
  72. package/dist/services/assets/index.js +89 -0
  73. package/dist/services/assets/index.js.map +1 -0
  74. package/dist/services/assets/local.d.ts +42 -0
  75. package/dist/services/assets/local.js +161 -0
  76. package/dist/services/assets/local.js.map +1 -0
  77. package/dist/services/assets/r2.d.ts +36 -0
  78. package/dist/services/assets/r2.js +182 -0
  79. package/dist/services/assets/r2.js.map +1 -0
  80. package/dist/services/csv-service.d.ts +36 -0
  81. package/dist/services/csv-service.js +143 -0
  82. package/dist/services/csv-service.js.map +1 -0
  83. package/dist/services/git.d.ts +99 -0
  84. package/dist/services/git.js +306 -0
  85. package/dist/services/git.js.map +1 -0
  86. package/dist/services/github-provisioner.d.ts +30 -0
  87. package/dist/services/github-provisioner.js +89 -0
  88. package/dist/services/github-provisioner.js.map +1 -0
  89. package/dist/services/markdown.d.ts +82 -0
  90. package/dist/services/markdown.js +338 -0
  91. package/dist/services/markdown.js.map +1 -0
  92. package/dist/services/memory-service.d.ts +74 -0
  93. package/dist/services/memory-service.js +183 -0
  94. package/dist/services/memory-service.js.map +1 -0
  95. package/dist/utils/git.d.ts +28 -0
  96. package/dist/utils/git.js +55 -0
  97. package/dist/utils/git.js.map +1 -0
  98. package/dist/utils/preflight.d.ts +44 -0
  99. package/dist/utils/preflight.js +95 -0
  100. package/dist/utils/preflight.js.map +1 -0
  101. package/package.json +55 -0
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Markdown service for Studiograph
3
+ *
4
+ * Handles parsing and writing markdown files with YAML frontmatter,
5
+ * extracting wikilinks, and validating relationships.
6
+ */
7
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
8
+ import { dirname, join } from 'path';
9
+ import matter from 'gray-matter';
10
+ import { glob } from 'glob';
11
+ export class MarkdownService {
12
+ /**
13
+ * Parse markdown file from path
14
+ */
15
+ parseFile(filePath) {
16
+ if (!existsSync(filePath)) {
17
+ throw new Error(`File not found: ${filePath}`);
18
+ }
19
+ const fileContent = readFileSync(filePath, 'utf-8');
20
+ return this.parseContent(fileContent);
21
+ }
22
+ /**
23
+ * Parse markdown content string
24
+ */
25
+ parseContent(content) {
26
+ const { data, content: markdownContent } = matter(content);
27
+ // Extract wikilinks from content
28
+ const wikilinks = this.extractWikilinks(markdownContent, data);
29
+ return {
30
+ frontmatter: data,
31
+ content: markdownContent,
32
+ wikilinks: [...new Set(wikilinks)], // Dedupe
33
+ };
34
+ }
35
+ /**
36
+ * Extract wikilinks from markdown content and frontmatter
37
+ */
38
+ extractWikilinks(content, frontmatter) {
39
+ const wikilinks = [];
40
+ // Extract from content: [[entity-id]] or [[entity-id|Display Name]]
41
+ const wikilinkRegex = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
42
+ let match;
43
+ while ((match = wikilinkRegex.exec(content)) !== null) {
44
+ wikilinks.push(match[1]);
45
+ }
46
+ // Extract from frontmatter (check string values and arrays)
47
+ this.extractWikilinksFromObject(frontmatter, wikilinks);
48
+ return wikilinks;
49
+ }
50
+ /**
51
+ * Recursively extract wikilinks from object (frontmatter)
52
+ */
53
+ extractWikilinksFromObject(obj, wikilinks) {
54
+ if (!obj || typeof obj !== 'object') {
55
+ return;
56
+ }
57
+ if (Array.isArray(obj)) {
58
+ obj.forEach(item => {
59
+ if (typeof item === 'string') {
60
+ const match = item.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/);
61
+ if (match) {
62
+ wikilinks.push(match[1]);
63
+ }
64
+ }
65
+ else {
66
+ this.extractWikilinksFromObject(item, wikilinks);
67
+ }
68
+ });
69
+ }
70
+ else {
71
+ Object.values(obj).forEach(value => {
72
+ if (typeof value === 'string') {
73
+ const match = value.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/);
74
+ if (match) {
75
+ wikilinks.push(match[1]);
76
+ }
77
+ }
78
+ else {
79
+ this.extractWikilinksFromObject(value, wikilinks);
80
+ }
81
+ });
82
+ }
83
+ }
84
+ /**
85
+ * Write markdown file with frontmatter
86
+ */
87
+ writeFile(filePath, doc) {
88
+ const { frontmatter, content } = doc;
89
+ // Generate markdown with frontmatter
90
+ const output = matter.stringify(content, frontmatter);
91
+ // Ensure directory exists
92
+ const dir = dirname(filePath);
93
+ if (!existsSync(dir)) {
94
+ mkdirSync(dir, { recursive: true });
95
+ }
96
+ // Write file
97
+ writeFileSync(filePath, output, 'utf-8');
98
+ }
99
+ /**
100
+ * Write markdown content from separate frontmatter and content
101
+ */
102
+ write(filePath, frontmatter, content) {
103
+ this.writeFile(filePath, { frontmatter, content, wikilinks: [] });
104
+ }
105
+ /**
106
+ * Validate wikilinks against a repo or set of repos
107
+ */
108
+ validateWikilinks(wikilinks, searchPaths) {
109
+ const valid = [];
110
+ const broken = [];
111
+ for (const link of wikilinks) {
112
+ // Try to find the entity file
113
+ const found = this.findEntity(link, searchPaths);
114
+ if (found) {
115
+ valid.push(link);
116
+ }
117
+ else {
118
+ broken.push(link);
119
+ }
120
+ }
121
+ return { valid, broken };
122
+ }
123
+ /**
124
+ * Find entity file by entity ID across multiple search paths
125
+ */
126
+ findEntity(entityId, searchPaths) {
127
+ // Clean entity ID (remove repo prefix if present)
128
+ // Format: [[repo/entity-id]] or [[entity-id]]
129
+ const parts = entityId.split('/');
130
+ const cleanId = parts.length === 2 ? parts[1] : parts[0];
131
+ // Search for {entityId}.md in all search paths
132
+ for (const searchPath of searchPaths) {
133
+ if (!existsSync(searchPath)) {
134
+ continue;
135
+ }
136
+ // Try direct match first (faster)
137
+ const directPath = join(searchPath, `${cleanId}.md`);
138
+ if (existsSync(directPath)) {
139
+ return directPath;
140
+ }
141
+ // Search recursively
142
+ const pattern = `**/${cleanId}.md`;
143
+ const files = glob.sync(pattern, {
144
+ cwd: searchPath,
145
+ absolute: true,
146
+ nodir: true,
147
+ });
148
+ if (files.length > 0) {
149
+ return files[0]; // Return first match
150
+ }
151
+ }
152
+ return null;
153
+ }
154
+ /**
155
+ * Find all entities of a given type in a directory
156
+ */
157
+ findEntitiesByType(searchPath, entityType) {
158
+ if (!existsSync(searchPath)) {
159
+ return [];
160
+ }
161
+ const files = [];
162
+ // Recursively search for markdown files
163
+ const pattern = '**/*.md';
164
+ const allFiles = glob.sync(pattern, {
165
+ cwd: searchPath,
166
+ absolute: true,
167
+ nodir: true,
168
+ });
169
+ // Filter by entity type in frontmatter
170
+ for (const file of allFiles) {
171
+ try {
172
+ const doc = this.parseFile(file);
173
+ if (doc.frontmatter.entity_type === entityType) {
174
+ files.push(file);
175
+ }
176
+ }
177
+ catch {
178
+ // Skip files that can't be parsed
179
+ continue;
180
+ }
181
+ }
182
+ return files;
183
+ }
184
+ /**
185
+ * Find all markdown files in a directory (recursive)
186
+ */
187
+ findAllEntities(searchPath) {
188
+ if (!existsSync(searchPath)) {
189
+ return [];
190
+ }
191
+ const pattern = '**/*.md';
192
+ return glob.sync(pattern, {
193
+ cwd: searchPath,
194
+ absolute: true,
195
+ nodir: true,
196
+ });
197
+ }
198
+ /**
199
+ * Search entities by content or frontmatter
200
+ */
201
+ search(searchPaths, query, options = {}) {
202
+ const { entityType, caseSensitive = false, searchContent = true, searchFrontmatter = true, limit = 100, } = options;
203
+ const results = [];
204
+ const pattern = caseSensitive ? query : query.toLowerCase();
205
+ // Search all paths
206
+ for (const searchPath of searchPaths) {
207
+ if (!existsSync(searchPath)) {
208
+ continue;
209
+ }
210
+ const files = this.findAllEntities(searchPath);
211
+ for (const file of files) {
212
+ if (results.length >= limit) {
213
+ break;
214
+ }
215
+ try {
216
+ const doc = this.parseFile(file);
217
+ // Filter by entity type if specified
218
+ if (entityType && doc.frontmatter.entity_type !== entityType) {
219
+ continue;
220
+ }
221
+ // Search frontmatter
222
+ let found = false;
223
+ if (searchFrontmatter) {
224
+ const frontmatterStr = JSON.stringify(doc.frontmatter);
225
+ const searchStr = caseSensitive ? frontmatterStr : frontmatterStr.toLowerCase();
226
+ if (searchStr.includes(pattern)) {
227
+ found = true;
228
+ }
229
+ }
230
+ // Search content
231
+ if (!found && searchContent) {
232
+ const searchStr = caseSensitive ? doc.content : doc.content.toLowerCase();
233
+ if (searchStr.includes(pattern)) {
234
+ found = true;
235
+ }
236
+ }
237
+ if (found) {
238
+ results.push(doc);
239
+ }
240
+ }
241
+ catch {
242
+ // Skip files that can't be parsed
243
+ continue;
244
+ }
245
+ }
246
+ if (results.length >= limit) {
247
+ break;
248
+ }
249
+ }
250
+ return results;
251
+ }
252
+ /**
253
+ * Get entity relationships (entities that link to this entity)
254
+ */
255
+ findBacklinks(entityId, searchPaths) {
256
+ const backlinks = [];
257
+ for (const searchPath of searchPaths) {
258
+ if (!existsSync(searchPath)) {
259
+ continue;
260
+ }
261
+ const files = this.findAllEntities(searchPath);
262
+ for (const file of files) {
263
+ try {
264
+ const doc = this.parseFile(file);
265
+ // Check if this document links to the target entity
266
+ const linksToTarget = doc.wikilinks.some(link => {
267
+ const cleanLink = link.split('/').pop() || link;
268
+ return cleanLink === entityId;
269
+ });
270
+ if (linksToTarget) {
271
+ backlinks.push({ file, doc });
272
+ }
273
+ }
274
+ catch {
275
+ // Skip files that can't be parsed
276
+ continue;
277
+ }
278
+ }
279
+ }
280
+ return backlinks;
281
+ }
282
+ /**
283
+ * Update wikilinks in a file (useful for refactoring entity IDs)
284
+ */
285
+ updateWikilinks(filePath, oldEntityId, newEntityId) {
286
+ if (!existsSync(filePath)) {
287
+ throw new Error(`File not found: ${filePath}`);
288
+ }
289
+ const doc = this.parseFile(filePath);
290
+ // Update content
291
+ let updatedContent = doc.content;
292
+ const wikilinkPattern = new RegExp(`\\[\\[${escapeRegex(oldEntityId)}(\\|[^\\]]+)?\\]\\]`, 'g');
293
+ updatedContent = updatedContent.replace(wikilinkPattern, `[[${newEntityId}$1]]`);
294
+ // Update frontmatter (recursively)
295
+ const updatedFrontmatter = this.updateWikilinksInObject(doc.frontmatter, oldEntityId, newEntityId);
296
+ // Write back
297
+ this.writeFile(filePath, {
298
+ frontmatter: updatedFrontmatter,
299
+ content: updatedContent,
300
+ wikilinks: [],
301
+ });
302
+ }
303
+ /**
304
+ * Recursively update wikilinks in an object (frontmatter)
305
+ */
306
+ updateWikilinksInObject(obj, oldEntityId, newEntityId) {
307
+ if (!obj || typeof obj !== 'object') {
308
+ return obj;
309
+ }
310
+ if (Array.isArray(obj)) {
311
+ return obj.map(item => {
312
+ if (typeof item === 'string') {
313
+ const wikilinkPattern = new RegExp(`\\[\\[${escapeRegex(oldEntityId)}(\\|[^\\]]+)?\\]\\]`, 'g');
314
+ return item.replace(wikilinkPattern, `[[${newEntityId}$1]]`);
315
+ }
316
+ return this.updateWikilinksInObject(item, oldEntityId, newEntityId);
317
+ });
318
+ }
319
+ const updated = {};
320
+ for (const [key, value] of Object.entries(obj)) {
321
+ if (typeof value === 'string') {
322
+ const wikilinkPattern = new RegExp(`\\[\\[${escapeRegex(oldEntityId)}(\\|[^\\]]+)?\\]\\]`, 'g');
323
+ updated[key] = value.replace(wikilinkPattern, `[[${newEntityId}$1]]`);
324
+ }
325
+ else {
326
+ updated[key] = this.updateWikilinksInObject(value, oldEntityId, newEntityId);
327
+ }
328
+ }
329
+ return updated;
330
+ }
331
+ }
332
+ /**
333
+ * Escape special regex characters
334
+ */
335
+ function escapeRegex(str) {
336
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
337
+ }
338
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/services/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Memory service for Studiograph
3
+ *
4
+ * Manages daily memory files similar to OpenClaw:
5
+ * - memory/YYYY-MM-DD.md for each day
6
+ * - Loads today + yesterday at session start
7
+ * - Appends conversation context throughout the day
8
+ */
9
+ export interface MemoryEntry {
10
+ timestamp: Date;
11
+ type: 'conversation' | 'note' | 'decision';
12
+ content: string;
13
+ metadata?: Record<string, any>;
14
+ }
15
+ export declare class MemoryService {
16
+ private workspacePath;
17
+ private memoryDir;
18
+ constructor(workspacePath: string);
19
+ /**
20
+ * Ensure memory directory exists
21
+ */
22
+ private ensureMemoryDir;
23
+ /**
24
+ * Get daily memory file path for a given date
25
+ */
26
+ private getDailyMemoryPath;
27
+ /**
28
+ * Format timestamp for memory entry
29
+ */
30
+ private formatTimestamp;
31
+ /**
32
+ * Write entry to today's memory file
33
+ */
34
+ writeMemory(entry: MemoryEntry): void;
35
+ /**
36
+ * Read memory for a specific date
37
+ */
38
+ readMemory(date: Date): string | null;
39
+ /**
40
+ * Read today's memory
41
+ */
42
+ readToday(): string | null;
43
+ /**
44
+ * Read yesterday's memory
45
+ */
46
+ readYesterday(): string | null;
47
+ /**
48
+ * Load recent memory (today + yesterday)
49
+ */
50
+ loadRecentMemory(): string;
51
+ /**
52
+ * List all memory files
53
+ */
54
+ listMemoryFiles(): string[];
55
+ /**
56
+ * Search memory files for a keyword
57
+ */
58
+ searchMemory(keyword: string, limit?: number): Array<{
59
+ date: string;
60
+ snippet: string;
61
+ }>;
62
+ /**
63
+ * Save session summary to memory
64
+ */
65
+ saveSessionSummary(summary: string, metadata?: Record<string, any>): void;
66
+ /**
67
+ * Save a note to memory
68
+ */
69
+ saveNote(note: string, metadata?: Record<string, any>): void;
70
+ /**
71
+ * Save a decision to memory
72
+ */
73
+ saveDecision(decision: string, metadata?: Record<string, any>): void;
74
+ }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Memory service for Studiograph
3
+ *
4
+ * Manages daily memory files similar to OpenClaw:
5
+ * - memory/YYYY-MM-DD.md for each day
6
+ * - Loads today + yesterday at session start
7
+ * - Appends conversation context throughout the day
8
+ */
9
+ import { existsSync, mkdirSync, readFileSync, appendFileSync, writeFileSync, readdirSync } from 'fs';
10
+ import { join } from 'path';
11
+ export class MemoryService {
12
+ workspacePath;
13
+ memoryDir;
14
+ constructor(workspacePath) {
15
+ this.workspacePath = workspacePath;
16
+ this.memoryDir = join(workspacePath, '.studiograph', 'memory');
17
+ this.ensureMemoryDir();
18
+ }
19
+ /**
20
+ * Ensure memory directory exists
21
+ */
22
+ ensureMemoryDir() {
23
+ if (!existsSync(this.memoryDir)) {
24
+ mkdirSync(this.memoryDir, { recursive: true });
25
+ }
26
+ }
27
+ /**
28
+ * Get daily memory file path for a given date
29
+ */
30
+ getDailyMemoryPath(date) {
31
+ const dateStr = date.toISOString().split('T')[0]; // YYYY-MM-DD
32
+ return join(this.memoryDir, `${dateStr}.md`);
33
+ }
34
+ /**
35
+ * Format timestamp for memory entry
36
+ */
37
+ formatTimestamp(date) {
38
+ return date.toISOString().replace('T', ' ').split('.')[0] + ' UTC';
39
+ }
40
+ /**
41
+ * Write entry to today's memory file
42
+ */
43
+ writeMemory(entry) {
44
+ const memoryPath = this.getDailyMemoryPath(entry.timestamp);
45
+ const timestamp = this.formatTimestamp(entry.timestamp);
46
+ // Format entry as markdown
47
+ const lines = [
48
+ `## ${timestamp} - ${entry.type}`,
49
+ '',
50
+ entry.content,
51
+ '',
52
+ ];
53
+ // Add metadata if present
54
+ if (entry.metadata) {
55
+ lines.push('**Metadata:**');
56
+ for (const [key, value] of Object.entries(entry.metadata)) {
57
+ lines.push(`- **${key}**: ${value}`);
58
+ }
59
+ lines.push('');
60
+ }
61
+ lines.push('---', '');
62
+ const entryText = lines.join('\n');
63
+ // Append to file (or create if doesn't exist)
64
+ if (!existsSync(memoryPath)) {
65
+ const header = `# Memory - ${entry.timestamp.toISOString().split('T')[0]}\n\n`;
66
+ writeFileSync(memoryPath, header + entryText, 'utf-8');
67
+ }
68
+ else {
69
+ appendFileSync(memoryPath, entryText, 'utf-8');
70
+ }
71
+ }
72
+ /**
73
+ * Read memory for a specific date
74
+ */
75
+ readMemory(date) {
76
+ const memoryPath = this.getDailyMemoryPath(date);
77
+ if (!existsSync(memoryPath)) {
78
+ return null;
79
+ }
80
+ return readFileSync(memoryPath, 'utf-8');
81
+ }
82
+ /**
83
+ * Read today's memory
84
+ */
85
+ readToday() {
86
+ return this.readMemory(new Date());
87
+ }
88
+ /**
89
+ * Read yesterday's memory
90
+ */
91
+ readYesterday() {
92
+ const yesterday = new Date();
93
+ yesterday.setDate(yesterday.getDate() - 1);
94
+ return this.readMemory(yesterday);
95
+ }
96
+ /**
97
+ * Load recent memory (today + yesterday)
98
+ */
99
+ loadRecentMemory() {
100
+ const parts = [];
101
+ const yesterday = this.readYesterday();
102
+ if (yesterday) {
103
+ parts.push('# Yesterday\n', yesterday, '\n');
104
+ }
105
+ const today = this.readToday();
106
+ if (today) {
107
+ parts.push('# Today\n', today, '\n');
108
+ }
109
+ if (parts.length === 0) {
110
+ return '# No recent memory\n\nNo memory entries from today or yesterday.';
111
+ }
112
+ return parts.join('\n');
113
+ }
114
+ /**
115
+ * List all memory files
116
+ */
117
+ listMemoryFiles() {
118
+ if (!existsSync(this.memoryDir)) {
119
+ return [];
120
+ }
121
+ return readdirSync(this.memoryDir)
122
+ .filter(file => file.endsWith('.md'))
123
+ .sort()
124
+ .reverse(); // Most recent first
125
+ }
126
+ /**
127
+ * Search memory files for a keyword
128
+ */
129
+ searchMemory(keyword, limit = 10) {
130
+ const files = this.listMemoryFiles().slice(0, limit);
131
+ const results = [];
132
+ for (const file of files) {
133
+ const filePath = join(this.memoryDir, file);
134
+ const content = readFileSync(filePath, 'utf-8');
135
+ if (content.toLowerCase().includes(keyword.toLowerCase())) {
136
+ // Extract snippet around keyword
137
+ const lines = content.split('\n');
138
+ const matchingLines = lines.filter(line => line.toLowerCase().includes(keyword.toLowerCase()));
139
+ if (matchingLines.length > 0) {
140
+ results.push({
141
+ date: file.replace('.md', ''),
142
+ snippet: matchingLines.slice(0, 3).join('\n'),
143
+ });
144
+ }
145
+ }
146
+ }
147
+ return results;
148
+ }
149
+ /**
150
+ * Save session summary to memory
151
+ */
152
+ saveSessionSummary(summary, metadata) {
153
+ this.writeMemory({
154
+ timestamp: new Date(),
155
+ type: 'conversation',
156
+ content: summary,
157
+ metadata,
158
+ });
159
+ }
160
+ /**
161
+ * Save a note to memory
162
+ */
163
+ saveNote(note, metadata) {
164
+ this.writeMemory({
165
+ timestamp: new Date(),
166
+ type: 'note',
167
+ content: note,
168
+ metadata,
169
+ });
170
+ }
171
+ /**
172
+ * Save a decision to memory
173
+ */
174
+ saveDecision(decision, metadata) {
175
+ this.writeMemory({
176
+ timestamp: new Date(),
177
+ type: 'decision',
178
+ content: decision,
179
+ metadata,
180
+ });
181
+ }
182
+ }
183
+ //# sourceMappingURL=memory-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-service.js","sourceRoot":"","sources":["../../src/services/memory-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Thin wrappers around git shell operations.
3
+ * Extracted so tests can mock them without mocking the built-in child_process.
4
+ */
5
+ export type PullResult = 'updated' | 'up-to-date' | 'conflict';
6
+ export type PushResult = 'pushed' | 'nothing-to-push';
7
+ /**
8
+ * Pull the latest changes in a local git repo.
9
+ * Returns 'updated', 'up-to-date', or 'conflict'.
10
+ * Throws on hard errors (no remote, auth failure, etc.).
11
+ */
12
+ export declare function gitPull(repoPath: string): PullResult;
13
+ /**
14
+ * Push local commits in a git repo to its remote.
15
+ * Returns 'pushed' or 'nothing-to-push'.
16
+ * Throws on errors (no remote, auth failure, etc.).
17
+ */
18
+ export declare function gitPush(repoPath: string): PushResult;
19
+ /**
20
+ * Clone a remote repository to a local path.
21
+ * Throws if the git command fails.
22
+ */
23
+ export declare function gitClone(remoteUrl: string, localPath: string): void;
24
+ /**
25
+ * Read a git config value.
26
+ * Returns undefined if the key is not set.
27
+ */
28
+ export declare function getGitConfig(key: string): string | undefined;