@stackmemoryai/stackmemory 1.0.1 → 1.2.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/dist/src/cli/claude-sm.js +65 -0
- package/dist/src/cli/commands/audit.js +134 -0
- package/dist/src/cli/commands/bench.js +252 -0
- package/dist/src/cli/commands/dashboard.js +2 -1
- package/dist/src/cli/commands/stats.js +118 -0
- package/dist/src/cli/index.js +6 -0
- package/dist/src/core/config/feature-flags.js +7 -1
- package/dist/src/core/context/enhanced-rehydration.js +24 -5
- package/dist/src/core/extensions/cerebras-adapter.js +28 -0
- package/dist/src/core/extensions/deepinfra-adapter.js +32 -0
- package/dist/src/core/extensions/provider-adapter.js +33 -240
- package/dist/src/core/models/complexity-scorer.js +154 -0
- package/dist/src/core/models/model-router.js +230 -36
- package/dist/src/core/models/provider-pricing.js +63 -0
- package/dist/src/core/models/sensitive-guard.js +112 -0
- package/dist/src/core/monitoring/feedback-loops.js +88 -0
- package/dist/src/hooks/schemas.js +12 -1
- package/dist/src/integrations/anthropic/batch-client.js +256 -0
- package/dist/src/integrations/anthropic/client.js +87 -72
- package/dist/src/integrations/claude-code/subagent-client.js +133 -12
- package/dist/src/integrations/graphiti/client.js +16 -4
- package/dist/src/integrations/mcp/handlers/index.js +25 -1
- package/dist/src/integrations/mcp/handlers/provider-handlers.js +227 -0
- package/dist/src/integrations/mcp/server.js +316 -1
- package/dist/src/integrations/mcp/tool-definitions.js +90 -1
- package/dist/src/orchestrators/multimodal/baselines.js +128 -0
- package/dist/src/orchestrators/multimodal/constants.js +9 -1
- package/dist/src/orchestrators/multimodal/harness.js +86 -6
- package/dist/src/orchestrators/multimodal/providers.js +113 -2
- package/dist/src/skills/recursive-agent-orchestrator.js +15 -10
- package/dist/src/utils/fuzzy-edit.js +162 -0
- package/dist/src/utils/hook-installer.js +155 -0
- package/package.json +6 -2
- package/scripts/gepa/.before-optimize.md +159 -0
- package/scripts/gepa/generations/gen-000/baseline.md +159 -124
- package/scripts/gepa/generations/gen-001/baseline.md +159 -0
- package/scripts/gepa/generations/gen-001/variant-a.md +166 -0
- package/scripts/gepa/generations/gen-001/variant-b.md +237 -0
- package/scripts/gepa/generations/gen-001/variant-c.md +61 -0
- package/scripts/gepa/generations/gen-001/variant-d.md +119 -0
- package/scripts/gepa/results/eval-1-baseline.json +41 -0
- package/scripts/gepa/results/eval-1-variant-a.json +41 -0
- package/scripts/gepa/results/eval-1-variant-b.json +41 -0
- package/scripts/gepa/results/eval-1-variant-c.json +41 -0
- package/scripts/gepa/results/eval-1-variant-d.json +41 -0
- package/scripts/gepa/state.json +41 -2
- package/scripts/install-claude-hooks-auto.js +176 -44
- package/templates/claude-hooks/auto-checkpoint.js +174 -0
- package/templates/claude-hooks/chime-on-stop.sh +22 -0
- package/templates/claude-hooks/session-rescue.sh +15 -0
- package/templates/claude-hooks/stop-checkpoint.js +120 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stop-Checkpoint Hook
|
|
5
|
+
*
|
|
6
|
+
* Fires on session stop. Reads checkpoint state for current project.
|
|
7
|
+
* If 3+ checkpoints accumulated, outputs a "context heavy" message.
|
|
8
|
+
* Writes a final checkpoint with session stop metadata.
|
|
9
|
+
*
|
|
10
|
+
* State is keyed per-session (process.ppid) to avoid race conditions
|
|
11
|
+
* when multiple Claude instances run concurrently.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const crypto = require('crypto');
|
|
17
|
+
|
|
18
|
+
const HOME = process.env.HOME || '/tmp';
|
|
19
|
+
const SESSION_ID = process.env.CLAUDE_INSTANCE_ID || String(process.ppid);
|
|
20
|
+
const STATE_FILE = path.join(
|
|
21
|
+
HOME,
|
|
22
|
+
'.stackmemory',
|
|
23
|
+
`checkpoint-state-${SESSION_ID}.json`
|
|
24
|
+
);
|
|
25
|
+
const MAX_FILES_TRACKED = 50;
|
|
26
|
+
const MAX_RECENT_TOOLS = 20;
|
|
27
|
+
|
|
28
|
+
function projectHash(cwd) {
|
|
29
|
+
return crypto.createHash('md5').update(cwd).digest('hex').slice(0, 12);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ensureDir(dir) {
|
|
33
|
+
if (!fs.existsSync(dir)) {
|
|
34
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function safeWriteFile(filePath, content) {
|
|
39
|
+
const tmp = filePath + '.tmp';
|
|
40
|
+
fs.writeFileSync(tmp, content);
|
|
41
|
+
fs.renameSync(tmp, filePath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function loadState() {
|
|
45
|
+
try {
|
|
46
|
+
if (fs.existsSync(STATE_FILE)) {
|
|
47
|
+
const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
|
|
48
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
49
|
+
for (const [cwd, proj] of Object.entries(state.projects)) {
|
|
50
|
+
if (
|
|
51
|
+
proj.sessionStart &&
|
|
52
|
+
new Date(proj.sessionStart).getTime() < cutoff
|
|
53
|
+
) {
|
|
54
|
+
delete state.projects[cwd];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
// Corrupted state, start fresh
|
|
61
|
+
}
|
|
62
|
+
return { projects: {} };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function main() {
|
|
66
|
+
try {
|
|
67
|
+
const cwd = process.cwd();
|
|
68
|
+
const state = loadState();
|
|
69
|
+
const proj = state.projects?.[cwd];
|
|
70
|
+
|
|
71
|
+
if (!proj) return;
|
|
72
|
+
|
|
73
|
+
const { toolCount, checkpointCount, sessionStart, filesModified } = proj;
|
|
74
|
+
|
|
75
|
+
// Write final checkpoint
|
|
76
|
+
const hash = projectHash(cwd);
|
|
77
|
+
const cpDir = path.join(HOME, '.stackmemory', 'checkpoints', hash);
|
|
78
|
+
ensureDir(cpDir);
|
|
79
|
+
|
|
80
|
+
// NaN duration guard
|
|
81
|
+
const startMs = sessionStart ? new Date(sessionStart).getTime() : 0;
|
|
82
|
+
const duration =
|
|
83
|
+
startMs > 0 ? Math.round((Date.now() - startMs) / 1000) : 0;
|
|
84
|
+
|
|
85
|
+
const finalCheckpoint = {
|
|
86
|
+
reason: 'session_stop',
|
|
87
|
+
toolCount,
|
|
88
|
+
checkpointNumber: checkpointCount,
|
|
89
|
+
totalFiles: filesModified?.length || 0,
|
|
90
|
+
duration,
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
filesModified: (filesModified || []).slice(-MAX_FILES_TRACKED),
|
|
93
|
+
recentTools: (proj.recentTools || []).slice(-MAX_RECENT_TOOLS),
|
|
94
|
+
cwd,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
safeWriteFile(
|
|
98
|
+
path.join(cpDir, 'latest.json'),
|
|
99
|
+
JSON.stringify(finalCheckpoint, null, 2)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Output context-heavy message if 3+ checkpoints
|
|
103
|
+
if (checkpointCount >= 3) {
|
|
104
|
+
console.error(
|
|
105
|
+
`\nContext heavy (${checkpointCount} checkpoints, ${toolCount} tool calls). State saved. Consider /clear to reload from checkpoint.\n`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Clean up session state file since session is ending
|
|
110
|
+
try {
|
|
111
|
+
fs.unlinkSync(STATE_FILE);
|
|
112
|
+
} catch {
|
|
113
|
+
// Best-effort cleanup
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
// Silent fail -- never block the agent
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
main();
|