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
|
@@ -21,7 +21,7 @@ import { getDb } from "../db/index.js";
|
|
|
21
21
|
import { getSchema } from "../db/schema.js";
|
|
22
22
|
import { eq } from "drizzle-orm";
|
|
23
23
|
const SERVER_NAME = "squish-memory";
|
|
24
|
-
const SERVER_VERSION = "1.0.
|
|
24
|
+
const SERVER_VERSION = "1.0.2";
|
|
25
25
|
function parseArgs() {
|
|
26
26
|
const args = process.argv.slice(2);
|
|
27
27
|
let mode = "stdio";
|
|
@@ -116,7 +116,9 @@ function createSquishServer() {
|
|
|
116
116
|
}, async ({ memoryId }) => {
|
|
117
117
|
const db = await getDb();
|
|
118
118
|
const schema = await getSchema();
|
|
119
|
-
|
|
119
|
+
// Cast to any to handle Drizzle ORM union type issue
|
|
120
|
+
const sqliteDb = db;
|
|
121
|
+
const result = await sqliteDb.delete(schema.memories).where(eq(schema.memories.id, memoryId));
|
|
120
122
|
return { content: [{ type: "text", text: `Memory deleted: ${memoryId}` }] };
|
|
121
123
|
}))
|
|
122
124
|
toolCount++;
|
|
@@ -141,7 +143,9 @@ function createSquishServer() {
|
|
|
141
143
|
if (Object.keys(updates).length === 0) {
|
|
142
144
|
return { content: [{ type: "text", text: "No updates provided" }], isError: true };
|
|
143
145
|
}
|
|
144
|
-
|
|
146
|
+
// Cast to any to handle Drizzle ORM union type issue
|
|
147
|
+
const sqliteDb2 = db;
|
|
148
|
+
await sqliteDb2.update(schema.memories).set(updates).where(eq(schema.memories.id, memoryId));
|
|
145
149
|
return { content: [{ type: "text", text: `Memory updated: ${memoryId}` }] };
|
|
146
150
|
}))
|
|
147
151
|
toolCount++;
|
package/dist/config.d.ts
CHANGED
|
@@ -6,12 +6,16 @@ export declare const config: {
|
|
|
6
6
|
dataDir: string;
|
|
7
7
|
mcpServerPort: number;
|
|
8
8
|
mcpServerEnabled: boolean;
|
|
9
|
-
embeddingsProvider: "
|
|
9
|
+
embeddingsProvider: "local" | "openai" | "ollama" | "google" | "none" | "auto";
|
|
10
10
|
openAiApiKey: string;
|
|
11
|
-
openAiApiUrl:
|
|
12
|
-
openAiEmbeddingModel:
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
openAiApiUrl: any;
|
|
12
|
+
openAiEmbeddingModel: any;
|
|
13
|
+
googleCloudApiKey: string;
|
|
14
|
+
googleCloudProject: string;
|
|
15
|
+
googleCloudLocation: string;
|
|
16
|
+
googleEmbeddingModel: any;
|
|
17
|
+
ollamaUrl: any;
|
|
18
|
+
ollamaEmbeddingModel: any;
|
|
15
19
|
lifecycleEnabled: boolean;
|
|
16
20
|
lifecycleInterval: number;
|
|
17
21
|
summarizationEnabled: boolean;
|
|
@@ -26,10 +30,6 @@ export declare const config: {
|
|
|
26
30
|
qmdCollectionsPath: string;
|
|
27
31
|
qmdFallbackMode: "qmd-only" | "cloud-first" | "hybrid" | "local-only";
|
|
28
32
|
qmdCollectionMapping: any;
|
|
29
|
-
googleCloudApiKey: string;
|
|
30
|
-
googleCloudProject: string;
|
|
31
|
-
googleCloudLocation: string;
|
|
32
|
-
multimodalEmbeddingsEnabled: boolean;
|
|
33
33
|
managedMode: boolean;
|
|
34
34
|
managedApiUrl: string;
|
|
35
35
|
managedApiKey: string;
|
|
@@ -53,7 +53,7 @@ export declare const config: {
|
|
|
53
53
|
embeddingsRetryDelayMs: number;
|
|
54
54
|
openAiTimeoutMs: number;
|
|
55
55
|
ollamaTimeoutMs: number;
|
|
56
|
-
|
|
56
|
+
googleTimeoutMs: number;
|
|
57
57
|
};
|
|
58
58
|
export default config;
|
|
59
59
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
|
-
import { mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { mkdirSync, existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname } from 'path';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
3
7
|
export function getDataDir() {
|
|
4
8
|
const projectRoot = process.env.CLAUDE_WORKING_DIRECTORY || process.cwd();
|
|
5
9
|
const dir = process.env.SQUISH_DATA_DIR || join(projectRoot, '.squish');
|
|
@@ -7,21 +11,58 @@ export function getDataDir() {
|
|
|
7
11
|
mkdirSync(dir, { recursive: true });
|
|
8
12
|
return dir;
|
|
9
13
|
}
|
|
14
|
+
// Load settings from config/settings.json
|
|
15
|
+
function loadSettings() {
|
|
16
|
+
const settingsPath = join(__dirname, 'config', 'settings.json');
|
|
17
|
+
try {
|
|
18
|
+
if (existsSync(settingsPath)) {
|
|
19
|
+
const content = readFileSync(settingsPath, 'utf-8');
|
|
20
|
+
return JSON.parse(content);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.warn('Failed to load settings.json, using defaults');
|
|
25
|
+
}
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
const settings = loadSettings();
|
|
29
|
+
// Helper to get env var or settings value
|
|
30
|
+
function getConfig(path, envVar, defaultValue) {
|
|
31
|
+
// Priority 1: Environment variable
|
|
32
|
+
if (envVar && process.env[envVar]) {
|
|
33
|
+
return process.env[envVar];
|
|
34
|
+
}
|
|
35
|
+
// Priority 2: Settings file
|
|
36
|
+
const keys = path.split('.');
|
|
37
|
+
let value = settings;
|
|
38
|
+
for (const key of keys) {
|
|
39
|
+
if (value && typeof value === 'object' && key in value) {
|
|
40
|
+
value = value[key];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
value = undefined;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (value !== undefined) {
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
// Priority 3: Default value
|
|
51
|
+
return defaultValue;
|
|
52
|
+
}
|
|
10
53
|
const isTeamMode = !!process.env.DATABASE_URL?.startsWith('postgres');
|
|
11
54
|
const isManagedMode = process.env.SQUISH_MANAGED_MODE === 'true';
|
|
12
|
-
const openAiApiKey = process.env.SQUISH_OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
13
55
|
// Embeddings providers:
|
|
14
56
|
// - openai: OpenAI API (requires API key)
|
|
15
57
|
// - ollama: Local Ollama server (requires nomic-embed-text)
|
|
16
58
|
// - local: TF-IDF offline (no dependencies)
|
|
17
59
|
// - none: Disable embeddings (stub)
|
|
18
|
-
// -
|
|
19
|
-
// -
|
|
20
|
-
|
|
21
|
-
const VALID_PROVIDERS = new Set(['openai', 'ollama', 'local', 'none', 'qmd', 'hybrid', 'google-multimodal', 'auto']);
|
|
60
|
+
// - google: Google Cloud embeddings
|
|
61
|
+
// - auto: Smart fallback (cloud if available, local fallback)
|
|
62
|
+
const VALID_PROVIDERS = new Set(['openai', 'ollama', 'local', 'none', 'google', 'auto']);
|
|
22
63
|
const embeddingsProvider = (() => {
|
|
23
|
-
const explicit =
|
|
24
|
-
if (
|
|
64
|
+
const explicit = getConfig('embeddings.provider', 'SQUISH_EMBEDDINGS_PROVIDER', 'local').toLowerCase();
|
|
65
|
+
if (VALID_PROVIDERS.has(explicit)) {
|
|
25
66
|
return explicit;
|
|
26
67
|
}
|
|
27
68
|
return 'local';
|
|
@@ -45,28 +86,47 @@ const defaultCollectionMapping = {
|
|
|
45
86
|
const qmdCollectionMapping = process.env.SQUISH_QMD_COLLECTION_MAPPING
|
|
46
87
|
? JSON.parse(process.env.SQUISH_QMD_COLLECTION_MAPPING)
|
|
47
88
|
: defaultCollectionMapping;
|
|
89
|
+
// OpenAI Configuration
|
|
90
|
+
const openAiApiKey = process.env.SQUISH_OPENAI_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
91
|
+
const openAiApiUrl = getConfig('api.openai.apiUrl', 'SQUISH_OPENAI_API_URL', 'https://api.openai.com/v1/embeddings');
|
|
92
|
+
const openAiEmbeddingModel = getConfig('embeddings.models.openai.model', 'SQUISH_OPENAI_EMBEDDING_MODEL', 'text-embedding-3-small');
|
|
93
|
+
// Google Configuration
|
|
94
|
+
const googleCloudApiKey = process.env.GOOGLE_CLOUD_API_KEY || process.env.SQUISH_GOOGLE_CLOUD_API_KEY || '';
|
|
95
|
+
const googleCloudProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.SQUISH_GOOGLE_CLOUD_PROJECT || '';
|
|
96
|
+
const googleCloudLocation = process.env.GOOGLE_CLOUD_LOCATION || process.env.SQUISH_GOOGLE_CLOUD_LOCATION || 'us-central1';
|
|
97
|
+
const googleEmbeddingModel = getConfig('embeddings.models.google.model', 'SQUISH_GOOGLE_EMBEDDING_MODEL', 'gemini-embedding-001');
|
|
98
|
+
// Ollama Configuration
|
|
99
|
+
const ollamaUrl = getConfig('api.ollama.url', 'SQUISH_OLLAMA_URL', 'http://localhost:11434');
|
|
100
|
+
const ollamaEmbeddingModel = getConfig('embeddings.models.ollama.model', 'SQUISH_OLLAMA_EMBEDDING_MODEL', 'nomic-embed-text:v1.5');
|
|
48
101
|
export const config = {
|
|
49
102
|
isTeamMode,
|
|
50
103
|
isManagedMode,
|
|
51
104
|
redisEnabled: !!process.env.REDIS_URL,
|
|
52
105
|
dataDir: getDataDir(),
|
|
53
|
-
mcpServerPort: parseInt(
|
|
54
|
-
mcpServerEnabled:
|
|
106
|
+
mcpServerPort: parseInt(getConfig('mcp.serverPort', 'SQUISH_MCP_PORT', '8767')),
|
|
107
|
+
mcpServerEnabled: getConfig('mcp.serverEnabled', 'SQUISH_MCP_SERVER_ENABLED', true) !== false,
|
|
55
108
|
embeddingsProvider: embeddingsProvider,
|
|
109
|
+
// OpenAI
|
|
56
110
|
openAiApiKey,
|
|
57
|
-
openAiApiUrl
|
|
58
|
-
openAiEmbeddingModel
|
|
59
|
-
|
|
60
|
-
|
|
111
|
+
openAiApiUrl,
|
|
112
|
+
openAiEmbeddingModel,
|
|
113
|
+
// Google
|
|
114
|
+
googleCloudApiKey,
|
|
115
|
+
googleCloudProject,
|
|
116
|
+
googleCloudLocation,
|
|
117
|
+
googleEmbeddingModel,
|
|
118
|
+
// Ollama
|
|
119
|
+
ollamaUrl,
|
|
120
|
+
ollamaEmbeddingModel,
|
|
61
121
|
// Lifecycle Management
|
|
62
|
-
lifecycleEnabled:
|
|
122
|
+
lifecycleEnabled: getConfig('features.lifecycleEnabled', 'SQUISH_LIFECYCLE_ENABLED', true) !== false,
|
|
63
123
|
lifecycleInterval: parseInt(process.env.SQUISH_LIFECYCLE_INTERVAL || '3600000'),
|
|
64
124
|
// Session Summarization
|
|
65
|
-
summarizationEnabled:
|
|
125
|
+
summarizationEnabled: getConfig('features.summarizationEnabled', 'SQUISH_SUMMARIZATION_ENABLED', true) !== false,
|
|
66
126
|
incrementalThreshold: parseInt(process.env.SQUISH_INCREMENTAL_THRESHOLD || '10'),
|
|
67
127
|
rollingWindowSize: parseInt(process.env.SQUISH_ROLLING_WINDOW_SIZE || '50'),
|
|
68
128
|
// Agent-Aware Memory
|
|
69
|
-
agentIsolationEnabled:
|
|
129
|
+
agentIsolationEnabled: getConfig('features.agentIsolation', 'SQUISH_AGENT_ISOLATION_ENABLED', true) !== false,
|
|
70
130
|
defaultVisibilityScope: (process.env.SQUISH_DEFAULT_VISIBILITY || 'private'),
|
|
71
131
|
// Memory Governance
|
|
72
132
|
governanceEnabled: process.env.SQUISH_GOVERNANCE_ENABLED !== 'false',
|
|
@@ -78,11 +138,6 @@ export const config = {
|
|
|
78
138
|
qmdCollectionsPath,
|
|
79
139
|
qmdFallbackMode: qmdFallbackMode,
|
|
80
140
|
qmdCollectionMapping,
|
|
81
|
-
// Google Cloud Multimodal Embeddings
|
|
82
|
-
googleCloudApiKey: process.env.GOOGLE_CLOUD_API_KEY || process.env.SQUISH_GOOGLE_CLOUD_API_KEY || '',
|
|
83
|
-
googleCloudProject: process.env.GOOGLE_CLOUD_PROJECT || process.env.SQUISH_GOOGLE_CLOUD_PROJECT || '',
|
|
84
|
-
googleCloudLocation: process.env.GOOGLE_CLOUD_LOCATION || process.env.SQUISH_GOOGLE_CLOUD_LOCATION || 'us-central1',
|
|
85
|
-
multimodalEmbeddingsEnabled: process.env.SQUISH_MULTIMODAL_EMBEDDINGS_ENABLED === 'true',
|
|
86
141
|
// Managed Mode
|
|
87
142
|
managedMode: process.env.SQUISH_MANAGED_MODE === 'true',
|
|
88
143
|
managedApiUrl: process.env.SQUISH_MANAGED_API_URL || 'https://api.squish.dev',
|
|
@@ -113,7 +168,7 @@ export const config = {
|
|
|
113
168
|
embeddingsRetryDelayMs: parseInt(process.env.SQUISH_EMBEDDINGS_RETRY_DELAY_MS || '1000'),
|
|
114
169
|
openAiTimeoutMs: parseInt(process.env.SQUISH_OPENAI_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
|
|
115
170
|
ollamaTimeoutMs: parseInt(process.env.SQUISH_OLLAMA_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
|
|
116
|
-
|
|
171
|
+
googleTimeoutMs: parseInt(process.env.SQUISH_GOOGLE_TIMEOUT_MS || process.env.SQUISH_EMBEDDINGS_TIMEOUT_MS || '30000'),
|
|
117
172
|
};
|
|
118
173
|
export default config;
|
|
119
174
|
//# sourceMappingURL=config.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultimodalInput } from './embeddings/google-multimodal.js';
|
|
2
|
-
export type EmbeddingProvider = '
|
|
2
|
+
export type EmbeddingProvider = 'local' | 'openai' | 'ollama' | 'google' | 'none' | 'auto';
|
|
3
3
|
export declare function getEmbedding(input: string | MultimodalInput): Promise<number[] | null>;
|
|
4
4
|
/**
|
|
5
5
|
* Get embeddings for multiple inputs in parallel batches
|
package/dist/core/embeddings.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { config } from '../config.js';
|
|
2
|
-
import { getQMDClient } from './embeddings/qmd-client.js';
|
|
3
2
|
import { getGoogleMultimodalEmbedding, isMultimodalInput } from './embeddings/google-multimodal.js';
|
|
4
3
|
import { logger } from './logger.js';
|
|
5
4
|
// Retry utility with exponential backoff
|
|
@@ -104,7 +103,7 @@ export async function getEmbedding(input) {
|
|
|
104
103
|
}
|
|
105
104
|
let result = null;
|
|
106
105
|
// Handle multimodal input
|
|
107
|
-
if (isMultimodalInput(input) &&
|
|
106
|
+
if (isMultimodalInput(input) && provider === 'google') {
|
|
108
107
|
const multimodalResult = await getGoogleMultimodalEmbedding(input);
|
|
109
108
|
if (multimodalResult) {
|
|
110
109
|
result = multimodalResult.embedding;
|
|
@@ -116,35 +115,10 @@ export async function getEmbedding(input) {
|
|
|
116
115
|
if (provider === 'none') {
|
|
117
116
|
result = null;
|
|
118
117
|
}
|
|
119
|
-
else if (provider === 'google
|
|
118
|
+
else if (provider === 'google') {
|
|
120
119
|
const multimodalResult = await getGoogleMultimodalEmbedding({ text: textInput });
|
|
121
120
|
result = multimodalResult?.embedding || null;
|
|
122
121
|
}
|
|
123
|
-
else if (provider === 'qmd') {
|
|
124
|
-
result = await getQMDEmbedding(textInput);
|
|
125
|
-
// Fallback if QMD fails (unless qmd-only mode)
|
|
126
|
-
if (!result && config.qmdFallbackMode !== 'qmd-only') {
|
|
127
|
-
result = getLocalEmbedding(textInput);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
else if (provider === 'hybrid') {
|
|
131
|
-
// Hybrid mode: Try cloud providers first (best quality), then local fallback
|
|
132
|
-
// Order: Google Multimodal → OpenAI → Ollama → Local TF-IDF
|
|
133
|
-
// Note: QMD is not used for embedding generation (search only)
|
|
134
|
-
if (config.multimodalEmbeddingsEnabled) {
|
|
135
|
-
const multimodalResult = await getGoogleMultimodalEmbedding({ text: textInput });
|
|
136
|
-
result = multimodalResult?.embedding || null;
|
|
137
|
-
}
|
|
138
|
-
if (!result && config.openAiApiKey) {
|
|
139
|
-
result = await getOpenAiEmbedding(textInput);
|
|
140
|
-
}
|
|
141
|
-
if (!result && config.ollamaUrl) {
|
|
142
|
-
result = await getOllamaEmbedding(textInput);
|
|
143
|
-
}
|
|
144
|
-
if (!result) {
|
|
145
|
-
result = getLocalEmbedding(textInput);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
122
|
else if (provider === 'openai') {
|
|
149
123
|
result = await getOpenAiEmbedding(textInput);
|
|
150
124
|
}
|
|
@@ -155,8 +129,7 @@ export async function getEmbedding(input) {
|
|
|
155
129
|
result = getLocalEmbedding(textInput);
|
|
156
130
|
}
|
|
157
131
|
else {
|
|
158
|
-
// Auto mode:
|
|
159
|
-
// Only try external providers if explicitly configured
|
|
132
|
+
// Auto mode: try cloud providers first if configured, then fall back to local
|
|
160
133
|
if (config.openAiApiKey) {
|
|
161
134
|
result = await getOpenAiEmbedding(textInput);
|
|
162
135
|
}
|
|
@@ -288,34 +261,6 @@ function getLocalEmbedding(input) {
|
|
|
288
261
|
}
|
|
289
262
|
return vector;
|
|
290
263
|
}
|
|
291
|
-
/**
|
|
292
|
-
* Get embedding via QMD
|
|
293
|
-
* Note: QMD doesn't expose direct embedding generation via MCP.
|
|
294
|
-
* This function returns null to trigger fallback to other providers.
|
|
295
|
-
* The main QMD integration value is through hybrid search (qmd_query).
|
|
296
|
-
*/
|
|
297
|
-
async function getQMDEmbedding(input) {
|
|
298
|
-
if (!config.qmdEnabled) {
|
|
299
|
-
return null;
|
|
300
|
-
}
|
|
301
|
-
try {
|
|
302
|
-
const client = await getQMDClient();
|
|
303
|
-
const available = await client.isAvailable();
|
|
304
|
-
if (!available) {
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
// QMD doesn't expose direct embedding generation via MCP
|
|
308
|
-
// The search tools use embeddings internally but don't return them
|
|
309
|
-
//
|
|
310
|
-
// For embedding generation, we rely on fallback providers
|
|
311
|
-
// QMD's main value is through the qmd_search, qmd_vsearch, qmd_query tools
|
|
312
|
-
return null;
|
|
313
|
-
}
|
|
314
|
-
catch (error) {
|
|
315
|
-
logger.debug('QMD embedding unavailable (expected if QMD server not running)');
|
|
316
|
-
return null;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
264
|
/**
|
|
320
265
|
* DJB2 hash function - fast, good distribution
|
|
321
266
|
*/
|
|
@@ -384,7 +329,7 @@ async function getOllamaEmbedding(input) {
|
|
|
384
329
|
*/
|
|
385
330
|
export async function checkEmbeddingProviderHealth() {
|
|
386
331
|
const results = new Map();
|
|
387
|
-
const providers = ['local', 'openai', 'ollama', 'google
|
|
332
|
+
const providers = ['local', 'openai', 'ollama', 'google', 'none', 'auto'];
|
|
388
333
|
// Test local provider (always available)
|
|
389
334
|
results.set('local', { available: true, latencyMs: 0 });
|
|
390
335
|
// Test OpenAI if configured
|
|
@@ -431,29 +376,27 @@ export async function checkEmbeddingProviderHealth() {
|
|
|
431
376
|
else {
|
|
432
377
|
results.set('ollama', { available: false, error: 'Not configured' });
|
|
433
378
|
}
|
|
434
|
-
// Test Google
|
|
435
|
-
if (config.
|
|
379
|
+
// Test Google if configured
|
|
380
|
+
if (config.googleCloudApiKey || config.googleCloudProject) {
|
|
436
381
|
const start = Date.now();
|
|
437
382
|
try {
|
|
438
|
-
const result = await withRetry(() => withTimeout(getGoogleMultimodalEmbedding({ text: 'health check' }), config.
|
|
383
|
+
const result = await withRetry(() => withTimeout(getGoogleMultimodalEmbedding({ text: 'health check' }), config.googleTimeoutMs), config.embeddingsMaxRetries, config.embeddingsRetryDelayMs);
|
|
439
384
|
const latency = Date.now() - start;
|
|
440
|
-
results.set('google
|
|
385
|
+
results.set('google', {
|
|
441
386
|
available: result !== null && result.embedding.length > 0,
|
|
442
387
|
latencyMs: latency
|
|
443
388
|
});
|
|
444
389
|
}
|
|
445
390
|
catch (error) {
|
|
446
|
-
results.set('google
|
|
391
|
+
results.set('google', {
|
|
447
392
|
available: false,
|
|
448
393
|
error: error.message
|
|
449
394
|
});
|
|
450
395
|
}
|
|
451
396
|
}
|
|
452
397
|
else {
|
|
453
|
-
results.set('google
|
|
398
|
+
results.set('google', { available: false, error: 'Not configured' });
|
|
454
399
|
}
|
|
455
|
-
// QMD is not used for embedding generation (search only)
|
|
456
|
-
results.set('qmd', { available: false, error: 'QMD not used for embeddings (search only)' });
|
|
457
400
|
return results;
|
|
458
401
|
}
|
|
459
402
|
//# sourceMappingURL=embeddings.js.map
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Utility functions for local embeddings
|
|
3
|
+
* Note: Actual embedding generation is in core/embeddings.ts
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
6
|
-
export declare const EMBEDDING_DIMENSIONS = 1536;
|
|
7
|
-
export interface EmbeddingProvider {
|
|
8
|
-
embed(text: string): Promise<Embedding>;
|
|
9
|
-
isAvailable(): Promise<boolean>;
|
|
10
|
-
getDimensions(): number;
|
|
11
|
-
}
|
|
12
|
-
export declare function initializeEmbeddingProvider(): Promise<void>;
|
|
13
|
-
export declare function cosineSimilarity(a: Embedding, b: Embedding): number;
|
|
5
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
14
6
|
//# sourceMappingURL=local-embeddings.d.ts.map
|
|
@@ -1,81 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Utility functions for local embeddings
|
|
3
|
+
* Note: Actual embedding generation is in core/embeddings.ts
|
|
4
4
|
*/
|
|
5
|
-
import { config } from '../config.js';
|
|
6
|
-
import { logger } from './logger.js';
|
|
7
|
-
export const EMBEDDING_DIMENSIONS = 1536;
|
|
8
|
-
class StubEmbeddingProvider {
|
|
9
|
-
async embed(_text) {
|
|
10
|
-
return Array(EMBEDDING_DIMENSIONS).fill(0);
|
|
11
|
-
}
|
|
12
|
-
async isAvailable() {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
getDimensions() {
|
|
16
|
-
return EMBEDDING_DIMENSIONS;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
class LocalTfidfEmbeddingProvider {
|
|
20
|
-
idf = new Map();
|
|
21
|
-
async embed(text) {
|
|
22
|
-
const words = this.tokenize(text);
|
|
23
|
-
const embedding = Array(EMBEDDING_DIMENSIONS).fill(0);
|
|
24
|
-
const wordFreq = new Map();
|
|
25
|
-
for (const word of words) {
|
|
26
|
-
wordFreq.set(word, (wordFreq.get(word) || 0) + 1);
|
|
27
|
-
}
|
|
28
|
-
for (const [word, freq] of wordFreq.entries()) {
|
|
29
|
-
const hash = this.hash(word) % EMBEDDING_DIMENSIONS;
|
|
30
|
-
const idf = this.idf.get(word) || 1;
|
|
31
|
-
embedding[hash] += freq * idf;
|
|
32
|
-
}
|
|
33
|
-
const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
|
|
34
|
-
if (norm > 0) {
|
|
35
|
-
for (let i = 0; i < embedding.length; i++) {
|
|
36
|
-
embedding[i] /= norm;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return embedding;
|
|
40
|
-
}
|
|
41
|
-
async isAvailable() {
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
getDimensions() {
|
|
45
|
-
return EMBEDDING_DIMENSIONS;
|
|
46
|
-
}
|
|
47
|
-
tokenize(text) {
|
|
48
|
-
return text.toLowerCase().split(/\s+/).filter(w => w.length > 2).slice(0, 100);
|
|
49
|
-
}
|
|
50
|
-
hash(str) {
|
|
51
|
-
let hash = 0;
|
|
52
|
-
for (let i = 0; i < str.length; i++) {
|
|
53
|
-
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
|
54
|
-
hash = hash & hash;
|
|
55
|
-
}
|
|
56
|
-
return Math.abs(hash);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
let currentProvider = null;
|
|
60
|
-
export async function initializeEmbeddingProvider() {
|
|
61
|
-
if (config.embeddingsProvider === 'openai' && config.openAiApiKey) {
|
|
62
|
-
logger.info('Using OpenAI embeddings (team mode - requires API key)');
|
|
63
|
-
currentProvider = new StubEmbeddingProvider();
|
|
64
|
-
}
|
|
65
|
-
else if (config.embeddingsProvider === 'ollama') {
|
|
66
|
-
logger.info('Using Ollama embeddings (team mode - local LLM)');
|
|
67
|
-
currentProvider = new StubEmbeddingProvider();
|
|
68
|
-
}
|
|
69
|
-
else if (config.embeddingsProvider === 'local') {
|
|
70
|
-
logger.info('Using local TF-IDF embeddings (SQLite mode - offline, no API key)');
|
|
71
|
-
currentProvider = new LocalTfidfEmbeddingProvider();
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
// 'none' mode
|
|
75
|
-
logger.info('Embeddings disabled (stub provider)');
|
|
76
|
-
currentProvider = new StubEmbeddingProvider();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
5
|
export function cosineSimilarity(a, b) {
|
|
80
6
|
if (a.length !== b.length) {
|
|
81
7
|
throw new Error('Embeddings must have same dimensions');
|
package/dist/core/mcp/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
import cors from 'cors';
|
|
3
|
+
import rateLimit from 'express-rate-limit';
|
|
3
4
|
import { logger } from '../logger.js';
|
|
4
5
|
export class MCPServer {
|
|
5
6
|
app = express();
|
|
@@ -16,7 +17,32 @@ export class MCPServer {
|
|
|
16
17
|
this.setupRoutes();
|
|
17
18
|
}
|
|
18
19
|
setupMiddleware() {
|
|
19
|
-
|
|
20
|
+
const allowedOrigins = process.env.SQUISH_CORS_ORIGINS?.split(',').map(s => s.trim()) || ['http://localhost:*', 'http://127.0.0.1:*'];
|
|
21
|
+
const appCors = cors({
|
|
22
|
+
origin: (origin, callback) => {
|
|
23
|
+
if (!origin || allowedOrigins.some(allowed => {
|
|
24
|
+
if (allowed.endsWith(':*')) {
|
|
25
|
+
const prefix = allowed.slice(0, -1);
|
|
26
|
+
return origin.startsWith(prefix);
|
|
27
|
+
}
|
|
28
|
+
return origin === allowed;
|
|
29
|
+
})) {
|
|
30
|
+
callback(null, true);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
callback(new Error('Not allowed by CORS'));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const limiter = rateLimit({
|
|
38
|
+
windowMs: 15 * 60 * 1000,
|
|
39
|
+
max: 100,
|
|
40
|
+
message: { error: 'Too many requests, please try again later.' },
|
|
41
|
+
standardHeaders: true,
|
|
42
|
+
legacyHeaders: false,
|
|
43
|
+
});
|
|
44
|
+
this.app.use(appCors);
|
|
45
|
+
this.app.use(limiter);
|
|
20
46
|
this.app.use(express.json());
|
|
21
47
|
}
|
|
22
48
|
setupRoutes() {
|
package/dist/core/mcp/types.d.ts
CHANGED
|
@@ -30,29 +30,29 @@ export declare const MCPToolResultSchema: z.ZodObject<{
|
|
|
30
30
|
mimeType: z.ZodOptional<z.ZodString>;
|
|
31
31
|
}, "strip", z.ZodTypeAny, {
|
|
32
32
|
type: "text" | "image" | "resource";
|
|
33
|
-
data?: string | undefined;
|
|
34
33
|
text?: string | undefined;
|
|
34
|
+
data?: string | undefined;
|
|
35
35
|
mimeType?: string | undefined;
|
|
36
36
|
}, {
|
|
37
37
|
type: "text" | "image" | "resource";
|
|
38
|
-
data?: string | undefined;
|
|
39
38
|
text?: string | undefined;
|
|
39
|
+
data?: string | undefined;
|
|
40
40
|
mimeType?: string | undefined;
|
|
41
41
|
}>, "many">;
|
|
42
42
|
isError: z.ZodOptional<z.ZodBoolean>;
|
|
43
43
|
}, "strip", z.ZodTypeAny, {
|
|
44
44
|
content: {
|
|
45
45
|
type: "text" | "image" | "resource";
|
|
46
|
-
data?: string | undefined;
|
|
47
46
|
text?: string | undefined;
|
|
47
|
+
data?: string | undefined;
|
|
48
48
|
mimeType?: string | undefined;
|
|
49
49
|
}[];
|
|
50
50
|
isError?: boolean | undefined;
|
|
51
51
|
}, {
|
|
52
52
|
content: {
|
|
53
53
|
type: "text" | "image" | "resource";
|
|
54
|
-
data?: string | undefined;
|
|
55
54
|
text?: string | undefined;
|
|
55
|
+
data?: string | undefined;
|
|
56
56
|
mimeType?: string | undefined;
|
|
57
57
|
}[];
|
|
58
58
|
isError?: boolean | undefined;
|
|
@@ -10,7 +10,8 @@ export async function collectRecentContext(sessionId, count = 5) {
|
|
|
10
10
|
return [];
|
|
11
11
|
}
|
|
12
12
|
try {
|
|
13
|
-
const
|
|
13
|
+
const sqliteDb = db;
|
|
14
|
+
const [conversation] = await sqliteDb
|
|
14
15
|
.select()
|
|
15
16
|
.from(conversations)
|
|
16
17
|
.where(eq(conversations.sessionId, sessionId))
|
|
@@ -20,7 +21,7 @@ export async function collectRecentContext(sessionId, count = 5) {
|
|
|
20
21
|
logger.debug(`[ContextCollector] No conversation found for session ${sessionId}`);
|
|
21
22
|
return [];
|
|
22
23
|
}
|
|
23
|
-
const recentMessages = await
|
|
24
|
+
const recentMessages = await sqliteDb
|
|
24
25
|
.select()
|
|
25
26
|
.from(messages)
|
|
26
27
|
.where(eq(messages.conversationId, conversation.id))
|
|
@@ -19,8 +19,9 @@ export async function recordInjection(sessionId, memoryIds, memoryContent) {
|
|
|
19
19
|
return;
|
|
20
20
|
try {
|
|
21
21
|
const now = new Date();
|
|
22
|
+
const sqliteDb = db;
|
|
22
23
|
for (const memoryId of memoryIds) {
|
|
23
|
-
await
|
|
24
|
+
await sqliteDb.insert(memoryFeedback).values({
|
|
24
25
|
memoryId,
|
|
25
26
|
sessionId,
|
|
26
27
|
wasInjected: true,
|
|
@@ -55,16 +56,17 @@ export async function analyzeAndRecordFeedback(sessionId, responseText) {
|
|
|
55
56
|
return;
|
|
56
57
|
try {
|
|
57
58
|
const now = new Date();
|
|
59
|
+
const sqliteDb = db;
|
|
58
60
|
for (const memoryId of injection.memoryIds) {
|
|
59
61
|
const wasReferenced = analysis.referencedMemoryIds.includes(memoryId);
|
|
60
62
|
const delta = wasReferenced ? config.feedbackEchoBonus : -config.feedbackFizzlePenalty;
|
|
61
|
-
const existing = await
|
|
63
|
+
const existing = await sqliteDb
|
|
62
64
|
.select()
|
|
63
65
|
.from(memoryFeedback)
|
|
64
66
|
.where(and(eq(memoryFeedback.memoryId, memoryId), eq(memoryFeedback.sessionId, sessionId)))
|
|
65
67
|
.limit(1);
|
|
66
68
|
if (existing.length > 0) {
|
|
67
|
-
await
|
|
69
|
+
await sqliteDb
|
|
68
70
|
.update(memoryFeedback)
|
|
69
71
|
.set({
|
|
70
72
|
wasReferenced,
|
|
@@ -99,7 +101,8 @@ export async function updateRetrievalPriority(memoryId, delta) {
|
|
|
99
101
|
if (!db)
|
|
100
102
|
return;
|
|
101
103
|
try {
|
|
102
|
-
const
|
|
104
|
+
const sqliteDb = db;
|
|
105
|
+
const [memory] = await sqliteDb
|
|
103
106
|
.select({ retrievalPriority: memories.retrievalPriority })
|
|
104
107
|
.from(memories)
|
|
105
108
|
.where(eq(memories.id, memoryId))
|
|
@@ -108,7 +111,7 @@ export async function updateRetrievalPriority(memoryId, delta) {
|
|
|
108
111
|
return;
|
|
109
112
|
const currentPriority = memory.retrievalPriority ?? 50;
|
|
110
113
|
const newPriority = Math.max(0, Math.min(100, currentPriority + delta));
|
|
111
|
-
await
|
|
114
|
+
await sqliteDb
|
|
112
115
|
.update(memories)
|
|
113
116
|
.set({ retrievalPriority: newPriority })
|
|
114
117
|
.where(eq(memories.id, memoryId));
|
|
@@ -124,7 +127,8 @@ export async function getMemoryFeedbackStats(memoryId) {
|
|
|
124
127
|
return { totalInjections: 0, totalReferences: 0, echoRate: 0, averagePriorityDelta: 0 };
|
|
125
128
|
}
|
|
126
129
|
try {
|
|
127
|
-
const
|
|
130
|
+
const sqliteDb = db;
|
|
131
|
+
const records = await sqliteDb
|
|
128
132
|
.select()
|
|
129
133
|
.from(memoryFeedback)
|
|
130
134
|
.where(eq(memoryFeedback.memoryId, memoryId));
|