@stackmemoryai/stackmemory 0.5.30 → 0.5.33

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 (64) hide show
  1. package/README.md +44 -44
  2. package/dist/cli/claude-sm.js +199 -16
  3. package/dist/cli/claude-sm.js.map +2 -2
  4. package/dist/cli/commands/context.js +0 -11
  5. package/dist/cli/commands/context.js.map +2 -2
  6. package/dist/cli/commands/linear.js +1 -14
  7. package/dist/cli/commands/linear.js.map +2 -2
  8. package/dist/cli/commands/login.js +32 -10
  9. package/dist/cli/commands/login.js.map +2 -2
  10. package/dist/cli/commands/migrate.js +80 -22
  11. package/dist/cli/commands/migrate.js.map +2 -2
  12. package/dist/cli/commands/model.js +533 -0
  13. package/dist/cli/commands/model.js.map +7 -0
  14. package/dist/cli/commands/ralph.js +93 -28
  15. package/dist/cli/commands/ralph.js.map +2 -2
  16. package/dist/cli/commands/service.js +10 -3
  17. package/dist/cli/commands/service.js.map +2 -2
  18. package/dist/cli/commands/skills.js +60 -10
  19. package/dist/cli/commands/skills.js.map +2 -2
  20. package/dist/cli/commands/sms-notify.js +342 -22
  21. package/dist/cli/commands/sms-notify.js.map +3 -3
  22. package/dist/cli/index.js +2 -0
  23. package/dist/cli/index.js.map +2 -2
  24. package/dist/core/context/dual-stack-manager.js +23 -7
  25. package/dist/core/context/dual-stack-manager.js.map +2 -2
  26. package/dist/core/context/frame-database.js +33 -5
  27. package/dist/core/context/frame-database.js.map +2 -2
  28. package/dist/core/context/frame-digest.js +6 -1
  29. package/dist/core/context/frame-digest.js.map +2 -2
  30. package/dist/core/context/frame-manager.js +56 -9
  31. package/dist/core/context/frame-manager.js.map +2 -2
  32. package/dist/core/context/permission-manager.js +0 -11
  33. package/dist/core/context/permission-manager.js.map +2 -2
  34. package/dist/core/context/recursive-context-manager.js +15 -9
  35. package/dist/core/context/recursive-context-manager.js.map +2 -2
  36. package/dist/core/context/shared-context-layer.js +0 -11
  37. package/dist/core/context/shared-context-layer.js.map +2 -2
  38. package/dist/core/context/validation.js +6 -1
  39. package/dist/core/context/validation.js.map +2 -2
  40. package/dist/core/models/fallback-monitor.js +229 -0
  41. package/dist/core/models/fallback-monitor.js.map +7 -0
  42. package/dist/core/models/model-router.js +331 -0
  43. package/dist/core/models/model-router.js.map +7 -0
  44. package/dist/hooks/claude-code-whatsapp-hook.js +197 -0
  45. package/dist/hooks/claude-code-whatsapp-hook.js.map +7 -0
  46. package/dist/hooks/linear-task-picker.js +1 -1
  47. package/dist/hooks/linear-task-picker.js.map +2 -2
  48. package/dist/hooks/schemas.js +55 -1
  49. package/dist/hooks/schemas.js.map +2 -2
  50. package/dist/hooks/session-summary.js +5 -1
  51. package/dist/hooks/session-summary.js.map +2 -2
  52. package/dist/hooks/sms-action-runner.js +12 -1
  53. package/dist/hooks/sms-action-runner.js.map +2 -2
  54. package/dist/hooks/sms-notify.js +4 -2
  55. package/dist/hooks/sms-notify.js.map +2 -2
  56. package/dist/hooks/sms-webhook.js +23 -2
  57. package/dist/hooks/sms-webhook.js.map +2 -2
  58. package/dist/hooks/whatsapp-commands.js +376 -0
  59. package/dist/hooks/whatsapp-commands.js.map +7 -0
  60. package/dist/hooks/whatsapp-scheduler.js +317 -0
  61. package/dist/hooks/whatsapp-scheduler.js.map +7 -0
  62. package/dist/hooks/whatsapp-sync.js +375 -0
  63. package/dist/hooks/whatsapp-sync.js.map +7 -0
  64. package/package.json +2 -3
@@ -0,0 +1,375 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { existsSync, readFileSync } from "fs";
6
+ import { join } from "path";
7
+ import { homedir } from "os";
8
+ import {
9
+ sendNotification,
10
+ loadSMSConfig,
11
+ saveSMSConfig
12
+ } from "./sms-notify.js";
13
+ import { writeFileSecure, ensureSecureDir } from "./secure-fs.js";
14
+ import { SyncOptionsSchema, parseConfigSafe } from "./schemas.js";
15
+ const SYNC_CONFIG_PATH = join(homedir(), ".stackmemory", "whatsapp-sync.json");
16
+ const DEFAULT_SYNC_OPTIONS = {
17
+ autoSyncOnClose: false,
18
+ minFrameDuration: 30,
19
+ // Skip frames shorter than 30 seconds
20
+ includeDecisions: true,
21
+ includeFiles: true,
22
+ includeTests: true,
23
+ maxDigestLength: 400
24
+ };
25
+ function loadSyncOptions() {
26
+ try {
27
+ if (existsSync(SYNC_CONFIG_PATH)) {
28
+ const data = JSON.parse(readFileSync(SYNC_CONFIG_PATH, "utf8"));
29
+ return parseConfigSafe(
30
+ SyncOptionsSchema,
31
+ { ...DEFAULT_SYNC_OPTIONS, ...data },
32
+ DEFAULT_SYNC_OPTIONS,
33
+ "whatsapp-sync"
34
+ );
35
+ }
36
+ } catch {
37
+ }
38
+ return { ...DEFAULT_SYNC_OPTIONS };
39
+ }
40
+ function saveSyncOptions(options) {
41
+ try {
42
+ ensureSecureDir(join(homedir(), ".stackmemory"));
43
+ writeFileSecure(SYNC_CONFIG_PATH, JSON.stringify(options, null, 2));
44
+ } catch {
45
+ }
46
+ }
47
+ function formatDuration(seconds) {
48
+ if (seconds < 60) {
49
+ return `${seconds}s`;
50
+ } else if (seconds < 3600) {
51
+ const mins = Math.floor(seconds / 60);
52
+ const secs = seconds % 60;
53
+ return secs > 0 ? `${mins}m${secs}s` : `${mins}m`;
54
+ } else {
55
+ const hours = Math.floor(seconds / 3600);
56
+ const mins = Math.floor(seconds % 3600 / 60);
57
+ return mins > 0 ? `${hours}h${mins}m` : `${hours}h`;
58
+ }
59
+ }
60
+ function truncate(text, maxLen) {
61
+ if (text.length <= maxLen) return text;
62
+ return text.slice(0, maxLen - 3) + "...";
63
+ }
64
+ function getStatusSymbol(status) {
65
+ switch (status) {
66
+ case "success":
67
+ return "OK";
68
+ case "failure":
69
+ return "FAIL";
70
+ case "partial":
71
+ return "PARTIAL";
72
+ case "ongoing":
73
+ return "ACTIVE";
74
+ default:
75
+ return "?";
76
+ }
77
+ }
78
+ function generateMobileDigest(data, options = DEFAULT_SYNC_OPTIONS) {
79
+ const parts = [];
80
+ const maxLen = options.maxDigestLength;
81
+ const header = `FRAME: ${truncate(data.name, 30)} [${data.type}] - ${formatDuration(data.durationSeconds)} ${getStatusSymbol(data.status)}`;
82
+ parts.push(header);
83
+ const activityParts = [];
84
+ if (options.includeFiles && data.filesModified.length > 0) {
85
+ activityParts.push(`FILES: ${data.filesModified.length}`);
86
+ }
87
+ if (data.toolCallCount > 0) {
88
+ activityParts.push(`TOOLS: ${data.toolCallCount}`);
89
+ }
90
+ if (options.includeTests && data.testsRun.length > 0) {
91
+ const passed = data.testsRun.filter((t) => t.status === "passed").length;
92
+ const failed = data.testsRun.filter((t) => t.status === "failed").length;
93
+ if (failed > 0) {
94
+ activityParts.push(`TESTS: ${passed}ok/${failed}fail`);
95
+ } else {
96
+ activityParts.push(`TESTS: ${passed} pass`);
97
+ }
98
+ }
99
+ if (activityParts.length > 0) {
100
+ parts.push(activityParts.join(" | "));
101
+ }
102
+ if (options.includeFiles && data.filesModified.length > 0) {
103
+ const fileList = data.filesModified.slice(0, 3).map((f) => {
104
+ const basename = f.path.split("/").pop() || f.path;
105
+ const op = f.operation.charAt(0).toUpperCase();
106
+ return `${op}:${truncate(basename, 20)}`;
107
+ }).join(", ");
108
+ const more = data.filesModified.length > 3 ? ` +${data.filesModified.length - 3}` : "";
109
+ parts.push(` ${fileList}${more}`);
110
+ }
111
+ if (options.includeDecisions && data.decisions.length > 0) {
112
+ parts.push("");
113
+ parts.push("DECISIONS:");
114
+ data.decisions.slice(0, 3).forEach((d) => {
115
+ parts.push(` ${truncate(d, 60)}`);
116
+ });
117
+ if (data.decisions.length > 3) {
118
+ parts.push(` +${data.decisions.length - 3} more`);
119
+ }
120
+ }
121
+ if (data.risks.length > 0) {
122
+ parts.push("");
123
+ parts.push("RISKS:");
124
+ data.risks.slice(0, 2).forEach((r) => {
125
+ parts.push(` ${truncate(r, 50)}`);
126
+ });
127
+ }
128
+ const unresolvedErrors = data.errors.filter((e) => !e.resolved);
129
+ if (unresolvedErrors.length > 0) {
130
+ parts.push("");
131
+ parts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);
132
+ unresolvedErrors.slice(0, 2).forEach((e) => {
133
+ parts.push(` ${truncate(e.message, 50)}`);
134
+ });
135
+ }
136
+ parts.push("");
137
+ if (data.status === "success") {
138
+ parts.push("NEXT: commit & test");
139
+ } else if (data.status === "failure") {
140
+ parts.push("NEXT: fix errors");
141
+ } else if (data.status === "partial") {
142
+ parts.push("NEXT: review & continue");
143
+ } else {
144
+ parts.push("NEXT: check status");
145
+ }
146
+ let result = parts.join("\n");
147
+ if (result.length > maxLen) {
148
+ const essentialParts = [header];
149
+ if (activityParts.length > 0) {
150
+ essentialParts.push(activityParts.join(" | "));
151
+ }
152
+ if (options.includeDecisions && data.decisions.length > 0) {
153
+ essentialParts.push("");
154
+ essentialParts.push(`DECISIONS: ${data.decisions.length}`);
155
+ essentialParts.push(` ${truncate(data.decisions[0], 50)}`);
156
+ }
157
+ if (unresolvedErrors.length > 0) {
158
+ essentialParts.push("");
159
+ essentialParts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);
160
+ }
161
+ essentialParts.push("");
162
+ essentialParts.push(
163
+ data.status === "success" ? "NEXT: commit" : "NEXT: review"
164
+ );
165
+ result = essentialParts.join("\n");
166
+ }
167
+ return result.slice(0, maxLen);
168
+ }
169
+ async function getFrameDigestData(frameId) {
170
+ try {
171
+ const digestPath = join(
172
+ homedir(),
173
+ ".stackmemory",
174
+ "latest-frame-digest.json"
175
+ );
176
+ if (existsSync(digestPath)) {
177
+ const data = JSON.parse(readFileSync(digestPath, "utf8"));
178
+ if (frameId && data.frameId !== frameId) {
179
+ return null;
180
+ }
181
+ return data;
182
+ }
183
+ return null;
184
+ } catch {
185
+ return null;
186
+ }
187
+ }
188
+ function storeFrameDigest(data) {
189
+ try {
190
+ ensureSecureDir(join(homedir(), ".stackmemory"));
191
+ const digestPath = join(
192
+ homedir(),
193
+ ".stackmemory",
194
+ "latest-frame-digest.json"
195
+ );
196
+ writeFileSecure(digestPath, JSON.stringify(data, null, 2));
197
+ } catch {
198
+ }
199
+ }
200
+ async function syncContext() {
201
+ const options = loadSyncOptions();
202
+ const data = await getFrameDigestData();
203
+ if (!data) {
204
+ return {
205
+ success: false,
206
+ error: "No context data available. Run a task first."
207
+ };
208
+ }
209
+ return syncFrameData(data, options);
210
+ }
211
+ async function syncFrame(frameId) {
212
+ const options = loadSyncOptions();
213
+ const data = await getFrameDigestData(frameId);
214
+ if (!data) {
215
+ return {
216
+ success: false,
217
+ error: `Frame not found: ${frameId}`
218
+ };
219
+ }
220
+ return syncFrameData(data, options);
221
+ }
222
+ async function syncFrameData(data, options) {
223
+ const config = loadSMSConfig();
224
+ if (!config.enabled) {
225
+ return { success: false, error: "Notifications disabled" };
226
+ }
227
+ if (data.durationSeconds < options.minFrameDuration) {
228
+ return {
229
+ success: false,
230
+ error: `Frame too short (${data.durationSeconds}s < ${options.minFrameDuration}s min)`
231
+ };
232
+ }
233
+ const digest = generateMobileDigest(data, options);
234
+ const payload = {
235
+ type: "custom",
236
+ title: "Context Sync",
237
+ message: digest,
238
+ prompt: {
239
+ type: "options",
240
+ options: [
241
+ { key: "1", label: "Commit", action: "git add -A && git commit" },
242
+ { key: "2", label: "Status", action: "stackmemory status" },
243
+ { key: "3", label: "Continue", action: 'echo "Continuing..."' }
244
+ ],
245
+ question: "Action?"
246
+ }
247
+ };
248
+ const result = await sendNotification(payload);
249
+ return {
250
+ success: result.success,
251
+ messageId: result.promptId,
252
+ channel: result.channel,
253
+ error: result.error,
254
+ digestLength: digest.length
255
+ };
256
+ }
257
+ function enableAutoSync(options) {
258
+ const current = loadSyncOptions();
259
+ const updated = {
260
+ ...current,
261
+ ...options,
262
+ autoSyncOnClose: true
263
+ };
264
+ saveSyncOptions(updated);
265
+ const smsConfig = loadSMSConfig();
266
+ if (!smsConfig.notifyOn.custom) {
267
+ smsConfig.notifyOn.custom = true;
268
+ saveSMSConfig(smsConfig);
269
+ }
270
+ }
271
+ function disableAutoSync() {
272
+ const current = loadSyncOptions();
273
+ current.autoSyncOnClose = false;
274
+ saveSyncOptions(current);
275
+ }
276
+ function isAutoSyncEnabled() {
277
+ const options = loadSyncOptions();
278
+ return options.autoSyncOnClose;
279
+ }
280
+ async function onFrameClosed(frameData) {
281
+ if (!isAutoSyncEnabled()) {
282
+ return null;
283
+ }
284
+ storeFrameDigest(frameData);
285
+ const options = loadSyncOptions();
286
+ return syncFrameData(frameData, options);
287
+ }
288
+ function createFrameDigestData(frame, events, anchors) {
289
+ const now = Math.floor(Date.now() / 1e3);
290
+ const duration = (frame.closed_at || now) - frame.created_at;
291
+ const filesModified = [];
292
+ const filesSeen = /* @__PURE__ */ new Set();
293
+ events.filter((e) => e.event_type === "tool_call").forEach((e) => {
294
+ const path = e.payload["path"];
295
+ if (path && !filesSeen.has(path)) {
296
+ filesSeen.add(path);
297
+ const toolName = e.payload["tool_name"] || "";
298
+ let operation = "modify";
299
+ if (toolName.includes("Write") || toolName.includes("Create")) {
300
+ operation = "create";
301
+ } else if (toolName.includes("Read")) {
302
+ operation = "read";
303
+ } else if (toolName.includes("Delete")) {
304
+ operation = "delete";
305
+ }
306
+ filesModified.push({ path, operation });
307
+ }
308
+ });
309
+ const testsRun = [];
310
+ events.filter(
311
+ (e) => e.event_type === "tool_result" && String(e.payload["output"] || "").includes("test")
312
+ ).forEach((e) => {
313
+ const output = String(e.payload["output"] || "");
314
+ const passMatch = output.match(/(\d+) pass/i);
315
+ const failMatch = output.match(/(\d+) fail/i);
316
+ if (passMatch) {
317
+ testsRun.push({ name: "Tests", status: "passed" });
318
+ }
319
+ if (failMatch && parseInt(failMatch[1]) > 0) {
320
+ testsRun.push({ name: "Tests", status: "failed" });
321
+ }
322
+ });
323
+ const decisions = anchors.filter((a) => a.type === "DECISION").map((a) => a.text);
324
+ const risks = anchors.filter((a) => a.type === "RISK").map((a) => a.text);
325
+ const errors = [];
326
+ events.filter((e) => e.payload["error"] || e.payload["status"] === "error").forEach((e) => {
327
+ const errorMsg = e.payload["error"] || e.payload["message"] || "Unknown error";
328
+ errors.push({
329
+ type: e.payload["type"] || "error",
330
+ message: errorMsg,
331
+ resolved: false
332
+ });
333
+ });
334
+ let status = "ongoing";
335
+ if (frame.closed_at) {
336
+ if (errors.filter((e) => !e.resolved).length > 0) {
337
+ status = "failure";
338
+ } else if (testsRun.some((t) => t.status === "failed") || filesModified.length === 0) {
339
+ status = "partial";
340
+ } else {
341
+ status = "success";
342
+ }
343
+ }
344
+ const toolCallCount = events.filter(
345
+ (e) => e.event_type === "tool_call"
346
+ ).length;
347
+ return {
348
+ frameId: frame.frame_id,
349
+ name: frame.name,
350
+ type: frame.type,
351
+ status,
352
+ durationSeconds: duration,
353
+ filesModified: filesModified.filter((f) => f.operation !== "read"),
354
+ testsRun,
355
+ decisions,
356
+ risks,
357
+ toolCallCount,
358
+ errors
359
+ };
360
+ }
361
+ export {
362
+ createFrameDigestData,
363
+ disableAutoSync,
364
+ enableAutoSync,
365
+ generateMobileDigest,
366
+ getFrameDigestData,
367
+ isAutoSyncEnabled,
368
+ loadSyncOptions,
369
+ onFrameClosed,
370
+ saveSyncOptions,
371
+ storeFrameDigest,
372
+ syncContext,
373
+ syncFrame
374
+ };
375
+ //# sourceMappingURL=whatsapp-sync.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/hooks/whatsapp-sync.ts"],
4
+ "sourcesContent": ["/**\n * WhatsApp Context Sync Engine\n * Push frame digests and context updates to WhatsApp\n */\n\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport {\n sendNotification,\n loadSMSConfig,\n saveSMSConfig,\n type NotificationPayload,\n} from './sms-notify.js';\nimport { writeFileSecure, ensureSecureDir } from './secure-fs.js';\nimport { SyncOptionsSchema, parseConfigSafe } from './schemas.js';\n\nexport interface SyncOptions {\n autoSyncOnClose: boolean;\n minFrameDuration: number; // seconds, skip short frames\n includeDecisions: boolean;\n includeFiles: boolean;\n includeTests: boolean;\n maxDigestLength: number; // chars, default 400\n}\n\nexport interface SyncResult {\n success: boolean;\n messageId?: string;\n channel?: 'whatsapp' | 'sms';\n error?: string;\n digestLength?: number;\n}\n\nexport interface FrameDigestData {\n frameId: string;\n name: string;\n type: string;\n status: 'success' | 'failure' | 'partial' | 'ongoing';\n durationSeconds: number;\n filesModified: Array<{ path: string; operation: string }>;\n testsRun: Array<{ name: string; status: string }>;\n decisions: string[];\n risks: string[];\n toolCallCount: number;\n errors: Array<{ type: string; message: string; resolved: boolean }>;\n}\n\nconst SYNC_CONFIG_PATH = join(homedir(), '.stackmemory', 'whatsapp-sync.json');\n\nconst DEFAULT_SYNC_OPTIONS: SyncOptions = {\n autoSyncOnClose: false,\n minFrameDuration: 30, // Skip frames shorter than 30 seconds\n includeDecisions: true,\n includeFiles: true,\n includeTests: true,\n maxDigestLength: 400,\n};\n\n/**\n * Load sync options from config file\n */\nexport function loadSyncOptions(): SyncOptions {\n try {\n if (existsSync(SYNC_CONFIG_PATH)) {\n const data = JSON.parse(readFileSync(SYNC_CONFIG_PATH, 'utf8'));\n return parseConfigSafe(\n SyncOptionsSchema,\n { ...DEFAULT_SYNC_OPTIONS, ...data },\n DEFAULT_SYNC_OPTIONS,\n 'whatsapp-sync'\n );\n }\n } catch {\n // Use defaults\n }\n return { ...DEFAULT_SYNC_OPTIONS };\n}\n\n/**\n * Save sync options to config file\n */\nexport function saveSyncOptions(options: SyncOptions): void {\n try {\n ensureSecureDir(join(homedir(), '.stackmemory'));\n writeFileSecure(SYNC_CONFIG_PATH, JSON.stringify(options, null, 2));\n } catch {\n // Silently fail\n }\n}\n\n/**\n * Format duration for mobile display\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 60) {\n return `${seconds}s`;\n } else if (seconds < 3600) {\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return secs > 0 ? `${mins}m${secs}s` : `${mins}m`;\n } else {\n const hours = Math.floor(seconds / 3600);\n const mins = Math.floor((seconds % 3600) / 60);\n return mins > 0 ? `${hours}h${mins}m` : `${hours}h`;\n }\n}\n\n/**\n * Truncate text to max length with ellipsis\n */\nfunction truncate(text: string, maxLen: number): string {\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen - 3) + '...';\n}\n\n/**\n * Get status symbol for mobile display\n */\nfunction getStatusSymbol(status: string): string {\n switch (status) {\n case 'success':\n return 'OK';\n case 'failure':\n return 'FAIL';\n case 'partial':\n return 'PARTIAL';\n case 'ongoing':\n return 'ACTIVE';\n default:\n return '?';\n }\n}\n\n/**\n * Generate WhatsApp-friendly digest (300-400 chars max)\n * Optimized for mobile readability\n */\nexport function generateMobileDigest(\n data: FrameDigestData,\n options: SyncOptions = DEFAULT_SYNC_OPTIONS\n): string {\n const parts: string[] = [];\n const maxLen = options.maxDigestLength;\n\n // Header: FRAME: Name [type] - duration status\n const header = `FRAME: ${truncate(data.name, 30)} [${data.type}] - ${formatDuration(data.durationSeconds)} ${getStatusSymbol(data.status)}`;\n parts.push(header);\n\n // Activity summary line\n const activityParts: string[] = [];\n\n if (options.includeFiles && data.filesModified.length > 0) {\n activityParts.push(`FILES: ${data.filesModified.length}`);\n }\n\n if (data.toolCallCount > 0) {\n activityParts.push(`TOOLS: ${data.toolCallCount}`);\n }\n\n if (options.includeTests && data.testsRun.length > 0) {\n const passed = data.testsRun.filter((t) => t.status === 'passed').length;\n const failed = data.testsRun.filter((t) => t.status === 'failed').length;\n if (failed > 0) {\n activityParts.push(`TESTS: ${passed}ok/${failed}fail`);\n } else {\n activityParts.push(`TESTS: ${passed} pass`);\n }\n }\n\n if (activityParts.length > 0) {\n parts.push(activityParts.join(' | '));\n }\n\n // Files modified (compact)\n if (options.includeFiles && data.filesModified.length > 0) {\n const fileList = data.filesModified\n .slice(0, 3)\n .map((f) => {\n const basename = f.path.split('/').pop() || f.path;\n const op = f.operation.charAt(0).toUpperCase();\n return `${op}:${truncate(basename, 20)}`;\n })\n .join(', ');\n const more =\n data.filesModified.length > 3 ? ` +${data.filesModified.length - 3}` : '';\n parts.push(` ${fileList}${more}`);\n }\n\n // Decisions (high value)\n if (options.includeDecisions && data.decisions.length > 0) {\n parts.push('');\n parts.push('DECISIONS:');\n data.decisions.slice(0, 3).forEach((d) => {\n parts.push(` ${truncate(d, 60)}`);\n });\n if (data.decisions.length > 3) {\n parts.push(` +${data.decisions.length - 3} more`);\n }\n }\n\n // Risks (important to surface)\n if (data.risks.length > 0) {\n parts.push('');\n parts.push('RISKS:');\n data.risks.slice(0, 2).forEach((r) => {\n parts.push(` ${truncate(r, 50)}`);\n });\n }\n\n // Errors (unresolved only)\n const unresolvedErrors = data.errors.filter((e) => !e.resolved);\n if (unresolvedErrors.length > 0) {\n parts.push('');\n parts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);\n unresolvedErrors.slice(0, 2).forEach((e) => {\n parts.push(` ${truncate(e.message, 50)}`);\n });\n }\n\n // Next action suggestion\n parts.push('');\n if (data.status === 'success') {\n parts.push('NEXT: commit & test');\n } else if (data.status === 'failure') {\n parts.push('NEXT: fix errors');\n } else if (data.status === 'partial') {\n parts.push('NEXT: review & continue');\n } else {\n parts.push('NEXT: check status');\n }\n\n // Join and truncate final result\n let result = parts.join('\\n');\n\n // If too long, trim aggressively\n if (result.length > maxLen) {\n // Remove less important sections\n const essentialParts = [header];\n\n if (activityParts.length > 0) {\n essentialParts.push(activityParts.join(' | '));\n }\n\n if (options.includeDecisions && data.decisions.length > 0) {\n essentialParts.push('');\n essentialParts.push(`DECISIONS: ${data.decisions.length}`);\n essentialParts.push(` ${truncate(data.decisions[0], 50)}`);\n }\n\n if (unresolvedErrors.length > 0) {\n essentialParts.push('');\n essentialParts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);\n }\n\n essentialParts.push('');\n essentialParts.push(\n data.status === 'success' ? 'NEXT: commit' : 'NEXT: review'\n );\n\n result = essentialParts.join('\\n');\n }\n\n return result.slice(0, maxLen);\n}\n\n/**\n * Get frame digest data from stackmemory database\n * Returns null if frame not found or context unavailable\n */\nexport async function getFrameDigestData(\n frameId?: string\n): Promise<FrameDigestData | null> {\n try {\n // Try to load from recent frame digests\n const digestPath = join(\n homedir(),\n '.stackmemory',\n 'latest-frame-digest.json'\n );\n\n if (existsSync(digestPath)) {\n const data = JSON.parse(readFileSync(digestPath, 'utf8'));\n\n // If frameId specified, check if it matches\n if (frameId && data.frameId !== frameId) {\n return null;\n }\n\n return data as FrameDigestData;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Store frame digest for sync\n */\nexport function storeFrameDigest(data: FrameDigestData): void {\n try {\n ensureSecureDir(join(homedir(), '.stackmemory'));\n const digestPath = join(\n homedir(),\n '.stackmemory',\n 'latest-frame-digest.json'\n );\n writeFileSecure(digestPath, JSON.stringify(data, null, 2));\n } catch {\n // Silently fail\n }\n}\n\n/**\n * Push current context to WhatsApp\n */\nexport async function syncContext(): Promise<SyncResult> {\n const options = loadSyncOptions();\n const data = await getFrameDigestData();\n\n if (!data) {\n return {\n success: false,\n error: 'No context data available. Run a task first.',\n };\n }\n\n return syncFrameData(data, options);\n}\n\n/**\n * Sync specific frame by ID\n */\nexport async function syncFrame(frameId: string): Promise<SyncResult> {\n const options = loadSyncOptions();\n const data = await getFrameDigestData(frameId);\n\n if (!data) {\n return {\n success: false,\n error: `Frame not found: ${frameId}`,\n };\n }\n\n return syncFrameData(data, options);\n}\n\n/**\n * Sync frame data to WhatsApp\n */\nasync function syncFrameData(\n data: FrameDigestData,\n options: SyncOptions\n): Promise<SyncResult> {\n const config = loadSMSConfig();\n\n if (!config.enabled) {\n return { success: false, error: 'Notifications disabled' };\n }\n\n // Check minimum duration\n if (data.durationSeconds < options.minFrameDuration) {\n return {\n success: false,\n error: `Frame too short (${data.durationSeconds}s < ${options.minFrameDuration}s min)`,\n };\n }\n\n // Generate mobile digest\n const digest = generateMobileDigest(data, options);\n\n // Send notification\n const payload: NotificationPayload = {\n type: 'custom',\n title: 'Context Sync',\n message: digest,\n prompt: {\n type: 'options',\n options: [\n { key: '1', label: 'Commit', action: 'git add -A && git commit' },\n { key: '2', label: 'Status', action: 'stackmemory status' },\n { key: '3', label: 'Continue', action: 'echo \"Continuing...\"' },\n ],\n question: 'Action?',\n },\n };\n\n const result = await sendNotification(payload);\n\n return {\n success: result.success,\n messageId: result.promptId,\n channel: result.channel,\n error: result.error,\n digestLength: digest.length,\n };\n}\n\n/**\n * Enable auto-sync on frame close\n */\nexport function enableAutoSync(options?: Partial<SyncOptions>): void {\n const current = loadSyncOptions();\n const updated: SyncOptions = {\n ...current,\n ...options,\n autoSyncOnClose: true,\n };\n saveSyncOptions(updated);\n\n // Update SMS config to enable context_sync notifications\n const smsConfig = loadSMSConfig();\n if (!smsConfig.notifyOn.custom) {\n smsConfig.notifyOn.custom = true;\n saveSMSConfig(smsConfig);\n }\n}\n\n/**\n * Disable auto-sync\n */\nexport function disableAutoSync(): void {\n const current = loadSyncOptions();\n current.autoSyncOnClose = false;\n saveSyncOptions(current);\n}\n\n/**\n * Check if auto-sync is enabled\n */\nexport function isAutoSyncEnabled(): boolean {\n const options = loadSyncOptions();\n return options.autoSyncOnClose;\n}\n\n/**\n * Callback for frame manager to trigger auto-sync\n * Call this when a frame closes\n */\nexport async function onFrameClosed(\n frameData: FrameDigestData\n): Promise<SyncResult | null> {\n if (!isAutoSyncEnabled()) {\n return null;\n }\n\n // Store for potential manual sync later\n storeFrameDigest(frameData);\n\n // Auto-sync\n const options = loadSyncOptions();\n return syncFrameData(frameData, options);\n}\n\n/**\n * Create frame digest data from raw frame info\n * Helper for integration with frame-manager\n */\nexport function createFrameDigestData(\n frame: {\n frame_id: string;\n name: string;\n type: string;\n created_at: number;\n closed_at?: number;\n },\n events: Array<{\n event_type: string;\n payload: Record<string, unknown>;\n }>,\n anchors: Array<{\n type: string;\n text: string;\n }>\n): FrameDigestData {\n const now = Math.floor(Date.now() / 1000);\n const duration = (frame.closed_at || now) - frame.created_at;\n\n // Extract files from tool_call events\n const filesModified: Array<{ path: string; operation: string }> = [];\n const filesSeen = new Set<string>();\n\n events\n .filter((e) => e.event_type === 'tool_call')\n .forEach((e) => {\n const path = e.payload['path'] as string | undefined;\n if (path && !filesSeen.has(path)) {\n filesSeen.add(path);\n const toolName = (e.payload['tool_name'] as string) || '';\n let operation = 'modify';\n if (toolName.includes('Write') || toolName.includes('Create')) {\n operation = 'create';\n } else if (toolName.includes('Read')) {\n operation = 'read';\n } else if (toolName.includes('Delete')) {\n operation = 'delete';\n }\n filesModified.push({ path, operation });\n }\n });\n\n // Extract tests\n const testsRun: Array<{ name: string; status: string }> = [];\n events\n .filter(\n (e) =>\n e.event_type === 'tool_result' &&\n String(e.payload['output'] || '').includes('test')\n )\n .forEach((e) => {\n const output = String(e.payload['output'] || '');\n // Simple test result extraction\n const passMatch = output.match(/(\\d+) pass/i);\n const failMatch = output.match(/(\\d+) fail/i);\n if (passMatch) {\n testsRun.push({ name: 'Tests', status: 'passed' });\n }\n if (failMatch && parseInt(failMatch[1]) > 0) {\n testsRun.push({ name: 'Tests', status: 'failed' });\n }\n });\n\n // Extract decisions and risks from anchors\n const decisions = anchors\n .filter((a) => a.type === 'DECISION')\n .map((a) => a.text);\n\n const risks = anchors.filter((a) => a.type === 'RISK').map((a) => a.text);\n\n // Extract errors\n const errors: Array<{ type: string; message: string; resolved: boolean }> =\n [];\n events\n .filter((e) => e.payload['error'] || e.payload['status'] === 'error')\n .forEach((e) => {\n const errorMsg =\n (e.payload['error'] as string) ||\n (e.payload['message'] as string) ||\n 'Unknown error';\n errors.push({\n type: (e.payload['type'] as string) || 'error',\n message: errorMsg,\n resolved: false,\n });\n });\n\n // Determine status\n let status: 'success' | 'failure' | 'partial' | 'ongoing' = 'ongoing';\n if (frame.closed_at) {\n if (errors.filter((e) => !e.resolved).length > 0) {\n status = 'failure';\n } else if (\n testsRun.some((t) => t.status === 'failed') ||\n filesModified.length === 0\n ) {\n status = 'partial';\n } else {\n status = 'success';\n }\n }\n\n // Count tool calls\n const toolCallCount = events.filter(\n (e) => e.event_type === 'tool_call'\n ).length;\n\n return {\n frameId: frame.frame_id,\n name: frame.name,\n type: frame.type,\n status,\n durationSeconds: duration,\n filesModified: filesModified.filter((f) => f.operation !== 'read'),\n testsRun,\n decisions,\n risks,\n toolCallCount,\n errors,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackmemoryai/stackmemory",
3
- "version": "0.5.30",
3
+ "version": "0.5.33",
4
4
  "description": "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention",
5
5
  "engines": {
6
6
  "node": ">=20.0.0",
@@ -52,7 +52,7 @@
52
52
  "build": "node esbuild.config.js",
53
53
  "build:types": "tsc --emitDeclarationOnly --project tsconfig.build.json",
54
54
  "lint": "eslint src/**/*.ts scripts/**/*.ts",
55
- "lint:fix": "eslint src/**/*.ts scripts/**/*.ts --fix",
55
+ "lint:fix": "eslint src/**/*.ts scripts/**/*.ts --fix --max-warnings=-1",
56
56
  "lint:fast": "oxlint src scripts",
57
57
  "format": "prettier --write src/**/*.ts scripts/**/*.ts",
58
58
  "test": "vitest",
@@ -142,7 +142,6 @@
142
142
  },
143
143
  "lint-staged": {
144
144
  "*.{ts,js}": [
145
- "npm run lint:fix",
146
145
  "prettier --write"
147
146
  ]
148
147
  },