@syntesseraai/opencode-feature-factory 0.3.2 → 0.3.3

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.
@@ -20,6 +20,36 @@ import { extractFromMessage } from './session-extractor.js';
20
20
  import { extractThinkingFromMessage } from './thinking-extractor.js';
21
21
  import { readProcessedLog, getProcessedMessageIDs, getProcessedHashes, markProcessed, contentHash, } from './processed-log.js';
22
22
  import { getMemoriesDir, storeMemories } from './memory-service.js';
23
+ function getErrorMessage(error) {
24
+ return error instanceof Error ? error.message : String(error);
25
+ }
26
+ function recordFailure(stats, failure) {
27
+ let message;
28
+ let rawError;
29
+ switch (failure.scope) {
30
+ case 'project':
31
+ message = `No OpenCode project found for directory: ${failure.directory}`;
32
+ break;
33
+ case 'message':
34
+ message = `Error processing message ${failure.messageID}: ${getErrorMessage(failure.error)}`;
35
+ rawError = failure.error;
36
+ break;
37
+ case 'session':
38
+ message = `Error processing session ${failure.sessionID}: ${getErrorMessage(failure.error)}`;
39
+ rawError = failure.error;
40
+ break;
41
+ case 'extraction':
42
+ message = `Extraction failed: ${getErrorMessage(failure.error)}`;
43
+ rawError = failure.error;
44
+ break;
45
+ }
46
+ stats.errors.push(message);
47
+ if (rawError !== undefined) {
48
+ console.error('[local-recall-daemon]', message, rawError);
49
+ return;
50
+ }
51
+ console.error('[local-recall-daemon]', message);
52
+ }
23
53
  // ────────────────────────────────────────────────────────────
24
54
  // Helpers
25
55
  // ────────────────────────────────────────────────────────────
@@ -69,7 +99,7 @@ export async function runExtraction(directory) {
69
99
  // Find project for this directory
70
100
  const project = await findProject(directory);
71
101
  if (!project) {
72
- stats.errors.push(`No OpenCode project found for directory: ${directory}`);
102
+ recordFailure(stats, { scope: 'project', directory });
73
103
  return stats;
74
104
  }
75
105
  // Ensure local-recall directories exist
@@ -147,6 +177,7 @@ export async function runExtraction(directory) {
147
177
  processedHashes.add(msgHash);
148
178
  // Mark as processed with content hash
149
179
  newProcessedEntries.push({
180
+ status: 'success',
150
181
  messageID: message.id,
151
182
  contentHash: msgHash,
152
183
  processedAt: Date.now(),
@@ -154,19 +185,29 @@ export async function runExtraction(directory) {
154
185
  });
155
186
  }
156
187
  catch (err) {
157
- stats.errors.push(`Error processing message ${message.id}: ${err instanceof Error ? err.message : String(err)}`);
188
+ recordFailure(stats, {
189
+ scope: 'message',
190
+ messageID: message.id,
191
+ error: err,
192
+ });
158
193
  // Still mark as processed to avoid re-trying broken messages
159
194
  newProcessedEntries.push({
195
+ status: 'failed',
160
196
  messageID: message.id,
161
197
  contentHash: msgHash,
162
198
  processedAt: Date.now(),
163
199
  memoriesCreated: 0,
200
+ failure: getErrorMessage(err),
164
201
  });
165
202
  }
166
203
  }
167
204
  }
168
205
  catch (err) {
169
- stats.errors.push(`Error processing session ${session.id}: ${err instanceof Error ? err.message : String(err)}`);
206
+ recordFailure(stats, {
207
+ scope: 'session',
208
+ sessionID: session.id,
209
+ error: err,
210
+ });
170
211
  }
171
212
  }
172
213
  // Batch store all new memories
@@ -180,7 +221,7 @@ export async function runExtraction(directory) {
180
221
  }
181
222
  }
182
223
  catch (err) {
183
- stats.errors.push(`Extraction failed: ${err instanceof Error ? err.message : String(err)}`);
224
+ recordFailure(stats, { scope: 'extraction', error: err });
184
225
  }
185
226
  return stats;
186
227
  }
@@ -119,11 +119,24 @@ export interface ExtractionResult {
119
119
  /** Where the extraction came from — used to generate logical IDs */
120
120
  source: 'session' | 'thinking';
121
121
  }
122
- /** Tracks which messages have already been processed */
123
- export interface ProcessedEntry {
122
+ interface ProcessedEntryBase {
124
123
  messageID: string;
125
124
  processedAt: number;
126
- memoriesCreated: number;
127
125
  /** SHA-256 hex hash of the concatenated extracted bodies for content-level idempotency */
128
126
  contentHash: string;
129
127
  }
128
+ /** Tracks which messages have already been processed */
129
+ export type ProcessedEntry = (ProcessedEntryBase & {
130
+ status: 'success';
131
+ memoriesCreated: number;
132
+ failure?: undefined;
133
+ }) | (ProcessedEntryBase & {
134
+ status: 'failed';
135
+ memoriesCreated: 0;
136
+ failure: string;
137
+ }) | (ProcessedEntryBase & {
138
+ status?: undefined;
139
+ memoriesCreated: number;
140
+ failure?: undefined;
141
+ });
142
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@syntesseraai/opencode-feature-factory",
4
- "version": "0.3.2",
4
+ "version": "0.3.3",
5
5
  "type": "module",
6
6
  "description": "OpenCode plugin for Feature Factory agents - provides sub-agents and skills for validation, review, security, and architecture assessment",
7
7
  "license": "MIT",