squish-memory 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/.env.mcp +30 -0
- package/.mcp.json +2 -5
- package/CHANGELOG.md +111 -0
- package/QUICK-START.md +65 -0
- package/README.md +188 -530
- package/commands/managed-sync.ts +69 -0
- package/commands/mcp-server.ts +519 -0
- package/config/mcp-cli-fallback-policy.json +22 -0
- package/config/mcp-migration-map.json +22 -0
- package/config/mcp-mode-semantics.json +21 -0
- package/config/mcp-remote-auth.json +36 -0
- package/config/mcp-universal.schema.json +48 -0
- package/config/mcp.json +38 -0
- package/config/remote-memory-policy.json +32 -0
- package/dist/algorithms/merge/detection/hash-filters.js +2 -2
- package/dist/algorithms/merge/detection/hash-filters.js.map +1 -1
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts +5 -2
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +1 -1
- package/dist/algorithms/merge/detection/two-stage-detector.js +139 -22
- package/dist/algorithms/merge/detection/two-stage-detector.js.map +1 -1
- package/dist/commands/managed-sync.d.ts +10 -0
- package/dist/commands/managed-sync.d.ts.map +1 -0
- package/dist/commands/managed-sync.js +64 -0
- package/dist/commands/managed-sync.js.map +1 -0
- package/dist/commands/mcp-server.d.ts +3 -0
- package/dist/commands/mcp-server.d.ts.map +1 -0
- package/dist/commands/mcp-server.js +389 -0
- package/dist/commands/mcp-server.js.map +1 -0
- package/dist/config.d.ts +24 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -1
- package/dist/config.js.map +1 -1
- package/dist/core/associations.d.ts +1 -1
- package/dist/core/associations.d.ts.map +1 -1
- package/dist/core/consolidation.d.ts +31 -0
- package/dist/core/consolidation.d.ts.map +1 -1
- package/dist/core/consolidation.js +237 -29
- package/dist/core/consolidation.js.map +1 -1
- package/dist/core/embeddings/google-multimodal.d.ts +14 -0
- package/dist/core/embeddings/google-multimodal.d.ts.map +1 -0
- package/dist/core/embeddings/google-multimodal.js +142 -0
- package/dist/core/embeddings/google-multimodal.js.map +1 -0
- package/dist/core/embeddings.d.ts +3 -2
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +61 -39
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/mcp/client.d.ts +17 -0
- package/dist/core/mcp/client.d.ts.map +1 -0
- package/dist/core/mcp/client.js +101 -0
- package/dist/core/mcp/client.js.map +1 -0
- package/dist/core/mcp/index.d.ts +6 -0
- package/dist/core/mcp/index.d.ts.map +1 -0
- package/dist/core/mcp/index.js +6 -0
- package/dist/core/mcp/index.js.map +1 -0
- package/dist/core/mcp/server.d.ts +18 -0
- package/dist/core/mcp/server.d.ts.map +1 -0
- package/dist/core/mcp/server.js +131 -0
- package/dist/core/mcp/server.js.map +1 -0
- package/dist/core/mcp/standalone-server.d.ts +13 -0
- package/dist/core/mcp/standalone-server.d.ts.map +1 -0
- package/dist/core/mcp/standalone-server.js +46 -0
- package/dist/core/mcp/standalone-server.js.map +1 -0
- package/dist/core/mcp/tools.d.ts +9 -0
- package/dist/core/mcp/tools.d.ts.map +1 -0
- package/dist/core/mcp/tools.js +262 -0
- package/dist/core/mcp/tools.js.map +1 -0
- package/dist/core/mcp/types.d.ts +315 -0
- package/dist/core/mcp/types.d.ts.map +1 -0
- package/dist/core/mcp/types.js +48 -0
- package/dist/core/mcp/types.js.map +1 -0
- package/dist/core/memory/categorizer.d.ts +27 -0
- package/dist/core/memory/categorizer.d.ts.map +1 -0
- package/dist/core/memory/categorizer.js +304 -0
- package/dist/core/memory/categorizer.js.map +1 -0
- package/dist/core/memory/conflict-detector.d.ts +7 -0
- package/dist/core/memory/conflict-detector.d.ts.map +1 -0
- package/dist/core/memory/conflict-detector.js +43 -0
- package/dist/core/memory/conflict-detector.js.map +1 -0
- package/dist/core/memory/context-collector.d.ts +10 -0
- package/dist/core/memory/context-collector.d.ts.map +1 -0
- package/dist/core/memory/context-collector.js +55 -0
- package/dist/core/memory/context-collector.js.map +1 -0
- package/dist/core/memory/contradiction-resolver.d.ts +40 -0
- package/dist/core/memory/contradiction-resolver.d.ts.map +1 -0
- package/dist/core/memory/contradiction-resolver.js +368 -0
- package/dist/core/memory/contradiction-resolver.js.map +1 -0
- package/dist/core/memory/edit-workflow.d.ts +19 -0
- package/dist/core/memory/edit-workflow.d.ts.map +1 -0
- package/dist/core/memory/edit-workflow.js +120 -0
- package/dist/core/memory/edit-workflow.js.map +1 -0
- package/dist/core/memory/feedback-tracker.d.ts +12 -0
- package/dist/core/memory/feedback-tracker.d.ts.map +1 -0
- package/dist/core/memory/feedback-tracker.js +151 -0
- package/dist/core/memory/feedback-tracker.js.map +1 -0
- package/dist/core/memory/hybrid-retrieval.d.ts +11 -12
- package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -1
- package/dist/core/memory/hybrid-retrieval.js +56 -28
- package/dist/core/memory/hybrid-retrieval.js.map +1 -1
- package/dist/core/memory/hybrid-scorer.d.ts +5 -16
- package/dist/core/memory/hybrid-scorer.d.ts.map +1 -1
- package/dist/core/memory/hybrid-scorer.js +161 -125
- package/dist/core/memory/hybrid-scorer.js.map +1 -1
- package/dist/core/memory/hybrid-search.js +53 -19
- package/dist/core/memory/hybrid-search.js.map +1 -1
- package/dist/core/memory/memories.d.ts +4 -0
- package/dist/core/memory/memories.d.ts.map +1 -1
- package/dist/core/memory/memories.js +133 -60
- package/dist/core/memory/memories.js.map +1 -1
- package/dist/core/memory/progressive-disclosure.d.ts +43 -0
- package/dist/core/memory/progressive-disclosure.d.ts.map +1 -0
- package/dist/core/memory/progressive-disclosure.js +280 -0
- package/dist/core/memory/progressive-disclosure.js.map +1 -0
- package/dist/core/memory/query-rewriter.d.ts +13 -0
- package/dist/core/memory/query-rewriter.d.ts.map +1 -0
- package/dist/core/memory/query-rewriter.js +118 -0
- package/dist/core/memory/query-rewriter.js.map +1 -0
- package/dist/core/memory/response-analyzer.d.ts +9 -0
- package/dist/core/memory/response-analyzer.d.ts.map +1 -0
- package/dist/core/memory/response-analyzer.js +61 -0
- package/dist/core/memory/response-analyzer.js.map +1 -0
- package/dist/core/memory/stats.d.ts +17 -0
- package/dist/core/memory/stats.d.ts.map +1 -0
- package/dist/core/memory/stats.js +87 -0
- package/dist/core/memory/stats.js.map +1 -0
- package/dist/core/memory/telemetry.d.ts +69 -0
- package/dist/core/memory/telemetry.d.ts.map +1 -0
- package/dist/core/memory/telemetry.js +313 -0
- package/dist/core/memory/telemetry.js.map +1 -0
- package/dist/core/memory/temporal-facts.d.ts +41 -0
- package/dist/core/memory/temporal-facts.d.ts.map +1 -0
- package/dist/core/memory/temporal-facts.js +262 -0
- package/dist/core/memory/temporal-facts.js.map +1 -0
- package/dist/core/memory/trigger-detector.d.ts +14 -0
- package/dist/core/memory/trigger-detector.d.ts.map +1 -0
- package/dist/core/memory/trigger-detector.js +42 -0
- package/dist/core/memory/trigger-detector.js.map +1 -0
- package/dist/core/memory/write-gate.d.ts +54 -0
- package/dist/core/memory/write-gate.d.ts.map +1 -0
- package/dist/core/memory/write-gate.js +210 -0
- package/dist/core/memory/write-gate.js.map +1 -0
- package/dist/core/projects.d.ts +2 -0
- package/dist/core/projects.d.ts.map +1 -1
- package/dist/core/projects.js +33 -0
- package/dist/core/projects.js.map +1 -1
- package/dist/core/scheduler/cron-scheduler.d.ts +32 -0
- package/dist/core/scheduler/cron-scheduler.d.ts.map +1 -0
- package/dist/core/scheduler/cron-scheduler.js +238 -0
- package/dist/core/scheduler/cron-scheduler.js.map +1 -0
- package/dist/core/scheduler/heartbeat.d.ts +11 -0
- package/dist/core/scheduler/heartbeat.d.ts.map +1 -0
- package/dist/core/scheduler/heartbeat.js +73 -0
- package/dist/core/scheduler/heartbeat.js.map +1 -0
- package/dist/core/scheduler/index.d.ts +8 -0
- package/dist/core/scheduler/index.d.ts.map +1 -0
- package/dist/core/scheduler/index.js +8 -0
- package/dist/core/scheduler/index.js.map +1 -0
- package/dist/core/scheduler/job-runner.d.ts +11 -0
- package/dist/core/scheduler/job-runner.d.ts.map +1 -0
- package/dist/core/scheduler/job-runner.js +161 -0
- package/dist/core/scheduler/job-runner.js.map +1 -0
- package/dist/core/session/auto-load.d.ts +6 -0
- package/dist/core/session/auto-load.d.ts.map +1 -0
- package/dist/core/session/auto-load.js +119 -0
- package/dist/core/session/auto-load.js.map +1 -0
- package/dist/core/session/index.d.ts +7 -0
- package/dist/core/session/index.d.ts.map +1 -0
- package/dist/core/session/index.js +7 -0
- package/dist/core/session/index.js.map +1 -0
- package/dist/core/session/types.d.ts +26 -0
- package/dist/core/session/types.d.ts.map +1 -0
- package/dist/core/session/types.js +10 -0
- package/dist/core/session/types.js.map +1 -0
- package/dist/core/snapshots/comparison.d.ts.map +1 -1
- package/dist/core/snapshots/comparison.js +8 -2
- package/dist/core/snapshots/comparison.js.map +1 -1
- package/dist/core/utils/content-extraction.d.ts.map +1 -1
- package/dist/core/utils/content-extraction.js +11 -1
- package/dist/core/utils/content-extraction.js.map +1 -1
- package/dist/core/utils/summarization-helpers.d.ts.map +1 -1
- package/dist/core/utils/summarization-helpers.js +4 -1
- package/dist/core/utils/summarization-helpers.js.map +1 -1
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +26 -3
- package/dist/core/utils.js.map +1 -1
- package/dist/core/worker.d.ts +20 -0
- package/dist/core/worker.d.ts.map +1 -1
- package/dist/core/worker.js +86 -0
- package/dist/core/worker.js.map +1 -1
- package/dist/db/adapter.d.ts +1 -5
- package/dist/db/adapter.d.ts.map +1 -1
- package/dist/db/adapter.js +125 -12
- package/dist/db/adapter.js.map +1 -1
- package/dist/db/bootstrap.d.ts.map +1 -1
- package/dist/db/bootstrap.js +178 -3
- package/dist/db/bootstrap.js.map +1 -1
- package/dist/db/index.d.ts +1 -5
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +7 -4
- package/dist/db/index.js.map +1 -1
- package/dist/drizzle/schema-sqlite.d.ts +1953 -612
- package/dist/drizzle/schema-sqlite.d.ts.map +1 -1
- package/dist/drizzle/schema-sqlite.js +134 -0
- package/dist/drizzle/schema-sqlite.js.map +1 -1
- package/dist/drizzle/schema.d.ts +684 -3
- package/dist/drizzle/schema.d.ts.map +1 -1
- package/dist/drizzle/schema.js +81 -1
- package/dist/drizzle/schema.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +152 -13
- package/dist/index.js.map +1 -1
- package/package.json +125 -103
- package/scripts/build-release.sh +33 -0
- package/scripts/db/check-db.mjs +88 -0
- package/scripts/db/fix-all-columns.mjs +52 -0
- package/scripts/db/fix-schema-all.mjs +55 -0
- package/scripts/db/fix-schema-full.mjs +46 -0
- package/scripts/db/fix-schema.mjs +38 -0
- package/scripts/db/init-db.mjs +13 -0
- package/scripts/db/recreate-db.mjs +14 -0
- package/scripts/generate-mcp.mjs +264 -0
- package/scripts/github-release.sh +61 -0
- package/scripts/init-dirs.mjs +13 -0
- package/scripts/init-dirs.ts +15 -0
- package/scripts/install-mcp.mjs +116 -0
- package/scripts/install-web.sh +120 -0
- package/scripts/install.mjs +340 -0
- package/scripts/openclaw-bootstrap.mjs +127 -0
- package/scripts/package-release.sh +71 -0
- package/scripts/remote-preflight.mjs +62 -0
- package/scripts/squish-fallback.mjs +132 -0
- package/scripts/test/test-all-systems.mjs +139 -0
- package/scripts/test/test-memory-system.mjs +139 -0
- package/scripts/test/test-v0.5.0.mjs +210 -0
- package/scripts/verify-mcp.mjs +214 -0
- package/skills/memory-guide/SKILL.md +181 -123
- package/skills/squish-cli/SKILL.md +200 -0
- package/skills/squish-mcp/SKILL.md +311 -0
- package/skills/squish-memory/SKILL.md +100 -62
- package/skills/squish-memory/claude-desktop.json +12 -0
- package/skills/squish-memory/install.mjs +335 -0
- package/skills/squish-memory/install.sh +94 -62
- package/skills/squish-memory/openclaw.json +13 -0
- package/skills/squish-memory/opencode.json +14 -0
- package/skills/squish-memory/skill.json +32 -0
- package/dist/adapters/claude-code/capture.d.ts +0 -11
- package/dist/adapters/claude-code/capture.d.ts.map +0 -1
- package/dist/adapters/claude-code/capture.js +0 -100
- package/dist/adapters/claude-code/capture.js.map +0 -1
- package/dist/adapters/claude-code/index.d.ts +0 -5
- package/dist/adapters/claude-code/index.d.ts.map +0 -1
- package/dist/adapters/claude-code/index.js +0 -6
- package/dist/adapters/claude-code/index.js.map +0 -1
- package/dist/adapters/claude-code/injection.d.ts +0 -34
- package/dist/adapters/claude-code/injection.d.ts.map +0 -1
- package/dist/adapters/claude-code/injection.js +0 -127
- package/dist/adapters/claude-code/injection.js.map +0 -1
- package/dist/adapters/claude-code/plugin-wrapper.d.ts +0 -21
- package/dist/adapters/claude-code/plugin-wrapper.d.ts.map +0 -1
- package/dist/adapters/claude-code/plugin-wrapper.js +0 -239
- package/dist/adapters/claude-code/plugin-wrapper.js.map +0 -1
- package/dist/adapters/claude-code/types.d.ts +0 -46
- package/dist/adapters/claude-code/types.d.ts.map +0 -1
- package/dist/adapters/claude-code/types.js +0 -6
- package/dist/adapters/claude-code/types.js.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { MCPClient } from '../core/mcp/client.js';
|
|
2
|
+
import { config } from '../config.js';
|
|
3
|
+
import { logger } from '../core/logger.js';
|
|
4
|
+
import { searchMemories, rememberMemory } from '../core/memory/memories.js';
|
|
5
|
+
|
|
6
|
+
export class ManagedSync {
|
|
7
|
+
private client: MCPClient;
|
|
8
|
+
private syncEnabled: boolean;
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
this.syncEnabled = config.managedMode && !!config.managedApiKey;
|
|
12
|
+
|
|
13
|
+
this.client = new MCPClient(config.managedApiUrl);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async sync(): Promise<void> {
|
|
17
|
+
if (!this.syncEnabled) {
|
|
18
|
+
logger.debug('Managed sync disabled');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await this.client.initialize();
|
|
24
|
+
logger.info('Connected to managed storage');
|
|
25
|
+
} catch (error) {
|
|
26
|
+
logger.error('Managed sync connection failed:', error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async pushMemory(memoryId: string): Promise<void> {
|
|
31
|
+
if (!this.syncEnabled) return;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const memory = await searchMemories({ query: memoryId, limit: 1 });
|
|
35
|
+
if (memory.length > 0) {
|
|
36
|
+
await this.client.callTool('managed_memory_store', {
|
|
37
|
+
memory: memory[0],
|
|
38
|
+
});
|
|
39
|
+
logger.debug(`Pushed memory ${memoryId} to managed storage`);
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
logger.error(`Failed to push memory ${memoryId}:`, error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async pullMemory(memoryId: string): Promise<void> {
|
|
47
|
+
if (!this.syncEnabled) return;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const result = await this.client.callTool('managed_memory_retrieve', {
|
|
51
|
+
memoryId,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (result.content[0]?.text) {
|
|
55
|
+
const memory = JSON.parse(result.content[0].text);
|
|
56
|
+
await rememberMemory(memory);
|
|
57
|
+
logger.debug(`Pulled memory ${memoryId} from managed storage`);
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
logger.error(`Failed to pull memory ${memoryId}:`, error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function startManagedSync(): Promise<ManagedSync> {
|
|
66
|
+
const sync = new ManagedSync();
|
|
67
|
+
await sync.sync();
|
|
68
|
+
return sync;
|
|
69
|
+
}
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// CRITICAL: Redirect console.log to stderr to prevent JSON-RPC stream corruption
|
|
4
|
+
// MCP stdio requires stdout to contain ONLY valid JSON-RPC messages
|
|
5
|
+
console.log = console.error;
|
|
6
|
+
console.info = console.error;
|
|
7
|
+
|
|
8
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
11
|
+
import express from "express";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { config } from "../config.js";
|
|
14
|
+
import { hybridSearch } from "../core/memory/hybrid-retrieval.js";
|
|
15
|
+
import { rememberMemory, searchMemories, getMemoryById, type MemoryType } from "../core/memory/memories.js";
|
|
16
|
+
import { getEmbedding, getBatchEmbeddings } from "../core/embeddings.js";
|
|
17
|
+
import { getQMDClient } from "../core/embeddings/qmd-client.js";
|
|
18
|
+
import { createAssociation, getRelatedMemories, trackCoactivation, type AssociationType } from "../core/associations.js";
|
|
19
|
+
import { createObservation, getObservationsForProject, type ObservationType } from "../core/observations.js";
|
|
20
|
+
import { ensureProject, getProjectByPath, getAllProjects } from "../core/projects.js";
|
|
21
|
+
import { getMemoryStats } from "../core/memory/stats.js";
|
|
22
|
+
import { logger } from "../core/logger.js";
|
|
23
|
+
import { getDb } from "../db/index.js";
|
|
24
|
+
import { getSchema } from "../db/schema.js";
|
|
25
|
+
import { eq } from "drizzle-orm";
|
|
26
|
+
|
|
27
|
+
const SERVER_NAME = "squish-memory";
|
|
28
|
+
const SERVER_VERSION = "0.9.0";
|
|
29
|
+
|
|
30
|
+
function parseArgs(): { mode: "stdio" | "http"; port: number; health: boolean } {
|
|
31
|
+
const args = process.argv.slice(2);
|
|
32
|
+
let mode: "stdio" | "http" = "stdio";
|
|
33
|
+
let port = config.mcpServerPort || 8767;
|
|
34
|
+
let health = false;
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < args.length; i++) {
|
|
37
|
+
if (args[i] === "--http" || args[i] === "-h") {
|
|
38
|
+
mode = "http";
|
|
39
|
+
} else if (args[i] === "--stdio" || args[i] === "-s") {
|
|
40
|
+
mode = "stdio";
|
|
41
|
+
} else if (args[i] === "--port" || args[i] === "-p") {
|
|
42
|
+
port = parseInt(args[i + 1], 10) || 8767;
|
|
43
|
+
i++;
|
|
44
|
+
} else if (args[i] === "--health" || args[i] === "--check") {
|
|
45
|
+
health = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (process.env.SQUISH_MCP_MODE === "http") {
|
|
50
|
+
mode = "http";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { mode, port, health };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function safeRegisterTool(
|
|
57
|
+
server: McpServer,
|
|
58
|
+
name: string,
|
|
59
|
+
definition: any,
|
|
60
|
+
handler: any
|
|
61
|
+
): boolean {
|
|
62
|
+
try {
|
|
63
|
+
server.registerTool(name, definition, handler);
|
|
64
|
+
console.error(`[MCP] Registered tool: ${name}`);
|
|
65
|
+
return true;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error(`[MCP] Failed to register tool ${name}:`, error);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createSquishServer(): { server: McpServer; toolCount: number } {
|
|
73
|
+
const server = new McpServer(
|
|
74
|
+
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
75
|
+
{ capabilities: { tools: {} } }
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
let toolCount = 0;
|
|
79
|
+
|
|
80
|
+
console.error(`[MCP] Starting tool registration...`);
|
|
81
|
+
|
|
82
|
+
if (safeRegisterTool(
|
|
83
|
+
server,
|
|
84
|
+
"squish_search",
|
|
85
|
+
{
|
|
86
|
+
description: "Hybrid search across QMD, SQLite DB, and embeddings with graph expansion",
|
|
87
|
+
inputSchema: {
|
|
88
|
+
query: z.string().describe("Search query"),
|
|
89
|
+
limit: z.number().min(1).max(100).default(5).describe("Maximum results"),
|
|
90
|
+
project: z.string().optional().describe("Project path filter"),
|
|
91
|
+
mode: z.enum(["hybrid", "qmd", "db", "semantic"]).default("hybrid").describe("Search mode")
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
async ({ query, limit = 5, project, mode = "hybrid" }: { query: string; limit?: number; project?: string; mode?: "hybrid" | "qmd" | "db" | "semantic" }) => {
|
|
95
|
+
const results = await hybridSearch({
|
|
96
|
+
query,
|
|
97
|
+
limit,
|
|
98
|
+
project,
|
|
99
|
+
candidateLimit: 50,
|
|
100
|
+
resultLimit: limit
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const formatted = results.map((r, i) =>
|
|
104
|
+
`${i + 1}. [${r.type || "memory"}] ${r.content?.substring(0, 200)}... (score: ${r.hybridScore?.toFixed(2)})`
|
|
105
|
+
).join("\n");
|
|
106
|
+
|
|
107
|
+
return { content: [{ type: "text", text: `Found ${results.length} memories:\n\n${formatted}` }] };
|
|
108
|
+
}
|
|
109
|
+
)) toolCount++;
|
|
110
|
+
|
|
111
|
+
if (safeRegisterTool(
|
|
112
|
+
server,
|
|
113
|
+
"squish_remember",
|
|
114
|
+
{
|
|
115
|
+
description: "Store a new memory in Squish with automatic embedding",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
content: z.string().describe("Memory content to store"),
|
|
118
|
+
type: z.enum(["observation", "fact", "decision", "context", "preference"]).default("observation").describe("Memory type"),
|
|
119
|
+
tags: z.array(z.string()).optional().describe("Optional tags"),
|
|
120
|
+
project: z.string().optional().describe("Project path")
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
async ({ content, type = "observation", tags = [], project }: { content: string; type?: MemoryType; tags?: string[]; project?: string }) => {
|
|
124
|
+
const memory = await rememberMemory({ content, type: type as MemoryType, tags, project });
|
|
125
|
+
return { content: [{ type: "text", text: `Memory stored: ${memory.id}` }] };
|
|
126
|
+
}
|
|
127
|
+
)) toolCount++;
|
|
128
|
+
|
|
129
|
+
if (safeRegisterTool(
|
|
130
|
+
server,
|
|
131
|
+
"squish_recall",
|
|
132
|
+
{
|
|
133
|
+
description: "Retrieve a specific memory by ID",
|
|
134
|
+
inputSchema: {
|
|
135
|
+
memoryId: z.string().uuid().describe("Memory ID to retrieve")
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
async ({ memoryId }: { memoryId: string }) => {
|
|
139
|
+
const memory = await getMemoryById(memoryId);
|
|
140
|
+
if (!memory) {
|
|
141
|
+
return { content: [{ type: "text", text: `Memory not found: ${memoryId}` }], isError: true };
|
|
142
|
+
}
|
|
143
|
+
return { content: [{ type: "text", text: JSON.stringify(memory, null, 2) }] };
|
|
144
|
+
}
|
|
145
|
+
)) toolCount++;
|
|
146
|
+
|
|
147
|
+
if (safeRegisterTool(
|
|
148
|
+
server,
|
|
149
|
+
"squish_forget",
|
|
150
|
+
{
|
|
151
|
+
description: "Delete a memory by ID",
|
|
152
|
+
inputSchema: {
|
|
153
|
+
memoryId: z.string().uuid().describe("Memory ID to delete")
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
async ({ memoryId }: { memoryId: string }) => {
|
|
157
|
+
const db = await getDb();
|
|
158
|
+
const schema = await getSchema();
|
|
159
|
+
const result = await db.delete(schema.memories).where(eq(schema.memories.id, memoryId));
|
|
160
|
+
return { content: [{ type: "text", text: `Memory deleted: ${memoryId}` }] };
|
|
161
|
+
}
|
|
162
|
+
)) toolCount++;
|
|
163
|
+
|
|
164
|
+
if (safeRegisterTool(
|
|
165
|
+
server,
|
|
166
|
+
"squish_update",
|
|
167
|
+
{
|
|
168
|
+
description: "Update an existing memory",
|
|
169
|
+
inputSchema: {
|
|
170
|
+
memoryId: z.string().uuid().describe("Memory ID to update"),
|
|
171
|
+
content: z.string().optional().describe("New content"),
|
|
172
|
+
tags: z.array(z.string()).optional().describe("New tags"),
|
|
173
|
+
type: z.enum(["observation", "fact", "decision", "context", "preference"]).optional().describe("New type")
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
async ({ memoryId, content, tags, type }: { memoryId: string; content?: string; tags?: string[]; type?: MemoryType }) => {
|
|
177
|
+
const db = await getDb();
|
|
178
|
+
const schema = await getSchema();
|
|
179
|
+
|
|
180
|
+
const updates: Record<string, any> = {};
|
|
181
|
+
if (content) updates.content = content;
|
|
182
|
+
if (tags) updates.tags = config.isTeamMode ? tags : JSON.stringify(tags);
|
|
183
|
+
if (type) updates.type = type;
|
|
184
|
+
|
|
185
|
+
if (Object.keys(updates).length === 0) {
|
|
186
|
+
return { content: [{ type: "text", text: "No updates provided" }], isError: true };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
await db.update(schema.memories).set(updates).where(eq(schema.memories.id, memoryId));
|
|
190
|
+
return { content: [{ type: "text", text: `Memory updated: ${memoryId}` }] };
|
|
191
|
+
}
|
|
192
|
+
)) toolCount++;
|
|
193
|
+
|
|
194
|
+
if (safeRegisterTool(
|
|
195
|
+
server,
|
|
196
|
+
"squish_qmd_search",
|
|
197
|
+
{
|
|
198
|
+
description: "Search markdown files using QMD (BM25 + vector)",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
query: z.string().describe("Search query"),
|
|
201
|
+
collection: z.string().optional().describe("QMD collection name"),
|
|
202
|
+
limit: z.number().min(1).max(100).default(10).describe("Maximum results")
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
async ({ query, collection, limit = 10 }: { query: string; collection?: string; limit?: number }) => {
|
|
206
|
+
const client = await getQMDClient();
|
|
207
|
+
const available = await client.isAvailable();
|
|
208
|
+
|
|
209
|
+
if (!available) {
|
|
210
|
+
return { content: [{ type: "text", text: "QMD not available. Install with: bun install -g qmd" }], isError: true };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const results = await client.search({ query, collection, limit });
|
|
214
|
+
const formatted = results.map((r: any, i: number) =>
|
|
215
|
+
`${i + 1}. ${r.path || r.file} (score: ${r.score?.toFixed(2)})\n ${r.content?.substring(0, 150)}...`
|
|
216
|
+
).join("\n\n");
|
|
217
|
+
|
|
218
|
+
return { content: [{ type: "text", text: `QMD found ${results.length} results:\n\n${formatted}` }] };
|
|
219
|
+
}
|
|
220
|
+
)) toolCount++;
|
|
221
|
+
|
|
222
|
+
if (safeRegisterTool(
|
|
223
|
+
server,
|
|
224
|
+
"squish_associate",
|
|
225
|
+
{
|
|
226
|
+
description: "Create an association between two memories in the graph",
|
|
227
|
+
inputSchema: {
|
|
228
|
+
fromMemoryId: z.string().uuid().describe("Source memory ID"),
|
|
229
|
+
toMemoryId: z.string().uuid().describe("Target memory ID"),
|
|
230
|
+
type: z.enum(["relates_to", "supersedes", "contradicts", "supports", "duplicate", "merged"]).describe("Association type"),
|
|
231
|
+
weight: z.number().min(0).max(1).default(0.5).describe("Association strength (0-1)")
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
async ({ fromMemoryId, toMemoryId, type, weight = 0.5 }: { fromMemoryId: string; toMemoryId: string; type: AssociationType; weight?: number }) => {
|
|
235
|
+
await createAssociation(fromMemoryId, toMemoryId, type, weight);
|
|
236
|
+
return { content: [{ type: "text", text: `Association created: ${fromMemoryId} -> ${toMemoryId} (${type})` }] };
|
|
237
|
+
}
|
|
238
|
+
)) toolCount++;
|
|
239
|
+
|
|
240
|
+
if (safeRegisterTool(
|
|
241
|
+
server,
|
|
242
|
+
"squish_related",
|
|
243
|
+
{
|
|
244
|
+
description: "Get related memories via graph traversal",
|
|
245
|
+
inputSchema: {
|
|
246
|
+
memoryId: z.string().uuid().describe("Memory ID to find relations for"),
|
|
247
|
+
depth: z.number().min(1).max(5).default(2).describe("Graph traversal depth"),
|
|
248
|
+
minWeight: z.number().min(0).max(1).default(0.3).describe("Minimum association weight")
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
async ({ memoryId, depth = 2, minWeight = 0.3 }: { memoryId: string; depth?: number; minWeight?: number }) => {
|
|
252
|
+
const related = await getRelatedMemories(memoryId, depth * 5);
|
|
253
|
+
const filtered = related.filter((r: any) => r.weight >= minWeight);
|
|
254
|
+
const formatted = filtered.map((r: any, i: number) =>
|
|
255
|
+
`${i + 1}. [${r.type || "memory"}] ${r.content?.substring(0, 100)}... (weight: ${r.weight?.toFixed(2)})`
|
|
256
|
+
).join("\n");
|
|
257
|
+
|
|
258
|
+
return { content: [{ type: "text", text: `Found ${related.length} related memories:\n\n${formatted}` }] };
|
|
259
|
+
}
|
|
260
|
+
)) toolCount++;
|
|
261
|
+
|
|
262
|
+
if (safeRegisterTool(
|
|
263
|
+
server,
|
|
264
|
+
"squish_context",
|
|
265
|
+
{
|
|
266
|
+
description: "Get project context with relevant memories",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
project: z.string().describe("Project path"),
|
|
269
|
+
limit: z.number().min(1).max(50).default(10).describe("Maximum memories to return")
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
async ({ project, limit = 10 }: { project: string; limit?: number }) => {
|
|
273
|
+
const projectRecord = await getProjectByPath(project);
|
|
274
|
+
if (!projectRecord) {
|
|
275
|
+
return { content: [{ type: "text", text: `Project not found: ${project}` }], isError: true };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const recentMemories = await searchMemories({ query: "", project, limit });
|
|
279
|
+
const observations = await getObservationsForProject(project, 5);
|
|
280
|
+
|
|
281
|
+
const context = {
|
|
282
|
+
project: projectRecord,
|
|
283
|
+
recentMemories: recentMemories.slice(0, limit),
|
|
284
|
+
recentObservations: observations
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
return { content: [{ type: "text", text: JSON.stringify(context, null, 2) }] };
|
|
288
|
+
}
|
|
289
|
+
)) toolCount++;
|
|
290
|
+
|
|
291
|
+
if (safeRegisterTool(
|
|
292
|
+
server,
|
|
293
|
+
"squish_observe",
|
|
294
|
+
{
|
|
295
|
+
description: "Store an observation about tool usage, patterns, or insights",
|
|
296
|
+
inputSchema: {
|
|
297
|
+
type: z.enum(["tool_use", "file_change", "error", "pattern", "insight"]).describe("Observation type"),
|
|
298
|
+
action: z.string().describe("Action performed"),
|
|
299
|
+
summary: z.string().describe("Summary of observation"),
|
|
300
|
+
target: z.string().optional().describe("Target file or resource"),
|
|
301
|
+
project: z.string().optional().describe("Project path")
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
async ({ type, action, summary, target, project }: { type: ObservationType; action: string; summary: string; target?: string; project?: string }) => {
|
|
305
|
+
const observation = await createObservation({ type, action, summary, target, project });
|
|
306
|
+
return { content: [{ type: "text", text: `Observation stored: ${observation.id}` }] };
|
|
307
|
+
}
|
|
308
|
+
)) toolCount++;
|
|
309
|
+
|
|
310
|
+
if (safeRegisterTool(
|
|
311
|
+
server,
|
|
312
|
+
"squish_embed",
|
|
313
|
+
{
|
|
314
|
+
description: "Generate embeddings for text using configured provider",
|
|
315
|
+
inputSchema: {
|
|
316
|
+
text: z.string().describe("Text to embed")
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
async ({ text }: { text: string }) => {
|
|
320
|
+
const embedding = await getEmbedding(text);
|
|
321
|
+
if (!embedding) {
|
|
322
|
+
return { content: [{ type: "text", text: "Failed to generate embedding" }], isError: true };
|
|
323
|
+
}
|
|
324
|
+
return { content: [{ type: "text", text: JSON.stringify({ dimensions: embedding.length, preview: embedding.slice(0, 5) }, null, 2) }] };
|
|
325
|
+
}
|
|
326
|
+
)) toolCount++;
|
|
327
|
+
|
|
328
|
+
if (safeRegisterTool(
|
|
329
|
+
server,
|
|
330
|
+
"squish_health",
|
|
331
|
+
{
|
|
332
|
+
description: "Check Squish system health status",
|
|
333
|
+
inputSchema: {}
|
|
334
|
+
},
|
|
335
|
+
async (): Promise<any> => {
|
|
336
|
+
const qmdClient = await getQMDClient();
|
|
337
|
+
const qmdAvailable = await qmdClient.isAvailable();
|
|
338
|
+
|
|
339
|
+
return { content: [{ type: "text", text: JSON.stringify({
|
|
340
|
+
status: "ok",
|
|
341
|
+
version: SERVER_VERSION,
|
|
342
|
+
mode: config.isManagedMode ? "managed" : "local",
|
|
343
|
+
embeddings: config.embeddingsProvider,
|
|
344
|
+
qmd: qmdAvailable ? "available" : "unavailable",
|
|
345
|
+
timestamp: new Date().toISOString()
|
|
346
|
+
}, null, 2) }] };
|
|
347
|
+
}
|
|
348
|
+
)) toolCount++;
|
|
349
|
+
|
|
350
|
+
if (safeRegisterTool(
|
|
351
|
+
server,
|
|
352
|
+
"squish_stats",
|
|
353
|
+
{
|
|
354
|
+
description: "Get memory statistics for a project",
|
|
355
|
+
inputSchema: {
|
|
356
|
+
project: z.string().optional().describe("Project path (defaults to current)")
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
async ({ project }: { project?: string }) => {
|
|
360
|
+
const stats = await getMemoryStats(project || process.cwd());
|
|
361
|
+
return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
|
|
362
|
+
}
|
|
363
|
+
)) toolCount++;
|
|
364
|
+
|
|
365
|
+
if (safeRegisterTool(
|
|
366
|
+
server,
|
|
367
|
+
"squish_projects",
|
|
368
|
+
{
|
|
369
|
+
description: "List all registered projects",
|
|
370
|
+
inputSchema: {}
|
|
371
|
+
},
|
|
372
|
+
async (): Promise<any> => {
|
|
373
|
+
const projects = await getAllProjects();
|
|
374
|
+
const formatted = projects.map((p, i) =>
|
|
375
|
+
`${i + 1}. ${p.name}\n Path: ${p.path}\n ID: ${p.id}`
|
|
376
|
+
).join("\n\n");
|
|
377
|
+
|
|
378
|
+
return { content: [{ type: "text", text: `Found ${projects.length} projects:\n\n${formatted}` }] };
|
|
379
|
+
}
|
|
380
|
+
)) toolCount++;
|
|
381
|
+
|
|
382
|
+
console.error(`[MCP] Tool registration complete. Registered ${toolCount} tools.`);
|
|
383
|
+
|
|
384
|
+
return { server, toolCount };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async function runStdio(server: McpServer, toolCount: number): Promise<void> {
|
|
388
|
+
console.error(`[MCP] Starting in STDIO mode...`);
|
|
389
|
+
const transport = new StdioServerTransport();
|
|
390
|
+
|
|
391
|
+
transport.onclose = () => {
|
|
392
|
+
console.error(`[MCP] STDIO transport closed`);
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
await server.connect(transport);
|
|
396
|
+
console.error(`[MCP] Connected via stdio. ${toolCount} tools available.`);
|
|
397
|
+
|
|
398
|
+
// Keep process alive - wait for stdin to close or process signals
|
|
399
|
+
await new Promise<void>((resolve) => {
|
|
400
|
+
process.stdin.on('close', () => {
|
|
401
|
+
console.error(`[MCP] STDIO stdin closed, shutting down`);
|
|
402
|
+
resolve();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
process.on('SIGINT', () => {
|
|
406
|
+
console.error(`[MCP] Received SIGINT, shutting down`);
|
|
407
|
+
resolve();
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
process.on('SIGTERM', () => {
|
|
411
|
+
console.error(`[MCP] Received SIGTERM, shutting down`);
|
|
412
|
+
resolve();
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async function runHttp(server: McpServer, port: number): Promise<void> {
|
|
418
|
+
console.error(`[MCP] Starting in HTTP mode on port ${port}...`);
|
|
419
|
+
|
|
420
|
+
const app = express();
|
|
421
|
+
app.use(express.json());
|
|
422
|
+
|
|
423
|
+
const transports = new Map<string, SSEServerTransport>();
|
|
424
|
+
|
|
425
|
+
app.get("/health", (req, res) => {
|
|
426
|
+
res.json({ status: "ok", server: SERVER_NAME, version: SERVER_VERSION });
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
app.get("/sse", async (req, res) => {
|
|
430
|
+
const transport = new SSEServerTransport("/message", res);
|
|
431
|
+
const sessionId = Math.random().toString(36).substring(7);
|
|
432
|
+
transports.set(sessionId, transport);
|
|
433
|
+
|
|
434
|
+
console.error(`[MCP] SSE connection established: ${sessionId}`);
|
|
435
|
+
|
|
436
|
+
await server.connect(transport);
|
|
437
|
+
|
|
438
|
+
req.on("close", () => {
|
|
439
|
+
console.error(`[MCP] SSE connection closed: ${sessionId}`);
|
|
440
|
+
transports.delete(sessionId);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
app.post("/message", async (req, res) => {
|
|
445
|
+
const sessionId = req.headers["mcp-session-id"] as string || "default";
|
|
446
|
+
const transport = transports.get(sessionId);
|
|
447
|
+
|
|
448
|
+
if (!transport) {
|
|
449
|
+
res.status(400).json({ error: "No active session" });
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
try {
|
|
454
|
+
await transport.handlePostMessage(req, res);
|
|
455
|
+
} catch (error) {
|
|
456
|
+
console.error(`[MCP] Error handling message:`, error);
|
|
457
|
+
res.status(500).json({ error: "Internal server error" });
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
await new Promise<void>((resolve) => app.listen(port, () => {
|
|
462
|
+
console.error(`[MCP] HTTP server listening on port ${port}`);
|
|
463
|
+
console.error(`[MCP] SSE endpoint: http://localhost:${port}/sse`);
|
|
464
|
+
console.error(`[MCP] Health: http://localhost:${port}/health`);
|
|
465
|
+
resolve();
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
async function runHealthCheck(): Promise<void> {
|
|
470
|
+
console.error(`[MCP] Running health check...`);
|
|
471
|
+
|
|
472
|
+
try {
|
|
473
|
+
const { server, toolCount } = createSquishServer();
|
|
474
|
+
console.error(`[MCP] Health check passed. Server initialized with ${toolCount} tools.`);
|
|
475
|
+
process.exit(0);
|
|
476
|
+
} catch (error) {
|
|
477
|
+
console.error(`[MCP] Health check failed:`, error);
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
async function main(): Promise<void> {
|
|
483
|
+
try {
|
|
484
|
+
console.error(`[${SERVER_NAME}] v${SERVER_VERSION} initializing...`);
|
|
485
|
+
console.error(`[${SERVER_NAME}] Mode: ${config.isManagedMode ? "managed" : "local"}`);
|
|
486
|
+
console.error(`[${SERVER_NAME}] Embeddings: ${config.embeddingsProvider}`);
|
|
487
|
+
|
|
488
|
+
const { mode, port, health } = parseArgs();
|
|
489
|
+
|
|
490
|
+
if (health) {
|
|
491
|
+
await runHealthCheck();
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const { server, toolCount } = createSquishServer();
|
|
496
|
+
|
|
497
|
+
const shutdown = async () => {
|
|
498
|
+
console.error(`[${SERVER_NAME}] Shutting down...`);
|
|
499
|
+
process.exit(0);
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
process.on("SIGINT", shutdown);
|
|
503
|
+
process.on("SIGTERM", shutdown);
|
|
504
|
+
|
|
505
|
+
if (mode === "stdio") {
|
|
506
|
+
await runStdio(server, toolCount);
|
|
507
|
+
} else {
|
|
508
|
+
await runHttp(server, port);
|
|
509
|
+
}
|
|
510
|
+
} catch (error) {
|
|
511
|
+
console.error(`[${SERVER_NAME}] Fatal error:`, error);
|
|
512
|
+
process.exit(1);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
main().catch((error) => {
|
|
517
|
+
console.error(`[${SERVER_NAME}] Fatal error:`, error);
|
|
518
|
+
process.exit(1);
|
|
519
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"allowOperations": [
|
|
3
|
+
"remember",
|
|
4
|
+
"search",
|
|
5
|
+
"recall",
|
|
6
|
+
"health"
|
|
7
|
+
],
|
|
8
|
+
"denyPatterns": [
|
|
9
|
+
"docker\\s+",
|
|
10
|
+
"\\|",
|
|
11
|
+
"&&",
|
|
12
|
+
";",
|
|
13
|
+
"`",
|
|
14
|
+
"\\$\\("
|
|
15
|
+
],
|
|
16
|
+
"fallbackTriggers": [
|
|
17
|
+
"mcp-unreachable",
|
|
18
|
+
"mcp-timeout",
|
|
19
|
+
"mcp-schema-error"
|
|
20
|
+
],
|
|
21
|
+
"telemetryField": "executionPath"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"from": "profile-based",
|
|
3
|
+
"to": "universal",
|
|
4
|
+
"legacyProfiles": [
|
|
5
|
+
"default",
|
|
6
|
+
"openclaw",
|
|
7
|
+
"nanoclaw",
|
|
8
|
+
"picoclaw",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"opencode",
|
|
11
|
+
"codex"
|
|
12
|
+
],
|
|
13
|
+
"outputChange": {
|
|
14
|
+
"from": "generated/mcp/{profile}/",
|
|
15
|
+
"to": "generated/mcp/"
|
|
16
|
+
},
|
|
17
|
+
"notes": [
|
|
18
|
+
"Universal generation removes per-profile directories.",
|
|
19
|
+
"Client-specific behavior moves to installer/bootstrap scripts.",
|
|
20
|
+
"Legacy profile references should emit migration warnings during upgrade windows."
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"canonicalModes": [
|
|
3
|
+
"local",
|
|
4
|
+
"remote"
|
|
5
|
+
],
|
|
6
|
+
"defaultMode": "local",
|
|
7
|
+
"legacyAliases": {
|
|
8
|
+
"team": "remote"
|
|
9
|
+
},
|
|
10
|
+
"legacyPolicy": {
|
|
11
|
+
"action": "warn-and-map",
|
|
12
|
+
"untilVersion": "1.0.0"
|
|
13
|
+
},
|
|
14
|
+
"remoteAuth": {
|
|
15
|
+
"supported": [
|
|
16
|
+
"oauth",
|
|
17
|
+
"token"
|
|
18
|
+
],
|
|
19
|
+
"defaultForCli": "token"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"methods": [
|
|
3
|
+
"oauth",
|
|
4
|
+
"token"
|
|
5
|
+
],
|
|
6
|
+
"defaultMethod": "token",
|
|
7
|
+
"precedence": [
|
|
8
|
+
"token",
|
|
9
|
+
"oauth"
|
|
10
|
+
],
|
|
11
|
+
"token": {
|
|
12
|
+
"requiredEnv": [
|
|
13
|
+
"SQUISH_REMOTE_TOKEN"
|
|
14
|
+
],
|
|
15
|
+
"header": "Authorization",
|
|
16
|
+
"scheme": "Bearer"
|
|
17
|
+
},
|
|
18
|
+
"oauth": {
|
|
19
|
+
"pkce": true,
|
|
20
|
+
"deviceCode": true,
|
|
21
|
+
"authorizationUrlEnv": "SQUISH_OAUTH_AUTH_URL",
|
|
22
|
+
"tokenUrlEnv": "SQUISH_OAUTH_TOKEN_URL",
|
|
23
|
+
"clientIdEnv": "SQUISH_OAUTH_CLIENT_ID"
|
|
24
|
+
},
|
|
25
|
+
"cli": {
|
|
26
|
+
"openclaw": {
|
|
27
|
+
"default": "token"
|
|
28
|
+
},
|
|
29
|
+
"claude-code": {
|
|
30
|
+
"default": "token"
|
|
31
|
+
},
|
|
32
|
+
"opencode": {
|
|
33
|
+
"default": "token"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|