@stackmemoryai/stackmemory
Version:
Lossless, project-scoped memory for AI coding tools. Durable context across sessions with 56 MCP tools, FTS5 search, conductor orchestrator, loop/watch monitoring, snapshot capture, pre-flight overlap checks, Claude/Codex/OpenCode wrappers, Linear sync, a
345 lines (344 loc) • 10.5 kB
JavaScript
import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { getQueryCache, createCacheKey } from "../database/query-cache.js";
import { logger } from "../monitoring/logger.js";
class OptimizedContextAssembler {
db;
cache = getQueryCache();
preparedStatements = /* @__PURE__ */ new Map();
constructor(db) {
this.db = db;
this.initializePreparedStatements();
}
/**
* Get hot stack context with optimizations
*/
async getHotStackContext(activeStack, options = {}) {
const startTime = performance.now();
const stats = {
cacheHits: 0,
dbQueries: 0,
totalRows: 0
};
const {
maxEvents = 20,
includeClosed = false,
enableCaching = true,
batchSize = 10
} = options;
try {
const contexts = [];
for (let i = 0; i < activeStack.length; i += batchSize) {
const batch = activeStack.slice(i, i + batchSize);
const batchContexts = await this.processBatch(
batch,
maxEvents,
includeClosed,
enableCaching,
stats
);
contexts.push(...batchContexts);
}
const assemblyTimeMs = performance.now() - startTime;
return contexts.map((context) => ({
...context,
performance: {
assemblyTimeMs: assemblyTimeMs / contexts.length,
...stats
}
}));
} catch (error) {
logger.error("Failed to assemble hot stack context", error, {
activeStack,
options
});
throw error;
}
}
/**
* Get single frame context with full optimization
*/
async getFrameContext(frameId, options = {}) {
const startTime = performance.now();
const stats = { cacheHits: 0, dbQueries: 0, totalRows: 0 };
const { maxEvents = 50, enableCaching = true } = options;
const cacheKey = createCacheKey("frame_context", [frameId, maxEvents]);
if (enableCaching) {
const cached = this.cache.getFrameContext(cacheKey);
if (cached) {
stats.cacheHits++;
return {
...cached,
performance: {
assemblyTimeMs: performance.now() - startTime,
...stats
}
};
}
}
try {
const context = await this.assembleFrameContext(
frameId,
maxEvents,
stats
);
if (!context) return null;
if (enableCaching) {
this.cache.cacheFrameContext(cacheKey, context);
}
const result = {
...context,
performance: {
assemblyTimeMs: performance.now() - startTime,
...stats
}
};
return result;
} catch (error) {
logger.error("Failed to get frame context", error, { frameId });
throw error;
}
}
/**
* Process a batch of frames efficiently
*/
async processBatch(frameIds, maxEvents, includeClosed, enableCaching, stats) {
const contexts = [];
const uncachedIds = [];
for (const frameId of frameIds) {
const cacheKey = createCacheKey("frame_context", [frameId, maxEvents]);
if (enableCaching) {
const cached = this.cache.getFrameContext(cacheKey);
if (cached) {
stats.cacheHits++;
contexts.push(cached);
continue;
}
}
uncachedIds.push(frameId);
}
if (uncachedIds.length === 0) {
return contexts;
}
const frames = await this.batchGetFrames(uncachedIds, stats);
const allEvents = await this.batchGetEvents(uncachedIds, maxEvents, stats);
const allAnchors = await this.batchGetAnchors(uncachedIds, stats);
const allArtifacts = await this.batchGetArtifacts(uncachedIds, stats);
for (const frameId of uncachedIds) {
const frame = frames.get(frameId);
if (!frame || !includeClosed && frame.state === "closed") {
continue;
}
const context = {
frameId,
header: {
goal: frame.name,
constraints: this.extractConstraints(frame.inputs),
definitions: frame.inputs.definitions
},
anchors: allAnchors.get(frameId) || [],
recentEvents: allEvents.get(frameId) || [],
activeArtifacts: allArtifacts.get(frameId) || []
};
if (enableCaching) {
const cacheKey = createCacheKey("frame_context", [frameId, maxEvents]);
this.cache.cacheFrameContext(cacheKey, context);
}
contexts.push(context);
}
return contexts;
}
/**
* Batch get frames with single query
*/
async batchGetFrames(frameIds, stats) {
if (frameIds.length === 0) return /* @__PURE__ */ new Map();
const stmt = this.preparedStatements.get("batch_frames");
if (!stmt) throw new Error("Prepared statement not found: batch_frames");
const placeholders = frameIds.map(() => "?").join(",");
const query = `SELECT * FROM frames WHERE frame_id IN (${placeholders})`;
stats.dbQueries++;
const rows = this.db.prepare(query).all(...frameIds);
stats.totalRows += rows.length;
const frameMap = /* @__PURE__ */ new Map();
for (const row of rows) {
frameMap.set(row.frame_id, {
...row,
inputs: JSON.parse(row.inputs || "{}"),
outputs: JSON.parse(row.outputs || "{}"),
digest_json: JSON.parse(row.digest_json || "{}")
});
}
return frameMap;
}
/**
* Batch get events for multiple frames
*/
async batchGetEvents(frameIds, maxEvents, stats) {
if (frameIds.length === 0) return /* @__PURE__ */ new Map();
const placeholders = frameIds.map(() => "?").join(",");
const query = `
SELECT *, ROW_NUMBER() OVER (PARTITION BY frame_id ORDER BY seq DESC) as rn
FROM events
WHERE frame_id IN (${placeholders})
AND rn <= ${maxEvents}
ORDER BY frame_id, seq DESC
`;
stats.dbQueries++;
const rows = this.db.prepare(query).all(...frameIds);
stats.totalRows += rows.length;
const eventMap = /* @__PURE__ */ new Map();
for (const row of rows) {
if (!eventMap.has(row.frame_id)) {
eventMap.set(row.frame_id, []);
}
eventMap.get(row.frame_id).push({
...row,
payload: JSON.parse(row.payload)
});
}
return eventMap;
}
/**
* Batch get anchors for multiple frames
*/
async batchGetAnchors(frameIds, stats) {
if (frameIds.length === 0) return /* @__PURE__ */ new Map();
const placeholders = frameIds.map(() => "?").join(",");
const query = `
SELECT * FROM anchors
WHERE frame_id IN (${placeholders})
ORDER BY frame_id, priority DESC, created_at ASC
`;
stats.dbQueries++;
const rows = this.db.prepare(query).all(...frameIds);
stats.totalRows += rows.length;
const anchorMap = /* @__PURE__ */ new Map();
for (const row of rows) {
if (!anchorMap.has(row.frame_id)) {
anchorMap.set(row.frame_id, []);
}
anchorMap.get(row.frame_id).push({
...row,
metadata: JSON.parse(row.metadata || "{}")
});
}
return anchorMap;
}
/**
* Batch get active artifacts for multiple frames
*/
async batchGetArtifacts(frameIds, stats) {
if (frameIds.length === 0) return /* @__PURE__ */ new Map();
const placeholders = frameIds.map(() => "?").join(",");
const query = `
SELECT frame_id, payload
FROM events
WHERE frame_id IN (${placeholders})
AND event_type = 'artifact'
ORDER BY frame_id, ts DESC
`;
stats.dbQueries++;
const rows = this.db.prepare(query).all(...frameIds);
stats.totalRows += rows.length;
const artifactMap = /* @__PURE__ */ new Map();
for (const row of rows) {
const payload = JSON.parse(row.payload);
if (!artifactMap.has(row.frame_id)) {
artifactMap.set(row.frame_id, []);
}
if (payload.path) {
artifactMap.get(row.frame_id).push(payload.path);
}
}
return artifactMap;
}
/**
* Assemble single frame context
*/
async assembleFrameContext(frameId, maxEvents, stats) {
const frame = await this.batchGetFrames([frameId], stats).then(
(map) => map.get(frameId)
);
if (!frame) return null;
const [events, anchors, artifacts] = await Promise.all([
this.batchGetEvents([frameId], maxEvents, stats).then(
(map) => map.get(frameId) || []
),
this.batchGetAnchors([frameId], stats).then(
(map) => map.get(frameId) || []
),
this.batchGetArtifacts([frameId], stats).then(
(map) => map.get(frameId) || []
)
]);
return {
frameId,
header: {
goal: frame.name,
constraints: this.extractConstraints(frame.inputs),
definitions: frame.inputs.definitions
},
anchors,
recentEvents: events,
activeArtifacts: artifacts
};
}
/**
* Extract constraints from frame inputs
*/
extractConstraints(inputs) {
const constraints = [];
if (inputs.constraints && Array.isArray(inputs.constraints)) {
constraints.push(...inputs.constraints);
}
if (inputs.requirements && Array.isArray(inputs.requirements)) {
constraints.push(...inputs.requirements);
}
if (inputs.limitations && Array.isArray(inputs.limitations)) {
constraints.push(...inputs.limitations);
}
return constraints;
}
/**
* Initialize prepared statements for common queries
*/
initializePreparedStatements() {
try {
this.preparedStatements.set(
"single_frame",
this.db.prepare("SELECT * FROM frames WHERE frame_id = ?")
);
this.preparedStatements.set(
"frame_events",
this.db.prepare(
"SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?"
)
);
this.preparedStatements.set(
"frame_anchors",
this.db.prepare(
"SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC"
)
);
logger.info(
"Prepared statements initialized for optimized context assembly"
);
} catch (error) {
logger.error("Failed to initialize prepared statements", error);
throw error;
}
}
/**
* Clear cache and reset prepared statements
*/
cleanup() {
this.cache.clear();
this.preparedStatements.clear();
}
}
export {
OptimizedContextAssembler
};