@xmemo/client 0.4.152 → 0.4.154
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 +120 -14
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.154';
|
|
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) {
|
|
@@ -3476,7 +3485,13 @@ function claudeJsonServerConfig(mcpUrl, identity = envReferenceIdentity('claude-
|
|
|
3476
3485
|
args: [
|
|
3477
3486
|
'-y',
|
|
3478
3487
|
'mcp-remote',
|
|
3479
|
-
mcpUrl
|
|
3488
|
+
mcpUrl,
|
|
3489
|
+
'--header',
|
|
3490
|
+
`Authorization:Bearer \${${TOKEN_ENV_VAR}}`,
|
|
3491
|
+
'--header',
|
|
3492
|
+
`X-Memory-OS-Agent-ID:${identity.agentId}`,
|
|
3493
|
+
'--header',
|
|
3494
|
+
`X-Memory-OS-Agent-Instance-ID:\${${AGENT_INSTANCE_ENV_VAR}}`
|
|
3480
3495
|
],
|
|
3481
3496
|
env: {
|
|
3482
3497
|
[TOKEN_ENV_VAR]: `\${env:${TOKEN_ENV_VAR}}`,
|
|
@@ -3624,7 +3639,13 @@ function zedJsonServerConfig(mcpUrl, identity = envReferenceIdentity('zed')) {
|
|
|
3624
3639
|
args: [
|
|
3625
3640
|
'-y',
|
|
3626
3641
|
'mcp-remote',
|
|
3627
|
-
mcpUrl
|
|
3642
|
+
mcpUrl,
|
|
3643
|
+
'--header',
|
|
3644
|
+
`Authorization:Bearer \${${TOKEN_ENV_VAR}}`,
|
|
3645
|
+
'--header',
|
|
3646
|
+
`X-Memory-OS-Agent-ID:${identity.agentId}`,
|
|
3647
|
+
'--header',
|
|
3648
|
+
`X-Memory-OS-Agent-Instance-ID:\${${AGENT_INSTANCE_ENV_VAR}}`
|
|
3628
3649
|
],
|
|
3629
3650
|
env: {
|
|
3630
3651
|
[TOKEN_ENV_VAR]: `\${env:${TOKEN_ENV_VAR}}`,
|
|
@@ -3746,6 +3767,12 @@ function hermesYamlSnippet(mcpUrl, identity = envReferenceIdentity('hermes')) {
|
|
|
3746
3767
|
- -y
|
|
3747
3768
|
- mcp-remote
|
|
3748
3769
|
- ${mcpUrl}
|
|
3770
|
+
- --header
|
|
3771
|
+
- "Authorization:Bearer \${${TOKEN_ENV_VAR}}"
|
|
3772
|
+
- --header
|
|
3773
|
+
- "X-Memory-OS-Agent-ID:${identity.agentId}"
|
|
3774
|
+
- --header
|
|
3775
|
+
- "X-Memory-OS-Agent-Instance-ID:\${${AGENT_INSTANCE_ENV_VAR}}"
|
|
3749
3776
|
env:
|
|
3750
3777
|
${TOKEN_ENV_VAR}: "\${env:${TOKEN_ENV_VAR}}"
|
|
3751
3778
|
${AGENT_INSTANCE_ENV_VAR}: "${identity.agentInstanceId}"
|
|
@@ -3831,17 +3858,33 @@ async function mergeQwenMcpConfig(configPath, mcpUrl, identity) {
|
|
|
3831
3858
|
}
|
|
3832
3859
|
|
|
3833
3860
|
function defaultTraeConfigPath(env) {
|
|
3861
|
+
if (process.platform === 'win32' && env.APPDATA) {
|
|
3862
|
+
return path.join(env.APPDATA, 'Trae', 'User', 'mcp.json');
|
|
3863
|
+
}
|
|
3834
3864
|
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3835
|
-
|
|
3865
|
+
if (process.platform === 'darwin') {
|
|
3866
|
+
return path.join(home, 'Library', 'Application Support', 'Trae', 'User', 'mcp.json');
|
|
3867
|
+
}
|
|
3868
|
+
return path.join(home, '.config', 'Trae', 'User', 'mcp.json');
|
|
3836
3869
|
}
|
|
3837
3870
|
|
|
3838
3871
|
function traeJsonServerConfig(mcpUrl, identity = envReferenceIdentity('trae')) {
|
|
3839
3872
|
return {
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3873
|
+
command: 'npx',
|
|
3874
|
+
args: [
|
|
3875
|
+
'-y',
|
|
3876
|
+
'mcp-remote',
|
|
3877
|
+
mcpUrl,
|
|
3878
|
+
'--header',
|
|
3879
|
+
`Authorization:Bearer \${${TOKEN_ENV_VAR}}`,
|
|
3880
|
+
'--header',
|
|
3881
|
+
`X-Memory-OS-Agent-ID:${identity.agentId}`,
|
|
3882
|
+
'--header',
|
|
3883
|
+
`X-Memory-OS-Agent-Instance-ID:\${${AGENT_INSTANCE_ENV_VAR}}`
|
|
3884
|
+
],
|
|
3885
|
+
env: {
|
|
3886
|
+
[TOKEN_ENV_VAR]: `\${env:${TOKEN_ENV_VAR}}`,
|
|
3887
|
+
[AGENT_INSTANCE_ENV_VAR]: identity.agentInstanceId
|
|
3845
3888
|
}
|
|
3846
3889
|
};
|
|
3847
3890
|
}
|
|
@@ -3878,6 +3921,69 @@ async function mergeTraeMcpConfig(configPath, mcpUrl, identity) {
|
|
|
3878
3921
|
await bestEffortChmod(configPath, 0o600);
|
|
3879
3922
|
}
|
|
3880
3923
|
|
|
3924
|
+
function defaultTraeSoloConfigPath(env) {
|
|
3925
|
+
if (process.platform === 'win32' && env.APPDATA) {
|
|
3926
|
+
return path.join(env.APPDATA, 'TRAE SOLO', 'User', 'mcp.json');
|
|
3927
|
+
}
|
|
3928
|
+
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3929
|
+
if (process.platform === 'darwin') {
|
|
3930
|
+
return path.join(home, 'Library', 'Application Support', 'TRAE SOLO', 'User', 'mcp.json');
|
|
3931
|
+
}
|
|
3932
|
+
return path.join(home, '.config', 'TRAE SOLO', 'User', 'mcp.json');
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
function traeSoloJsonServerConfig(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3936
|
+
return {
|
|
3937
|
+
command: 'npx',
|
|
3938
|
+
args: [
|
|
3939
|
+
'-y',
|
|
3940
|
+
'mcp-remote',
|
|
3941
|
+
mcpUrl,
|
|
3942
|
+
'--header',
|
|
3943
|
+
`Authorization:Bearer \${${TOKEN_ENV_VAR}}`,
|
|
3944
|
+
'--header',
|
|
3945
|
+
`X-Memory-OS-Agent-ID:${identity.agentId}`,
|
|
3946
|
+
'--header',
|
|
3947
|
+
`X-Memory-OS-Agent-Instance-ID:\${${AGENT_INSTANCE_ENV_VAR}}`
|
|
3948
|
+
],
|
|
3949
|
+
env: {
|
|
3950
|
+
[TOKEN_ENV_VAR]: `\${env:${TOKEN_ENV_VAR}}`,
|
|
3951
|
+
[AGENT_INSTANCE_ENV_VAR]: identity.agentInstanceId
|
|
3952
|
+
}
|
|
3953
|
+
};
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3956
|
+
function traeSoloJsonConfig(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3957
|
+
return {
|
|
3958
|
+
mcpServers: {
|
|
3959
|
+
[MCP_SERVER_NAME]: traeSoloJsonServerConfig(mcpUrl, identity)
|
|
3960
|
+
}
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
function traeSoloJsonSnippet(mcpUrl, identity = envReferenceIdentity('trae-solo')) {
|
|
3965
|
+
return `${JSON.stringify(traeSoloJsonConfig(mcpUrl, identity), null, 2)}\n`;
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
async function mergeTraeSoloMcpConfig(configPath, mcpUrl, identity) {
|
|
3969
|
+
const existing = await readTextIfExists(configPath);
|
|
3970
|
+
const parsed = existing.trim().length === 0 ? {} : parseJsonConfig(existing, configPath);
|
|
3971
|
+
if (!isPlainObject(parsed)) {
|
|
3972
|
+
throw new UsageError(`MCP JSON config must be an object: ${configPath}`);
|
|
3973
|
+
}
|
|
3974
|
+
if (!isPlainObject(parsed.mcpServers)) {
|
|
3975
|
+
parsed.mcpServers = {};
|
|
3976
|
+
}
|
|
3977
|
+
const existingName = existingJsonMcpServerName(parsed.mcpServers);
|
|
3978
|
+
if (existingName) {
|
|
3979
|
+
throw new UsageError(`MCP config already contains mcpServers.${existingName}. Edit ${configPath} manually to avoid duplicate server definitions.`);
|
|
3980
|
+
}
|
|
3981
|
+
parsed.mcpServers[MCP_SERVER_NAME] = traeSoloJsonServerConfig(mcpUrl, identity);
|
|
3982
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 });
|
|
3983
|
+
await fs.writeFile(configPath, `${JSON.stringify(parsed, null, 2)}\n`, { mode: 0o600 });
|
|
3984
|
+
await bestEffortChmod(configPath, 0o600);
|
|
3985
|
+
}
|
|
3986
|
+
|
|
3881
3987
|
function defaultClaudecodeConfigPath(env) {
|
|
3882
3988
|
const home = env.USERPROFILE || env.HOME || os.homedir();
|
|
3883
3989
|
return path.join(home, '.claude.json');
|