contextmate 0.1.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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/dist/src/adapters/base.d.ts +32 -0
  4. package/dist/src/adapters/base.d.ts.map +1 -0
  5. package/dist/src/adapters/base.js +49 -0
  6. package/dist/src/adapters/base.js.map +1 -0
  7. package/dist/src/adapters/claude.d.ts +30 -0
  8. package/dist/src/adapters/claude.d.ts.map +1 -0
  9. package/dist/src/adapters/claude.js +534 -0
  10. package/dist/src/adapters/claude.js.map +1 -0
  11. package/dist/src/adapters/index.d.ts +7 -0
  12. package/dist/src/adapters/index.d.ts.map +1 -0
  13. package/dist/src/adapters/index.js +16 -0
  14. package/dist/src/adapters/index.js.map +1 -0
  15. package/dist/src/adapters/openclaw.d.ts +15 -0
  16. package/dist/src/adapters/openclaw.d.ts.map +1 -0
  17. package/dist/src/adapters/openclaw.js +198 -0
  18. package/dist/src/adapters/openclaw.js.map +1 -0
  19. package/dist/src/bin/contextmate.d.ts +3 -0
  20. package/dist/src/bin/contextmate.d.ts.map +1 -0
  21. package/dist/src/bin/contextmate.js +4 -0
  22. package/dist/src/bin/contextmate.js.map +1 -0
  23. package/dist/src/cli/adapter.d.ts +3 -0
  24. package/dist/src/cli/adapter.d.ts.map +1 -0
  25. package/dist/src/cli/adapter.js +187 -0
  26. package/dist/src/cli/adapter.js.map +1 -0
  27. package/dist/src/cli/daemon.d.ts +3 -0
  28. package/dist/src/cli/daemon.d.ts.map +1 -0
  29. package/dist/src/cli/daemon.js +212 -0
  30. package/dist/src/cli/daemon.js.map +1 -0
  31. package/dist/src/cli/files.d.ts +3 -0
  32. package/dist/src/cli/files.d.ts.map +1 -0
  33. package/dist/src/cli/files.js +158 -0
  34. package/dist/src/cli/files.js.map +1 -0
  35. package/dist/src/cli/index.d.ts +3 -0
  36. package/dist/src/cli/index.d.ts.map +1 -0
  37. package/dist/src/cli/index.js +20 -0
  38. package/dist/src/cli/index.js.map +1 -0
  39. package/dist/src/cli/init.d.ts +3 -0
  40. package/dist/src/cli/init.d.ts.map +1 -0
  41. package/dist/src/cli/init.js +88 -0
  42. package/dist/src/cli/init.js.map +1 -0
  43. package/dist/src/cli/log.d.ts +3 -0
  44. package/dist/src/cli/log.d.ts.map +1 -0
  45. package/dist/src/cli/log.js +141 -0
  46. package/dist/src/cli/log.js.map +1 -0
  47. package/dist/src/cli/mcp.d.ts +3 -0
  48. package/dist/src/cli/mcp.d.ts.map +1 -0
  49. package/dist/src/cli/mcp.js +186 -0
  50. package/dist/src/cli/mcp.js.map +1 -0
  51. package/dist/src/cli/status.d.ts +3 -0
  52. package/dist/src/cli/status.d.ts.map +1 -0
  53. package/dist/src/cli/status.js +107 -0
  54. package/dist/src/cli/status.js.map +1 -0
  55. package/dist/src/config.d.ts +42 -0
  56. package/dist/src/config.d.ts.map +1 -0
  57. package/dist/src/config.js +93 -0
  58. package/dist/src/config.js.map +1 -0
  59. package/dist/src/crypto/auth.d.ts +4 -0
  60. package/dist/src/crypto/auth.d.ts.map +1 -0
  61. package/dist/src/crypto/auth.js +21 -0
  62. package/dist/src/crypto/auth.js.map +1 -0
  63. package/dist/src/crypto/encrypt.d.ts +9 -0
  64. package/dist/src/crypto/encrypt.d.ts.map +1 -0
  65. package/dist/src/crypto/encrypt.js +39 -0
  66. package/dist/src/crypto/encrypt.js.map +1 -0
  67. package/dist/src/crypto/index.d.ts +4 -0
  68. package/dist/src/crypto/index.d.ts.map +1 -0
  69. package/dist/src/crypto/index.js +4 -0
  70. package/dist/src/crypto/index.js.map +1 -0
  71. package/dist/src/crypto/keys.d.ts +9 -0
  72. package/dist/src/crypto/keys.d.ts.map +1 -0
  73. package/dist/src/crypto/keys.js +43 -0
  74. package/dist/src/crypto/keys.js.map +1 -0
  75. package/dist/src/mcp/embeddings.d.ts +16 -0
  76. package/dist/src/mcp/embeddings.d.ts.map +1 -0
  77. package/dist/src/mcp/embeddings.js +237 -0
  78. package/dist/src/mcp/embeddings.js.map +1 -0
  79. package/dist/src/mcp/index.d.ts +10 -0
  80. package/dist/src/mcp/index.d.ts.map +1 -0
  81. package/dist/src/mcp/index.js +6 -0
  82. package/dist/src/mcp/index.js.map +1 -0
  83. package/dist/src/mcp/rerank.d.ts +14 -0
  84. package/dist/src/mcp/rerank.d.ts.map +1 -0
  85. package/dist/src/mcp/rerank.js +47 -0
  86. package/dist/src/mcp/rerank.js.map +1 -0
  87. package/dist/src/mcp/scope.d.ts +26 -0
  88. package/dist/src/mcp/scope.d.ts.map +1 -0
  89. package/dist/src/mcp/scope.js +71 -0
  90. package/dist/src/mcp/scope.js.map +1 -0
  91. package/dist/src/mcp/search.d.ts +18 -0
  92. package/dist/src/mcp/search.d.ts.map +1 -0
  93. package/dist/src/mcp/search.js +110 -0
  94. package/dist/src/mcp/search.js.map +1 -0
  95. package/dist/src/mcp/server.d.ts +15 -0
  96. package/dist/src/mcp/server.d.ts.map +1 -0
  97. package/dist/src/mcp/server.js +340 -0
  98. package/dist/src/mcp/server.js.map +1 -0
  99. package/dist/src/sync/client.d.ts +25 -0
  100. package/dist/src/sync/client.d.ts.map +1 -0
  101. package/dist/src/sync/client.js +109 -0
  102. package/dist/src/sync/client.js.map +1 -0
  103. package/dist/src/sync/engine.d.ts +21 -0
  104. package/dist/src/sync/engine.d.ts.map +1 -0
  105. package/dist/src/sync/engine.js +304 -0
  106. package/dist/src/sync/engine.js.map +1 -0
  107. package/dist/src/sync/index.d.ts +6 -0
  108. package/dist/src/sync/index.d.ts.map +1 -0
  109. package/dist/src/sync/index.js +6 -0
  110. package/dist/src/sync/index.js.map +1 -0
  111. package/dist/src/sync/state.d.ts +33 -0
  112. package/dist/src/sync/state.d.ts.map +1 -0
  113. package/dist/src/sync/state.js +146 -0
  114. package/dist/src/sync/state.js.map +1 -0
  115. package/dist/src/sync/watcher.d.ts +14 -0
  116. package/dist/src/sync/watcher.d.ts.map +1 -0
  117. package/dist/src/sync/watcher.js +74 -0
  118. package/dist/src/sync/watcher.js.map +1 -0
  119. package/dist/src/sync/websocket.d.ts +22 -0
  120. package/dist/src/sync/websocket.d.ts.map +1 -0
  121. package/dist/src/sync/websocket.js +103 -0
  122. package/dist/src/sync/websocket.js.map +1 -0
  123. package/dist/src/types.d.ts +63 -0
  124. package/dist/src/types.d.ts.map +1 -0
  125. package/dist/src/types.js +2 -0
  126. package/dist/src/types.js.map +1 -0
  127. package/dist/src/utils/paths.d.ts +9 -0
  128. package/dist/src/utils/paths.d.ts.map +1 -0
  129. package/dist/src/utils/paths.js +24 -0
  130. package/dist/src/utils/paths.js.map +1 -0
  131. package/package.json +61 -0
@@ -0,0 +1,198 @@
1
+ import { readFile, readdir, access, stat, unlink, copyFile, mkdir } from 'node:fs/promises';
2
+ import { join, relative, dirname } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { BaseAdapter } from './base.js';
5
+ export class OpenClawAdapter extends BaseAdapter {
6
+ get name() {
7
+ return 'openclaw';
8
+ }
9
+ async detect() {
10
+ const workspacePath = join(homedir(), '.openclaw', 'workspace');
11
+ try {
12
+ await access(workspacePath);
13
+ return workspacePath;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ async import(workspacePath) {
20
+ const result = { imported: [], skipped: [], errors: [] };
21
+ const filesToImport = await this.discoverFiles(workspacePath);
22
+ for (const filePath of filesToImport) {
23
+ const relativeSrc = relative(workspacePath, filePath);
24
+ const vaultRelative = join('openclaw', relativeSrc);
25
+ try {
26
+ const sourceContent = await readFile(filePath, 'utf-8');
27
+ // Check if file already exists in vault with same content
28
+ const vaultDest = join(this.vaultPath, vaultRelative);
29
+ try {
30
+ const existingContent = await readFile(vaultDest, 'utf-8');
31
+ if (existingContent === sourceContent) {
32
+ result.skipped.push(vaultRelative);
33
+ continue;
34
+ }
35
+ }
36
+ catch {
37
+ // File doesn't exist in vault yet
38
+ }
39
+ await this.copyToVault(filePath, vaultRelative);
40
+ result.imported.push(vaultRelative);
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : String(err);
44
+ result.errors.push(`${relativeSrc}: ${message}`);
45
+ }
46
+ }
47
+ return result;
48
+ }
49
+ async createSymlinks(workspacePath) {
50
+ const result = { created: [], errors: [] };
51
+ const filesToLink = await this.discoverFiles(workspacePath);
52
+ for (const filePath of filesToLink) {
53
+ const relativeSrc = relative(workspacePath, filePath);
54
+ const vaultRelative = join('openclaw', relativeSrc);
55
+ const vaultPath = join(this.vaultPath, vaultRelative);
56
+ try {
57
+ if (!(await this.isSymlink(filePath))) {
58
+ await this.backupFile(filePath, 'openclaw');
59
+ }
60
+ await this.safeSymlink(vaultPath, filePath);
61
+ result.created.push(relativeSrc);
62
+ }
63
+ catch (err) {
64
+ const message = err instanceof Error ? err.message : String(err);
65
+ result.errors.push(`${relativeSrc}: ${message}`);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ async verifySymlinks(workspacePath) {
71
+ const valid = [];
72
+ const broken = [];
73
+ const filesToCheck = await this.discoverFiles(workspacePath);
74
+ for (const filePath of filesToCheck) {
75
+ const relativeSrc = relative(workspacePath, filePath);
76
+ if (await this.isSymlink(filePath)) {
77
+ try {
78
+ await stat(filePath);
79
+ valid.push(relativeSrc);
80
+ }
81
+ catch {
82
+ broken.push(relativeSrc);
83
+ }
84
+ }
85
+ else {
86
+ broken.push(relativeSrc);
87
+ }
88
+ }
89
+ return { valid, broken };
90
+ }
91
+ async removeSymlinks(workspacePath) {
92
+ const filesToRestore = await this.discoverVaultFiles();
93
+ for (const vaultRelative of filesToRestore) {
94
+ const relativeSrc = vaultRelative.replace(/^openclaw\//, '');
95
+ const originalPath = join(workspacePath, relativeSrc);
96
+ if (!(await this.isSymlink(originalPath))) {
97
+ continue;
98
+ }
99
+ await unlink(originalPath);
100
+ // Try to restore from backup
101
+ const backupPath = join(this.backupsPath, 'openclaw', relative('/', originalPath));
102
+ try {
103
+ await mkdir(dirname(originalPath), { recursive: true });
104
+ await copyFile(backupPath, originalPath);
105
+ }
106
+ catch {
107
+ // No backup -- move vault file back
108
+ const vaultFilePath = join(this.vaultPath, vaultRelative);
109
+ try {
110
+ await copyFile(vaultFilePath, originalPath);
111
+ }
112
+ catch {
113
+ // Vault file also missing
114
+ }
115
+ }
116
+ }
117
+ }
118
+ async discoverFiles(workspacePath) {
119
+ const files = [];
120
+ const topLevelFiles = ['MEMORY.md', 'IDENTITY.md', 'USER.md', 'SOUL.md'];
121
+ for (const name of topLevelFiles) {
122
+ const filePath = join(workspacePath, name);
123
+ try {
124
+ await access(filePath);
125
+ files.push(filePath);
126
+ }
127
+ catch {
128
+ // File doesn't exist
129
+ }
130
+ }
131
+ // skills/*/SKILL.md
132
+ try {
133
+ const skillsDir = join(workspacePath, 'skills');
134
+ const skillNames = await readdir(skillsDir);
135
+ for (const name of skillNames) {
136
+ const skillPath = join(skillsDir, name);
137
+ const s = await stat(skillPath);
138
+ if (s.isDirectory()) {
139
+ const skillFile = join(skillPath, 'SKILL.md');
140
+ try {
141
+ await access(skillFile);
142
+ files.push(skillFile);
143
+ }
144
+ catch {
145
+ // No SKILL.md
146
+ }
147
+ }
148
+ }
149
+ }
150
+ catch {
151
+ // No skills directory
152
+ }
153
+ // memory/*.md
154
+ try {
155
+ const memoryDir = join(workspacePath, 'memory');
156
+ const memoryNames = await readdir(memoryDir);
157
+ for (const name of memoryNames) {
158
+ if (name.endsWith('.md')) {
159
+ const memPath = join(memoryDir, name);
160
+ const s = await stat(memPath);
161
+ if (s.isFile()) {
162
+ files.push(memPath);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ catch {
168
+ // No memory directory
169
+ }
170
+ return files;
171
+ }
172
+ async discoverVaultFiles() {
173
+ const files = [];
174
+ const openclawVault = join(this.vaultPath, 'openclaw');
175
+ const walkDir = async (dir, baseDir) => {
176
+ try {
177
+ const names = await readdir(dir);
178
+ for (const name of names) {
179
+ const fullPath = join(dir, name);
180
+ const s = await stat(fullPath);
181
+ if (s.isDirectory()) {
182
+ await walkDir(fullPath, baseDir);
183
+ }
184
+ else if (s.isFile() && name.endsWith('.md')) {
185
+ const rel = relative(baseDir, fullPath);
186
+ files.push(join('openclaw', rel));
187
+ }
188
+ }
189
+ }
190
+ catch {
191
+ // Directory doesn't exist or not readable
192
+ }
193
+ };
194
+ await walkDir(openclawVault, openclawVault);
195
+ return files;
196
+ }
197
+ }
198
+ //# sourceMappingURL=openclaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw.js","sourceRoot":"","sources":["../../../src/adapters/openclaw.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=contextmate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextmate.d.ts","sourceRoot":"","sources":["../../../src/bin/contextmate.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { program } from '../cli/index.js';
3
+ program.parse();
4
+ //# sourceMappingURL=contextmate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextmate.js","sourceRoot":"","sources":["../../../src/bin/contextmate.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const adapterCommand: Command;
3
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/cli/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0NpC,eAAO,MAAM,cAAc,SAGqC,CAAC"}
@@ -0,0 +1,187 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { loadConfig, saveConfig, getConfigPath } from '../config.js';
4
+ import { getAdapter } from '../adapters/index.js';
5
+ import { getBackupsPath } from '../utils/paths.js';
6
+ import { access } from 'node:fs/promises';
7
+ async function isInitialized() {
8
+ try {
9
+ await access(getConfigPath());
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ function countByPrefix(items, prefix) {
17
+ return items.filter((i) => i.startsWith(prefix)).length;
18
+ }
19
+ function createAdapterSubcommands(agentName, displayName) {
20
+ const cmd = new Command(agentName).description(`Manage ${displayName} adapter`);
21
+ cmd
22
+ .command('init')
23
+ .description(`Import and symlink ${displayName} workspace`)
24
+ .action(async () => {
25
+ try {
26
+ if (!(await isInitialized())) {
27
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
28
+ process.exit(1);
29
+ }
30
+ const config = await loadConfig();
31
+ const adapter = getAdapter(agentName, {
32
+ vaultPath: config.vault.path,
33
+ backupsPath: getBackupsPath(),
34
+ });
35
+ // Detect workspace
36
+ console.log(chalk.dim(`Detecting ${displayName} workspace...`));
37
+ const workspacePath = await adapter.detect();
38
+ if (!workspacePath) {
39
+ console.error(chalk.red(`Could not detect ${displayName} workspace.`));
40
+ if (agentName === 'openclaw') {
41
+ console.error(chalk.dim(' Expected at: ~/.openclaw/workspace'));
42
+ }
43
+ else {
44
+ console.error(chalk.dim(' Expected at: ~/.claude'));
45
+ }
46
+ process.exit(1);
47
+ }
48
+ console.log(` Found: ${workspacePath}`);
49
+ // Import files
50
+ console.log(chalk.dim('Importing files to vault...'));
51
+ const importResult = await adapter.import(workspacePath);
52
+ if (agentName === 'claude') {
53
+ const skills = countByPrefix(importResult.imported, 'skills/');
54
+ const rules = countByPrefix(importResult.imported, 'claude/rules/');
55
+ const claudeMd = importResult.imported.includes('claude/CLAUDE.md') ? 1 : 0;
56
+ const memories = countByPrefix(importResult.imported, 'claude/projects/');
57
+ console.log(` Found: ${skills} skills, ${rules} rules, ${memories} project memory files` +
58
+ (claudeMd ? ', CLAUDE.md' : ''));
59
+ }
60
+ console.log(` ${chalk.green(`${importResult.imported.length} imported`)}, ` +
61
+ `${chalk.dim(`${importResult.skipped.length} skipped`)}`);
62
+ if (importResult.errors.length > 0) {
63
+ for (const err of importResult.errors) {
64
+ console.log(` ${chalk.red('Error:')} ${err}`);
65
+ }
66
+ }
67
+ // Create symlinks
68
+ console.log(chalk.dim('Creating symlinks...'));
69
+ const symlinkResult = await adapter.createSymlinks(workspacePath);
70
+ console.log(` ${chalk.green(`${symlinkResult.created.length} symlinks created`)}`);
71
+ if (symlinkResult.errors.length > 0) {
72
+ for (const err of symlinkResult.errors) {
73
+ console.log(` ${chalk.red('Error:')} ${err}`);
74
+ }
75
+ }
76
+ // Update config
77
+ if (agentName === 'openclaw') {
78
+ config.adapters.openclaw.enabled = true;
79
+ config.adapters.openclaw.workspacePath = workspacePath;
80
+ }
81
+ else {
82
+ config.adapters.claude.enabled = true;
83
+ config.adapters.claude.claudeDir = workspacePath;
84
+ }
85
+ await saveConfig(config);
86
+ console.log('');
87
+ console.log(chalk.green(`${displayName} adapter initialized successfully.`));
88
+ }
89
+ catch (err) {
90
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
91
+ process.exit(1);
92
+ }
93
+ });
94
+ cmd
95
+ .command('status')
96
+ .description(`Show ${displayName} symlink status`)
97
+ .action(async () => {
98
+ try {
99
+ if (!(await isInitialized())) {
100
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
101
+ process.exit(1);
102
+ }
103
+ const config = await loadConfig();
104
+ const adapter = getAdapter(agentName, {
105
+ vaultPath: config.vault.path,
106
+ backupsPath: getBackupsPath(),
107
+ });
108
+ const isEnabled = agentName === 'openclaw'
109
+ ? config.adapters.openclaw.enabled
110
+ : config.adapters.claude.enabled;
111
+ if (!isEnabled) {
112
+ console.log(chalk.dim(`${displayName} adapter is not enabled.`));
113
+ console.log(chalk.dim(`Run "contextmate adapter ${agentName} init" to set it up.`));
114
+ return;
115
+ }
116
+ const workspacePath = agentName === 'openclaw'
117
+ ? config.adapters.openclaw.workspacePath
118
+ : config.adapters.claude.claudeDir;
119
+ const result = await adapter.verifySymlinks(workspacePath);
120
+ console.log('');
121
+ console.log(chalk.bold(`${displayName} Adapter Status`));
122
+ console.log(chalk.dim('─'.repeat(40)));
123
+ console.log(` Workspace: ${workspacePath}`);
124
+ console.log(` Valid symlinks: ${chalk.green(String(result.valid.length))}`);
125
+ console.log(` Broken symlinks: ${chalk.red(String(result.broken.length))}`);
126
+ if (result.broken.length > 0) {
127
+ console.log('');
128
+ console.log(chalk.red(' Broken:'));
129
+ for (const b of result.broken) {
130
+ console.log(` - ${b}`);
131
+ }
132
+ }
133
+ console.log('');
134
+ }
135
+ catch (err) {
136
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
137
+ process.exit(1);
138
+ }
139
+ });
140
+ cmd
141
+ .command('remove')
142
+ .description(`Remove ${displayName} symlinks and restore originals`)
143
+ .action(async () => {
144
+ try {
145
+ if (!(await isInitialized())) {
146
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
147
+ process.exit(1);
148
+ }
149
+ const config = await loadConfig();
150
+ const adapter = getAdapter(agentName, {
151
+ vaultPath: config.vault.path,
152
+ backupsPath: getBackupsPath(),
153
+ });
154
+ const isEnabled = agentName === 'openclaw'
155
+ ? config.adapters.openclaw.enabled
156
+ : config.adapters.claude.enabled;
157
+ if (!isEnabled) {
158
+ console.log(chalk.dim(`${displayName} adapter is not enabled.`));
159
+ return;
160
+ }
161
+ const workspacePath = agentName === 'openclaw'
162
+ ? config.adapters.openclaw.workspacePath
163
+ : config.adapters.claude.claudeDir;
164
+ console.log(chalk.dim('Removing symlinks and restoring originals...'));
165
+ await adapter.removeSymlinks(workspacePath);
166
+ // Update config
167
+ if (agentName === 'openclaw') {
168
+ config.adapters.openclaw.enabled = false;
169
+ }
170
+ else {
171
+ config.adapters.claude.enabled = false;
172
+ }
173
+ await saveConfig(config);
174
+ console.log(chalk.green(`${displayName} adapter removed.`));
175
+ }
176
+ catch (err) {
177
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
178
+ process.exit(1);
179
+ }
180
+ });
181
+ return cmd;
182
+ }
183
+ export const adapterCommand = new Command('adapter')
184
+ .description('Manage agent adapters')
185
+ .addCommand(createAdapterSubcommands('openclaw', 'OpenClaw'))
186
+ .addCommand(createAdapterSubcommands('claude', 'Claude Code'));
187
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/cli/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const daemonCommand: Command;
3
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiOpC,eAAO,MAAM,aAAa,SAIK,CAAC"}
@@ -0,0 +1,212 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import * as readline from 'node:readline/promises';
4
+ import { stdin, stdout } from 'node:process';
5
+ import { readFile, writeFile, unlink, access } from 'node:fs/promises';
6
+ import { join } from 'node:path';
7
+ import { hexToBytes } from '@noble/hashes/utils';
8
+ import { loadConfig, getConfigPath } from '../config.js';
9
+ import { getPidFilePath } from '../utils/paths.js';
10
+ import { deriveMasterKey, deriveVaultKey, decryptString } from '../crypto/index.js';
11
+ import { SyncEngine } from '../sync/index.js';
12
+ async function isInitialized() {
13
+ try {
14
+ await access(getConfigPath());
15
+ return true;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ function isPidRunning(pid) {
22
+ try {
23
+ process.kill(pid, 0);
24
+ return true;
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ async function readPassphrase(prompt) {
31
+ const rl = readline.createInterface({ input: stdin, output: stdout });
32
+ const answer = await rl.question(prompt);
33
+ rl.close();
34
+ return answer;
35
+ }
36
+ const startCommand = new Command('start')
37
+ .description('Start the sync daemon')
38
+ .option('--foreground', 'Run in the foreground (default for MVP)')
39
+ .action(async () => {
40
+ try {
41
+ if (!(await isInitialized())) {
42
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
43
+ process.exit(1);
44
+ }
45
+ const config = await loadConfig();
46
+ const pidFile = getPidFilePath(config);
47
+ // Check if already running
48
+ try {
49
+ await access(pidFile);
50
+ const pidStr = await readFile(pidFile, 'utf-8');
51
+ const pid = parseInt(pidStr.trim(), 10);
52
+ if (isPidRunning(pid)) {
53
+ console.error(chalk.red(`Daemon is already running (PID: ${pid}).`));
54
+ process.exit(1);
55
+ }
56
+ // Stale PID file, remove it
57
+ await unlink(pidFile);
58
+ }
59
+ catch {
60
+ // No PID file or already cleaned up
61
+ }
62
+ // Load credentials
63
+ const credentialsPath = join(config.data.path, 'credentials.json');
64
+ let credentialsRaw;
65
+ try {
66
+ credentialsRaw = await readFile(credentialsPath, 'utf-8');
67
+ }
68
+ catch {
69
+ console.error(chalk.red('No credentials found. Run "contextmate init" first.'));
70
+ process.exit(1);
71
+ }
72
+ const credentials = JSON.parse(credentialsRaw);
73
+ // Prompt for passphrase
74
+ const passphrase = await readPassphrase(chalk.bold('Enter passphrase: '));
75
+ if (!passphrase) {
76
+ console.error(chalk.red('Error: Passphrase cannot be empty.'));
77
+ process.exit(1);
78
+ }
79
+ // Derive keys
80
+ console.log(chalk.dim('Deriving encryption keys...'));
81
+ const salt = hexToBytes(credentials.salt);
82
+ const masterKey = await deriveMasterKey(passphrase, salt);
83
+ const vaultKey = deriveVaultKey(masterKey);
84
+ // Verify passphrase by trying to decrypt the stored master key
85
+ try {
86
+ const encryptedMasterKeyBytes = hexToBytes(credentials.encryptedMasterKey);
87
+ decryptString(encryptedMasterKeyBytes, vaultKey);
88
+ }
89
+ catch {
90
+ console.error(chalk.red('Error: Invalid passphrase.'));
91
+ process.exit(1);
92
+ }
93
+ // Write PID file
94
+ await writeFile(pidFile, String(process.pid), 'utf-8');
95
+ // Start sync engine (foreground)
96
+ console.log(chalk.green(`Daemon started (PID: ${process.pid})`));
97
+ console.log(chalk.dim('Press Ctrl+C to stop.'));
98
+ const engine = new SyncEngine(config, vaultKey);
99
+ await engine.start();
100
+ // Handle graceful shutdown
101
+ const shutdown = async () => {
102
+ console.log(chalk.dim('\nStopping daemon...'));
103
+ await engine.stop();
104
+ try {
105
+ await unlink(pidFile);
106
+ }
107
+ catch {
108
+ // Already removed
109
+ }
110
+ console.log(chalk.green('Daemon stopped.'));
111
+ process.exit(0);
112
+ };
113
+ process.on('SIGINT', () => void shutdown());
114
+ process.on('SIGTERM', () => void shutdown());
115
+ }
116
+ catch (err) {
117
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
118
+ process.exit(1);
119
+ }
120
+ });
121
+ const stopCommand = new Command('stop')
122
+ .description('Stop the sync daemon')
123
+ .action(async () => {
124
+ try {
125
+ if (!(await isInitialized())) {
126
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
127
+ process.exit(1);
128
+ }
129
+ const config = await loadConfig();
130
+ const pidFile = getPidFilePath(config);
131
+ let pidStr;
132
+ try {
133
+ pidStr = await readFile(pidFile, 'utf-8');
134
+ }
135
+ catch {
136
+ console.log(chalk.dim('Daemon is not running.'));
137
+ return;
138
+ }
139
+ const pid = parseInt(pidStr.trim(), 10);
140
+ if (!isPidRunning(pid)) {
141
+ console.log(chalk.dim('Daemon is not running (stale PID file).'));
142
+ await unlink(pidFile);
143
+ return;
144
+ }
145
+ // Send SIGTERM
146
+ process.kill(pid, 'SIGTERM');
147
+ console.log(chalk.dim(`Sent SIGTERM to PID ${pid}...`));
148
+ // Wait for process to exit (up to 10 seconds)
149
+ let stopped = false;
150
+ for (let i = 0; i < 20; i++) {
151
+ await new Promise((resolve) => setTimeout(resolve, 500));
152
+ if (!isPidRunning(pid)) {
153
+ stopped = true;
154
+ break;
155
+ }
156
+ }
157
+ if (stopped) {
158
+ try {
159
+ await unlink(pidFile);
160
+ }
161
+ catch {
162
+ // Already removed by the daemon
163
+ }
164
+ console.log(chalk.green('Daemon stopped.'));
165
+ }
166
+ else {
167
+ console.log(chalk.yellow(`Daemon (PID: ${pid}) did not stop within 10 seconds.`));
168
+ console.log(chalk.dim(`You may need to kill it manually: kill ${pid}`));
169
+ }
170
+ }
171
+ catch (err) {
172
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
173
+ process.exit(1);
174
+ }
175
+ });
176
+ const statusSubCommand = new Command('status')
177
+ .description('Check daemon status')
178
+ .action(async () => {
179
+ try {
180
+ if (!(await isInitialized())) {
181
+ console.error(chalk.red('ContextMate is not initialized. Run "contextmate init" first.'));
182
+ process.exit(1);
183
+ }
184
+ const config = await loadConfig();
185
+ const pidFile = getPidFilePath(config);
186
+ let pidStr;
187
+ try {
188
+ pidStr = await readFile(pidFile, 'utf-8');
189
+ }
190
+ catch {
191
+ console.log(chalk.dim('Daemon is not running.'));
192
+ return;
193
+ }
194
+ const pid = parseInt(pidStr.trim(), 10);
195
+ if (isPidRunning(pid)) {
196
+ console.log(chalk.green(`Daemon is running (PID: ${pid}).`));
197
+ }
198
+ else {
199
+ console.log(chalk.red(`Daemon is not running (stale PID file, PID: ${pid}).`));
200
+ }
201
+ }
202
+ catch (err) {
203
+ console.error(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
204
+ process.exit(1);
205
+ }
206
+ });
207
+ export const daemonCommand = new Command('daemon')
208
+ .description('Manage the sync daemon')
209
+ .addCommand(startCommand)
210
+ .addCommand(stopCommand)
211
+ .addCommand(statusSubCommand);
212
+ //# sourceMappingURL=daemon.js.map