@xmemo/client 0.4.152 → 0.4.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +75 -7
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ const PACKAGE_NAME = '@xmemo/client';
|
|
|
11
11
|
const FALLBACK_PACKAGE_NAME = '@yonro/xmemo-client';
|
|
12
12
|
const COMMAND_NAME = 'xmemo';
|
|
13
13
|
const LEGACY_COMMAND_NAME = 'memory-os';
|
|
14
|
-
const CLI_VERSION = '0.4.
|
|
14
|
+
const CLI_VERSION = '0.4.153';
|
|
15
15
|
const DEFAULT_SERVICE_URL = 'https://xmemo.dev';
|
|
16
16
|
const TOKEN_ENV_VAR = 'XMEMO_KEY';
|
|
17
17
|
const LEGACY_TOKEN_ENV_VAR = 'MEMORY_OS_MCP_TOKEN';
|
|
@@ -171,6 +171,13 @@ const MCP_CLIENTS = new Map([
|
|
|
171
171
|
writeConfig: mergeTraeMcpConfig,
|
|
172
172
|
configKind: 'json'
|
|
173
173
|
}],
|
|
174
|
+
['trae-solo', {
|
|
175
|
+
label: 'Trae Solo',
|
|
176
|
+
defaultConfigPath: defaultTraeSoloConfigPath,
|
|
177
|
+
buildSnippet: traeSoloJsonSnippet,
|
|
178
|
+
writeConfig: mergeTraeSoloMcpConfig,
|
|
179
|
+
configKind: 'json'
|
|
180
|
+
}],
|
|
174
181
|
['claude-code', {
|
|
175
182
|
label: 'Claude Code',
|
|
176
183
|
defaultConfigPath: defaultClaudecodeConfigPath,
|
|
@@ -206,6 +213,8 @@ const SETUP_CLIENT_ALIASES = new Map([
|
|
|
206
213
|
['qwencli', 'qwen'],
|
|
207
214
|
['qwen-cli', 'qwen'],
|
|
208
215
|
['trae', 'trae'],
|
|
216
|
+
['traesolo', 'trae-solo'],
|
|
217
|
+
['trae-solo', 'trae-solo'],
|
|
209
218
|
['claude-code', 'claude-code'],
|
|
210
219
|
['claudecode', 'claude-code'],
|
|
211
220
|
['claude-cli', 'claude-code'],
|
|
@@ -583,7 +592,7 @@ async function setupCommand(args, io) {
|
|
|
583
592
|
|
|
584
593
|
if (setupAll) {
|
|
585
594
|
setupPlan.detectedClients = [];
|
|
586
|
-
const scanIds = ['codex', 'cursor', 'copilot-cli', 'gemini-cli', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude-desktop', 'qwen', 'opencode', 'trae'];
|
|
595
|
+
const scanIds = ['codex', 'cursor', 'copilot-cli', 'gemini-cli', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude-desktop', 'qwen', 'opencode', 'trae', 'trae-solo'];
|
|
587
596
|
for (const scanId of scanIds) {
|
|
588
597
|
const detection = await detectClient(scanId, io.env);
|
|
589
598
|
if (detection.detected) {
|
|
@@ -1921,9 +1930,9 @@ function writeSetupSummary(plan, io) {
|
|
|
1921
1930
|
writeLine(io.stdout, ' 1. Open or restart Qwen.');
|
|
1922
1931
|
writeLine(io.stdout, ' 2. When Qwen connects to XMemo MCP, a browser window will automatically pop up requesting OAuth authorization.');
|
|
1923
1932
|
writeLine(io.stdout, ' 3. Follow the page prompts to sign in and click "Authorize" to link Qwen.');
|
|
1924
|
-
} else if (cid === 'trae') {
|
|
1925
|
-
writeLine(io.stdout,
|
|
1926
|
-
writeLine(io.stdout,
|
|
1933
|
+
} else if (cid === 'trae' || cid === 'trae-solo') {
|
|
1934
|
+
writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
|
|
1935
|
+
writeLine(io.stdout, ` 1. Restart ${plan.selectedClient.label} to load the new MCP configuration.`);
|
|
1927
1936
|
writeLine(io.stdout, ` 2. Make sure the ${TOKEN_ENV_VAR} environment variable is set in your user environment.`);
|
|
1928
1937
|
if (plan.tokenPortalUrl) {
|
|
1929
1938
|
writeLine(io.stdout, ` (Token portal: ${plan.tokenPortalUrl})`);
|
|
@@ -2973,7 +2982,7 @@ function supportedMcpClientIds() {
|
|
|
2973
2982
|
}
|
|
2974
2983
|
|
|
2975
2984
|
function supportedSetupClientIds() {
|
|
2976
|
-
return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude', 'qwen', 'opencode', 'trae'];
|
|
2985
|
+
return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude', 'qwen', 'opencode', 'trae', 'trae-solo'];
|
|
2977
2986
|
}
|
|
2978
2987
|
|
|
2979
2988
|
function usesClientOAuth(clientId) {
|
|
@@ -3831,8 +3840,14 @@ async function mergeQwenMcpConfig(configPath, mcpUrl, identity) {
|
|
|
3831
3840
|
}
|
|
3832
3841
|
|
|
3833
3842
|
function defaultTraeConfigPath(env) {
|
|
3843
|
+
if (process.platform === 'win32' && env.APPDATA) {
|
|
3844
|
+
return path.join(env.APPDATA, 'Trae', 'User', 'mcp.json');
|
|
3845
|
+
}
|
|
3834
3846
|
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3835
|
-
|
|
3847
|
+
if (process.platform === 'darwin') {
|
|
3848
|
+
return path.join(home, 'Library', 'Application Support', 'Trae', 'User', 'mcp.json');
|
|
3849
|
+
}
|
|
3850
|
+
return path.join(home, '.config', 'Trae', 'User', 'mcp.json');
|
|
3836
3851
|
}
|
|
3837
3852
|
|
|
3838
3853
|
function traeJsonServerConfig(mcpUrl, identity = envReferenceIdentity('trae')) {
|
|
@@ -3878,6 +3893,59 @@ async function mergeTraeMcpConfig(configPath, mcpUrl, identity) {
|
|
|
3878
3893
|
await bestEffortChmod(configPath, 0o600);
|
|
3879
3894
|
}
|
|
3880
3895
|
|
|
3896
|
+
function defaultTraeSoloConfigPath(env) {
|
|
3897
|
+
if (process.platform === 'win32' && env.APPDATA) {
|
|
3898
|
+
return path.join(env.APPDATA, 'TRAE SOLO', 'User', 'mcp.json');
|
|
3899
|
+
}
|
|
3900
|
+
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3901
|
+
if (process.platform === 'darwin') {
|
|
3902
|
+
return path.join(home, 'Library', 'Application Support', 'TRAE SOLO', 'User', 'mcp.json');
|
|
3903
|
+
}
|
|
3904
|
+
return path.join(home, '.config', 'TRAE SOLO', 'User', 'mcp.json');
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3907
|
+
function traeSoloJsonServerConfig(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3908
|
+
return {
|
|
3909
|
+
url: mcpUrl,
|
|
3910
|
+
headers: {
|
|
3911
|
+
Authorization: `Bearer \${env:${TOKEN_ENV_VAR}}`,
|
|
3912
|
+
[AGENT_ID_HEADER]: identity.agentId,
|
|
3913
|
+
[AGENT_INSTANCE_HEADER]: identity.agentInstanceId
|
|
3914
|
+
}
|
|
3915
|
+
};
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
function traeSoloJsonConfig(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3919
|
+
return {
|
|
3920
|
+
mcpServers: {
|
|
3921
|
+
[MCP_SERVER_NAME]: traeSoloJsonServerConfig(mcpUrl, identity)
|
|
3922
|
+
}
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
|
|
3926
|
+
function traeSoloJsonSnippet(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3927
|
+
return `${JSON.stringify(traeSoloJsonConfig(mcpUrl, identity), null, 2)}\n`;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
async function mergeTraeSoloMcpConfig(configPath, mcpUrl, identity) {
|
|
3931
|
+
const existing = await readTextIfExists(configPath);
|
|
3932
|
+
const parsed = existing.trim().length === 0 ? {} : parseJsonConfig(existing, configPath);
|
|
3933
|
+
if (!isPlainObject(parsed)) {
|
|
3934
|
+
throw new UsageError(`MCP JSON config must be an object: ${configPath}`);
|
|
3935
|
+
}
|
|
3936
|
+
if (!isPlainObject(parsed.mcpServers)) {
|
|
3937
|
+
parsed.mcpServers = {};
|
|
3938
|
+
}
|
|
3939
|
+
const existingName = existingJsonMcpServerName(parsed.mcpServers);
|
|
3940
|
+
if (existingName) {
|
|
3941
|
+
throw new UsageError(`MCP config already contains mcpServers.${existingName}. Edit ${configPath} manually to avoid duplicate server definitions.`);
|
|
3942
|
+
}
|
|
3943
|
+
parsed.mcpServers[MCP_SERVER_NAME] = traeSoloJsonServerConfig(mcpUrl, identity);
|
|
3944
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 });
|
|
3945
|
+
await fs.writeFile(configPath, `${JSON.stringify(parsed, null, 2)}\n`, { mode: 0o600 });
|
|
3946
|
+
await bestEffortChmod(configPath, 0o600);
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3881
3949
|
function defaultClaudecodeConfigPath(env) {
|
|
3882
3950
|
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3883
3951
|
return path.join(home, '.claude.json');
|