squish-memory 0.9.3 → 1.0.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/.env.mcp.example +14 -11
- package/CHANGELOG.md +68 -0
- package/README.md +82 -9
- package/bin/squish-add.mjs +32 -0
- package/bin/squish-rm.mjs +21 -0
- package/config/plugin-manifest.json +152 -0
- package/config/plugin-manifest.schema.json +244 -0
- package/config/settings.json +51 -0
- package/dist/algorithms/{merge/analytics → analytics}/token-estimator.d.ts +1 -1
- package/dist/algorithms/analytics/token-estimator.d.ts.map +1 -0
- package/dist/algorithms/{merge/analytics → analytics}/token-estimator.js +3 -3
- package/dist/algorithms/analytics/token-estimator.js.map +1 -0
- package/dist/algorithms/detection/hash-filters.d.ts.map +1 -0
- package/dist/algorithms/detection/hash-filters.js.map +1 -0
- package/dist/algorithms/{merge/detection → detection}/semantic-ranker.d.ts +1 -1
- package/dist/algorithms/detection/semantic-ranker.d.ts.map +1 -0
- package/dist/algorithms/{merge/detection → detection}/semantic-ranker.js +1 -1
- package/dist/algorithms/detection/semantic-ranker.js.map +1 -0
- package/dist/algorithms/{merge/detection → detection}/two-stage-detector.d.ts +1 -1
- package/dist/algorithms/detection/two-stage-detector.d.ts.map +1 -0
- package/dist/algorithms/{merge/detection → detection}/two-stage-detector.js +4 -4
- package/dist/algorithms/detection/two-stage-detector.js.map +1 -0
- package/dist/algorithms/handlers/approve-merge.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/approve-merge.js +4 -4
- package/dist/algorithms/handlers/approve-merge.js.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/detect-duplicates.d.ts +1 -1
- package/dist/algorithms/handlers/detect-duplicates.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/detect-duplicates.js +55 -75
- package/dist/algorithms/handlers/detect-duplicates.js.map +1 -0
- package/dist/algorithms/handlers/get-stats.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/get-stats.js +3 -3
- package/dist/algorithms/handlers/get-stats.js.map +1 -0
- package/dist/algorithms/handlers/list-proposals.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/list-proposals.js +3 -3
- package/dist/algorithms/handlers/list-proposals.js.map +1 -0
- package/dist/algorithms/handlers/preview-merge.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/preview-merge.js +3 -3
- package/dist/algorithms/handlers/preview-merge.js.map +1 -0
- package/dist/algorithms/handlers/reject-merge.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/reject-merge.js +3 -3
- package/dist/algorithms/handlers/reject-merge.js.map +1 -0
- package/dist/algorithms/handlers/reverse-merge.d.ts.map +1 -0
- package/dist/algorithms/{merge/handlers → handlers}/reverse-merge.js +3 -3
- package/dist/algorithms/handlers/reverse-merge.js.map +1 -0
- package/dist/algorithms/{merge/safety → safety}/safety-checks.d.ts +1 -1
- package/dist/algorithms/safety/safety-checks.d.ts.map +1 -0
- package/dist/algorithms/safety/safety-checks.js +179 -0
- package/dist/algorithms/safety/safety-checks.js.map +1 -0
- package/dist/algorithms/{merge/strategies → strategies}/merge-strategies.d.ts +1 -1
- package/dist/algorithms/strategies/merge-strategies.d.ts.map +1 -0
- package/dist/algorithms/strategies/merge-strategies.js.map +1 -0
- package/dist/algorithms/utils/response-builder.d.ts +28 -0
- package/dist/algorithms/utils/response-builder.d.ts.map +1 -0
- package/dist/algorithms/utils/response-builder.js +37 -0
- package/dist/algorithms/utils/response-builder.js.map +1 -0
- package/dist/api/web/web.d.ts.map +1 -1
- package/dist/api/web/web.js +452 -472
- package/dist/api/web/web.js.map +1 -1
- package/dist/commands/mcp-server.js +7 -3
- package/dist/commands/mcp-server.js.map +1 -1
- package/dist/config.d.ts +10 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +102 -55
- package/dist/config.js.map +1 -1
- package/dist/core/associations.js +2 -2
- package/dist/core/associations.js.map +1 -1
- package/dist/core/embeddings.d.ts +1 -1
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +10 -67
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/layers/generator.d.ts +25 -0
- package/dist/core/layers/generator.d.ts.map +1 -0
- package/dist/core/layers/generator.js +76 -0
- package/dist/core/layers/generator.js.map +1 -0
- package/dist/core/local-embeddings.d.ts +3 -11
- package/dist/core/local-embeddings.d.ts.map +1 -1
- package/dist/core/local-embeddings.js +2 -76
- package/dist/core/local-embeddings.js.map +1 -1
- package/dist/core/mcp/tools.d.ts.map +1 -1
- package/dist/core/mcp/tools.js +71 -0
- package/dist/core/mcp/tools.js.map +1 -1
- package/dist/core/memory/context-collector.d.ts.map +1 -1
- package/dist/core/memory/context-collector.js +3 -2
- package/dist/core/memory/context-collector.js.map +1 -1
- package/dist/core/memory/feedback-tracker.d.ts.map +1 -1
- package/dist/core/memory/feedback-tracker.js +10 -6
- package/dist/core/memory/feedback-tracker.js.map +1 -1
- package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -1
- package/dist/core/memory/hybrid-retrieval.js +49 -1
- package/dist/core/memory/hybrid-retrieval.js.map +1 -1
- package/dist/core/memory/hybrid-search.d.ts.map +1 -1
- package/dist/core/memory/hybrid-search.js +32 -39
- package/dist/core/memory/hybrid-search.js.map +1 -1
- package/dist/core/memory/memories.d.ts.map +1 -1
- package/dist/core/memory/memories.js +1 -7
- package/dist/core/memory/memories.js.map +1 -1
- package/dist/core/memory/progressive-disclosure.d.ts.map +1 -1
- package/dist/core/memory/progressive-disclosure.js.map +1 -1
- package/dist/core/memory/query-rewriter.js +9 -9
- package/dist/core/memory/stats.js +5 -5
- package/dist/core/namespaces/index.d.ts +71 -0
- package/dist/core/namespaces/index.d.ts.map +1 -0
- package/dist/core/namespaces/index.js +305 -0
- package/dist/core/namespaces/index.js.map +1 -0
- package/dist/core/namespaces/uri-parser.d.ts +31 -0
- package/dist/core/namespaces/uri-parser.d.ts.map +1 -0
- package/dist/core/namespaces/uri-parser.js +74 -0
- package/dist/core/namespaces/uri-parser.js.map +1 -0
- package/dist/core/observations.d.ts.map +1 -1
- package/dist/core/observations.js +3 -12
- package/dist/core/observations.js.map +1 -1
- package/dist/core/projects.d.ts.map +1 -1
- package/dist/core/projects.js +0 -12
- package/dist/core/projects.js.map +1 -1
- package/dist/core/scheduler/cron-scheduler.d.ts.map +1 -1
- package/dist/core/scheduler/cron-scheduler.js +26 -7
- package/dist/core/scheduler/cron-scheduler.js.map +1 -1
- package/dist/core/scheduler/job-runner.js +8 -5
- package/dist/core/scheduler/job-runner.js.map +1 -1
- package/dist/core/search/conversations.js +33 -33
- package/dist/core/session-hooks/self-iteration-job.d.ts +20 -0
- package/dist/core/session-hooks/self-iteration-job.d.ts.map +1 -0
- package/dist/core/session-hooks/self-iteration-job.js +282 -0
- package/dist/core/session-hooks/self-iteration-job.js.map +1 -0
- package/dist/core/session-hooks/session-hooks.d.ts +18 -0
- package/dist/core/session-hooks/session-hooks.d.ts.map +1 -0
- package/dist/core/session-hooks/session-hooks.js +58 -0
- package/dist/core/session-hooks/session-hooks.js.map +1 -0
- package/dist/core/tracing/collector.d.ts +111 -0
- package/dist/core/tracing/collector.d.ts.map +1 -0
- package/dist/core/tracing/collector.js +350 -0
- package/dist/core/tracing/collector.js.map +1 -0
- package/dist/core/tracing/visualizer.d.ts +32 -0
- package/dist/core/tracing/visualizer.d.ts.map +1 -0
- package/dist/core/tracing/visualizer.js +165 -0
- package/dist/core/tracing/visualizer.js.map +1 -0
- package/dist/db/adapter.d.ts +6 -1
- package/dist/db/adapter.d.ts.map +1 -1
- package/dist/db/adapter.js +54 -126
- package/dist/db/adapter.js.map +1 -1
- package/dist/db/bootstrap.js +477 -477
- package/dist/db/index.d.ts +5 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/drizzle/schema-sqlite.d.ts +384 -0
- package/dist/drizzle/schema-sqlite.d.ts.map +1 -1
- package/dist/drizzle/schema-sqlite.js +65 -0
- package/dist/drizzle/schema-sqlite.js.map +1 -1
- package/dist/drizzle/schema.d.ts +368 -0
- package/dist/drizzle/schema.d.ts.map +1 -1
- package/dist/drizzle/schema.js +63 -0
- package/dist/drizzle/schema.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +101 -62
- package/dist/index.js.map +1 -1
- package/generated/mcp/manifest.json +23 -0
- package/generated/mcp/mcp-servers.json +25 -0
- package/generated/mcp/mcporter.json +34 -0
- package/generated/mcp/openclaw-memory-qmd.json +17 -0
- package/generated/mcp/runtime.json +12 -0
- package/package.json +70 -28
- package/packages/plugin-claude-code/README.md +73 -0
- package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts +35 -0
- package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts.map +1 -0
- package/packages/plugin-claude-code/dist/plugin-wrapper.js +191 -0
- package/packages/plugin-claude-code/dist/plugin-wrapper.js.map +1 -0
- package/packages/plugin-claude-code/package.json +31 -0
- package/packages/plugin-openclaw/README.md +70 -0
- package/packages/plugin-openclaw/dist/index.d.ts +49 -0
- package/packages/plugin-openclaw/dist/index.d.ts.map +1 -0
- package/packages/plugin-openclaw/dist/index.js +262 -0
- package/packages/plugin-openclaw/dist/index.js.map +1 -0
- package/packages/plugin-openclaw/openclaw.plugin.json +94 -0
- package/packages/plugin-openclaw/package.json +31 -0
- package/packages/plugin-opencode/install.mjs +217 -0
- package/packages/plugin-opencode/package.json +21 -0
- package/scripts/dependency-manager.mjs +217 -0
- package/scripts/detect-clients.mjs +78 -0
- package/scripts/install-interactive.mjs +674 -0
- package/scripts/install-plugin.mjs +415 -0
- package/scripts/test-interactive.mjs +131 -0
- package/commands/managed-sync.ts +0 -69
- package/commands/mcp-server.ts +0 -519
- package/dist/algorithms/merge/analytics/token-estimator.d.ts.map +0 -1
- package/dist/algorithms/merge/analytics/token-estimator.js.map +0 -1
- package/dist/algorithms/merge/detection/hash-filters.d.ts.map +0 -1
- package/dist/algorithms/merge/detection/hash-filters.js.map +0 -1
- package/dist/algorithms/merge/detection/semantic-ranker.d.ts.map +0 -1
- package/dist/algorithms/merge/detection/semantic-ranker.js.map +0 -1
- package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +0 -1
- package/dist/algorithms/merge/detection/two-stage-detector.js.map +0 -1
- package/dist/algorithms/merge/handlers/approve-merge.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/approve-merge.js.map +0 -1
- package/dist/algorithms/merge/handlers/detect-duplicates.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/detect-duplicates.js.map +0 -1
- package/dist/algorithms/merge/handlers/get-stats.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/get-stats.js.map +0 -1
- package/dist/algorithms/merge/handlers/list-proposals.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/list-proposals.js.map +0 -1
- package/dist/algorithms/merge/handlers/preview-merge.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/preview-merge.js.map +0 -1
- package/dist/algorithms/merge/handlers/reject-merge.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/reject-merge.js.map +0 -1
- package/dist/algorithms/merge/handlers/reverse-merge.d.ts.map +0 -1
- package/dist/algorithms/merge/handlers/reverse-merge.js.map +0 -1
- package/dist/algorithms/merge/safety/safety-checks.d.ts.map +0 -1
- package/dist/algorithms/merge/safety/safety-checks.js +0 -215
- package/dist/algorithms/merge/safety/safety-checks.js.map +0 -1
- package/dist/algorithms/merge/strategies/merge-strategies.d.ts.map +0 -1
- package/dist/algorithms/merge/strategies/merge-strategies.js.map +0 -1
- package/dist/core/embeddings/qmd-provider.d.ts +0 -65
- package/dist/core/embeddings/qmd-provider.d.ts.map +0 -1
- package/dist/core/embeddings/qmd-provider.js +0 -133
- package/dist/core/embeddings/qmd-provider.js.map +0 -1
- package/scripts/init-dirs.ts +0 -15
- /package/dist/algorithms/{merge/detection → detection}/hash-filters.d.ts +0 -0
- /package/dist/algorithms/{merge/detection → detection}/hash-filters.js +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/approve-merge.d.ts +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/get-stats.d.ts +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/list-proposals.d.ts +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/preview-merge.d.ts +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/reject-merge.d.ts +0 -0
- /package/dist/algorithms/{merge/handlers → handlers}/reverse-merge.d.ts +0 -0
- /package/dist/algorithms/{merge/strategies → strategies}/merge-strategies.js +0 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
|
|
8
|
+
const root = process.cwd();
|
|
9
|
+
const manifestPath = path.join(root, "config", "plugin-manifest.json");
|
|
10
|
+
|
|
11
|
+
// Client default directories
|
|
12
|
+
const CLIENT_DIRS = {
|
|
13
|
+
"claude-code": path.join(os.homedir(), ".claude"),
|
|
14
|
+
opencode: path.join(os.homedir(), ".config", "opencode"),
|
|
15
|
+
codex: path.join(os.homedir(), ".codex"),
|
|
16
|
+
cursor: path.join(os.homedir(), ".cursor"),
|
|
17
|
+
vscode: path.join(os.homedir(), ".vscode", "mcp"),
|
|
18
|
+
windsurf: path.join(os.homedir(), ".windsurf"),
|
|
19
|
+
openclaw: path.join(os.homedir(), ".openclaw")
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Must-have clients (launch priority)
|
|
23
|
+
const MUST_HAVE = ["claude-code", "openclaw", "opencode"];
|
|
24
|
+
const NICE_TO_HAVE = ["codex", "cursor", "vscode", "windsurf"];
|
|
25
|
+
|
|
26
|
+
function loadManifest() {
|
|
27
|
+
if (!fs.existsSync(manifestPath)) {
|
|
28
|
+
throw new Error(`Plugin manifest not found: ${manifestPath}`);
|
|
29
|
+
}
|
|
30
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseArgs(argv) {
|
|
34
|
+
const args = {
|
|
35
|
+
client: [],
|
|
36
|
+
dryRun: false,
|
|
37
|
+
verify: false,
|
|
38
|
+
uninstall: false,
|
|
39
|
+
strict: false,
|
|
40
|
+
skipDeps: false
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const argHandlers = {
|
|
44
|
+
"--dry-run": () => args.dryRun = true,
|
|
45
|
+
"-d": () => args.dryRun = true,
|
|
46
|
+
"--verify": () => args.verify = true,
|
|
47
|
+
"-v": () => args.verify = true,
|
|
48
|
+
"--uninstall": () => args.uninstall = true,
|
|
49
|
+
"-u": () => args.uninstall = true,
|
|
50
|
+
"--strict": () => args.strict = true,
|
|
51
|
+
"--skip-deps": () => args.skipDeps = true,
|
|
52
|
+
"--client": (i) => {
|
|
53
|
+
const clientList = argv[i + 1];
|
|
54
|
+
args.client = clientList.split(",").map(c => c.trim());
|
|
55
|
+
},
|
|
56
|
+
"-c": (i) => {
|
|
57
|
+
const clientList = argv[i + 1];
|
|
58
|
+
args.client = clientList.split(",").map(c => c.trim());
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
for (let i = 2; i < argv.length; i++) {
|
|
63
|
+
const token = argv[i];
|
|
64
|
+
const handler = argHandlers[token];
|
|
65
|
+
|
|
66
|
+
if (handler) {
|
|
67
|
+
if (token === "--client" || token === "-c") {
|
|
68
|
+
handler(i);
|
|
69
|
+
i++;
|
|
70
|
+
} else {
|
|
71
|
+
handler();
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
throw new Error(`Unknown argument: ${token}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return args;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function ensureDir(dirPath) {
|
|
82
|
+
if (!fs.existsSync(dirPath)) {
|
|
83
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function expandHomePath(filePath) {
|
|
88
|
+
if (filePath.startsWith("~")) {
|
|
89
|
+
return path.join(os.homedir(), filePath.slice(2));
|
|
90
|
+
}
|
|
91
|
+
return filePath;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function backupFile(filePath) {
|
|
95
|
+
if (fs.existsSync(filePath)) {
|
|
96
|
+
const backupPath = `${filePath}.bak`;
|
|
97
|
+
fs.copyFileSync(filePath, backupPath);
|
|
98
|
+
console.log(`[INSTALL] Backed up: ${filePath} → ${backupPath}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function copyFile(sourcePath, targetPath, options = {}) {
|
|
103
|
+
if (!fs.existsSync(sourcePath)) {
|
|
104
|
+
throw new Error(`Source file not found: ${sourcePath}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (options.backup !== false) {
|
|
108
|
+
backupFile(targetPath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!options.dryRun) {
|
|
112
|
+
ensureDir(path.dirname(targetPath));
|
|
113
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const mode = options.dryRun ? "DRY_RUN" : "COPIED";
|
|
117
|
+
console.log(`[INSTALL] ${mode}: ${sourcePath} → ${targetPath}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function runCommand(command, args = [], options = {}) {
|
|
121
|
+
const mode = options.dryRun ? "[DRY_RUN] Would run:" : "Running:";
|
|
122
|
+
console.log(`[INSTALL] ${mode} ${command} ${args.join(" ")}`);
|
|
123
|
+
|
|
124
|
+
if (options.dryRun) {
|
|
125
|
+
return { status: 0, stdout: "", stderr: "" };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const result = spawnSync(command, args, {
|
|
129
|
+
encoding: "utf8",
|
|
130
|
+
stdio: options.silent ? "pipe" : "inherit",
|
|
131
|
+
timeout: options.timeout || 30000
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function checkDependencies(manifest, options) {
|
|
138
|
+
console.log("\n[DEP] Checking dependencies...");
|
|
139
|
+
|
|
140
|
+
if (options.skipDeps) {
|
|
141
|
+
console.log("[DEP] Skipping dependency check (--skip-deps)");
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Run dependency manager
|
|
146
|
+
const depArgs = options.dryRun ? ["--dry-run"] : [];
|
|
147
|
+
const depResult = runCommand(
|
|
148
|
+
process.execPath,
|
|
149
|
+
[path.join(root, "scripts", "dependency-manager.mjs"), ...depArgs],
|
|
150
|
+
{ ...options, silent: true }
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
if (depResult.status !== 0) {
|
|
154
|
+
console.error("[DEP] Dependency check failed:");
|
|
155
|
+
console.error(depResult.stderr);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log(depResult.stdout);
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function installForClient(client, manifest, options) {
|
|
164
|
+
const targetConfig = manifest.targets[client];
|
|
165
|
+
if (!targetConfig) {
|
|
166
|
+
throw new Error(`Unsupported client: ${client}. Supported: ${Object.keys(manifest.targets).join(", ")}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(`\n[INSTALL] Installing for ${client}...`);
|
|
170
|
+
|
|
171
|
+
const install = targetConfig.install;
|
|
172
|
+
if (!install) {
|
|
173
|
+
console.log(`[INSTALL] ⚠ No install steps defined for ${client}, skipping`);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
if (install.copy) {
|
|
179
|
+
for (const item of install.copy) {
|
|
180
|
+
const sourcePath = path.join(root, item.from);
|
|
181
|
+
const targetPath = expandHomePath(item.to);
|
|
182
|
+
copyFile(sourcePath, targetPath, options);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (install.command) {
|
|
187
|
+
runCommand(install.command, [], { dryRun: options.dryRun });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
console.log(`[INSTALL] ✓ ${client} installation complete`);
|
|
191
|
+
return true;
|
|
192
|
+
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error(`[INSTALL] ✗ Failed to install for ${client}:`, error.message);
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function verifyClient(client, manifest) {
|
|
200
|
+
const targetConfig = manifest.targets[client];
|
|
201
|
+
if (!targetConfig || !targetConfig.verify) {
|
|
202
|
+
console.log(`[VERIFY] ⚠ No verification steps for ${client}`);
|
|
203
|
+
return { ok: true, message: "No verification defined" };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
console.log(`[VERIFY] Verifying ${client} installation...`);
|
|
207
|
+
const verify = targetConfig.verify;
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
if (verify.fileExists) {
|
|
211
|
+
const filePath = expandHomePath(verify.fileExists);
|
|
212
|
+
if (!fs.existsSync(filePath)) {
|
|
213
|
+
return { ok: false, error: `File not found: ${filePath}` };
|
|
214
|
+
}
|
|
215
|
+
console.log(`[VERIFY] ✓ File exists: ${filePath}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (verify.toolCheck) {
|
|
219
|
+
console.log(`[VERIFY] Testing tool: ${verify.toolCheck}`);
|
|
220
|
+
const result = spawnSync(
|
|
221
|
+
process.execPath,
|
|
222
|
+
[path.join(root, "dist", "commands", "mcp-server.cjs"), "--health"],
|
|
223
|
+
{ encoding: "utf8", timeout: 10000 }
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
if (result.status !== 0) {
|
|
227
|
+
return { ok: false, error: "MCP server health check failed" };
|
|
228
|
+
}
|
|
229
|
+
console.log(`[VERIFY] ✓ MCP server healthy`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return { ok: true, message: "Verification passed" };
|
|
233
|
+
|
|
234
|
+
} catch (error) {
|
|
235
|
+
return { ok: false, error: error.message };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function uninstallClient(client, manifest, options) {
|
|
240
|
+
const targetConfig = manifest.targets[client];
|
|
241
|
+
if (!targetConfig) {
|
|
242
|
+
throw new Error(`Unsupported client: ${client}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
console.log(`\n[UNINSTALL] Removing ${client} configuration...`);
|
|
246
|
+
const install = targetConfig.install;
|
|
247
|
+
|
|
248
|
+
if (!install || !install.copy) {
|
|
249
|
+
console.log(`[UNINSTALL] ⚠ No files to remove for ${client}`);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
for (const item of install.copy) {
|
|
255
|
+
const targetPath = expandHomePath(item.to);
|
|
256
|
+
|
|
257
|
+
if (fs.existsSync(targetPath)) {
|
|
258
|
+
if (!options.dryRun) {
|
|
259
|
+
try {
|
|
260
|
+
fs.unlinkSync(targetPath);
|
|
261
|
+
} catch (e) {
|
|
262
|
+
if (fs.statSync(targetPath).isDirectory()) {
|
|
263
|
+
console.log(`[UNINSTALL] Skipping directory: ${targetPath} (manual removal required)`);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
throw e;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
console.log(`[UNINSTALL] ${options.dryRun ? "[DRY_RUN] Would remove:" : "Removed"}: ${targetPath}`);
|
|
270
|
+
} else {
|
|
271
|
+
console.log(`[UNINSTALL] Not found: ${targetPath}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return true;
|
|
276
|
+
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error(`[UNINSTALL] ✗ Failed to uninstall ${client}:`, error.message);
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function detectInstalledClients() {
|
|
284
|
+
const detected = {};
|
|
285
|
+
for (const [client, dir] of Object.entries(CLIENT_DIRS)) {
|
|
286
|
+
try {
|
|
287
|
+
detected[client] = fs.existsSync(dir);
|
|
288
|
+
} catch {
|
|
289
|
+
detected[client] = false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return detected;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function main() {
|
|
296
|
+
const args = parseArgs(process.argv);
|
|
297
|
+
const manifest = loadManifest();
|
|
298
|
+
|
|
299
|
+
console.log(`[INSTALL] Squish Universal Plugin Installer v${manifest.version}`);
|
|
300
|
+
console.log(`[INSTALL] Mode: ${args.dryRun ? "DRY_RUN" : args.verify ? "VERIFY" : args.uninstall ? "UNINSTALL" : "INSTALL"}`);
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
// Verify mode
|
|
304
|
+
if (args.verify) {
|
|
305
|
+
let allOk = true;
|
|
306
|
+
const clientsToVerify = args.client.length > 0
|
|
307
|
+
? args.client
|
|
308
|
+
: [...MUST_HAVE, ...NICE_TO_HAVE];
|
|
309
|
+
|
|
310
|
+
for (const client of clientsToVerify) {
|
|
311
|
+
const result = verifyClient(client, manifest);
|
|
312
|
+
if (!result.ok) {
|
|
313
|
+
console.error(`[VERIFY] ✗ ${client}: ${result.error}`);
|
|
314
|
+
allOk = false;
|
|
315
|
+
} else {
|
|
316
|
+
console.log(`[VERIFY] ✓ ${client}: ${result.message}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
process.exit(allOk ? 0 : 1);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Uninstall mode
|
|
325
|
+
if (args.uninstall) {
|
|
326
|
+
if (args.client.length === 0) {
|
|
327
|
+
throw new Error("--uninstall requires --client specification");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
let allOk = true;
|
|
331
|
+
for (const client of args.client) {
|
|
332
|
+
const ok = uninstallClient(client, manifest, args);
|
|
333
|
+
if (!ok) allOk = false;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
process.exit(allOk ? 0 : 1);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Install mode
|
|
341
|
+
|
|
342
|
+
// 1. Check dependencies
|
|
343
|
+
if (!args.skipDeps && !checkDependencies(manifest, args)) {
|
|
344
|
+
process.exit(1);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// 2. Determine client list
|
|
349
|
+
let clientsToInstall = args.client;
|
|
350
|
+
if (clientsToInstall.length === 0) {
|
|
351
|
+
console.log("[INSTALL] No clients specified, use --client=<client> or --client=all");
|
|
352
|
+
console.log(`[INSTALL] Supported clients: ${Object.keys(CLIENT_DIRS).join(", ")}`);
|
|
353
|
+
console.log(`[INSTALL] Must-have: ${MUST_HAVE.join(", ")}`);
|
|
354
|
+
console.log(`[INSTALL] Nice-to-have: ${NICE_TO_HAVE.join(", ")}`);
|
|
355
|
+
process.exit(1);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (clientsToInstall.includes("all")) {
|
|
360
|
+
clientsToInstall = [...MUST_HAVE, ...NICE_TO_HAVE];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// 3. Validate all clients
|
|
364
|
+
const unknown = clientsToInstall.filter(c => !manifest.targets[c]);
|
|
365
|
+
if (unknown.length > 0) {
|
|
366
|
+
console.error(`[INSTALL] Unknown clients: ${unknown.join(", ")}`);
|
|
367
|
+
process.exit(1);
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// 4. Install each client
|
|
372
|
+
let allOk = true;
|
|
373
|
+
for (const client of clientsToInstall) {
|
|
374
|
+
const ok = installForClient(client, manifest, args);
|
|
375
|
+
if (!ok) allOk = false;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// 5. Post-install summary
|
|
379
|
+
console.log("\n[INSTALL] ================================");
|
|
380
|
+
console.log(`[INSTALL] ${allOk ? "✓" : "✗"} Installation ${allOk ? "complete" : "completed with errors"}`);
|
|
381
|
+
|
|
382
|
+
if (allOk && !args.dryRun) {
|
|
383
|
+
console.log("\n[INSTALL] Next steps:");
|
|
384
|
+
|
|
385
|
+
for (const client of clientsToInstall) {
|
|
386
|
+
const targetConfig = manifest.targets[client];
|
|
387
|
+
console.log(`\n ${client}:`);
|
|
388
|
+
|
|
389
|
+
if (client === "claude-code") {
|
|
390
|
+
console.log(" → Restart Claude Code if running");
|
|
391
|
+
console.log(" → The plugin will auto-activate on next session");
|
|
392
|
+
} else if (client === "openclaw") {
|
|
393
|
+
console.log(" → Start OpenClaw agent");
|
|
394
|
+
console.log(" → Memory backend is now active");
|
|
395
|
+
console.log(" → First sync may take a minute");
|
|
396
|
+
} else {
|
|
397
|
+
console.log(" → Restart your MCP client");
|
|
398
|
+
console.log(" → Tools should appear automatically");
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
console.log("\n[INSTALL] Verify with:");
|
|
403
|
+
console.log(` npx squish-memory install-plugin --client=${clientsToInstall[0]} --verify`);
|
|
404
|
+
console.log("\n[INSTALL] Get help: npx squish-memory install-plugin --help");
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
process.exit(allOk ? 0 : 1);
|
|
408
|
+
|
|
409
|
+
} catch (error) {
|
|
410
|
+
console.error("[INSTALL] Fatal error:", error.message);
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
main();
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
const colors = {
|
|
7
|
+
green: "\x1b[32m",
|
|
8
|
+
yellow: "\x1b[33m",
|
|
9
|
+
cyan: "\x1b[36m",
|
|
10
|
+
red: "\x1b[31m",
|
|
11
|
+
reset: "\x1b[0m",
|
|
12
|
+
gray: "\x1b[90m"
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const root = process.cwd();
|
|
16
|
+
const testScriptPath = path.join(root, "scripts", "install-interactive.mjs");
|
|
17
|
+
|
|
18
|
+
let testsRun = 0;
|
|
19
|
+
let testsPassed = 0;
|
|
20
|
+
let testsFailed = 0;
|
|
21
|
+
|
|
22
|
+
function logTest(testName) {
|
|
23
|
+
testsRun++;
|
|
24
|
+
console.log(`\n${colors.cyan}TEST ${testsRun}:${colors.reset} ${testName}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function logPass(message) {
|
|
28
|
+
testsPassed++;
|
|
29
|
+
console.log(` ${colors.green}✓${colors.reset} ${message}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function logFail(message, error) {
|
|
33
|
+
testsFailed++;
|
|
34
|
+
console.log(` ${colors.red}✗${colors.reset} ${message}`);
|
|
35
|
+
if (error) {
|
|
36
|
+
console.log(` ${colors.gray}${error}${colors.reset}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function logSkip(message) {
|
|
41
|
+
console.log(` ${colors.yellow}○${colors.reset} ${message}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function runTest(description, args, envVars = {}, expectedExitCode = 0) {
|
|
45
|
+
logTest(description);
|
|
46
|
+
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const child = spawn(process.execPath, [testScriptPath, ...args], {
|
|
49
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
50
|
+
timeout: 5000,
|
|
51
|
+
env: { ...process.env, ...envVars }
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
let stdout = "";
|
|
55
|
+
let stderr = "";
|
|
56
|
+
|
|
57
|
+
child.stdout?.on("data", (data) => {
|
|
58
|
+
stdout += data.toString();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
child.stderr?.on("data", (data) => {
|
|
62
|
+
stderr += data.toString();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
child.on("close", (code) => {
|
|
66
|
+
if (code === expectedExitCode) {
|
|
67
|
+
logPass(`Exit code: ${code}`);
|
|
68
|
+
} else {
|
|
69
|
+
logFail(`Expected exit code ${expectedExitCode}, got ${code}`, stderr);
|
|
70
|
+
}
|
|
71
|
+
resolve({ code, stdout, stderr });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
child.on("error", (err) => {
|
|
75
|
+
logFail("Spawn failed", err.message);
|
|
76
|
+
resolve({ code: -1, stderr: err.message });
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function runTests() {
|
|
82
|
+
console.log(`${colors.cyan}═════════════════════════════════════════════${colors.reset}`);
|
|
83
|
+
console.log(`${colors.cyan}Interactive Installer Test Suite${colors.reset}`);
|
|
84
|
+
console.log(`${colors.cyan}═══════════════════════════════════════════${colors.reset}`);
|
|
85
|
+
console.log("");
|
|
86
|
+
|
|
87
|
+
await runTest("Syntax check (no syntax errors)", ["--help"]);
|
|
88
|
+
|
|
89
|
+
await runTest("Help flag displays usage", ["--help"]);
|
|
90
|
+
|
|
91
|
+
await runTest("List flag shows available plugins", ["--list"]);
|
|
92
|
+
|
|
93
|
+
await runTest("Auto mode with --all flag", ["--all", "--dry-run"]);
|
|
94
|
+
|
|
95
|
+
await runTest("Auto mode with --select flag", ["--select=claude-code", "--dry-run"]);
|
|
96
|
+
|
|
97
|
+
await runTest("Environment detection - CI mode", ["--list"], { CI: "true" });
|
|
98
|
+
|
|
99
|
+
await runTest("Environment detection - NON_INTERACTIVE mode", ["--list"], { NON_INTERACTIVE: "1" });
|
|
100
|
+
|
|
101
|
+
await runTest("Dry-run preview mode", ["--list", "--dry-run"]);
|
|
102
|
+
|
|
103
|
+
await runTest("Multiple flag combination", ["--select=claude-code,openclaw", "--verbose", "--dry-run"]);
|
|
104
|
+
|
|
105
|
+
await runTest("Invalid flag handling", ["--invalid-flag"], {}, 1);
|
|
106
|
+
|
|
107
|
+
await runTest("Invalid plugin in --select", ["--select=nonexistent"], {}, 1);
|
|
108
|
+
|
|
109
|
+
console.log("");
|
|
110
|
+
console.log(`${colors.cyan}═════════════════════════════════════════════${colors.reset}`);
|
|
111
|
+
console.log(`${colors.cyan}Test Summary${colors.reset}`);
|
|
112
|
+
console.log(`${colors.cyan}═══════════════════════════════════════════${colors.reset}`);
|
|
113
|
+
console.log("");
|
|
114
|
+
console.log(` ${colors.gray}Total tests:${colors.reset} ${testsRun}`);
|
|
115
|
+
console.log(` ${colors.green}Passed:${colors.reset} ${testsPassed}`);
|
|
116
|
+
console.log(` ${colors.red}Failed:${colors.reset} ${testsFailed}`);
|
|
117
|
+
console.log("");
|
|
118
|
+
|
|
119
|
+
if (testsFailed === 0) {
|
|
120
|
+
console.log(`${colors.green}All tests passed!${colors.reset}`);
|
|
121
|
+
} else {
|
|
122
|
+
console.log(`${colors.yellow}${testsFailed} test(s) failed${colors.reset}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
runTests().then(() => {
|
|
127
|
+
process.exit(testsFailed > 0 ? 1 : 0);
|
|
128
|
+
}).catch((err) => {
|
|
129
|
+
console.log(`${colors.red}Fatal test error:${colors.reset} ${err.message}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
});
|
package/commands/managed-sync.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
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
|
-
}
|