@ulrichc1/sparn 1.1.0 → 1.2.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.
- package/README.md +52 -7
- package/dist/cli/index.cjs +580 -33
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +575 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/daemon/index.cjs +728 -159
- package/dist/daemon/index.cjs.map +1 -1
- package/dist/daemon/index.js +697 -150
- package/dist/daemon/index.js.map +1 -1
- package/dist/index.cjs +221 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +217 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.cjs +957 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +934 -0
- package/dist/mcp/index.js.map +1 -0
- package/package.json +8 -3
package/dist/index.cjs
CHANGED
|
@@ -47,6 +47,7 @@ __export(src_exports, {
|
|
|
47
47
|
createLogger: () => createLogger,
|
|
48
48
|
createSessionWatcher: () => createSessionWatcher,
|
|
49
49
|
createSleepCompressor: () => createSleepCompressor,
|
|
50
|
+
createSparnMcpServer: () => createSparnMcpServer,
|
|
50
51
|
createSparsePruner: () => createSparsePruner,
|
|
51
52
|
estimateTokens: () => estimateTokens,
|
|
52
53
|
hashContent: () => hashContent,
|
|
@@ -55,6 +56,10 @@ __export(src_exports, {
|
|
|
55
56
|
});
|
|
56
57
|
module.exports = __toCommonJS(src_exports);
|
|
57
58
|
|
|
59
|
+
// node_modules/tsup/assets/cjs_shims.js
|
|
60
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
61
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
62
|
+
|
|
58
63
|
// src/core/btsp-embedder.ts
|
|
59
64
|
var import_node_crypto2 = require("crypto");
|
|
60
65
|
|
|
@@ -1366,6 +1371,7 @@ function createSleepCompressor() {
|
|
|
1366
1371
|
var import_node_child_process = require("child_process");
|
|
1367
1372
|
var import_node_fs2 = require("fs");
|
|
1368
1373
|
var import_node_path = require("path");
|
|
1374
|
+
var import_node_url = require("url");
|
|
1369
1375
|
function createDaemonCommand() {
|
|
1370
1376
|
function isDaemonRunning(pidFile) {
|
|
1371
1377
|
if (!(0, import_node_fs2.existsSync)(pidFile)) {
|
|
@@ -1412,6 +1418,8 @@ function createDaemonCommand() {
|
|
|
1412
1418
|
};
|
|
1413
1419
|
}
|
|
1414
1420
|
try {
|
|
1421
|
+
const __filename2 = (0, import_node_url.fileURLToPath)(importMetaUrl);
|
|
1422
|
+
const __dirname = (0, import_node_path.dirname)(__filename2);
|
|
1415
1423
|
const daemonPath = (0, import_node_path.join)(__dirname, "index.js");
|
|
1416
1424
|
const child = (0, import_node_child_process.fork)(daemonPath, [], {
|
|
1417
1425
|
detached: true,
|
|
@@ -1761,6 +1769,10 @@ function createSessionWatcher(config) {
|
|
|
1761
1769
|
};
|
|
1762
1770
|
}
|
|
1763
1771
|
|
|
1772
|
+
// src/mcp/server.ts
|
|
1773
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
1774
|
+
var import_zod = require("zod");
|
|
1775
|
+
|
|
1764
1776
|
// src/types/config.ts
|
|
1765
1777
|
var DEFAULT_CONFIG = {
|
|
1766
1778
|
pruning: {
|
|
@@ -1790,10 +1802,217 @@ var DEFAULT_CONFIG = {
|
|
|
1790
1802
|
logFile: ".sparn/daemon.log",
|
|
1791
1803
|
debounceMs: 5e3,
|
|
1792
1804
|
incremental: true,
|
|
1793
|
-
windowSize: 500
|
|
1805
|
+
windowSize: 500,
|
|
1806
|
+
consolidationInterval: null
|
|
1794
1807
|
}
|
|
1795
1808
|
};
|
|
1796
1809
|
|
|
1810
|
+
// src/mcp/server.ts
|
|
1811
|
+
function createSparnMcpServer(options) {
|
|
1812
|
+
const { memory, config = DEFAULT_CONFIG } = options;
|
|
1813
|
+
const server = new import_mcp.McpServer({
|
|
1814
|
+
name: "sparn",
|
|
1815
|
+
version: "1.1.1"
|
|
1816
|
+
});
|
|
1817
|
+
registerOptimizeTool(server, memory, config);
|
|
1818
|
+
registerStatsTool(server, memory);
|
|
1819
|
+
registerConsolidateTool(server, memory);
|
|
1820
|
+
return server;
|
|
1821
|
+
}
|
|
1822
|
+
function registerOptimizeTool(server, memory, config) {
|
|
1823
|
+
server.registerTool(
|
|
1824
|
+
"sparn_optimize",
|
|
1825
|
+
{
|
|
1826
|
+
title: "Sparn Optimize",
|
|
1827
|
+
description: "Optimize context using neuroscience-inspired pruning. Applies BTSP detection, engram scoring, confidence states, and sparse pruning to reduce token usage while preserving important information.",
|
|
1828
|
+
inputSchema: {
|
|
1829
|
+
context: import_zod.z.string().describe("The context text to optimize"),
|
|
1830
|
+
dryRun: import_zod.z.boolean().optional().default(false).describe("If true, do not persist changes to the memory store"),
|
|
1831
|
+
verbose: import_zod.z.boolean().optional().default(false).describe("If true, include per-entry details in the response"),
|
|
1832
|
+
threshold: import_zod.z.number().min(0).max(100).optional().describe("Custom pruning threshold (1-100, overrides config)")
|
|
1833
|
+
}
|
|
1834
|
+
},
|
|
1835
|
+
async ({ context, dryRun, verbose, threshold }) => {
|
|
1836
|
+
try {
|
|
1837
|
+
const effectiveConfig = threshold ? { ...config, pruning: { ...config.pruning, threshold } } : config;
|
|
1838
|
+
const adapter = createGenericAdapter(memory, effectiveConfig);
|
|
1839
|
+
const result = await adapter.optimize(context, {
|
|
1840
|
+
dryRun,
|
|
1841
|
+
verbose,
|
|
1842
|
+
threshold
|
|
1843
|
+
});
|
|
1844
|
+
const response = {
|
|
1845
|
+
optimizedContext: result.optimizedContext,
|
|
1846
|
+
tokensBefore: result.tokensBefore,
|
|
1847
|
+
tokensAfter: result.tokensAfter,
|
|
1848
|
+
reduction: `${(result.reduction * 100).toFixed(1)}%`,
|
|
1849
|
+
entriesProcessed: result.entriesProcessed,
|
|
1850
|
+
entriesKept: result.entriesKept,
|
|
1851
|
+
durationMs: result.durationMs,
|
|
1852
|
+
stateDistribution: result.stateDistribution,
|
|
1853
|
+
...verbose && result.details ? { details: result.details } : {}
|
|
1854
|
+
};
|
|
1855
|
+
return {
|
|
1856
|
+
content: [
|
|
1857
|
+
{
|
|
1858
|
+
type: "text",
|
|
1859
|
+
text: JSON.stringify(response, null, 2)
|
|
1860
|
+
}
|
|
1861
|
+
]
|
|
1862
|
+
};
|
|
1863
|
+
} catch (error) {
|
|
1864
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1865
|
+
return {
|
|
1866
|
+
content: [
|
|
1867
|
+
{
|
|
1868
|
+
type: "text",
|
|
1869
|
+
text: JSON.stringify({ error: message })
|
|
1870
|
+
}
|
|
1871
|
+
],
|
|
1872
|
+
isError: true
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
function registerStatsTool(server, memory) {
|
|
1879
|
+
server.registerTool(
|
|
1880
|
+
"sparn_stats",
|
|
1881
|
+
{
|
|
1882
|
+
title: "Sparn Stats",
|
|
1883
|
+
description: "Get optimization statistics including total commands run, tokens saved, and average reduction percentage.",
|
|
1884
|
+
inputSchema: {
|
|
1885
|
+
reset: import_zod.z.boolean().optional().default(false).describe("If true, reset all optimization statistics")
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
async ({ reset }) => {
|
|
1889
|
+
try {
|
|
1890
|
+
if (reset) {
|
|
1891
|
+
await memory.clearOptimizationStats();
|
|
1892
|
+
return {
|
|
1893
|
+
content: [
|
|
1894
|
+
{
|
|
1895
|
+
type: "text",
|
|
1896
|
+
text: JSON.stringify(
|
|
1897
|
+
{
|
|
1898
|
+
message: "Optimization statistics have been reset.",
|
|
1899
|
+
totalCommands: 0,
|
|
1900
|
+
totalTokensSaved: 0,
|
|
1901
|
+
averageReduction: "0.0%"
|
|
1902
|
+
},
|
|
1903
|
+
null,
|
|
1904
|
+
2
|
|
1905
|
+
)
|
|
1906
|
+
}
|
|
1907
|
+
]
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
const stats = await memory.getOptimizationStats();
|
|
1911
|
+
const totalCommands = stats.length;
|
|
1912
|
+
const totalTokensSaved = stats.reduce(
|
|
1913
|
+
(sum, s) => sum + (s.tokens_before - s.tokens_after),
|
|
1914
|
+
0
|
|
1915
|
+
);
|
|
1916
|
+
const averageReduction = totalCommands > 0 ? stats.reduce((sum, s) => {
|
|
1917
|
+
const reduction = s.tokens_before > 0 ? (s.tokens_before - s.tokens_after) / s.tokens_before : 0;
|
|
1918
|
+
return sum + reduction;
|
|
1919
|
+
}, 0) / totalCommands : 0;
|
|
1920
|
+
const recentOptimizations = stats.slice(0, 10).map((s) => ({
|
|
1921
|
+
timestamp: new Date(s.timestamp).toISOString(),
|
|
1922
|
+
tokensBefore: s.tokens_before,
|
|
1923
|
+
tokensAfter: s.tokens_after,
|
|
1924
|
+
entriesPruned: s.entries_pruned,
|
|
1925
|
+
durationMs: s.duration_ms,
|
|
1926
|
+
reduction: `${((s.tokens_before - s.tokens_after) / Math.max(s.tokens_before, 1) * 100).toFixed(1)}%`
|
|
1927
|
+
}));
|
|
1928
|
+
const response = {
|
|
1929
|
+
totalCommands,
|
|
1930
|
+
totalTokensSaved,
|
|
1931
|
+
averageReduction: `${(averageReduction * 100).toFixed(1)}%`,
|
|
1932
|
+
recentOptimizations
|
|
1933
|
+
};
|
|
1934
|
+
return {
|
|
1935
|
+
content: [
|
|
1936
|
+
{
|
|
1937
|
+
type: "text",
|
|
1938
|
+
text: JSON.stringify(response, null, 2)
|
|
1939
|
+
}
|
|
1940
|
+
]
|
|
1941
|
+
};
|
|
1942
|
+
} catch (error) {
|
|
1943
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1944
|
+
return {
|
|
1945
|
+
content: [
|
|
1946
|
+
{
|
|
1947
|
+
type: "text",
|
|
1948
|
+
text: JSON.stringify({ error: message })
|
|
1949
|
+
}
|
|
1950
|
+
],
|
|
1951
|
+
isError: true
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
function registerConsolidateTool(server, memory) {
|
|
1958
|
+
server.registerTool(
|
|
1959
|
+
"sparn_consolidate",
|
|
1960
|
+
{
|
|
1961
|
+
title: "Sparn Consolidate",
|
|
1962
|
+
description: "Run memory consolidation (sleep replay). Removes decayed entries and merges duplicates to reclaim space. Inspired by the neuroscience principle of sleep-based memory consolidation."
|
|
1963
|
+
},
|
|
1964
|
+
async () => {
|
|
1965
|
+
try {
|
|
1966
|
+
const allIds = await memory.list();
|
|
1967
|
+
const allEntries = await Promise.all(
|
|
1968
|
+
allIds.map(async (id) => {
|
|
1969
|
+
const entry = await memory.get(id);
|
|
1970
|
+
return entry;
|
|
1971
|
+
})
|
|
1972
|
+
);
|
|
1973
|
+
const entries = allEntries.filter((e) => e !== null);
|
|
1974
|
+
const compressor = createSleepCompressor();
|
|
1975
|
+
const result = compressor.consolidate(entries);
|
|
1976
|
+
for (const removed of result.removed) {
|
|
1977
|
+
await memory.delete(removed.id);
|
|
1978
|
+
}
|
|
1979
|
+
for (const kept of result.kept) {
|
|
1980
|
+
await memory.put(kept);
|
|
1981
|
+
}
|
|
1982
|
+
await memory.compact();
|
|
1983
|
+
const response = {
|
|
1984
|
+
entriesBefore: result.entriesBefore,
|
|
1985
|
+
entriesAfter: result.entriesAfter,
|
|
1986
|
+
decayedRemoved: result.decayedRemoved,
|
|
1987
|
+
duplicatesRemoved: result.duplicatesRemoved,
|
|
1988
|
+
compressionRatio: `${(result.compressionRatio * 100).toFixed(1)}%`,
|
|
1989
|
+
durationMs: result.durationMs,
|
|
1990
|
+
vacuumCompleted: true
|
|
1991
|
+
};
|
|
1992
|
+
return {
|
|
1993
|
+
content: [
|
|
1994
|
+
{
|
|
1995
|
+
type: "text",
|
|
1996
|
+
text: JSON.stringify(response, null, 2)
|
|
1997
|
+
}
|
|
1998
|
+
]
|
|
1999
|
+
};
|
|
2000
|
+
} catch (error) {
|
|
2001
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2002
|
+
return {
|
|
2003
|
+
content: [
|
|
2004
|
+
{
|
|
2005
|
+
type: "text",
|
|
2006
|
+
text: JSON.stringify({ error: message })
|
|
2007
|
+
}
|
|
2008
|
+
],
|
|
2009
|
+
isError: true
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
1797
2016
|
// src/utils/logger.ts
|
|
1798
2017
|
function createLogger(verbose = false) {
|
|
1799
2018
|
return {
|
|
@@ -1832,6 +2051,7 @@ function createLogger(verbose = false) {
|
|
|
1832
2051
|
createLogger,
|
|
1833
2052
|
createSessionWatcher,
|
|
1834
2053
|
createSleepCompressor,
|
|
2054
|
+
createSparnMcpServer,
|
|
1835
2055
|
createSparsePruner,
|
|
1836
2056
|
estimateTokens,
|
|
1837
2057
|
hashContent,
|