@stackmemoryai/stackmemory 1.2.7 → 1.2.9

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 (27) hide show
  1. package/README.md +3 -3
  2. package/dist/src/cli/commands/daemon.js +306 -2
  3. package/dist/src/cli/commands/desires.js +117 -0
  4. package/dist/src/cli/commands/digest.js +73 -0
  5. package/dist/src/cli/commands/setup.js +369 -39
  6. package/dist/src/cli/commands/team.js +168 -0
  7. package/dist/src/cli/index.js +6 -0
  8. package/dist/src/core/digest/chronological-digest.js +143 -0
  9. package/dist/src/core/digest/index.js +1 -0
  10. package/dist/src/integrations/mcp/server.js +622 -251
  11. package/dist/src/integrations/mcp/tool-definitions.js +607 -50
  12. package/dist/src/utils/hook-installer.js +35 -0
  13. package/package.json +2 -2
  14. package/scripts/install-claude-hooks-auto.js +35 -0
  15. package/templates/claude-hooks/daemon-auto-start.js +125 -0
  16. package/templates/claude-hooks/desire-path-trace.js +118 -0
  17. package/templates/claude-hooks/session-rescue.sh +3 -0
  18. package/templates/claude-hooks/team-subagent-stop.js +77 -0
  19. package/templates/claude-hooks/team-task-complete.js +83 -0
  20. package/templates/claude-hooks/team-teammate-idle.js +96 -0
  21. /package/templates/claude-hooks/{auto-background-hook.js → archive/auto-background-hook.js} +0 -0
  22. /package/templates/claude-hooks/{hook-config.json → archive/hook-config.json} +0 -0
  23. /package/templates/claude-hooks/{hooks.json → archive/hooks.json} +0 -0
  24. /package/templates/claude-hooks/{on-compact-detected → archive/on-compact-detected} +0 -0
  25. /package/templates/claude-hooks/{on-exit → archive/on-exit} +0 -0
  26. /package/templates/claude-hooks/{post-edit-sweep.js → archive/post-edit-sweep.js} +0 -0
  27. /package/templates/claude-hooks/{pre-tool-use → archive/pre-tool-use} +0 -0
@@ -0,0 +1,143 @@
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
+ function getTimeRange(period) {
6
+ const now = /* @__PURE__ */ new Date();
7
+ const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
8
+ switch (period) {
9
+ case "today": {
10
+ return {
11
+ start: Math.floor(todayStart.getTime() / 1e3),
12
+ end: Math.floor(now.getTime() / 1e3),
13
+ label: `Today \u2014 ${todayStart.toISOString().slice(0, 10)}`
14
+ };
15
+ }
16
+ case "yesterday": {
17
+ const yesterdayStart = new Date(todayStart);
18
+ yesterdayStart.setDate(yesterdayStart.getDate() - 1);
19
+ return {
20
+ start: Math.floor(yesterdayStart.getTime() / 1e3),
21
+ end: Math.floor(todayStart.getTime() / 1e3),
22
+ label: `Yesterday \u2014 ${yesterdayStart.toISOString().slice(0, 10)}`
23
+ };
24
+ }
25
+ case "week": {
26
+ const weekStart = new Date(todayStart);
27
+ weekStart.setDate(weekStart.getDate() - 7);
28
+ return {
29
+ start: Math.floor(weekStart.getTime() / 1e3),
30
+ end: Math.floor(now.getTime() / 1e3),
31
+ label: `Week \u2014 ${weekStart.toISOString().slice(0, 10)} to ${todayStart.toISOString().slice(0, 10)}`
32
+ };
33
+ }
34
+ }
35
+ }
36
+ function formatDate(epoch) {
37
+ return new Date(epoch * 1e3).toISOString().slice(0, 10);
38
+ }
39
+ function generateChronologicalDigest(db, period, projectId) {
40
+ const { start, end, label } = getTimeRange(period);
41
+ let frames = db.prepare(
42
+ `SELECT frame_id, name, type, state, created_at, closed_at, inputs, outputs
43
+ FROM frames
44
+ WHERE project_id = ? AND created_at >= ? AND created_at < ?
45
+ ORDER BY created_at ASC`
46
+ ).all(projectId, start, end);
47
+ if (frames.length === 0 && projectId !== "default") {
48
+ frames = db.prepare(
49
+ `SELECT frame_id, name, type, state, created_at, closed_at, inputs, outputs
50
+ FROM frames
51
+ WHERE project_id = 'default' AND created_at >= ? AND created_at < ?
52
+ ORDER BY created_at ASC`
53
+ ).all(start, end);
54
+ }
55
+ if (frames.length === 0) {
56
+ return `# ${label}
57
+
58
+ No activity recorded.
59
+ `;
60
+ }
61
+ const frameIds = frames.map((f) => f.frame_id);
62
+ const placeholders = frameIds.map(() => "?").join(",");
63
+ const anchors = db.prepare(
64
+ `SELECT anchor_id, frame_id, type, text, priority, created_at
65
+ FROM anchors
66
+ WHERE frame_id IN (${placeholders})
67
+ ORDER BY priority DESC, created_at ASC`
68
+ ).all(...frameIds);
69
+ const events = db.prepare(
70
+ `SELECT event_id, frame_id, event_type, payload, ts
71
+ FROM events
72
+ WHERE frame_id IN (${placeholders}) AND event_type IN ('tool_call', 'decision')
73
+ ORDER BY ts ASC`
74
+ ).all(...frameIds);
75
+ const anchorsByFrame = /* @__PURE__ */ new Map();
76
+ for (const a of anchors) {
77
+ const list = anchorsByFrame.get(a.frame_id) || [];
78
+ list.push(a);
79
+ anchorsByFrame.set(a.frame_id, list);
80
+ }
81
+ const eventsByFrame = /* @__PURE__ */ new Map();
82
+ for (const e of events) {
83
+ const list = eventsByFrame.get(e.frame_id) || [];
84
+ list.push(e);
85
+ eventsByFrame.set(e.frame_id, list);
86
+ }
87
+ const framesByDate = /* @__PURE__ */ new Map();
88
+ for (const f of frames) {
89
+ const date = formatDate(f.created_at);
90
+ const list = framesByDate.get(date) || [];
91
+ list.push(f);
92
+ framesByDate.set(date, list);
93
+ }
94
+ const lines = [`# ${label}
95
+ `];
96
+ const renderFrame = (f) => {
97
+ lines.push(`## ${f.name} (${f.type}, ${f.state})`);
98
+ const frameAnchors = anchorsByFrame.get(f.frame_id) || [];
99
+ const frameEvents = eventsByFrame.get(f.frame_id) || [];
100
+ for (const a of frameAnchors.slice(0, 8)) {
101
+ lines.push(`- ${a.type}: ${a.text}`);
102
+ }
103
+ const files = /* @__PURE__ */ new Set();
104
+ for (const e of frameEvents) {
105
+ try {
106
+ const payload = JSON.parse(e.payload);
107
+ if (payload.arguments?.file_path)
108
+ files.add(payload.arguments.file_path);
109
+ if (payload.arguments?.path) files.add(payload.arguments.path);
110
+ } catch {
111
+ }
112
+ }
113
+ if (files.size > 0) {
114
+ lines.push(`- ${files.size} files touched`);
115
+ }
116
+ lines.push("");
117
+ };
118
+ if (period === "week") {
119
+ for (const [date, dateFrames] of framesByDate) {
120
+ lines.push(`### ${date}
121
+ `);
122
+ for (const f of dateFrames) {
123
+ renderFrame(f);
124
+ }
125
+ }
126
+ } else {
127
+ for (const f of frames) {
128
+ renderFrame(f);
129
+ }
130
+ }
131
+ const completed = frames.filter((f) => f.state === "completed").length;
132
+ const active = frames.filter((f) => f.state === "active").length;
133
+ lines.push("---");
134
+ lines.push(
135
+ `*${frames.length} frames total: ${completed} completed, ${active} active*`
136
+ );
137
+ lines.push(`*Generated: ${(/* @__PURE__ */ new Date()).toISOString()}*
138
+ `);
139
+ return lines.join("\n");
140
+ }
141
+ export {
142
+ generateChronologicalDigest
143
+ };
@@ -6,3 +6,4 @@ export * from "./types.js";
6
6
  export * from "./hybrid-digest-generator.js";
7
7
  export * from "./hybrid-digest.js";
8
8
  export * from "./frame-digest-integration.js";
9
+ export * from "./chronological-digest.js";