squish-memory 0.9.2 → 1.0.0

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.
Files changed (208) hide show
  1. package/{.env.mcp → .env.mcp.example} +23 -0
  2. package/CHANGELOG.md +102 -0
  3. package/QUICK-START.md +10 -4
  4. package/README.md +73 -4
  5. package/config/plugin-manifest.json +152 -0
  6. package/config/plugin-manifest.schema.json +244 -0
  7. package/dist/algorithms/{merge/analytics → analytics}/token-estimator.d.ts +1 -1
  8. package/dist/algorithms/analytics/token-estimator.d.ts.map +1 -0
  9. package/dist/algorithms/{merge/analytics → analytics}/token-estimator.js +3 -3
  10. package/dist/algorithms/analytics/token-estimator.js.map +1 -0
  11. package/dist/algorithms/detection/hash-filters.d.ts.map +1 -0
  12. package/dist/algorithms/detection/hash-filters.js.map +1 -0
  13. package/dist/algorithms/{merge/detection → detection}/semantic-ranker.d.ts +1 -1
  14. package/dist/algorithms/detection/semantic-ranker.d.ts.map +1 -0
  15. package/dist/algorithms/{merge/detection → detection}/semantic-ranker.js +1 -1
  16. package/dist/algorithms/detection/semantic-ranker.js.map +1 -0
  17. package/dist/algorithms/{merge/detection → detection}/two-stage-detector.d.ts +1 -1
  18. package/dist/algorithms/detection/two-stage-detector.d.ts.map +1 -0
  19. package/dist/algorithms/{merge/detection → detection}/two-stage-detector.js +4 -4
  20. package/dist/algorithms/detection/two-stage-detector.js.map +1 -0
  21. package/dist/algorithms/handlers/approve-merge.d.ts.map +1 -0
  22. package/dist/algorithms/{merge/handlers → handlers}/approve-merge.js +4 -4
  23. package/dist/algorithms/handlers/approve-merge.js.map +1 -0
  24. package/dist/algorithms/{merge/handlers → handlers}/detect-duplicates.d.ts +1 -1
  25. package/dist/algorithms/handlers/detect-duplicates.d.ts.map +1 -0
  26. package/dist/algorithms/{merge/handlers → handlers}/detect-duplicates.js +55 -75
  27. package/dist/algorithms/handlers/detect-duplicates.js.map +1 -0
  28. package/dist/algorithms/handlers/get-stats.d.ts.map +1 -0
  29. package/dist/algorithms/{merge/handlers → handlers}/get-stats.js +3 -3
  30. package/dist/algorithms/handlers/get-stats.js.map +1 -0
  31. package/dist/algorithms/handlers/list-proposals.d.ts.map +1 -0
  32. package/dist/algorithms/{merge/handlers → handlers}/list-proposals.js +3 -3
  33. package/dist/algorithms/handlers/list-proposals.js.map +1 -0
  34. package/dist/algorithms/handlers/preview-merge.d.ts.map +1 -0
  35. package/dist/algorithms/{merge/handlers → handlers}/preview-merge.js +3 -3
  36. package/dist/algorithms/handlers/preview-merge.js.map +1 -0
  37. package/dist/algorithms/handlers/reject-merge.d.ts.map +1 -0
  38. package/dist/algorithms/{merge/handlers → handlers}/reject-merge.js +3 -3
  39. package/dist/algorithms/handlers/reject-merge.js.map +1 -0
  40. package/dist/algorithms/handlers/reverse-merge.d.ts.map +1 -0
  41. package/dist/algorithms/{merge/handlers → handlers}/reverse-merge.js +3 -3
  42. package/dist/algorithms/handlers/reverse-merge.js.map +1 -0
  43. package/dist/algorithms/{merge/safety → safety}/safety-checks.d.ts +1 -1
  44. package/dist/algorithms/safety/safety-checks.d.ts.map +1 -0
  45. package/dist/algorithms/safety/safety-checks.js +179 -0
  46. package/dist/algorithms/safety/safety-checks.js.map +1 -0
  47. package/dist/algorithms/{merge/strategies → strategies}/merge-strategies.d.ts +1 -1
  48. package/dist/algorithms/strategies/merge-strategies.d.ts.map +1 -0
  49. package/dist/algorithms/strategies/merge-strategies.js.map +1 -0
  50. package/dist/algorithms/utils/response-builder.d.ts +28 -0
  51. package/dist/algorithms/utils/response-builder.d.ts.map +1 -0
  52. package/dist/algorithms/utils/response-builder.js +37 -0
  53. package/dist/algorithms/utils/response-builder.js.map +1 -0
  54. package/dist/api/web/web.d.ts.map +1 -1
  55. package/dist/api/web/web.js +0 -21
  56. package/dist/api/web/web.js.map +1 -1
  57. package/dist/commands/mcp-server.js +1 -1
  58. package/dist/config.d.ts +9 -1
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +35 -32
  61. package/dist/config.js.map +1 -1
  62. package/dist/core/associations.js +2 -2
  63. package/dist/core/associations.js.map +1 -1
  64. package/dist/core/core-memory.d.ts +5 -0
  65. package/dist/core/core-memory.d.ts.map +1 -1
  66. package/dist/core/core-memory.js +17 -5
  67. package/dist/core/core-memory.js.map +1 -1
  68. package/dist/core/embeddings.d.ts +9 -0
  69. package/dist/core/embeddings.d.ts.map +1 -1
  70. package/dist/core/embeddings.js +153 -16
  71. package/dist/core/embeddings.js.map +1 -1
  72. package/dist/core/layers/generator.d.ts +25 -0
  73. package/dist/core/layers/generator.d.ts.map +1 -0
  74. package/dist/core/layers/generator.js +76 -0
  75. package/dist/core/layers/generator.js.map +1 -0
  76. package/dist/core/mcp/tools.d.ts.map +1 -1
  77. package/dist/core/mcp/tools.js +71 -0
  78. package/dist/core/mcp/tools.js.map +1 -1
  79. package/dist/core/memory/hybrid-retrieval.d.ts.map +1 -1
  80. package/dist/core/memory/hybrid-retrieval.js +49 -1
  81. package/dist/core/memory/hybrid-retrieval.js.map +1 -1
  82. package/dist/core/memory/hybrid-search.d.ts.map +1 -1
  83. package/dist/core/memory/hybrid-search.js +0 -7
  84. package/dist/core/memory/hybrid-search.js.map +1 -1
  85. package/dist/core/memory/memories.d.ts.map +1 -1
  86. package/dist/core/memory/memories.js +47 -53
  87. package/dist/core/memory/memories.js.map +1 -1
  88. package/dist/core/memory/progressive-disclosure.d.ts.map +1 -1
  89. package/dist/core/memory/progressive-disclosure.js.map +1 -1
  90. package/dist/core/namespaces/index.d.ts +71 -0
  91. package/dist/core/namespaces/index.d.ts.map +1 -0
  92. package/dist/core/namespaces/index.js +296 -0
  93. package/dist/core/namespaces/index.js.map +1 -0
  94. package/dist/core/namespaces/uri-parser.d.ts +31 -0
  95. package/dist/core/namespaces/uri-parser.d.ts.map +1 -0
  96. package/dist/core/namespaces/uri-parser.js +74 -0
  97. package/dist/core/namespaces/uri-parser.js.map +1 -0
  98. package/dist/core/observations.d.ts.map +1 -1
  99. package/dist/core/observations.js +3 -12
  100. package/dist/core/observations.js.map +1 -1
  101. package/dist/core/projects.d.ts.map +1 -1
  102. package/dist/core/projects.js +0 -12
  103. package/dist/core/projects.js.map +1 -1
  104. package/dist/core/scheduler/cron-scheduler.d.ts.map +1 -1
  105. package/dist/core/scheduler/cron-scheduler.js +14 -0
  106. package/dist/core/scheduler/cron-scheduler.js.map +1 -1
  107. package/dist/core/session-hooks/self-iteration-job.d.ts +20 -0
  108. package/dist/core/session-hooks/self-iteration-job.d.ts.map +1 -0
  109. package/dist/core/session-hooks/self-iteration-job.js +278 -0
  110. package/dist/core/session-hooks/self-iteration-job.js.map +1 -0
  111. package/dist/core/session-hooks/session-hooks.d.ts +18 -0
  112. package/dist/core/session-hooks/session-hooks.d.ts.map +1 -0
  113. package/dist/core/session-hooks/session-hooks.js +55 -0
  114. package/dist/core/session-hooks/session-hooks.js.map +1 -0
  115. package/dist/core/tracing/collector.d.ts +111 -0
  116. package/dist/core/tracing/collector.d.ts.map +1 -0
  117. package/dist/core/tracing/collector.js +338 -0
  118. package/dist/core/tracing/collector.js.map +1 -0
  119. package/dist/core/tracing/visualizer.d.ts +32 -0
  120. package/dist/core/tracing/visualizer.d.ts.map +1 -0
  121. package/dist/core/tracing/visualizer.js +165 -0
  122. package/dist/core/tracing/visualizer.js.map +1 -0
  123. package/dist/db/bootstrap.d.ts.map +1 -1
  124. package/dist/db/bootstrap.js +33 -6
  125. package/dist/db/bootstrap.js.map +1 -1
  126. package/dist/drizzle/schema-sqlite.d.ts +401 -0
  127. package/dist/drizzle/schema-sqlite.d.ts.map +1 -1
  128. package/dist/drizzle/schema-sqlite.js +66 -0
  129. package/dist/drizzle/schema-sqlite.js.map +1 -1
  130. package/dist/drizzle/schema.d.ts +385 -0
  131. package/dist/drizzle/schema.d.ts.map +1 -1
  132. package/dist/drizzle/schema.js +64 -0
  133. package/dist/drizzle/schema.js.map +1 -1
  134. package/dist/index.d.ts +4 -4
  135. package/dist/index.js +101 -62
  136. package/dist/index.js.map +1 -1
  137. package/generated/mcp/manifest.json +23 -0
  138. package/generated/mcp/mcp-servers.json +25 -0
  139. package/generated/mcp/mcporter.json +34 -0
  140. package/generated/mcp/openclaw-memory-qmd.json +17 -0
  141. package/generated/mcp/runtime.json +12 -0
  142. package/package.json +68 -26
  143. package/packages/plugin-claude-code/README.md +73 -0
  144. package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts +35 -0
  145. package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts.map +1 -0
  146. package/packages/plugin-claude-code/dist/plugin-wrapper.js +191 -0
  147. package/packages/plugin-claude-code/dist/plugin-wrapper.js.map +1 -0
  148. package/packages/plugin-claude-code/package.json +31 -0
  149. package/packages/plugin-openclaw/README.md +70 -0
  150. package/packages/plugin-openclaw/dist/index.d.ts +49 -0
  151. package/packages/plugin-openclaw/dist/index.d.ts.map +1 -0
  152. package/packages/plugin-openclaw/dist/index.js +262 -0
  153. package/packages/plugin-openclaw/dist/index.js.map +1 -0
  154. package/packages/plugin-openclaw/openclaw.plugin.json +94 -0
  155. package/packages/plugin-openclaw/package.json +31 -0
  156. package/packages/plugin-opencode/install.mjs +217 -0
  157. package/packages/plugin-opencode/package.json +21 -0
  158. package/scripts/build-release.sh +20 -17
  159. package/scripts/check-secrets.js +132 -0
  160. package/scripts/dependency-manager.mjs +217 -0
  161. package/scripts/detect-clients.mjs +78 -0
  162. package/scripts/github-release.sh +43 -27
  163. package/scripts/install-interactive.mjs +674 -0
  164. package/scripts/install-plugin.mjs +415 -0
  165. package/scripts/test-interactive.mjs +131 -0
  166. package/commands/managed-sync.ts +0 -69
  167. package/commands/mcp-server.ts +0 -519
  168. package/dist/algorithms/merge/analytics/token-estimator.d.ts.map +0 -1
  169. package/dist/algorithms/merge/analytics/token-estimator.js.map +0 -1
  170. package/dist/algorithms/merge/detection/hash-filters.d.ts.map +0 -1
  171. package/dist/algorithms/merge/detection/hash-filters.js.map +0 -1
  172. package/dist/algorithms/merge/detection/semantic-ranker.d.ts.map +0 -1
  173. package/dist/algorithms/merge/detection/semantic-ranker.js.map +0 -1
  174. package/dist/algorithms/merge/detection/two-stage-detector.d.ts.map +0 -1
  175. package/dist/algorithms/merge/detection/two-stage-detector.js.map +0 -1
  176. package/dist/algorithms/merge/handlers/approve-merge.d.ts.map +0 -1
  177. package/dist/algorithms/merge/handlers/approve-merge.js.map +0 -1
  178. package/dist/algorithms/merge/handlers/detect-duplicates.d.ts.map +0 -1
  179. package/dist/algorithms/merge/handlers/detect-duplicates.js.map +0 -1
  180. package/dist/algorithms/merge/handlers/get-stats.d.ts.map +0 -1
  181. package/dist/algorithms/merge/handlers/get-stats.js.map +0 -1
  182. package/dist/algorithms/merge/handlers/list-proposals.d.ts.map +0 -1
  183. package/dist/algorithms/merge/handlers/list-proposals.js.map +0 -1
  184. package/dist/algorithms/merge/handlers/preview-merge.d.ts.map +0 -1
  185. package/dist/algorithms/merge/handlers/preview-merge.js.map +0 -1
  186. package/dist/algorithms/merge/handlers/reject-merge.d.ts.map +0 -1
  187. package/dist/algorithms/merge/handlers/reject-merge.js.map +0 -1
  188. package/dist/algorithms/merge/handlers/reverse-merge.d.ts.map +0 -1
  189. package/dist/algorithms/merge/handlers/reverse-merge.js.map +0 -1
  190. package/dist/algorithms/merge/safety/safety-checks.d.ts.map +0 -1
  191. package/dist/algorithms/merge/safety/safety-checks.js +0 -215
  192. package/dist/algorithms/merge/safety/safety-checks.js.map +0 -1
  193. package/dist/algorithms/merge/strategies/merge-strategies.d.ts.map +0 -1
  194. package/dist/algorithms/merge/strategies/merge-strategies.js.map +0 -1
  195. package/dist/core/embeddings/qmd-provider.d.ts +0 -65
  196. package/dist/core/embeddings/qmd-provider.d.ts.map +0 -1
  197. package/dist/core/embeddings/qmd-provider.js +0 -133
  198. package/dist/core/embeddings/qmd-provider.js.map +0 -1
  199. package/scripts/init-dirs.ts +0 -15
  200. /package/dist/algorithms/{merge/detection → detection}/hash-filters.d.ts +0 -0
  201. /package/dist/algorithms/{merge/detection → detection}/hash-filters.js +0 -0
  202. /package/dist/algorithms/{merge/handlers → handlers}/approve-merge.d.ts +0 -0
  203. /package/dist/algorithms/{merge/handlers → handlers}/get-stats.d.ts +0 -0
  204. /package/dist/algorithms/{merge/handlers → handlers}/list-proposals.d.ts +0 -0
  205. /package/dist/algorithms/{merge/handlers → handlers}/preview-merge.d.ts +0 -0
  206. /package/dist/algorithms/{merge/handlers → handlers}/reject-merge.d.ts +0 -0
  207. /package/dist/algorithms/{merge/handlers → handlers}/reverse-merge.d.ts +0 -0
  208. /package/dist/algorithms/{merge/strategies → strategies}/merge-strategies.js +0 -0
@@ -0,0 +1,94 @@
1
+ {
2
+ "id": "squish-memory-openclaw",
3
+ "name": "Squish Memory for OpenClaw",
4
+ "description": "Connect OpenClaw to Squish memory system via MCP",
5
+ "version": "1.0.0",
6
+ "pluginApiVersion": "1.0.0",
7
+ "author": "michielhdoteth",
8
+ "license": "MIT",
9
+ "homepage": "https://github.com/michielhdoteth/squish",
10
+ "slot": "memory",
11
+ "tools": [
12
+ {
13
+ "name": "memory_search",
14
+ "description": "Search memories using Squish hybrid search",
15
+ "parameters": {
16
+ "type": "object",
17
+ "properties": {
18
+ "query": {
19
+ "type": "string",
20
+ "description": "Search query"
21
+ },
22
+ "maxResults": {
23
+ "type": "number",
24
+ "description": "Maximum results to return",
25
+ "default": 6
26
+ },
27
+ "project": {
28
+ "type": "string",
29
+ "description": "Project path to scope search"
30
+ }
31
+ },
32
+ "required": ["query"]
33
+ }
34
+ },
35
+ {
36
+ "name": "memory_get",
37
+ "description": "Get memory content by URI or ID",
38
+ "parameters": {
39
+ "type": "object",
40
+ "properties": {
41
+ "uri": {
42
+ "type": "string",
43
+ "description": "Memory URI (e.g., squish://memory/<id>) or file path"
44
+ },
45
+ "lineRange": {
46
+ "type": "array",
47
+ "items": { "type": "number" },
48
+ "minItems": 2,
49
+ "maxItems": 2,
50
+ "description": "Line range [start, end]"
51
+ },
52
+ "overview": {
53
+ "type": "boolean",
54
+ "description": "Get overview instead of full content",
55
+ "default": false
56
+ }
57
+ },
58
+ "required": ["uri"]
59
+ }
60
+ }
61
+ ],
62
+ "config": {
63
+ "baseUrl": {
64
+ "type": "string",
65
+ "default": "http://127.0.0.1:8767",
66
+ "description": "Squish MCP server URL"
67
+ },
68
+ "autoStart": {
69
+ "type": "boolean",
70
+ "default": false,
71
+ "description": "Auto-start Squish MCP server if not running"
72
+ },
73
+ "sync": {
74
+ "type": "object",
75
+ "properties": {
76
+ "enabled": {
77
+ "type": "boolean",
78
+ "default": true
79
+ },
80
+ "interval": {
81
+ "type": "string",
82
+ "default": "5m",
83
+ "description": "Sync interval (e.g., 5m, 1h)"
84
+ },
85
+ "extraPaths": {
86
+ "type": "array",
87
+ "items": { "type": "string" },
88
+ "default": ["notes", "docs/memory"],
89
+ "description": "Extra directories to sync"
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@squish/memory-openclaw",
3
+ "version": "1.0.0",
4
+ "description": "OpenClaw memory plugin for Squish - provides memory_search and memory_get tools via Squish MCP",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "bun --hot src/index.ts",
10
+ "prepublishOnly": "npm run clean && npm run build",
11
+ "prepare": "npm run build",
12
+ "clean": "rm -rf dist"
13
+ },
14
+ "keywords": ["openclaw", "plugin", "memory", "mcp", "squish"],
15
+ "author": "michielhdoteth",
16
+ "license": "MIT",
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.27.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.0.0",
22
+ "typescript": "^5.7.0",
23
+ "vitest": "^4.0.17"
24
+ },
25
+ "peerDependencies": {
26
+ "squish-memory": ">=1.0.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ }
31
+ }
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * OpenCode Plugin Installer for Squish
5
+ * Auto-installs CLI + configures OpenCode to use Squish as MCP server
6
+ */
7
+
8
+ import fs from "node:fs";
9
+ import path from "node:path";
10
+ import os from "node:os";
11
+ import { spawnSync } from "node:child_process";
12
+
13
+ const CONFIG_DIR = path.join(os.homedir(), ".config", "opencode");
14
+ const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
15
+
16
+ const OPENCODE_SCHEMA = "https://opencode.ai/config.json";
17
+
18
+ function ensureDir(dirPath) {
19
+ if (!fs.existsSync(dirPath)) {
20
+ fs.mkdirSync(dirPath, { recursive: true });
21
+ }
22
+ }
23
+
24
+ function getSquishMcpConfig() {
25
+ return {
26
+ type: "local",
27
+ command: ["squish-mcp"],
28
+ enabled: true,
29
+ environment: {}
30
+ };
31
+ }
32
+
33
+ function loadOpenCodeConfig() {
34
+ if (!fs.existsSync(CONFIG_PATH)) {
35
+ return null;
36
+ }
37
+
38
+ try {
39
+ const content = fs.readFileSync(CONFIG_PATH, "utf8");
40
+ return JSON.parse(content);
41
+ } catch (error) {
42
+ console.error(`[ERROR] Failed to parse OpenCode config: ${error.message}`);
43
+ return null;
44
+ }
45
+ }
46
+
47
+ function saveOpenCodeConfig(config) {
48
+ ensureDir(CONFIG_DIR);
49
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
50
+ }
51
+
52
+ function createNewConfig() {
53
+ return {
54
+ $schema: OPENCODE_SCHEMA,
55
+ mcp: {
56
+ squish: getSquishMcpConfig()
57
+ }
58
+ };
59
+ }
60
+
61
+ function installForOpenCode(options = {}) {
62
+ console.log("[INSTALL] Installing Squish for OpenCode...");
63
+
64
+ let config = loadOpenCodeConfig();
65
+ let created = false;
66
+
67
+ if (!config) {
68
+ if (options.dryRun) {
69
+ console.log("[DRY-RUN] Would create new OpenCode config at:", CONFIG_PATH);
70
+ return true;
71
+ }
72
+
73
+ config = createNewConfig();
74
+ created = true;
75
+ console.log("[INSTALL] Created new OpenCode config");
76
+ } else {
77
+ if (options.dryRun) {
78
+ console.log("[DRY-RUN] Would update existing OpenCode config at:", CONFIG_PATH);
79
+ return true;
80
+ }
81
+
82
+ // Ensure mcp section exists
83
+ if (!config.mcp) {
84
+ config.mcp = {};
85
+ }
86
+
87
+ // Add or update squish MCP config
88
+ config.mcp.squish = getSquishMcpConfig();
89
+ console.log("[INSTALL] Updated existing OpenCode config");
90
+ }
91
+
92
+ saveOpenCodeConfig(config);
93
+ console.log(`[INSTALL] ${created ? 'Created' : 'Updated'}: ${CONFIG_PATH}`);
94
+
95
+ return true;
96
+ }
97
+
98
+ function uninstallForOpenCode(options = {}) {
99
+ console.log("[UNINSTALL] Removing Squish from OpenCode...");
100
+
101
+ const config = loadOpenCodeConfig();
102
+ if (!config) {
103
+ console.log("[UNINSTALL] No OpenCode config found");
104
+ return true;
105
+ }
106
+
107
+ if (!config.mcp || !config.mcp.squish) {
108
+ console.log("[UNINSTALL] Squish not found in OpenCode config");
109
+ return true;
110
+ }
111
+
112
+ if (options.dryRun) {
113
+ console.log("[DRY-RUN] Would remove Squish from OpenCode config");
114
+ return true;
115
+ }
116
+
117
+ delete config.mcp.squish;
118
+
119
+ // Clean up empty mcp section
120
+ if (Object.keys(config.mcp).length === 0) {
121
+ delete config.mcp;
122
+ }
123
+
124
+ saveOpenCodeConfig(config);
125
+ console.log("[UNINSTALL] Removed Squish from OpenCode config");
126
+
127
+ return true;
128
+ }
129
+
130
+ function verifyOpenCodeInstallation() {
131
+ console.log("[VERIFY] Checking OpenCode installation...");
132
+
133
+ const config = loadOpenCodeConfig();
134
+ if (!config) {
135
+ return { ok: false, error: "OpenCode config not found" };
136
+ }
137
+
138
+ if (!config.mcp || !config.mcp.squish) {
139
+ return { ok: false, error: "Squish MCP not configured" };
140
+ }
141
+
142
+ const squishConfig = config.mcp.squish;
143
+
144
+ if (squishConfig.type !== "local") {
145
+ return { ok: false, error: `Expected type 'local', got '${squishConfig.type}'` };
146
+ }
147
+
148
+ if (!squishConfig.enabled) {
149
+ return { ok: false, error: "Squish MCP is disabled" };
150
+ }
151
+
152
+ // Check if squish-mcp command is available
153
+ const result = spawnSync("which", ["squish-mcp"], { encoding: "utf8", shell: true });
154
+ if (result.status !== 0) {
155
+ return { ok: false, error: "squish-mcp command not found in PATH" };
156
+ }
157
+
158
+ console.log("[VERIFY] OpenCode config:", CONFIG_PATH);
159
+ console.log("[VERIFY] Squish MCP configured:", squishConfig.command.join(" "));
160
+ console.log("[VERIFY] Status: enabled");
161
+
162
+ return { ok: true, message: "OpenCode installation verified" };
163
+ }
164
+
165
+ function main() {
166
+ const args = process.argv.slice(2);
167
+ const options = {
168
+ dryRun: args.includes("--dry-run") || args.includes("-d"),
169
+ uninstall: args.includes("--uninstall") || args.includes("-u"),
170
+ verify: args.includes("--verify") || args.includes("-v")
171
+ };
172
+
173
+ console.log("[OpenCode Plugin for Squish]");
174
+ console.log();
175
+
176
+ try {
177
+ if (options.verify) {
178
+ const result = verifyOpenCodeInstallation();
179
+ if (result.ok) {
180
+ console.log("\n[VERIFY] " + result.message);
181
+ process.exit(0);
182
+ } else {
183
+ console.error("\n[VERIFY] Failed:", result.error);
184
+ process.exit(1);
185
+ }
186
+ }
187
+
188
+ if (options.uninstall) {
189
+ const success = uninstallForOpenCode(options);
190
+ process.exit(success ? 0 : 1);
191
+ }
192
+
193
+ const success = installForOpenCode(options);
194
+
195
+ if (success && !options.dryRun) {
196
+ const verify = verifyOpenCodeInstallation();
197
+ if (verify.ok) {
198
+ console.log("\n[SUCCESS] OpenCode plugin installed successfully!");
199
+ console.log("\nTo use Squish in OpenCode:");
200
+ console.log(" 1. Restart OpenCode if it's running");
201
+ console.log(" 2. Start a conversation and ask about memories");
202
+ console.log(" 3. Or explicitly: 'use the squish tool to search for...'");
203
+ } else {
204
+ console.error("\n[WARNING] Installation succeeded but verification failed:");
205
+ console.error(" ", verify.error);
206
+ }
207
+ }
208
+
209
+ process.exit(success ? 0 : 1);
210
+
211
+ } catch (error) {
212
+ console.error("[ERROR]", error.message);
213
+ process.exit(1);
214
+ }
215
+ }
216
+
217
+ main();
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@squish/plugin-opencode",
3
+ "version": "1.0.0",
4
+ "description": "OpenCode plugin for Squish - auto-installs CLI and configures OpenCode to use Squish as MCP server",
5
+ "main": "install.mjs",
6
+ "type": "module",
7
+ "scripts": {
8
+ "install": "node install.mjs",
9
+ "verify": "node install.mjs --verify",
10
+ "uninstall": "node install.mjs --uninstall"
11
+ },
12
+ "keywords": ["opencode", "plugin", "memory", "mcp", "squish"],
13
+ "author": "michielhdoteth",
14
+ "license": "MIT",
15
+ "peerDependencies": {
16
+ "squish-memory": ">=1.0.0"
17
+ },
18
+ "engines": {
19
+ "node": ">=18.0.0"
20
+ }
21
+ }
@@ -5,29 +5,32 @@
5
5
 
6
6
  set -e
7
7
 
8
- echo "🔨 Building Squish v0.3.0..."
8
+ # Auto-detect version from package.json
9
+ VERSION=$(node -p "require('./package.json').version")
10
+ echo "Building Squish v$VERSION..."
9
11
 
10
12
  # Clean previous builds
11
13
  npm run clean
12
14
 
13
- # Build the project (core only, merge system disabled)
14
- echo "Building core functionality..."
15
- npx tsc index.ts --outDir dist --skipLibCheck --esModuleInterop --module commonjs
16
- npx tsc features/web/web.ts --outDir dist/features/web --skipLibCheck --esModuleInterop --module commonjs
17
- npx tsc features/web/web-server.ts --outDir dist/features/web --skipLibCheck --esModuleInterop --module commonjs
15
+ # Build the project using standard build script
16
+ echo "Building project..."
17
+ npm run build
18
18
 
19
- # Rename to .js extension for CommonJS
20
- mv dist/features/web/web-server.js dist/features/web/web-server.cjs 2>/dev/null || true
19
+ # Verify MCP artifacts are generated
20
+ echo "🔨 Generating MCP artifacts..."
21
+ node scripts/generate-mcp.mjs
21
22
 
22
- echo "✅ Build complete!"
23
+ # Verify MCP artifacts
24
+ echo "🧪 Verifying MCP artifacts..."
25
+ node scripts/verify-mcp.mjs
23
26
 
24
- # Test the build
25
- echo "🧪 Testing build..."
26
- timeout 5 node dist/index.js &
27
- sleep 2
28
- curl -s http://localhost:37777/api/health | grep -q "ok" && echo "✅ API working" || echo "❌ API failed"
27
+ echo "Build complete!"
29
28
 
30
- # Kill test server
31
- pkill -f "node dist/index.js" || true
29
+ # Optional: Test the build (uncomment if needed)
30
+ # echo "🧪 Testing build..."
31
+ # timeout 5 node dist/index.js &
32
+ # sleep 2
33
+ # curl -s http://localhost:37777/api/health | grep -q "ok" && echo "✅ API working" || echo "❌ API failed"
34
+ # pkill -f "node dist/index.js" || true
32
35
 
33
- echo "🎉 Ready for release!"
36
+ echo "Ready for release!"
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Secret Scanner - Checks for accidentally committed secrets
5
+ * Run this before committing or use the pre-commit hook
6
+ *
7
+ * Usage: node scripts/check-secrets.js
8
+ */
9
+
10
+ import { execSync } from 'child_process';
11
+ import { existsSync, readFileSync } from 'fs';
12
+
13
+ // Common secret patterns
14
+ const SECRET_PATTERNS = [
15
+ // API Keys
16
+ { pattern: /(sk|sg)-[0-9a-zA-Z]{24,}/gi, name: 'Stripe/General API Key' },
17
+ { pattern: /AIza[0-9A-Za-z\\-_]{35}/gi, name: 'Google API Key' },
18
+ { pattern: /xox[baprs]-[0-9a-zA-Z-]{10,}/gi, name: 'Slack Token' },
19
+ { pattern: /xox[baprs]-[0-9a-zA-Z-]{10,}/gi, name: 'Slack Token' },
20
+ { pattern: /ghp_[0-9a-zA-Z]{36}/gi, name: 'GitHub Personal Access Token' },
21
+ { pattern: /github_pat_[0-9a-zA-Z]{22}_[0-9a-zA-Z]{59}/gi, name: 'GitHub Fine-grained Token' },
22
+ { pattern: /Bearer\s+[A-Za-z0-9\-_]+/gi, name: 'Bearer Token' },
23
+ { pattern: /Authorization:\s*Bearer\s+[A-Za-z0-9\-_]+/gi, name: 'Authorization Header' },
24
+ { pattern: /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/gi, name: 'JWT Token' },
25
+
26
+ // AWS
27
+ { pattern: /(?:A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}/gi, name: 'AWS Access Key' },
28
+ { pattern: /(?:\")?aws_access_key_id(?:\\s*:\\s*\")([A-Z0-9]{20})(?:\"|$)/gi, name: 'AWS Access Key ID' },
29
+ { pattern: /(?:\")?aws_secret_access_key(?:\\s*:\\s*\")([A-Za-z0-9/+=]{40})(?:\"|$)/gi, name: 'AWS Secret Access Key' },
30
+
31
+ // Database
32
+ { pattern: /(?:mongodb|mysql|postgres|postgresql|redis):\/\/[^\s]+:[^\s]+@/gi, name: 'Database Connection String' },
33
+ { pattern: /(?:password|passwd|pwd)\s*[=:]\s*['"]?[^'"]{8,}['"]?/gi, name: 'Password in config' },
34
+
35
+ // .env specific
36
+ { pattern: /^[A-Z_]+=sk-|^[A-Z_]+=AIza/gi, name: 'API Key in .env format' },
37
+ ];
38
+
39
+ // File extensions to check
40
+ const TEXT_EXTENSIONS = [
41
+ '.ts', '.js', '.json', '.md', '.txt', '.yml', '.yaml', '.toml',
42
+ '.sh', '.bash', '.zsh', '.ini', '.cfg', '.conf', '.env', '.env.local'
43
+ ];
44
+
45
+ function isTextFile(filePath) {
46
+ return TEXT_EXTENSIONS.some(ext => filePath.endsWith(ext)) || filePath.includes('.env');
47
+ }
48
+
49
+ function getStagedFiles() {
50
+ try {
51
+ const output = execSync('git diff --cached --name-only', { encoding: 'utf-8' });
52
+ return output.split('\n').filter(f => f.trim());
53
+ } catch (error) {
54
+ console.error('Failed to get staged files:', error.message);
55
+ return [];
56
+ }
57
+ }
58
+
59
+ function readFileContent(filePath) {
60
+ try {
61
+ return readFileSync(filePath, 'utf-8');
62
+ } catch (error) {
63
+ // File may have been removed or unreadable
64
+ return '';
65
+ }
66
+ }
67
+
68
+ function scanContent(content, filePath) {
69
+ const findings = [];
70
+
71
+ for (const { pattern, name } of SECRET_PATTERNS) {
72
+ let match;
73
+ const regex = new RegExp(pattern);
74
+ while ((match = regex.exec(content)) !== null) {
75
+ const lineNumber = content.substring(0, match.index).split('\n').length;
76
+ findings.push({
77
+ file: filePath,
78
+ line: lineNumber,
79
+ type: name,
80
+ value: maskSecret(match[0]),
81
+ });
82
+ }
83
+ }
84
+
85
+ return findings;
86
+ }
87
+
88
+ function maskSecret(secret) {
89
+ if (secret.length <= 8) return '***';
90
+ return secret.substring(0, 6) + '...' + secret.substring(secret.length - 4);
91
+ }
92
+
93
+ function main() {
94
+ console.log('🔍 Scanning for secrets...\n');
95
+
96
+ const stagedFiles = getStagedFiles();
97
+ const textFiles = stagedFiles.filter(isTextFile);
98
+
99
+ if (textFiles.length === 0) {
100
+ console.log('No text files to scan.');
101
+ process.exit(0);
102
+ }
103
+
104
+ let totalFindings = 0;
105
+
106
+ for (const file of textFiles) {
107
+ const content = readFileContent(file);
108
+ if (!content) continue;
109
+
110
+ const findings = scanContent(content, file);
111
+ if (findings.length > 0) {
112
+ console.log(`❌ ${file}:`);
113
+ for (const finding of findings) {
114
+ console.log(` Line ${finding.line}: ${finding.type} - ${finding.value}`);
115
+ totalFindings++;
116
+ }
117
+ console.log('');
118
+ }
119
+ }
120
+
121
+ if (totalFindings > 0) {
122
+ console.log(`\n🚨 Found ${totalFindings} potential secret(s).`);
123
+ console.log(' Please remove these before committing!');
124
+ console.log(' Use environment variables or a secret manager instead.\n');
125
+ process.exit(1);
126
+ } else {
127
+ console.log('✅ No secrets detected.\n');
128
+ process.exit(0);
129
+ }
130
+ }
131
+
132
+ main();