@wipcomputer/memory-crystal 0.7.30 → 0.7.32

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 (211) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/SKILL.md +1 -1
  3. package/package.json +1 -1
  4. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/.env.example +0 -20
  5. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/.publish-skill.json +0 -1
  6. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/CHANGELOG.md +0 -1297
  7. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/CLA.md +0 -19
  8. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/LICENSE +0 -52
  9. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/README-ENTERPRISE.md +0 -226
  10. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/README.md +0 -151
  11. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/RELAY.md +0 -199
  12. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/SKILL.md +0 -462
  13. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/TECHNICAL.md +0 -656
  14. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-23.md +0 -48
  15. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-25.md +0 -24
  16. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-26.md +0 -7
  17. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-28.md +0 -31
  18. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-29.md +0 -28
  19. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-4.md +0 -64
  20. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/_trash/RELEASE-NOTES-v0-7-5.md +0 -19
  21. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/cloud/README.md +0 -116
  22. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/cloud/docs/gpt-system-instructions.md +0 -69
  23. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/cloud/migrations/0001_init.sql +0 -52
  24. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/migrations/0001_init.sql +0 -51
  25. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/migrations/0002_cloud_storage.sql +0 -49
  26. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/openclaw.plugin.json +0 -11
  27. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/package-lock.json +0 -4169
  28. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/package.json +0 -61
  29. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/scripts/crystal-capture.sh +0 -29
  30. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/scripts/deploy-cloud.sh +0 -153
  31. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/scripts/ldm-backup.sh +0 -116
  32. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/scripts/migrate-lance-to-sqlite.mjs +0 -218
  33. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/skills/memory/SKILL.md +0 -438
  34. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/wrangler-demo.toml +0 -8
  35. package/.worktrees/memory-crystal-private--cc-mini-fix-home-fallback/wrangler-mcp.toml +0 -24
  36. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/.env.example +0 -20
  37. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/.publish-skill.json +0 -1
  38. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/CHANGELOG.md +0 -1297
  39. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/CLA.md +0 -19
  40. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/LICENSE +0 -52
  41. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/README-ENTERPRISE.md +0 -226
  42. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/README.md +0 -151
  43. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/RELAY.md +0 -199
  44. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/RELEASE-NOTES-v0.7.30.md +0 -29
  45. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/SKILL.md +0 -462
  46. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/TECHNICAL.md +0 -656
  47. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-23.md +0 -48
  48. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-25.md +0 -24
  49. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-26.md +0 -7
  50. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-28.md +0 -31
  51. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-29.md +0 -28
  52. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-4.md +0 -64
  53. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/_trash/RELEASE-NOTES-v0-7-5.md +0 -19
  54. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/cloud/README.md +0 -116
  55. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/cloud/docs/gpt-system-instructions.md +0 -69
  56. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/cloud/migrations/0001_init.sql +0 -52
  57. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/migrations/0001_init.sql +0 -51
  58. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/migrations/0002_cloud_storage.sql +0 -49
  59. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/openclaw.plugin.json +0 -11
  60. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/package-lock.json +0 -4169
  61. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/package.json +0 -61
  62. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/scripts/crystal-capture.sh +0 -29
  63. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/scripts/deploy-cloud.sh +0 -153
  64. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/scripts/ldm-backup.sh +0 -116
  65. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/scripts/migrate-lance-to-sqlite.mjs +0 -218
  66. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/skills/memory/SKILL.md +0 -438
  67. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/wrangler-demo.toml +0 -8
  68. package/.worktrees/memory-crystal-private--cc-mini-release-notes-v0.7.30/wrangler-mcp.toml +0 -24
  69. package/_trash/RELEASE-NOTES-v0-7-23.md +0 -48
  70. package/_trash/RELEASE-NOTES-v0-7-25.md +0 -24
  71. package/_trash/RELEASE-NOTES-v0-7-26.md +0 -7
  72. package/_trash/RELEASE-NOTES-v0-7-28.md +0 -31
  73. package/_trash/RELEASE-NOTES-v0-7-29.md +0 -28
  74. package/_trash/RELEASE-NOTES-v0-7-4.md +0 -64
  75. package/_trash/RELEASE-NOTES-v0-7-5.md +0 -19
  76. package/_trash/RELEASE-NOTES-v0.7.30.md +0 -29
  77. package/dist/bridge.d.ts +0 -7
  78. package/dist/bridge.js +0 -14
  79. package/dist/bulk-copy.d.ts +0 -17
  80. package/dist/bulk-copy.js +0 -90
  81. package/dist/cc-hook.d.ts +0 -8
  82. package/dist/cc-hook.js +0 -368
  83. package/dist/cc-poller.d.ts +0 -1
  84. package/dist/cc-poller.js +0 -550
  85. package/dist/chunk-25LXQJ4Z.js +0 -110
  86. package/dist/chunk-2DRXIRQW.js +0 -97
  87. package/dist/chunk-2ZNH5F6E.js +0 -1281
  88. package/dist/chunk-3G3SFYYI.js +0 -288
  89. package/dist/chunk-3RG5ZIWI.js +0 -10
  90. package/dist/chunk-3S6TI23B.js +0 -97
  91. package/dist/chunk-3VFIJYS4.js +0 -818
  92. package/dist/chunk-52QE3YI3.js +0 -1169
  93. package/dist/chunk-57RP3DIN.js +0 -1205
  94. package/dist/chunk-5HSZ4W2P.js +0 -62
  95. package/dist/chunk-645IPXW3.js +0 -290
  96. package/dist/chunk-7A7ELD4C.js +0 -1205
  97. package/dist/chunk-7FYY4GZM.js +0 -1205
  98. package/dist/chunk-7IUE7ODU.js +0 -254
  99. package/dist/chunk-7RMLKZIS.js +0 -108
  100. package/dist/chunk-AA3OPP4Z.js +0 -432
  101. package/dist/chunk-AEWLSYPH.js +0 -72
  102. package/dist/chunk-ASSZDR6I.js +0 -108
  103. package/dist/chunk-AYRJVWUC.js +0 -1205
  104. package/dist/chunk-CCYI5O3D.js +0 -148
  105. package/dist/chunk-D3I3ZSE2.js +0 -411
  106. package/dist/chunk-DACSKLY6.js +0 -219
  107. package/dist/chunk-DW5B4BL7.js +0 -108
  108. package/dist/chunk-EKSACBTJ.js +0 -1070
  109. package/dist/chunk-EXEZZADG.js +0 -248
  110. package/dist/chunk-F3Y7EL7K.js +0 -83
  111. package/dist/chunk-FBQWSDPC.js +0 -1328
  112. package/dist/chunk-FHRZNOMW.js +0 -1205
  113. package/dist/chunk-IM7N24MT.js +0 -129
  114. package/dist/chunk-IPNYIXFK.js +0 -1178
  115. package/dist/chunk-J7MRSZIO.js +0 -167
  116. package/dist/chunk-JITKI2OI.js +0 -106
  117. package/dist/chunk-JWZXYVET.js +0 -1068
  118. package/dist/chunk-KCQUXVYT.js +0 -108
  119. package/dist/chunk-KOQ43OX6.js +0 -1281
  120. package/dist/chunk-KYVWO6ZM.js +0 -1069
  121. package/dist/chunk-L3VHARQH.js +0 -413
  122. package/dist/chunk-LBWDS6BE.js +0 -288
  123. package/dist/chunk-LOVAHSQV.js +0 -411
  124. package/dist/chunk-LQOYCAGG.js +0 -446
  125. package/dist/chunk-LWAIPJ2W.js +0 -146
  126. package/dist/chunk-M5DHKW7M.js +0 -127
  127. package/dist/chunk-MBKCIJHM.js +0 -1328
  128. package/dist/chunk-MK42FMEG.js +0 -147
  129. package/dist/chunk-MOBMYHKL.js +0 -1205
  130. package/dist/chunk-MPLTNMRG.js +0 -67
  131. package/dist/chunk-NIJCVN3O.js +0 -147
  132. package/dist/chunk-NZCFSZQ7.js +0 -1205
  133. package/dist/chunk-O2UITJGH.js +0 -465
  134. package/dist/chunk-OCRA44AZ.js +0 -108
  135. package/dist/chunk-P3KJR66H.js +0 -117
  136. package/dist/chunk-PEK6JH65.js +0 -432
  137. package/dist/chunk-PJ6FFKEX.js +0 -77
  138. package/dist/chunk-PLUBBZYR.js +0 -800
  139. package/dist/chunk-PNKVD2UK.js +0 -26
  140. package/dist/chunk-PSQZURHO.js +0 -229
  141. package/dist/chunk-SGL6ISBJ.js +0 -1061
  142. package/dist/chunk-SJABZZT5.js +0 -97
  143. package/dist/chunk-TD3P3K32.js +0 -1199
  144. package/dist/chunk-TMDZJJKV.js +0 -288
  145. package/dist/chunk-UNHVZB5G.js +0 -411
  146. package/dist/chunk-VAFTWSTE.js +0 -1061
  147. package/dist/chunk-VNFXFQBB.js +0 -217
  148. package/dist/chunk-X3GVFKSJ.js +0 -1205
  149. package/dist/chunk-XZ3S56RQ.js +0 -1061
  150. package/dist/chunk-Y72C7F6O.js +0 -148
  151. package/dist/chunk-YLICP577.js +0 -1205
  152. package/dist/chunk-YX6AXLVK.js +0 -159
  153. package/dist/chunk-ZCQYHTNU.js +0 -146
  154. package/dist/cli.d.ts +0 -1
  155. package/dist/cli.js +0 -1105
  156. package/dist/cloud-crystal.js +0 -6
  157. package/dist/core.d.ts +0 -232
  158. package/dist/core.js +0 -12
  159. package/dist/crypto.d.ts +0 -20
  160. package/dist/crypto.js +0 -27
  161. package/dist/crystal-capture.sh +0 -29
  162. package/dist/crystal-serve.d.ts +0 -4
  163. package/dist/crystal-serve.js +0 -252
  164. package/dist/dev-update-SZ2Z4WCQ.js +0 -6
  165. package/dist/discover.d.ts +0 -30
  166. package/dist/discover.js +0 -177
  167. package/dist/doctor.d.ts +0 -9
  168. package/dist/doctor.js +0 -334
  169. package/dist/dream-weaver.d.ts +0 -8
  170. package/dist/dream-weaver.js +0 -56
  171. package/dist/file-sync.d.ts +0 -48
  172. package/dist/file-sync.js +0 -18
  173. package/dist/installer.d.ts +0 -61
  174. package/dist/installer.js +0 -676
  175. package/dist/ldm-backup.sh +0 -116
  176. package/dist/ldm.d.ts +0 -50
  177. package/dist/ldm.js +0 -32
  178. package/dist/mcp-server.d.ts +0 -1
  179. package/dist/mcp-server.js +0 -265
  180. package/dist/migrate.d.ts +0 -1
  181. package/dist/migrate.js +0 -89
  182. package/dist/mirror-sync.d.ts +0 -1
  183. package/dist/mirror-sync.js +0 -159
  184. package/dist/oc-backfill.d.ts +0 -19
  185. package/dist/oc-backfill.js +0 -74
  186. package/dist/openclaw.d.ts +0 -5
  187. package/dist/openclaw.js +0 -423
  188. package/dist/pair.d.ts +0 -4
  189. package/dist/pair.js +0 -75
  190. package/dist/poller.d.ts +0 -1
  191. package/dist/poller.js +0 -634
  192. package/dist/role.d.ts +0 -24
  193. package/dist/role.js +0 -13
  194. package/dist/search-pipeline-4K4OJSSS.js +0 -255
  195. package/dist/search-pipeline-4PRS6LI7.js +0 -280
  196. package/dist/search-pipeline-7UJMXPLO.js +0 -280
  197. package/dist/search-pipeline-DQTRLGBH.js +0 -74
  198. package/dist/search-pipeline-HNG37REH.js +0 -282
  199. package/dist/search-pipeline-IZFPLBUB.js +0 -280
  200. package/dist/search-pipeline-MID6F26Q.js +0 -73
  201. package/dist/search-pipeline-N52JZFNN.js +0 -282
  202. package/dist/search-pipeline-OPB2PRQQ.js +0 -280
  203. package/dist/search-pipeline-VXTE5HAD.js +0 -262
  204. package/dist/search-pipeline-XHFKADRG.js +0 -73
  205. package/dist/staging.d.ts +0 -29
  206. package/dist/staging.js +0 -21
  207. package/dist/summarize.d.ts +0 -19
  208. package/dist/summarize.js +0 -10
  209. package/dist/worker-demo.js +0 -186
  210. package/dist/worker-mcp.js +0 -404
  211. package/dist/worker.js +0 -137
package/dist/installer.js DELETED
@@ -1,676 +0,0 @@
1
- import {
2
- deployBackupScript,
3
- deployCaptureScript,
4
- getAgentId,
5
- installCron,
6
- ldmPaths,
7
- loadAgentConfig,
8
- saveAgentConfig,
9
- scaffoldLdm
10
- } from "./chunk-EXEZZADG.js";
11
-
12
- // src/installer.ts
13
- import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, copyFileSync, readdirSync, statSync } from "fs";
14
- import { join, dirname } from "path";
15
- import { execSync } from "child_process";
16
- import { fileURLToPath } from "url";
17
- var HOME = process.env.HOME || "";
18
- var LDM_ROOT = join(HOME, ".ldm");
19
- var OC_ROOT = join(HOME, ".openclaw");
20
- var CC_SETTINGS = join(HOME, ".claude", "settings.json");
21
- var CC_MCP = join(HOME, ".claude", ".mcp.json");
22
- var OC_MCP = join(OC_ROOT, ".mcp.json");
23
- function readVersion(pkgPath) {
24
- try {
25
- if (existsSync(pkgPath)) {
26
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
27
- return pkg.version || null;
28
- }
29
- } catch {
30
- }
31
- return null;
32
- }
33
- function getRepoRoot() {
34
- const thisDir = dirname(fileURLToPath(import.meta.url));
35
- let dir = thisDir;
36
- for (let i = 0; i < 5; i++) {
37
- const pkgPath = join(dir, "package.json");
38
- if (existsSync(pkgPath)) {
39
- try {
40
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
41
- if (pkg.name === "@wipcomputer/memory-crystal") return dir;
42
- } catch {
43
- }
44
- }
45
- dir = dirname(dir);
46
- }
47
- return dirname(thisDir);
48
- }
49
- function semverCompare(a, b) {
50
- const pa = a.split(".").map(Number);
51
- const pb = b.split(".").map(Number);
52
- for (let i = 0; i < 3; i++) {
53
- if ((pa[i] || 0) > (pb[i] || 0)) return 1;
54
- if ((pa[i] || 0) < (pb[i] || 0)) return -1;
55
- }
56
- return 0;
57
- }
58
- function getLatestNpmVersion() {
59
- const names = ["@wipcomputer/memory-crystal", "memory-crystal"];
60
- for (const name of names) {
61
- try {
62
- const v = execSync(`npm view ${name} version 2>/dev/null`, { encoding: "utf-8", timeout: 1e4 }).trim();
63
- if (v) return v;
64
- } catch {
65
- }
66
- }
67
- return null;
68
- }
69
- function detectInstallState() {
70
- const ldmExtDir = join(LDM_ROOT, "extensions", "memory-crystal");
71
- const ocExtDir = join(OC_ROOT, "extensions", "memory-crystal");
72
- const paths = ldmPaths();
73
- const installedVersion = readVersion(join(ldmExtDir, "package.json"));
74
- const repoRoot = getRepoRoot();
75
- let repoVersion = readVersion(join(repoRoot, "package.json")) || "0.0.0";
76
- const npmVersion = getLatestNpmVersion();
77
- if (npmVersion && semverCompare(npmVersion, repoVersion) > 0) repoVersion = npmVersion;
78
- const ccHookDeployed = existsSync(join(ldmExtDir, "dist", "cc-hook.js"));
79
- let ccHookConfigured = false;
80
- try {
81
- if (existsSync(CC_SETTINGS)) {
82
- const settings = JSON.parse(readFileSync(CC_SETTINGS, "utf-8"));
83
- const stopHooks = settings?.hooks?.Stop;
84
- if (Array.isArray(stopHooks)) {
85
- ccHookConfigured = stopHooks.some((entry) => {
86
- const hooks = entry?.hooks;
87
- if (!Array.isArray(hooks)) return false;
88
- return hooks.some((h) => h?.command?.includes("memory-crystal") && h?.command?.includes("cc-hook"));
89
- });
90
- }
91
- }
92
- } catch {
93
- }
94
- let mcpRegistered = false;
95
- for (const mcpPath of [CC_MCP, OC_MCP, join(process.cwd(), ".mcp.json")]) {
96
- try {
97
- if (existsSync(mcpPath)) {
98
- const config = JSON.parse(readFileSync(mcpPath, "utf-8"));
99
- if (config?.mcpServers?.["memory-crystal"]) {
100
- mcpRegistered = true;
101
- break;
102
- }
103
- }
104
- } catch {
105
- }
106
- }
107
- if (!mcpRegistered) {
108
- try {
109
- execSync("claude mcp get memory-crystal 2>/dev/null", { encoding: "utf-8", timeout: 5e3, stdio: "pipe" });
110
- mcpRegistered = true;
111
- } catch {
112
- }
113
- }
114
- const ocDetected = existsSync(join(OC_ROOT, "openclaw.json"));
115
- const ocPluginDeployed = existsSync(join(ocExtDir, "dist", "openclaw.js"));
116
- let cronInstalled = false;
117
- try {
118
- const crontab = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" });
119
- cronInstalled = crontab.includes("crystal-capture");
120
- } catch {
121
- }
122
- const role = "standalone";
123
- const relayKeyExists = existsSync(join(LDM_ROOT, "secrets", "crystal-relay-key"));
124
- return {
125
- ldmExists: existsSync(LDM_ROOT),
126
- crystalDbExists: existsSync(paths.crystalDb),
127
- ccHookDeployed,
128
- ccHookConfigured,
129
- mcpRegistered,
130
- ocDetected,
131
- ocPluginDeployed,
132
- cronInstalled,
133
- installedVersion,
134
- repoVersion,
135
- needsUpdate: installedVersion !== null && installedVersion !== repoVersion,
136
- role,
137
- relayKeyExists
138
- };
139
- }
140
- function deployToLdm() {
141
- const repoRoot = getRepoRoot();
142
- const sourceDir = join(repoRoot, "dist");
143
- const extDir = join(LDM_ROOT, "extensions", "memory-crystal");
144
- const destDist = join(extDir, "dist");
145
- if (!existsSync(sourceDir)) {
146
- throw new Error(`dist/ not found at ${sourceDir}. Run "npm run build" first.`);
147
- }
148
- mkdirSync(destDist, { recursive: true });
149
- const distFiles = readdirSync(sourceDir);
150
- for (const file of distFiles) {
151
- const srcPath = join(sourceDir, file);
152
- const destPath = join(destDist, file);
153
- const stat = statSync(srcPath);
154
- if (stat.isFile()) {
155
- copyFileSync(srcPath, destPath);
156
- } else if (stat.isDirectory()) {
157
- cpSync(srcPath, destPath, { recursive: true });
158
- }
159
- }
160
- copyFileSync(join(repoRoot, "package.json"), join(extDir, "package.json"));
161
- const pluginJson = join(repoRoot, "openclaw.plugin.json");
162
- if (existsSync(pluginJson)) {
163
- copyFileSync(pluginJson, join(extDir, "openclaw.plugin.json"));
164
- }
165
- const skillsDir = join(repoRoot, "skills");
166
- if (existsSync(skillsDir)) {
167
- cpSync(skillsDir, join(extDir, "skills"), { recursive: true });
168
- }
169
- const version = readVersion(join(extDir, "package.json")) || "unknown";
170
- return { extensionDir: extDir, version };
171
- }
172
- function installLdmDeps() {
173
- const extDir = join(LDM_ROOT, "extensions", "memory-crystal");
174
- if (!existsSync(join(extDir, "package.json"))) {
175
- throw new Error("package.json not found in LDM extension dir. Deploy first.");
176
- }
177
- execSync("npm install --omit=dev", {
178
- cwd: extDir,
179
- encoding: "utf-8",
180
- stdio: "pipe",
181
- timeout: 12e4
182
- });
183
- }
184
- function deployToOpenClaw() {
185
- const repoRoot = getRepoRoot();
186
- const sourceDir = join(repoRoot, "dist");
187
- const extDir = join(OC_ROOT, "extensions", "memory-crystal");
188
- const destDist = join(extDir, "dist");
189
- if (!existsSync(sourceDir)) {
190
- throw new Error(`dist/ not found at ${sourceDir}. Run "npm run build" first.`);
191
- }
192
- mkdirSync(destDist, { recursive: true });
193
- const distFiles = readdirSync(sourceDir);
194
- for (const file of distFiles) {
195
- const srcPath = join(sourceDir, file);
196
- const destPath = join(destDist, file);
197
- const stat = statSync(srcPath);
198
- if (stat.isFile()) {
199
- copyFileSync(srcPath, destPath);
200
- } else if (stat.isDirectory()) {
201
- cpSync(srcPath, destPath, { recursive: true });
202
- }
203
- }
204
- copyFileSync(join(repoRoot, "package.json"), join(extDir, "package.json"));
205
- const pluginJson = join(repoRoot, "openclaw.plugin.json");
206
- if (existsSync(pluginJson)) {
207
- copyFileSync(pluginJson, join(extDir, "openclaw.plugin.json"));
208
- }
209
- const skillsDir = join(repoRoot, "skills");
210
- if (existsSync(skillsDir)) {
211
- cpSync(skillsDir, join(extDir, "skills"), { recursive: true });
212
- }
213
- const version = readVersion(join(extDir, "package.json")) || "unknown";
214
- return { extensionDir: extDir, version };
215
- }
216
- function installOcDeps() {
217
- const extDir = join(OC_ROOT, "extensions", "memory-crystal");
218
- if (!existsSync(join(extDir, "package.json"))) {
219
- throw new Error("package.json not found in OC extension dir. Deploy first.");
220
- }
221
- execSync("npm install --omit=dev", {
222
- cwd: extDir,
223
- encoding: "utf-8",
224
- stdio: "pipe",
225
- timeout: 12e4
226
- });
227
- }
228
- function configureCCHook() {
229
- const hookCommand = `node ${join(LDM_ROOT, "extensions", "memory-crystal", "dist", "cc-hook.js")}`;
230
- let settings = {};
231
- if (existsSync(CC_SETTINGS)) {
232
- try {
233
- settings = JSON.parse(readFileSync(CC_SETTINGS, "utf-8"));
234
- } catch {
235
- throw new Error(`~/.claude/settings.json exists but is not valid JSON. Fix it manually before proceeding.`);
236
- }
237
- }
238
- if (!settings.hooks) settings.hooks = {};
239
- if (!Array.isArray(settings.hooks.Stop)) settings.hooks.Stop = [];
240
- const existingIdx = settings.hooks.Stop.findIndex((entry) => {
241
- const hooks = entry?.hooks;
242
- if (!Array.isArray(hooks)) return false;
243
- return hooks.some((h) => h?.command?.includes("memory-crystal") || h?.command?.includes("cc-hook"));
244
- });
245
- const hookEntry = {
246
- hooks: [{
247
- type: "command",
248
- command: hookCommand,
249
- timeout: 30
250
- }]
251
- };
252
- if (existingIdx >= 0) {
253
- settings.hooks.Stop[existingIdx] = hookEntry;
254
- } else {
255
- settings.hooks.Stop.push(hookEntry);
256
- }
257
- mkdirSync(join(HOME, ".claude"), { recursive: true });
258
- writeFileSync(CC_SETTINGS, JSON.stringify(settings, null, 2) + "\n");
259
- }
260
- function registerMCPServer() {
261
- const mcpServerPath = join(LDM_ROOT, "extensions", "memory-crystal", "dist", "mcp-server.js");
262
- const addCmd = `claude mcp add --scope user -e OPENCLAW_HOME=${OC_ROOT} memory-crystal -- node "${mcpServerPath}"`;
263
- try {
264
- execSync(addCmd, {
265
- encoding: "utf-8",
266
- stdio: "pipe",
267
- timeout: 15e3
268
- });
269
- return;
270
- } catch (err) {
271
- const output = (err.stderr || "") + (err.stdout || "");
272
- if (output.includes("already exists")) {
273
- try {
274
- execSync("claude mcp remove memory-crystal --scope user", { encoding: "utf-8", stdio: "pipe", timeout: 1e4 });
275
- execSync(addCmd, { encoding: "utf-8", stdio: "pipe", timeout: 15e3 });
276
- } catch {
277
- }
278
- return;
279
- }
280
- }
281
- let config = {};
282
- if (existsSync(CC_MCP)) {
283
- try {
284
- config = JSON.parse(readFileSync(CC_MCP, "utf-8"));
285
- } catch {
286
- }
287
- }
288
- if (!config.mcpServers) config.mcpServers = {};
289
- config.mcpServers["memory-crystal"] = {
290
- command: "node",
291
- args: [mcpServerPath],
292
- env: { OPENCLAW_HOME: OC_ROOT }
293
- };
294
- mkdirSync(join(HOME, ".claude"), { recursive: true });
295
- writeFileSync(CC_MCP, JSON.stringify(config, null, 2) + "\n");
296
- }
297
- function registerOcMCPServer() {
298
- const mcpServerPath = join(OC_ROOT, "extensions", "memory-crystal", "dist", "mcp-server.js");
299
- let config = {};
300
- if (existsSync(OC_MCP)) {
301
- try {
302
- config = JSON.parse(readFileSync(OC_MCP, "utf-8"));
303
- } catch {
304
- }
305
- }
306
- if (!config.mcpServers) config.mcpServers = {};
307
- config.mcpServers["memory-crystal"] = {
308
- command: "node",
309
- args: [mcpServerPath],
310
- env: { OPENCLAW_HOME: OC_ROOT }
311
- };
312
- writeFileSync(OC_MCP, JSON.stringify(config, null, 2) + "\n");
313
- }
314
- function backupCrystalDb() {
315
- const paths = ldmPaths();
316
- const dbPath = paths.crystalDb;
317
- if (!existsSync(dbPath)) {
318
- throw new Error(`crystal.db not found at ${dbPath}`);
319
- }
320
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
321
- const backupPath = `${dbPath}.pre-update-${timestamp}`;
322
- copyFileSync(dbPath, backupPath);
323
- const walPath = dbPath + "-wal";
324
- const shmPath = dbPath + "-shm";
325
- if (existsSync(walPath)) copyFileSync(walPath, backupPath + "-wal");
326
- if (existsSync(shmPath)) copyFileSync(shmPath, backupPath + "-shm");
327
- const origSize = statSync(dbPath).size;
328
- const backupSize = statSync(backupPath).size;
329
- if (backupSize !== origSize) {
330
- throw new Error(`Backup size mismatch: original ${origSize}, backup ${backupSize}`);
331
- }
332
- return backupPath;
333
- }
334
- async function verifyCrystalDbReadable() {
335
- const paths = ldmPaths();
336
- const dbPath = paths.crystalDb;
337
- if (!existsSync(dbPath)) return;
338
- const { default: Database } = await import("better-sqlite3");
339
- const db = new Database(dbPath, { readonly: true });
340
- try {
341
- const row = db.prepare("SELECT COUNT(*) as count FROM chunks").get();
342
- if (typeof row.count !== "number") {
343
- throw new Error("chunks table returned unexpected data");
344
- }
345
- const tables = db.prepare(
346
- "SELECT name FROM sqlite_master WHERE type='table'"
347
- ).all();
348
- const tableNames = tables.map((t) => t.name);
349
- if (!tableNames.includes("chunks")) {
350
- throw new Error("chunks table missing from database");
351
- }
352
- } finally {
353
- db.close();
354
- }
355
- }
356
- function formatUpdateSummary(oldVersion, newVersion) {
357
- const lines = [];
358
- lines.push(`Updating v${oldVersion} -> v${newVersion}`);
359
- lines.push("");
360
- lines.push("What will be updated:");
361
- lines.push(" - Code in ~/.ldm/extensions/memory-crystal/dist/");
362
- lines.push(" - Skills in ~/.ldm/extensions/memory-crystal/skills/");
363
- lines.push(" - package.json (version tracking)");
364
- lines.push("");
365
- lines.push("What will NOT be touched:");
366
- lines.push(" - ~/.ldm/memory/crystal.db (your data)");
367
- lines.push(" - ~/.ldm/state/* (watermarks, role)");
368
- lines.push(" - ~/.ldm/secrets/* (relay key)");
369
- lines.push(" - ~/.ldm/agents/* (agent data)");
370
- return lines.join("\n");
371
- }
372
- function ldmCliAvailable() {
373
- try {
374
- execSync("ldm --version", { stdio: "pipe", timeout: 5e3 });
375
- return true;
376
- } catch {
377
- return false;
378
- }
379
- }
380
- function bootstrapLdmOs(steps) {
381
- try {
382
- steps.push("Installing LDM OS infrastructure...");
383
- execSync("npm install -g @wipcomputer/wip-ldm-os", { stdio: "pipe", timeout: 12e4 });
384
- execSync("ldm --version", { stdio: "pipe", timeout: 5e3 });
385
- steps.push("LDM OS installed.");
386
- return true;
387
- } catch {
388
- steps.push("LDM OS install skipped (npm offline or permissions issue). Using standalone.");
389
- return false;
390
- }
391
- }
392
- function runLdmInstall(repoDir) {
393
- const steps = [];
394
- try {
395
- execSync("ldm init --yes --none", { stdio: "pipe", timeout: 3e4 });
396
- steps.push("LDM initialized via ldm CLI");
397
- } catch (err) {
398
- const msg = (err.stderr || err.message || "").toString().trim();
399
- if (!msg.includes("already")) {
400
- steps.push(`ldm init warning: ${msg.slice(0, 120)}`);
401
- }
402
- }
403
- try {
404
- execSync(`ldm install "${repoDir}"`, { stdio: "pipe", timeout: 6e4 });
405
- steps.push("Generic deployment handled by ldm install (extensions, MCP, hooks)");
406
- return { ok: true, steps };
407
- } catch (err) {
408
- const msg = (err.stderr || err.message || "").toString().trim();
409
- steps.push(`ldm install failed: ${msg.slice(0, 200)}`);
410
- return { ok: false, steps };
411
- }
412
- }
413
- async function runInstallOrUpdate(options) {
414
- const agentId = options.agentId || getAgentId();
415
- const state = detectInstallState();
416
- const steps = [];
417
- const deployedTo = [];
418
- let dbStatus = "none";
419
- let chunkCount = 0;
420
- const isFresh = !state.ldmExists || state.installedVersion === null;
421
- const isUpdate = !isFresh && state.needsUpdate;
422
- if (!isFresh && !isUpdate) {
423
- return {
424
- action: "up-to-date",
425
- version: state.repoVersion,
426
- deployedTo: [],
427
- steps: [`Already at v${state.repoVersion}. Nothing to do.`]
428
- };
429
- }
430
- if (isUpdate && state.installedVersion) {
431
- const npmV = getLatestNpmVersion();
432
- if (npmV && semverCompare(npmV, state.installedVersion) > 0) {
433
- steps.push(`Upgrading v${state.installedVersion} -> v${npmV} via npm...`);
434
- try {
435
- execSync("npm install -g @wipcomputer/memory-crystal 2>&1", { encoding: "utf-8", timeout: 6e4, stdio: "pipe" });
436
- steps.push(`Installed @wipcomputer/memory-crystal@${npmV}`);
437
- steps.push("Continuing with updated code...");
438
- } catch (err) {
439
- steps.push(`npm upgrade failed: ${err.message}. Continuing with local code.`);
440
- }
441
- }
442
- }
443
- let hasLdmCli = ldmCliAvailable();
444
- if (!hasLdmCli) {
445
- hasLdmCli = bootstrapLdmOs(steps);
446
- }
447
- let ldmDelegated = false;
448
- if (hasLdmCli) {
449
- steps.push("LDM OS detected. Using ldm install for deployment...");
450
- const repoRoot = getRepoRoot();
451
- const delegateResult = runLdmInstall(repoRoot);
452
- steps.push(...delegateResult.steps);
453
- if (delegateResult.ok) {
454
- ldmDelegated = true;
455
- const ldmExtDir = join(LDM_ROOT, "extensions", "memory-crystal");
456
- if (existsSync(ldmExtDir)) deployedTo.push(ldmExtDir);
457
- const ocExtDir = join(OC_ROOT, "extensions", "memory-crystal");
458
- if (existsSync(ocExtDir)) deployedTo.push(ocExtDir);
459
- }
460
- }
461
- if (ldmDelegated) {
462
- steps.push("Scaffold + agent config handled by ldm CLI");
463
- } else {
464
- scaffoldLdm(agentId);
465
- steps.push(`LDM scaffolded for agent "${agentId}"`);
466
- const existingCfg = loadAgentConfig(agentId);
467
- if (existingCfg && !existingCfg.agentId) {
468
- existingCfg.agentId = agentId;
469
- saveAgentConfig(agentId, existingCfg);
470
- steps.push(`Added agentId "${agentId}" to existing config.json`);
471
- } else if (!existingCfg) {
472
- const harness = agentId.startsWith("oc-") ? "openclaw" : "claude-code-cli";
473
- saveAgentConfig(agentId, {
474
- agentId,
475
- agent: agentId.startsWith("oc-") ? agentId.replace(/^oc-/, "").replace(/-[^-]+$/, "") : "cc",
476
- harness,
477
- created: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
478
- });
479
- steps.push(`Created config.json for agent "${agentId}"`);
480
- }
481
- }
482
- if (state.crystalDbExists) {
483
- try {
484
- const { default: Database } = await import("better-sqlite3");
485
- const db = new Database(ldmPaths().crystalDb, { readonly: true });
486
- const row = db.prepare("SELECT COUNT(*) as count FROM chunks").get();
487
- chunkCount = row.count;
488
- db.close();
489
- dbStatus = "existing";
490
- steps.push(`Existing database found: ${chunkCount.toLocaleString()} chunks in crystal.db`);
491
- } catch {
492
- dbStatus = "existing";
493
- steps.push("Existing database found (could not read chunk count)");
494
- }
495
- try {
496
- const backupPath = backupCrystalDb();
497
- steps.push(`Database backed up to ${backupPath}`);
498
- } catch (err) {
499
- steps.push(`Database backup FAILED: ${err.message}`);
500
- return {
501
- action: "up-to-date",
502
- version: state.repoVersion,
503
- deployedTo: [],
504
- steps: [...steps, "Aborted. Fix the backup issue before retrying."],
505
- dbStatus
506
- };
507
- }
508
- try {
509
- await verifyCrystalDbReadable();
510
- steps.push("Database read verification passed");
511
- } catch (err) {
512
- steps.push(`Database read verification FAILED: ${err.message}`);
513
- return {
514
- action: "up-to-date",
515
- version: state.repoVersion,
516
- deployedTo: [],
517
- steps: [...steps, "Aborted. New code cannot read existing database."],
518
- dbStatus
519
- };
520
- }
521
- } else if (options.importDb) {
522
- const importPath = options.importDb;
523
- if (!existsSync(importPath)) {
524
- steps.push(`Import path not found: ${importPath}`);
525
- } else {
526
- try {
527
- const paths = ldmPaths();
528
- mkdirSync(join(paths.root, "memory"), { recursive: true });
529
- copyFileSync(importPath, paths.crystalDb);
530
- const { default: Database } = await import("better-sqlite3");
531
- const db = new Database(paths.crystalDb, { readonly: true });
532
- const row = db.prepare("SELECT COUNT(*) as count FROM chunks").get();
533
- chunkCount = row.count;
534
- db.close();
535
- dbStatus = "imported";
536
- steps.push(`Database imported: ${chunkCount.toLocaleString()} chunks from ${importPath}`);
537
- } catch (err) {
538
- steps.push(`Database import failed: ${err.message}`);
539
- }
540
- }
541
- } else {
542
- dbStatus = "fresh";
543
- steps.push("No existing database. A new one will be created on first capture.");
544
- }
545
- if (ldmDelegated) {
546
- const repoRoot = getRepoRoot();
547
- const ldmExtDir = join(LDM_ROOT, "extensions", "memory-crystal");
548
- if (existsSync(ldmExtDir)) copyFileSync(join(repoRoot, "package.json"), join(ldmExtDir, "package.json"));
549
- const ocExtDir = join(OC_ROOT, "extensions", "memory-crystal");
550
- if (existsSync(ocExtDir)) copyFileSync(join(repoRoot, "package.json"), join(ocExtDir, "package.json"));
551
- steps.push(`Version synced to v${readVersion(join(repoRoot, "package.json")) || "unknown"}`);
552
- }
553
- if (!ldmDelegated) {
554
- const ldmResult = deployToLdm();
555
- steps.push(`Code deployed to ${ldmResult.extensionDir}`);
556
- deployedTo.push(ldmResult.extensionDir);
557
- try {
558
- installLdmDeps();
559
- steps.push("Dependencies installed (LDM)");
560
- } catch (err) {
561
- steps.push(`Dependencies install failed (LDM): ${err.message}`);
562
- }
563
- try {
564
- configureCCHook();
565
- steps.push("CC Stop hook configured in ~/.claude/settings.json");
566
- } catch (err) {
567
- steps.push(`CC Stop hook config failed: ${err.message}`);
568
- }
569
- if (!state.mcpRegistered || isUpdate) {
570
- try {
571
- registerMCPServer();
572
- steps.push("MCP server registered with Claude Code");
573
- } catch (err) {
574
- steps.push(`MCP registration failed: ${err.message}`);
575
- }
576
- } else {
577
- steps.push("MCP server already registered");
578
- }
579
- }
580
- try {
581
- deployCaptureScript();
582
- steps.push("Capture script deployed");
583
- } catch (err) {
584
- steps.push(`Capture script failed: ${err.message}`);
585
- }
586
- if (!state.cronInstalled || isFresh) {
587
- try {
588
- installCron();
589
- steps.push("Cron job installed (every minute)");
590
- } catch (err) {
591
- steps.push(`Cron install failed: ${err.message}`);
592
- }
593
- } else {
594
- steps.push("Cron job already installed");
595
- }
596
- try {
597
- deployBackupScript();
598
- steps.push("Backup script deployed");
599
- } catch (err) {
600
- steps.push(`Backup script failed: ${err.message}`);
601
- }
602
- if (!ldmDelegated && state.ocDetected) {
603
- try {
604
- const ocResult = deployToOpenClaw();
605
- steps.push(`OC plugin deployed to ${ocResult.extensionDir}`);
606
- deployedTo.push(ocResult.extensionDir);
607
- } catch (err) {
608
- steps.push(`OC plugin deploy failed: ${err.message}`);
609
- }
610
- try {
611
- installOcDeps();
612
- steps.push("Dependencies installed (OC)");
613
- } catch (err) {
614
- steps.push(`Dependencies install failed (OC): ${err.message}`);
615
- }
616
- try {
617
- registerOcMCPServer();
618
- steps.push("OC MCP server config updated");
619
- } catch (err) {
620
- steps.push(`OC MCP config failed: ${err.message}`);
621
- }
622
- }
623
- if (options.role === "core") {
624
- try {
625
- const { promoteToCore } = await import("./role.js");
626
- promoteToCore();
627
- steps.push("Role set to Core");
628
- } catch (err) {
629
- steps.push(`Role setup failed: ${err.message}`);
630
- }
631
- } else if (options.role === "node") {
632
- try {
633
- const { demoteToNode } = await import("./role.js");
634
- demoteToNode();
635
- steps.push("Role set to Node");
636
- } catch (err) {
637
- steps.push(`Role setup failed: ${err.message}`);
638
- }
639
- }
640
- if (options.pairCode) {
641
- try {
642
- const { pairReceive } = await import("./pair.js");
643
- pairReceive(options.pairCode);
644
- steps.push("Pairing code accepted");
645
- } catch (err) {
646
- steps.push(`Pairing failed: ${err.message}`);
647
- }
648
- }
649
- if (hasLdmCli) {
650
- steps.push('Tip: Run "ldm install" to see more components you can add.');
651
- } else if (!ldmDelegated) {
652
- steps.push("Tip: Install LDM OS for more components: npm install -g @wipcomputer/wip-ldm-os");
653
- }
654
- return {
655
- action: isFresh ? "installed" : "updated",
656
- version: state.repoVersion,
657
- deployedTo,
658
- steps,
659
- dbStatus,
660
- chunkCount
661
- };
662
- }
663
- export {
664
- backupCrystalDb,
665
- configureCCHook,
666
- deployToLdm,
667
- deployToOpenClaw,
668
- detectInstallState,
669
- formatUpdateSummary,
670
- installLdmDeps,
671
- installOcDeps,
672
- registerMCPServer,
673
- registerOcMCPServer,
674
- runInstallOrUpdate,
675
- verifyCrystalDbReadable
676
- };