squish-memory 1.0.0 → 1.0.2
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/.env.mcp.example +18 -11
- package/README.md +59 -24
- package/bin/squish-add.mjs +32 -0
- package/bin/squish-rm.mjs +21 -0
- package/config/plugin-manifest.json +1 -1
- package/config/settings.json +51 -0
- package/dist/api/web/web.js +479 -452
- package/dist/commands/mcp-server.js +7 -3
- package/dist/config.d.ts +10 -10
- package/dist/config.js +78 -23
- package/dist/core/embeddings.d.ts +1 -1
- package/dist/core/embeddings.js +10 -67
- package/dist/core/local-embeddings.d.ts +3 -11
- package/dist/core/local-embeddings.js +2 -76
- package/dist/core/mcp/server.js +27 -1
- package/dist/core/mcp/types.d.ts +4 -4
- package/dist/core/memory/context-collector.js +3 -2
- package/dist/core/memory/feedback-tracker.js +10 -6
- package/dist/core/memory/hybrid-search.js +32 -32
- package/dist/core/memory/memories.js +55 -52
- package/dist/core/memory/query-rewriter.js +9 -9
- package/dist/core/memory/stats.js +5 -5
- package/dist/core/namespaces/index.js +20 -11
- package/dist/core/scheduler/cron-scheduler.js +78 -20
- package/dist/core/scheduler/job-runner.js +8 -5
- package/dist/core/search/conversations.js +33 -33
- package/dist/core/session-hooks/self-iteration-job.js +43 -39
- package/dist/core/session-hooks/session-hooks.js +6 -3
- package/dist/core/tracing/collector.js +25 -13
- package/dist/db/adapter.d.ts +6 -1
- package/dist/db/adapter.js +122 -126
- package/dist/db/bootstrap.js +622 -548
- package/dist/db/index.d.ts +5 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +195 -49
- package/generated/mcp/manifest.json +23 -23
- package/package.json +72 -59
- package/scripts/install-interactive.mjs +7 -4
- package/skills/memory-guide/SKILL.md +94 -18
- package/skills/squish-cli/SKILL.md +61 -21
- package/skills/squish-mcp/SKILL.md +46 -2
- package/skills/squish-memory/SKILL.md +30 -16
- package/dist/algorithms/analytics/token-estimator.d.ts.map +0 -1
- package/dist/algorithms/analytics/token-estimator.js.map +0 -1
- package/dist/algorithms/detection/hash-filters.d.ts.map +0 -1
- package/dist/algorithms/detection/hash-filters.js.map +0 -1
- package/dist/algorithms/detection/semantic-ranker.d.ts.map +0 -1
- package/dist/algorithms/detection/semantic-ranker.js.map +0 -1
- package/dist/algorithms/detection/two-stage-detector.d.ts.map +0 -1
- package/dist/algorithms/detection/two-stage-detector.js.map +0 -1
- package/dist/algorithms/handlers/approve-merge.d.ts.map +0 -1
- package/dist/algorithms/handlers/approve-merge.js.map +0 -1
- package/dist/algorithms/handlers/detect-duplicates.d.ts.map +0 -1
- package/dist/algorithms/handlers/detect-duplicates.js.map +0 -1
- package/dist/algorithms/handlers/get-stats.d.ts.map +0 -1
- package/dist/algorithms/handlers/get-stats.js.map +0 -1
- package/dist/algorithms/handlers/list-proposals.d.ts.map +0 -1
- package/dist/algorithms/handlers/list-proposals.js.map +0 -1
- package/dist/algorithms/handlers/preview-merge.d.ts.map +0 -1
- package/dist/algorithms/handlers/preview-merge.js.map +0 -1
- package/dist/algorithms/handlers/reject-merge.d.ts.map +0 -1
- package/dist/algorithms/handlers/reject-merge.js.map +0 -1
- package/dist/algorithms/handlers/reverse-merge.d.ts.map +0 -1
- package/dist/algorithms/handlers/reverse-merge.js.map +0 -1
- package/dist/algorithms/safety/safety-checks.d.ts.map +0 -1
- package/dist/algorithms/safety/safety-checks.js.map +0 -1
- package/dist/algorithms/strategies/merge-strategies.d.ts.map +0 -1
- package/dist/algorithms/strategies/merge-strategies.js.map +0 -1
- package/dist/algorithms/utils/response-builder.d.ts.map +0 -1
- package/dist/algorithms/utils/response-builder.js.map +0 -1
- package/dist/api/web/index.d.ts.map +0 -1
- package/dist/api/web/index.js.map +0 -1
- package/dist/api/web/web-server.d.ts.map +0 -1
- package/dist/api/web/web-server.js.map +0 -1
- package/dist/api/web/web.d.ts.map +0 -1
- package/dist/api/web/web.js.map +0 -1
- package/dist/commands/managed-sync.d.ts.map +0 -1
- package/dist/commands/managed-sync.js.map +0 -1
- package/dist/commands/mcp-server.d.ts.map +0 -1
- package/dist/commands/mcp-server.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/agent-memory.d.ts.map +0 -1
- package/dist/core/agent-memory.js.map +0 -1
- package/dist/core/associations.d.ts.map +0 -1
- package/dist/core/associations.js.map +0 -1
- package/dist/core/cache.d.ts.map +0 -1
- package/dist/core/cache.js.map +0 -1
- package/dist/core/consolidation.d.ts.map +0 -1
- package/dist/core/consolidation.js.map +0 -1
- package/dist/core/context-paging.d.ts.map +0 -1
- package/dist/core/context-paging.js.map +0 -1
- package/dist/core/context.d.ts.map +0 -1
- package/dist/core/context.js.map +0 -1
- package/dist/core/core-memory.d.ts.map +0 -1
- package/dist/core/core-memory.js.map +0 -1
- package/dist/core/database.d.ts.map +0 -1
- package/dist/core/database.js.map +0 -1
- package/dist/core/embeddings/google-multimodal.d.ts.map +0 -1
- package/dist/core/embeddings/google-multimodal.js.map +0 -1
- package/dist/core/embeddings/qmd-client.d.ts.map +0 -1
- package/dist/core/embeddings/qmd-client.js.map +0 -1
- package/dist/core/embeddings.d.ts.map +0 -1
- package/dist/core/embeddings.js.map +0 -1
- package/dist/core/governance.d.ts.map +0 -1
- package/dist/core/governance.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/layers/generator.d.ts.map +0 -1
- package/dist/core/layers/generator.js.map +0 -1
- package/dist/core/lifecycle.d.ts.map +0 -1
- package/dist/core/lifecycle.js.map +0 -1
- package/dist/core/local-embeddings.d.ts.map +0 -1
- package/dist/core/local-embeddings.js.map +0 -1
- package/dist/core/logger.d.ts.map +0 -1
- package/dist/core/logger.js.map +0 -1
- package/dist/core/mcp/client.d.ts.map +0 -1
- package/dist/core/mcp/client.js.map +0 -1
- package/dist/core/mcp/index.d.ts.map +0 -1
- package/dist/core/mcp/index.js.map +0 -1
- package/dist/core/mcp/server.d.ts.map +0 -1
- package/dist/core/mcp/server.js.map +0 -1
- package/dist/core/mcp/standalone-server.d.ts.map +0 -1
- package/dist/core/mcp/standalone-server.js.map +0 -1
- package/dist/core/mcp/tools.d.ts.map +0 -1
- package/dist/core/mcp/tools.js.map +0 -1
- package/dist/core/mcp/types.d.ts.map +0 -1
- package/dist/core/mcp/types.js.map +0 -1
- package/dist/core/memory/bridge-discovery.d.ts.map +0 -1
- package/dist/core/memory/bridge-discovery.js.map +0 -1
- package/dist/core/memory/categorizer.d.ts.map +0 -1
- package/dist/core/memory/categorizer.js.map +0 -1
- package/dist/core/memory/conflict-detector.d.ts.map +0 -1
- package/dist/core/memory/conflict-detector.js.map +0 -1
- package/dist/core/memory/consolidation.d.ts.map +0 -1
- package/dist/core/memory/consolidation.js.map +0 -1
- package/dist/core/memory/context-collector.d.ts.map +0 -1
- package/dist/core/memory/context-collector.js.map +0 -1
- package/dist/core/memory/contradiction-resolver.d.ts.map +0 -1
- package/dist/core/memory/contradiction-resolver.js.map +0 -1
- package/dist/core/memory/edit-workflow.d.ts.map +0 -1
- package/dist/core/memory/edit-workflow.js.map +0 -1
- package/dist/core/memory/entity-extractor.d.ts.map +0 -1
- package/dist/core/memory/entity-extractor.js.map +0 -1
- package/dist/core/memory/entity-resolver.d.ts.map +0 -1
- package/dist/core/memory/entity-resolver.js.map +0 -1
- package/dist/core/memory/fact-extractor.d.ts.map +0 -1
- package/dist/core/memory/fact-extractor.js.map +0 -1
- package/dist/core/memory/feedback-tracker.d.ts.map +0 -1
- package/dist/core/memory/feedback-tracker.js.map +0 -1
- package/dist/core/memory/hybrid-retrieval.d.ts.map +0 -1
- package/dist/core/memory/hybrid-retrieval.js.map +0 -1
- package/dist/core/memory/hybrid-scorer.d.ts.map +0 -1
- package/dist/core/memory/hybrid-scorer.js.map +0 -1
- package/dist/core/memory/hybrid-search.d.ts.map +0 -1
- package/dist/core/memory/hybrid-search.js.map +0 -1
- package/dist/core/memory/importance.d.ts.map +0 -1
- package/dist/core/memory/importance.js.map +0 -1
- package/dist/core/memory/index.d.ts.map +0 -1
- package/dist/core/memory/index.js.map +0 -1
- package/dist/core/memory/memories.d.ts.map +0 -1
- package/dist/core/memory/memories.js.map +0 -1
- package/dist/core/memory/memory-manager.d.ts.map +0 -1
- package/dist/core/memory/memory-manager.js.map +0 -1
- package/dist/core/memory/progressive-disclosure.d.ts.map +0 -1
- package/dist/core/memory/progressive-disclosure.js.map +0 -1
- package/dist/core/memory/query-processor.d.ts.map +0 -1
- package/dist/core/memory/query-processor.js.map +0 -1
- package/dist/core/memory/query-rewriter.d.ts.map +0 -1
- package/dist/core/memory/query-rewriter.js.map +0 -1
- package/dist/core/memory/response-analyzer.d.ts.map +0 -1
- package/dist/core/memory/response-analyzer.js.map +0 -1
- package/dist/core/memory/serialization.d.ts.map +0 -1
- package/dist/core/memory/serialization.js.map +0 -1
- package/dist/core/memory/stats.d.ts.map +0 -1
- package/dist/core/memory/stats.js.map +0 -1
- package/dist/core/memory/telemetry.d.ts.map +0 -1
- package/dist/core/memory/telemetry.js.map +0 -1
- package/dist/core/memory/temporal-facts.d.ts.map +0 -1
- package/dist/core/memory/temporal-facts.js.map +0 -1
- package/dist/core/memory/temporal-parser.d.ts.map +0 -1
- package/dist/core/memory/temporal-parser.js.map +0 -1
- package/dist/core/memory/trigger-detector.d.ts.map +0 -1
- package/dist/core/memory/trigger-detector.js.map +0 -1
- package/dist/core/memory/write-gate.d.ts.map +0 -1
- package/dist/core/memory/write-gate.js.map +0 -1
- package/dist/core/namespaces/index.d.ts.map +0 -1
- package/dist/core/namespaces/index.js.map +0 -1
- package/dist/core/namespaces/uri-parser.d.ts.map +0 -1
- package/dist/core/namespaces/uri-parser.js.map +0 -1
- package/dist/core/observations.d.ts.map +0 -1
- package/dist/core/observations.js.map +0 -1
- package/dist/core/privacy.d.ts.map +0 -1
- package/dist/core/privacy.js.map +0 -1
- package/dist/core/projects.d.ts.map +0 -1
- package/dist/core/projects.js.map +0 -1
- package/dist/core/redis.d.ts.map +0 -1
- package/dist/core/redis.js.map +0 -1
- package/dist/core/requirements.d.ts.map +0 -1
- package/dist/core/requirements.js.map +0 -1
- package/dist/core/scheduler/cron-scheduler.d.ts.map +0 -1
- package/dist/core/scheduler/cron-scheduler.js.map +0 -1
- package/dist/core/scheduler/heartbeat.d.ts.map +0 -1
- package/dist/core/scheduler/heartbeat.js.map +0 -1
- package/dist/core/scheduler/index.d.ts.map +0 -1
- package/dist/core/scheduler/index.js.map +0 -1
- package/dist/core/scheduler/job-runner.d.ts.map +0 -1
- package/dist/core/scheduler/job-runner.js.map +0 -1
- package/dist/core/search/conversations.d.ts.map +0 -1
- package/dist/core/search/conversations.js.map +0 -1
- package/dist/core/search/entities.d.ts.map +0 -1
- package/dist/core/search/entities.js.map +0 -1
- package/dist/core/search/folder-context.d.ts.map +0 -1
- package/dist/core/search/folder-context.js.map +0 -1
- package/dist/core/search/index.d.ts.map +0 -1
- package/dist/core/search/index.js.map +0 -1
- package/dist/core/search/qmd-search.d.ts.map +0 -1
- package/dist/core/search/qmd-search.js.map +0 -1
- package/dist/core/secret-detector.d.ts.map +0 -1
- package/dist/core/secret-detector.js.map +0 -1
- package/dist/core/session/auto-load.d.ts.map +0 -1
- package/dist/core/session/auto-load.js.map +0 -1
- package/dist/core/session/index.d.ts.map +0 -1
- package/dist/core/session/index.js.map +0 -1
- package/dist/core/session/types.d.ts.map +0 -1
- package/dist/core/session/types.js.map +0 -1
- package/dist/core/session-hooks/self-iteration-job.d.ts.map +0 -1
- package/dist/core/session-hooks/self-iteration-job.js.map +0 -1
- package/dist/core/session-hooks/session-hooks.d.ts.map +0 -1
- package/dist/core/session-hooks/session-hooks.js.map +0 -1
- package/dist/core/snapshots/cleanup.d.ts.map +0 -1
- package/dist/core/snapshots/cleanup.js.map +0 -1
- package/dist/core/snapshots/comparison.d.ts.map +0 -1
- package/dist/core/snapshots/comparison.js.map +0 -1
- package/dist/core/snapshots/creation.d.ts.map +0 -1
- package/dist/core/snapshots/creation.js.map +0 -1
- package/dist/core/snapshots/retrieval.d.ts.map +0 -1
- package/dist/core/snapshots/retrieval.js.map +0 -1
- package/dist/core/snapshots/stats.d.ts.map +0 -1
- package/dist/core/snapshots/stats.js.map +0 -1
- package/dist/core/snapshots.d.ts.map +0 -1
- package/dist/core/snapshots.js.map +0 -1
- package/dist/core/summarization/cleanup.d.ts.map +0 -1
- package/dist/core/summarization/cleanup.js.map +0 -1
- package/dist/core/summarization/queries.d.ts.map +0 -1
- package/dist/core/summarization/queries.js.map +0 -1
- package/dist/core/summarization/stats.d.ts.map +0 -1
- package/dist/core/summarization/stats.js.map +0 -1
- package/dist/core/summarization/strategies.d.ts.map +0 -1
- package/dist/core/summarization/strategies.js.map +0 -1
- package/dist/core/summarization.d.ts.map +0 -1
- package/dist/core/summarization.js.map +0 -1
- package/dist/core/sync/qmd-sync.d.ts.map +0 -1
- package/dist/core/sync/qmd-sync.js.map +0 -1
- package/dist/core/temporal-facts.d.ts.map +0 -1
- package/dist/core/temporal-facts.js.map +0 -1
- package/dist/core/tracing/collector.d.ts.map +0 -1
- package/dist/core/tracing/collector.js.map +0 -1
- package/dist/core/tracing/visualizer.d.ts.map +0 -1
- package/dist/core/tracing/visualizer.js.map +0 -1
- package/dist/core/utils/cleanup-operations.d.ts.map +0 -1
- package/dist/core/utils/cleanup-operations.js.map +0 -1
- package/dist/core/utils/content-extraction.d.ts.map +0 -1
- package/dist/core/utils/content-extraction.js.map +0 -1
- package/dist/core/utils/filter-builder.d.ts.map +0 -1
- package/dist/core/utils/filter-builder.js.map +0 -1
- package/dist/core/utils/history-traversal.d.ts.map +0 -1
- package/dist/core/utils/history-traversal.js.map +0 -1
- package/dist/core/utils/memory-operations.d.ts.map +0 -1
- package/dist/core/utils/memory-operations.js.map +0 -1
- package/dist/core/utils/query-operations.d.ts.map +0 -1
- package/dist/core/utils/query-operations.js.map +0 -1
- package/dist/core/utils/summarization-helpers.d.ts.map +0 -1
- package/dist/core/utils/summarization-helpers.js.map +0 -1
- package/dist/core/utils/temporal-queries.d.ts.map +0 -1
- package/dist/core/utils/temporal-queries.js.map +0 -1
- package/dist/core/utils/version-management.d.ts.map +0 -1
- package/dist/core/utils/version-management.js.map +0 -1
- package/dist/core/utils.d.ts.map +0 -1
- package/dist/core/utils.js.map +0 -1
- package/dist/core/worker.d.ts.map +0 -1
- package/dist/core/worker.js.map +0 -1
- package/dist/db/adapter.d.ts.map +0 -1
- package/dist/db/adapter.js.map +0 -1
- package/dist/db/bootstrap.d.ts.map +0 -1
- package/dist/db/bootstrap.js.map +0 -1
- package/dist/db/index.d.ts.map +0 -1
- package/dist/db/index.js.map +0 -1
- package/dist/db/schema.d.ts.map +0 -1
- package/dist/db/schema.js.map +0 -1
- package/dist/drizzle/schema-sqlite.d.ts.map +0 -1
- package/dist/drizzle/schema-sqlite.js.map +0 -1
- package/dist/drizzle/schema.d.ts.map +0 -1
- package/dist/drizzle/schema.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts.map +0 -1
- package/packages/plugin-claude-code/dist/plugin-wrapper.js.map +0 -1
- package/packages/plugin-openclaw/dist/index.d.ts.map +0 -1
- package/packages/plugin-openclaw/dist/index.js.map +0 -1
|
@@ -73,22 +73,22 @@ async function bm25Search(input, options) {
|
|
|
73
73
|
// For empty query with no filters, use "1=1" to match all
|
|
74
74
|
const whereClause = conditions.length > 0 ? conditions.join(' AND ') : '1=1';
|
|
75
75
|
// Build query based on whether we have a search term or not
|
|
76
|
-
const statement = sqlite.prepare(`
|
|
77
|
-
SELECT
|
|
78
|
-
m.id as id,
|
|
79
|
-
m.project_id as projectId,
|
|
80
|
-
m.type as type,
|
|
81
|
-
m.content as content,
|
|
82
|
-
m.summary as summary,
|
|
83
|
-
m.tags as tags,
|
|
84
|
-
m.metadata as metadata,
|
|
85
|
-
${isEmptyQuery ? '0 as bm25Score' : 'bm25(memories_fts) as bm25Score'},
|
|
86
|
-
m.created_at as createdAt
|
|
87
|
-
FROM memories m
|
|
88
|
-
${isEmptyQuery ? '' : 'INNER JOIN memories_fts ON m.rowid = memories_fts.rowid'}
|
|
89
|
-
WHERE ${whereClause}
|
|
90
|
-
${isEmptyQuery ? 'ORDER BY m.created_at DESC' : 'ORDER BY bm25(memories_fts)'}
|
|
91
|
-
LIMIT ?
|
|
76
|
+
const statement = sqlite.prepare(`
|
|
77
|
+
SELECT
|
|
78
|
+
m.id as id,
|
|
79
|
+
m.project_id as projectId,
|
|
80
|
+
m.type as type,
|
|
81
|
+
m.content as content,
|
|
82
|
+
m.summary as summary,
|
|
83
|
+
m.tags as tags,
|
|
84
|
+
m.metadata as metadata,
|
|
85
|
+
${isEmptyQuery ? '0 as bm25Score' : 'bm25(memories_fts) as bm25Score'},
|
|
86
|
+
m.created_at as createdAt
|
|
87
|
+
FROM memories m
|
|
88
|
+
${isEmptyQuery ? '' : 'INNER JOIN memories_fts ON m.rowid = memories_fts.rowid'}
|
|
89
|
+
WHERE ${whereClause}
|
|
90
|
+
${isEmptyQuery ? 'ORDER BY m.created_at DESC' : 'ORDER BY bm25(memories_fts)'}
|
|
91
|
+
LIMIT ?
|
|
92
92
|
`);
|
|
93
93
|
const rows = statement.all(...params, limit * 3);
|
|
94
94
|
// Return as ranked results (lower BM25 score = better rank)
|
|
@@ -154,22 +154,22 @@ async function vectorSearch(input, options) {
|
|
|
154
154
|
? 'WHERE ' + conditions.join(' AND ')
|
|
155
155
|
: '';
|
|
156
156
|
// Fetch candidates for vector search
|
|
157
|
-
const statement = sqlite.prepare(`
|
|
158
|
-
SELECT
|
|
159
|
-
m.id as id,
|
|
160
|
-
m.project_id as projectId,
|
|
161
|
-
m.type as type,
|
|
162
|
-
m.content as content,
|
|
163
|
-
m.summary as summary,
|
|
164
|
-
m.tags as tags,
|
|
165
|
-
m.metadata as metadata,
|
|
166
|
-
m.embedding as embedding,
|
|
167
|
-
m.embedding_json as embeddingJson,
|
|
168
|
-
m.created_at as createdAt
|
|
169
|
-
FROM memories m
|
|
170
|
-
${whereClause}
|
|
171
|
-
ORDER BY m.created_at DESC
|
|
172
|
-
LIMIT ?
|
|
157
|
+
const statement = sqlite.prepare(`
|
|
158
|
+
SELECT
|
|
159
|
+
m.id as id,
|
|
160
|
+
m.project_id as projectId,
|
|
161
|
+
m.type as type,
|
|
162
|
+
m.content as content,
|
|
163
|
+
m.summary as summary,
|
|
164
|
+
m.tags as tags,
|
|
165
|
+
m.metadata as metadata,
|
|
166
|
+
m.embedding as embedding,
|
|
167
|
+
m.embedding_json as embeddingJson,
|
|
168
|
+
m.created_at as createdAt
|
|
169
|
+
FROM memories m
|
|
170
|
+
${whereClause}
|
|
171
|
+
ORDER BY m.created_at DESC
|
|
172
|
+
LIMIT ?
|
|
173
173
|
`);
|
|
174
174
|
const rows = statement.all(...params, limit * 3);
|
|
175
175
|
// If no embedding available, return results ordered by recency
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { eq } from 'drizzle-orm';
|
|
3
3
|
import { getDb } from '../../db/index.js';
|
|
4
4
|
import { getSchema } from '../../db/schema.js';
|
|
5
5
|
import { config } from '../../config.js';
|
|
@@ -143,14 +143,17 @@ export async function getMemoryById(id, incrementAccess = true) {
|
|
|
143
143
|
export async function getRecentMemories(projectPath, limit) {
|
|
144
144
|
try {
|
|
145
145
|
const db = createDatabaseClient(await getDb());
|
|
146
|
-
const
|
|
146
|
+
const sqlite = db.$client;
|
|
147
147
|
const project = await getProjectByPath(projectPath);
|
|
148
148
|
if (!project)
|
|
149
149
|
return [];
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
// Use raw SQL to avoid drizzle column name issues
|
|
151
|
+
const rows = sqlite.prepare(`
|
|
152
|
+
SELECT * FROM memories
|
|
153
|
+
WHERE project_id = ?
|
|
154
|
+
ORDER BY created_at DESC
|
|
155
|
+
LIMIT ?
|
|
156
|
+
`).all(project.id, limit);
|
|
154
157
|
return rows.map((row) => normalizeMemory(row));
|
|
155
158
|
}
|
|
156
159
|
catch (error) {
|
|
@@ -257,22 +260,22 @@ async function searchMemoriesSqlite(input, tags, limit) {
|
|
|
257
260
|
const whereClause = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
|
|
258
261
|
// Fetch memories with embeddings for semantic search
|
|
259
262
|
const fetchLimit = Math.max(limit * 3, 50); // Fetch more for re-ranking
|
|
260
|
-
const statement = sqlite.prepare(`
|
|
261
|
-
SELECT
|
|
262
|
-
m.id as id,
|
|
263
|
-
m.project_id as projectId,
|
|
264
|
-
m.type as type,
|
|
265
|
-
m.content as content,
|
|
266
|
-
m.summary as summary,
|
|
267
|
-
m.tags as tags,
|
|
268
|
-
m.metadata as metadata,
|
|
269
|
-
m.embedding as embedding,
|
|
270
|
-
m.embedding_json as embeddingJson,
|
|
271
|
-
m.created_at as createdAt
|
|
272
|
-
FROM memories m
|
|
273
|
-
${whereClause}
|
|
274
|
-
ORDER BY m.created_at DESC
|
|
275
|
-
LIMIT ?
|
|
263
|
+
const statement = sqlite.prepare(`
|
|
264
|
+
SELECT
|
|
265
|
+
m.id as id,
|
|
266
|
+
m.project_id as projectId,
|
|
267
|
+
m.type as type,
|
|
268
|
+
m.content as content,
|
|
269
|
+
m.summary as summary,
|
|
270
|
+
m.tags as tags,
|
|
271
|
+
m.metadata as metadata,
|
|
272
|
+
m.embedding as embedding,
|
|
273
|
+
m.embedding_json as embeddingJson,
|
|
274
|
+
m.created_at as createdAt
|
|
275
|
+
FROM memories m
|
|
276
|
+
${whereClause}
|
|
277
|
+
ORDER BY m.created_at DESC
|
|
278
|
+
LIMIT ?
|
|
276
279
|
`);
|
|
277
280
|
const rows = statement.all(...params, fetchLimit);
|
|
278
281
|
if (rows.length === 0)
|
|
@@ -326,42 +329,42 @@ async function searchMemoriesPostgres(input, tags, limit) {
|
|
|
326
329
|
const whereClause = whereParts.length ? `WHERE ${whereParts.join(' AND ')}` : '';
|
|
327
330
|
const embedding = await getEmbedding(input.query);
|
|
328
331
|
if (embedding) {
|
|
329
|
-
const rows = await db.$client.query(`SELECT
|
|
330
|
-
id,
|
|
331
|
-
project_id as "projectId",
|
|
332
|
-
type,
|
|
333
|
-
content,
|
|
334
|
-
summary,
|
|
335
|
-
tags,
|
|
336
|
-
metadata,
|
|
337
|
-
created_at as "createdAt",
|
|
338
|
-
valid_from as "validFrom",
|
|
339
|
-
valid_to as "validTo",
|
|
340
|
-
recorded_at as "recordedAt"
|
|
341
|
-
FROM memories
|
|
342
|
-
${whereClause}
|
|
343
|
-
ORDER BY created_at DESC
|
|
332
|
+
const rows = await db.$client.query(`SELECT
|
|
333
|
+
id,
|
|
334
|
+
project_id as "projectId",
|
|
335
|
+
type,
|
|
336
|
+
content,
|
|
337
|
+
summary,
|
|
338
|
+
tags,
|
|
339
|
+
metadata,
|
|
340
|
+
created_at as "createdAt",
|
|
341
|
+
valid_from as "validFrom",
|
|
342
|
+
valid_to as "validTo",
|
|
343
|
+
recorded_at as "recordedAt"
|
|
344
|
+
FROM memories
|
|
345
|
+
${whereClause}
|
|
346
|
+
ORDER BY created_at DESC
|
|
344
347
|
LIMIT $${values.length + 1}`, [...values, limit]);
|
|
345
348
|
return rows.rows.map((row) => ({
|
|
346
349
|
...normalizeMemory(row),
|
|
347
350
|
similarity: row.similarity ?? 0,
|
|
348
351
|
}));
|
|
349
352
|
}
|
|
350
|
-
const rows = await db.$client.query(`SELECT
|
|
351
|
-
id,
|
|
352
|
-
project_id as "projectId",
|
|
353
|
-
type,
|
|
354
|
-
content,
|
|
355
|
-
summary,
|
|
356
|
-
tags,
|
|
357
|
-
metadata,
|
|
358
|
-
created_at as "createdAt",
|
|
359
|
-
valid_from as "validFrom",
|
|
360
|
-
valid_to as "validTo",
|
|
361
|
-
recorded_at as "recordedAt"
|
|
362
|
-
FROM memories
|
|
363
|
-
${whereClause}
|
|
364
|
-
ORDER BY created_at DESC
|
|
353
|
+
const rows = await db.$client.query(`SELECT
|
|
354
|
+
id,
|
|
355
|
+
project_id as "projectId",
|
|
356
|
+
type,
|
|
357
|
+
content,
|
|
358
|
+
summary,
|
|
359
|
+
tags,
|
|
360
|
+
metadata,
|
|
361
|
+
created_at as "createdAt",
|
|
362
|
+
valid_from as "validFrom",
|
|
363
|
+
valid_to as "validTo",
|
|
364
|
+
recorded_at as "recordedAt"
|
|
365
|
+
FROM memories
|
|
366
|
+
${whereClause}
|
|
367
|
+
ORDER BY created_at DESC
|
|
365
368
|
LIMIT $${values.length + 1}`, [...values, limit]);
|
|
366
369
|
return rows.rows.map((row) => ({
|
|
367
370
|
...normalizeMemory(row),
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import { logger } from '../logger.js';
|
|
3
3
|
import { config } from '../../config.js';
|
|
4
4
|
import { expandQuery } from './query-processor.js';
|
|
5
|
-
const REWRITE_SYSTEM_PROMPT = `You are a search query optimizer. Given a conversation context and a user's latest message, rewrite the message into the single most effective search query to retrieve relevant memories.
|
|
6
|
-
|
|
7
|
-
Rules:
|
|
8
|
-
1. Output ONLY the optimized search query - no explanations or extra text
|
|
9
|
-
2. Remove filler words (please, can you, etc.)
|
|
10
|
-
3. Focus on the core information need
|
|
11
|
-
4. Preserve important entities (names, dates, technical terms)
|
|
12
|
-
5. Add synonyms for key terms if helpful
|
|
13
|
-
6. Consider what memories would be most relevant
|
|
5
|
+
const REWRITE_SYSTEM_PROMPT = `You are a search query optimizer. Given a conversation context and a user's latest message, rewrite the message into the single most effective search query to retrieve relevant memories.
|
|
6
|
+
|
|
7
|
+
Rules:
|
|
8
|
+
1. Output ONLY the optimized search query - no explanations or extra text
|
|
9
|
+
2. Remove filler words (please, can you, etc.)
|
|
10
|
+
3. Focus on the core information need
|
|
11
|
+
4. Preserve important entities (names, dates, technical terms)
|
|
12
|
+
5. Add synonyms for key terms if helpful
|
|
13
|
+
6. Consider what memories would be most relevant
|
|
14
14
|
7. If the message is about recalling something specific, include those details`;
|
|
15
15
|
export async function rewriteQuery(query, context) {
|
|
16
16
|
if (!config.queryRewritingEnabled) {
|
|
@@ -36,11 +36,11 @@ export async function getMemoryStats(projectPath = process.cwd()) {
|
|
|
36
36
|
// Count by type
|
|
37
37
|
if (config.isTeamMode) {
|
|
38
38
|
// PostgreSQL - use raw query for GROUP BY
|
|
39
|
-
const typeCounts = await db.execute(sql `
|
|
40
|
-
SELECT type, COUNT(*) as count
|
|
41
|
-
FROM memories
|
|
42
|
-
${project ? sql `WHERE project_id = ${project.id}` : sql ``}
|
|
43
|
-
GROUP BY type
|
|
39
|
+
const typeCounts = await db.execute(sql `
|
|
40
|
+
SELECT type, COUNT(*) as count
|
|
41
|
+
FROM memories
|
|
42
|
+
${project ? sql `WHERE project_id = ${project.id}` : sql ``}
|
|
43
|
+
GROUP BY type
|
|
44
44
|
`);
|
|
45
45
|
for (const row of typeCounts.rows) {
|
|
46
46
|
stats.byType[row.type] = Number(row.count);
|
|
@@ -15,7 +15,8 @@ export async function createNamespace(input) {
|
|
|
15
15
|
const schema = await getSchema();
|
|
16
16
|
const id = randomUUID();
|
|
17
17
|
// Check if namespace with same name exists under parent
|
|
18
|
-
const
|
|
18
|
+
const sqliteDb = db;
|
|
19
|
+
const existing = await sqliteDb.select()
|
|
19
20
|
.from(schema.namespaces)
|
|
20
21
|
.where(and(eq(schema.namespaces.projectId, input.projectId), eq(schema.namespaces.name, input.name), input.parentId
|
|
21
22
|
? eq(schema.namespaces.parentId, input.parentId)
|
|
@@ -26,7 +27,7 @@ export async function createNamespace(input) {
|
|
|
26
27
|
}
|
|
27
28
|
// Build namespace path
|
|
28
29
|
const path = await buildNamespacePath(input.projectId, input.name, input.parentId ?? null);
|
|
29
|
-
await
|
|
30
|
+
await sqliteDb.insert(schema.namespaces).values({
|
|
30
31
|
id,
|
|
31
32
|
projectId: input.projectId,
|
|
32
33
|
name: input.name,
|
|
@@ -58,7 +59,8 @@ async function buildNamespacePath(projectId, name, parentId) {
|
|
|
58
59
|
}
|
|
59
60
|
const db = await getDb();
|
|
60
61
|
const schema = await getSchema();
|
|
61
|
-
const
|
|
62
|
+
const sqliteDb = db;
|
|
63
|
+
const [parent] = await sqliteDb.select()
|
|
62
64
|
.from(schema.namespaces)
|
|
63
65
|
.where(eq(schema.namespaces.id, parentId))
|
|
64
66
|
.limit(1);
|
|
@@ -75,7 +77,8 @@ export async function getNamespaceById(id) {
|
|
|
75
77
|
if (!db)
|
|
76
78
|
return null;
|
|
77
79
|
const schema = await getSchema();
|
|
78
|
-
const
|
|
80
|
+
const sqliteDb = db;
|
|
81
|
+
const [row] = await sqliteDb.select()
|
|
79
82
|
.from(schema.namespaces)
|
|
80
83
|
.where(eq(schema.namespaces.id, id))
|
|
81
84
|
.limit(1);
|
|
@@ -104,11 +107,12 @@ export async function resolveNamespacePath(projectId, path) {
|
|
|
104
107
|
if (!db)
|
|
105
108
|
return null;
|
|
106
109
|
const schema = await getSchema();
|
|
110
|
+
const sqliteDb = db;
|
|
107
111
|
let parentId = null;
|
|
108
112
|
let targetNamespace = null;
|
|
109
113
|
// Traverse path segments
|
|
110
114
|
for (const segment of path) {
|
|
111
|
-
const [result] = await
|
|
115
|
+
const [result] = await sqliteDb.select()
|
|
112
116
|
.from(schema.namespaces)
|
|
113
117
|
.where(and(eq(schema.namespaces.projectId, projectId), eq(schema.namespaces.name, segment), parentId
|
|
114
118
|
? eq(schema.namespaces.parentId, parentId)
|
|
@@ -129,8 +133,9 @@ export async function getNamespaceTree(projectId) {
|
|
|
129
133
|
if (!db)
|
|
130
134
|
return [];
|
|
131
135
|
const schema = await getSchema();
|
|
136
|
+
const sqliteDb = db;
|
|
132
137
|
// Get all namespaces for project
|
|
133
|
-
const all = await
|
|
138
|
+
const all = await sqliteDb.select()
|
|
134
139
|
.from(schema.namespaces)
|
|
135
140
|
.where(eq(schema.namespaces.projectId, projectId))
|
|
136
141
|
.orderBy(schema.namespaces.name);
|
|
@@ -167,6 +172,7 @@ export async function getDefaultNamespaces(projectId) {
|
|
|
167
172
|
if (!db)
|
|
168
173
|
return [];
|
|
169
174
|
const schema = await getSchema();
|
|
175
|
+
const sqliteDb = db;
|
|
170
176
|
const created = [];
|
|
171
177
|
const defaults = [
|
|
172
178
|
{ name: 'user', type: 'user', description: 'User-specific memories and preferences' },
|
|
@@ -175,7 +181,7 @@ export async function getDefaultNamespaces(projectId) {
|
|
|
175
181
|
];
|
|
176
182
|
const defaultNames = ['user', 'agent', 'project'];
|
|
177
183
|
// Check all default namespaces at once with IN clause
|
|
178
|
-
const existing = await
|
|
184
|
+
const existing = await sqliteDb.select()
|
|
179
185
|
.from(schema.namespaces)
|
|
180
186
|
.where(and(eq(schema.namespaces.projectId, projectId), eq(schema.namespaces.name, defaultNames[0]), eq(schema.namespaces.type, 'user'), isNull(schema.namespaces.parentId)));
|
|
181
187
|
if (existing.length > 0) {
|
|
@@ -199,7 +205,7 @@ export async function getDefaultNamespaces(projectId) {
|
|
|
199
205
|
}
|
|
200
206
|
// Check remaining defaults sequentially (agent and project)
|
|
201
207
|
for (const defName of defaultNames.slice(1)) {
|
|
202
|
-
const existing = await
|
|
208
|
+
const existing = await sqliteDb.select()
|
|
203
209
|
.from(schema.namespaces)
|
|
204
210
|
.where(and(eq(schema.namespaces.projectId, projectId), eq(schema.namespaces.name, defName), eq(schema.namespaces.type, defName), isNull(schema.namespaces.parentId)))
|
|
205
211
|
.limit(1);
|
|
@@ -237,6 +243,7 @@ export async function listNamespaces(options = {}) {
|
|
|
237
243
|
if (!db)
|
|
238
244
|
return [];
|
|
239
245
|
const schema = await getSchema();
|
|
246
|
+
const sqliteDb = db;
|
|
240
247
|
const conditions = [];
|
|
241
248
|
if (options.projectId) {
|
|
242
249
|
conditions.push(eq(schema.namespaces.projectId, options.projectId));
|
|
@@ -252,7 +259,7 @@ export async function listNamespaces(options = {}) {
|
|
|
252
259
|
conditions.push(eq(schema.namespaces.parentId, options.parentId));
|
|
253
260
|
}
|
|
254
261
|
}
|
|
255
|
-
const rows = await
|
|
262
|
+
const rows = await sqliteDb.select()
|
|
256
263
|
.from(schema.namespaces)
|
|
257
264
|
.where(conditions.length > 0 ? and(...conditions) : undefined)
|
|
258
265
|
.orderBy(schema.namespaces.name);
|
|
@@ -276,7 +283,8 @@ export async function deleteNamespace(id) {
|
|
|
276
283
|
if (!db)
|
|
277
284
|
return;
|
|
278
285
|
const schema = await getSchema();
|
|
279
|
-
|
|
286
|
+
const sqliteDb = db;
|
|
287
|
+
await sqliteDb.delete(schema.namespaces).where(eq(schema.namespaces.id, id));
|
|
280
288
|
logger.info(`[Namespaces] Deleted namespace: ${id}`);
|
|
281
289
|
}
|
|
282
290
|
/**
|
|
@@ -287,7 +295,8 @@ export async function updateNamespace(id, updates) {
|
|
|
287
295
|
if (!db)
|
|
288
296
|
return;
|
|
289
297
|
const schema = await getSchema();
|
|
290
|
-
|
|
298
|
+
const sqliteDb = db;
|
|
299
|
+
await sqliteDb.update(schema.namespaces).set({
|
|
291
300
|
...updates,
|
|
292
301
|
updatedAt: new Date(),
|
|
293
302
|
}).where(eq(schema.namespaces.id, id));
|
|
@@ -26,7 +26,8 @@ export async function initializeScheduler() {
|
|
|
26
26
|
}
|
|
27
27
|
try {
|
|
28
28
|
await ensureDefaultJobs(db);
|
|
29
|
-
const
|
|
29
|
+
const sqliteDb = db;
|
|
30
|
+
const jobs = await sqliteDb
|
|
30
31
|
.select()
|
|
31
32
|
.from(maintenanceJobs)
|
|
32
33
|
.where(eq(maintenanceJobs.enabled, true));
|
|
@@ -64,18 +65,61 @@ async function ensureDefaultJobs(db) {
|
|
|
64
65
|
},
|
|
65
66
|
];
|
|
66
67
|
for (const job of defaultJobs) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
let existing;
|
|
69
|
+
try {
|
|
70
|
+
existing = await db
|
|
71
|
+
.select()
|
|
72
|
+
.from(maintenanceJobs)
|
|
73
|
+
.where(eq(maintenanceJobs.jobName, job.jobName))
|
|
74
|
+
.limit(1);
|
|
75
|
+
}
|
|
76
|
+
catch (queryError) {
|
|
77
|
+
logger.error(`[Scheduler] Query failed for job ${job.jobName}:`, queryError.message);
|
|
78
|
+
// Try raw SQL fallback
|
|
79
|
+
try {
|
|
80
|
+
const rawDb = db.$client;
|
|
81
|
+
if (rawDb && typeof rawDb.prepare === 'function') {
|
|
82
|
+
existing = rawDb.prepare('SELECT * FROM maintenance_jobs WHERE job_name = ?').all(job.jobName);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (fallbackError) {
|
|
86
|
+
logger.error(`[Scheduler] Fallback query also failed:`, fallbackError.message);
|
|
87
|
+
throw queryError;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
72
90
|
if (existing.length === 0) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
try {
|
|
92
|
+
await db.insert(maintenanceJobs).values({
|
|
93
|
+
jobName: job.jobName,
|
|
94
|
+
jobType: job.jobType,
|
|
95
|
+
cronExpression: job.cronExpression,
|
|
96
|
+
enabled: job.enabled,
|
|
97
|
+
jobConfig: job.jobConfig,
|
|
98
|
+
totalRuns: 0,
|
|
99
|
+
successCount: 0,
|
|
100
|
+
failureCount: 0,
|
|
101
|
+
lastRunAt: null,
|
|
102
|
+
nextRunAt: null,
|
|
103
|
+
lastRunDuration: null,
|
|
104
|
+
lastRunStatus: null,
|
|
105
|
+
lastRunError: null,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (insertError) {
|
|
109
|
+
// Fallback to raw SQL if drizzle insert fails
|
|
110
|
+
logger.warn(`[Scheduler] Drizzle insert failed, using raw SQL: ${insertError.message}`);
|
|
111
|
+
const rawDb = db.$client;
|
|
112
|
+
if (rawDb && typeof rawDb.prepare === 'function') {
|
|
113
|
+
const stmt = rawDb.prepare(`
|
|
114
|
+
INSERT INTO maintenance_jobs
|
|
115
|
+
(id, job_name, job_type, cron_expression, enabled, job_config,
|
|
116
|
+
total_runs, success_count, failure_count, last_run_at, next_run_at,
|
|
117
|
+
last_run_duration, last_run_status, last_run_error)
|
|
118
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
119
|
+
`);
|
|
120
|
+
stmt.run(crypto.randomUUID(), job.jobName, job.jobType, job.cronExpression, job.enabled ? 1 : 0, JSON.stringify(job.jobConfig), 0, 0, 0, null, null, null, null, null);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
79
123
|
logger.info(`[Scheduler] Created default job: ${job.jobName}`);
|
|
80
124
|
// Register self-iteration handler
|
|
81
125
|
if (job.jobName === 'self_iteration') {
|
|
@@ -108,12 +152,13 @@ export async function scheduleJob(job) {
|
|
|
108
152
|
const nextRun = getNextRunTime(job.cronExpression);
|
|
109
153
|
const db = await getDb();
|
|
110
154
|
if (db) {
|
|
111
|
-
|
|
155
|
+
const sqliteDb = db;
|
|
156
|
+
await sqliteDb
|
|
112
157
|
.update(maintenanceJobs)
|
|
113
158
|
.set({ nextRunAt: nextRun })
|
|
114
159
|
.where(eq(maintenanceJobs.id, job.id));
|
|
115
160
|
}
|
|
116
|
-
logger.info(`[Scheduler] Scheduled ${job.jobName} with cron: ${job.cronExpression}
|
|
161
|
+
logger.info(`[Scheduler] Scheduled ${job.jobName} with cron: ${job.cronExpression}${nextRun ? `, next run: ${nextRun.toISOString()}` : ''}`);
|
|
117
162
|
}
|
|
118
163
|
export async function executeJob(job) {
|
|
119
164
|
const db = await getDb();
|
|
@@ -147,11 +192,12 @@ export async function executeJob(job) {
|
|
|
147
192
|
}
|
|
148
193
|
const completedAt = new Date();
|
|
149
194
|
if (db) {
|
|
150
|
-
const
|
|
195
|
+
const sqliteDb = db;
|
|
196
|
+
const [currentJob] = await sqliteDb
|
|
151
197
|
.select()
|
|
152
198
|
.from(maintenanceJobs)
|
|
153
199
|
.where(eq(maintenanceJobs.id, job.id));
|
|
154
|
-
await
|
|
200
|
+
await sqliteDb
|
|
155
201
|
.update(maintenanceJobs)
|
|
156
202
|
.set({
|
|
157
203
|
lastRunAt: startedAt,
|
|
@@ -164,7 +210,7 @@ export async function executeJob(job) {
|
|
|
164
210
|
nextRunAt: job.cronExpression ? getNextRunTime(job.cronExpression) : null,
|
|
165
211
|
})
|
|
166
212
|
.where(eq(maintenanceJobs.id, job.id));
|
|
167
|
-
await
|
|
213
|
+
await sqliteDb.insert(maintenanceJobHistory).values({
|
|
168
214
|
jobId: job.id,
|
|
169
215
|
startedAt,
|
|
170
216
|
completedAt,
|
|
@@ -180,13 +226,23 @@ function getNextRunTime(cronExpression) {
|
|
|
180
226
|
try {
|
|
181
227
|
const now = new Date();
|
|
182
228
|
const parts = cronExpression.split(' ');
|
|
183
|
-
|
|
229
|
+
// Daily jobs: MM HH * * *
|
|
230
|
+
if (parts[2] === '*' && parts[3] === '*' && parts[4] === '*' && parts[1] !== '*') {
|
|
184
231
|
const next = new Date(now);
|
|
185
232
|
next.setHours(parseInt(parts[1]), parseInt(parts[0]), 0, 0);
|
|
186
233
|
if (next <= now)
|
|
187
234
|
next.setDate(next.getDate() + 1);
|
|
188
235
|
return next;
|
|
189
236
|
}
|
|
237
|
+
// Hourly jobs: MM * * * *
|
|
238
|
+
if (parts[1] === '*' && parts[2] === '*' && parts[3] === '*' && parts[4] === '*') {
|
|
239
|
+
const next = new Date(now);
|
|
240
|
+
next.setMinutes(parseInt(parts[0]), 0, 0);
|
|
241
|
+
if (next <= now)
|
|
242
|
+
next.setHours(next.getHours() + 1);
|
|
243
|
+
return next;
|
|
244
|
+
}
|
|
245
|
+
// Weekly jobs: MM HH * * D
|
|
190
246
|
if (parts[4] !== '*') {
|
|
191
247
|
const dayOfWeek = parseInt(parts[4]);
|
|
192
248
|
const next = new Date(now);
|
|
@@ -205,7 +261,8 @@ export async function getScheduledJobs() {
|
|
|
205
261
|
const db = await getDb();
|
|
206
262
|
if (!db)
|
|
207
263
|
return [];
|
|
208
|
-
const
|
|
264
|
+
const sqliteDb = db;
|
|
265
|
+
const jobs = await sqliteDb.select().from(maintenanceJobs);
|
|
209
266
|
return jobs.map((job) => ({
|
|
210
267
|
id: job.id,
|
|
211
268
|
jobName: job.jobName,
|
|
@@ -222,7 +279,8 @@ export async function getOverdueJobs() {
|
|
|
222
279
|
if (!db)
|
|
223
280
|
return [];
|
|
224
281
|
const now = new Date();
|
|
225
|
-
const
|
|
282
|
+
const sqliteDb = db;
|
|
283
|
+
const jobs = await sqliteDb.select().from(maintenanceJobs);
|
|
226
284
|
return jobs
|
|
227
285
|
.filter((job) => {
|
|
228
286
|
if (!job.enabled)
|
|
@@ -113,7 +113,8 @@ async function boostFrequentlyAccessed() {
|
|
|
113
113
|
const db = await getDb();
|
|
114
114
|
if (!db)
|
|
115
115
|
return 0;
|
|
116
|
-
const
|
|
116
|
+
const sqliteDb = db;
|
|
117
|
+
const frequentlyAccessed = await sqliteDb
|
|
117
118
|
.select()
|
|
118
119
|
.from(memories)
|
|
119
120
|
.where(gt(memories.accessCount, 3));
|
|
@@ -121,7 +122,7 @@ async function boostFrequentlyAccessed() {
|
|
|
121
122
|
for (const memory of frequentlyAccessed) {
|
|
122
123
|
const currentPriority = memory.retrievalPriority ?? 50;
|
|
123
124
|
const newPriority = Math.min(100, currentPriority + 5);
|
|
124
|
-
await
|
|
125
|
+
await sqliteDb
|
|
125
126
|
.update(memories)
|
|
126
127
|
.set({ retrievalPriority: newPriority })
|
|
127
128
|
.where(eq(memories.id, memory.id));
|
|
@@ -134,13 +135,14 @@ async function archiveStaleMemories(daysOld) {
|
|
|
134
135
|
if (!db)
|
|
135
136
|
return 0;
|
|
136
137
|
const staleThreshold = new Date(Date.now() - daysOld * 24 * 60 * 60 * 1000);
|
|
137
|
-
const
|
|
138
|
+
const sqliteDb = db;
|
|
139
|
+
const staleMemories = await sqliteDb
|
|
138
140
|
.select()
|
|
139
141
|
.from(memories)
|
|
140
142
|
.where(and(lt(memories.lastAccessedAt, staleThreshold), lt(memories.importanceScore, 30), eq(memories.isProtected, false), eq(memories.isPinned, false)));
|
|
141
143
|
let archived = 0;
|
|
142
144
|
for (const memory of staleMemories) {
|
|
143
|
-
await
|
|
145
|
+
await sqliteDb
|
|
144
146
|
.update(memories)
|
|
145
147
|
.set({ tier: 'cold' })
|
|
146
148
|
.where(eq(memories.id, memory.id));
|
|
@@ -153,7 +155,8 @@ async function cleanupOldFeedbackRecords(daysOld) {
|
|
|
153
155
|
if (!db)
|
|
154
156
|
return 0;
|
|
155
157
|
const oldThreshold = new Date(Date.now() - daysOld * 24 * 60 * 60 * 1000);
|
|
156
|
-
|
|
158
|
+
const sqliteDb = db;
|
|
159
|
+
await sqliteDb
|
|
157
160
|
.delete(memoryFeedback)
|
|
158
161
|
.where(lt(memoryFeedback.createdAt, oldThreshold));
|
|
159
162
|
return 0;
|