@xmemo/client 0.4.148 → 0.4.152

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +68 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmemo/client",
3
- "version": "0.4.148",
3
+ "version": "0.4.152",
4
4
  "description": "Privacy-first CLI and MCP setup helper for XMemo.",
5
5
  "type": "module",
6
6
  "bin": {
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.148';
14
+ const CLI_VERSION = '0.4.152';
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';
@@ -583,7 +583,7 @@ async function setupCommand(args, io) {
583
583
 
584
584
  if (setupAll) {
585
585
  setupPlan.detectedClients = [];
586
- const scanIds = ['codex', 'cursor', 'copilot-cli', 'gemini-cli', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude-desktop', 'qwen'];
586
+ const scanIds = ['codex', 'cursor', 'copilot-cli', 'gemini-cli', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude-desktop', 'qwen', 'opencode', 'trae'];
587
587
  for (const scanId of scanIds) {
588
588
  const detection = await detectClient(scanId, io.env);
589
589
  if (detection.detected) {
@@ -684,9 +684,9 @@ async function profileCommand(args, io) {
684
684
  const subcommand = args[0] ?? 'help';
685
685
  if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
686
686
  writeLine(io.stdout, 'Profile commands:');
687
- writeLine(io.stdout, ` ${COMMAND_NAME} profile install <codex|cursor|gemini|antigravity|qwen> [--target <path>] [--dry-run|--json]`);
688
- writeLine(io.stdout, ` ${COMMAND_NAME} profile status <codex|cursor|gemini|antigravity|qwen> [--target <path>] [--json]`);
689
- writeLine(io.stdout, ` ${COMMAND_NAME} profile uninstall <codex|cursor|gemini|antigravity|qwen> [--target <path>] [--json]`);
687
+ writeLine(io.stdout, ` ${COMMAND_NAME} profile install <codex|cursor|gemini|antigravity|qwen|opencode> [--target <path>] [--dry-run|--json]`);
688
+ writeLine(io.stdout, ` ${COMMAND_NAME} profile status <codex|cursor|gemini|antigravity|qwen|opencode> [--target <path>] [--json]`);
689
+ writeLine(io.stdout, ` ${COMMAND_NAME} profile uninstall <codex|cursor|gemini|antigravity|qwen|opencode> [--target <path>] [--json]`);
690
690
  writeLine(io.stdout, '');
691
691
  writeLine(io.stdout, 'Profile installs are marker-scoped and never write token values.');
692
692
  return 0;
@@ -1655,7 +1655,11 @@ function mcpConfigTemplate(clientId, mcpUrl) {
1655
1655
  }
1656
1656
 
1657
1657
  if (clientId === 'qwen') {
1658
- return bearerJsonMcpTemplate(clientId, mcpUrl, qwenJsonConfig(mcpUrl));
1658
+ return oauthJsonMcpTemplate(clientId, mcpUrl, qwenJsonConfig(mcpUrl));
1659
+ }
1660
+
1661
+ if (clientId === 'opencode') {
1662
+ return oauthJsonMcpTemplate(clientId, mcpUrl, opencodeJsonConfig(mcpUrl));
1659
1663
  }
1660
1664
 
1661
1665
  return {
@@ -1903,7 +1907,40 @@ function writeSetupSummary(plan, io) {
1903
1907
  writeLine(io.stdout, ` Profile preview: ${COMMAND_NAME} profile install ${profile.client} --target ${profile.targetPath}`);
1904
1908
  }
1905
1909
  }
1906
- if (!plan.selectedClient.written) {
1910
+ if (plan.selectedClient.written) {
1911
+ writeLine(io.stdout, '');
1912
+ const cid = plan.selectedClient.id;
1913
+ if (cid === 'opencode') {
1914
+ writeLine(io.stdout, '💡 Next steps for OpenCode:');
1915
+ writeLine(io.stdout, ' 1. Open or restart OpenCode.');
1916
+ writeLine(io.stdout, ' 2. Trigger any XMemo tool call, or manually run `opencode mcp auth XMemo` in your terminal.');
1917
+ writeLine(io.stdout, ' 3. A browser window will automatically pop up requesting XMemo OAuth authorization.');
1918
+ writeLine(io.stdout, ' 4. Log in or register on the webpage, then click "Authorize" to link OpenCode.');
1919
+ } else if (cid === 'qwen') {
1920
+ writeLine(io.stdout, '💡 Next steps for Qwen:');
1921
+ writeLine(io.stdout, ' 1. Open or restart Qwen.');
1922
+ writeLine(io.stdout, ' 2. When Qwen connects to XMemo MCP, a browser window will automatically pop up requesting OAuth authorization.');
1923
+ 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, '💡 Next steps for Trae:');
1926
+ writeLine(io.stdout, ' 1. Restart Trae to load the new MCP configuration.');
1927
+ writeLine(io.stdout, ` 2. Make sure the ${TOKEN_ENV_VAR} environment variable is set in your user environment.`);
1928
+ if (plan.tokenPortalUrl) {
1929
+ writeLine(io.stdout, ` (Token portal: ${plan.tokenPortalUrl})`);
1930
+ }
1931
+ } else if (usesClientOAuth(cid)) {
1932
+ writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
1933
+ writeLine(io.stdout, ' 1. When the agent starts or first makes an XMemo tool call, a browser window will automatically pop up requesting OAuth authorization.');
1934
+ writeLine(io.stdout, ' 2. Follow the page prompts to sign in and click "Authorize".');
1935
+ } else {
1936
+ writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
1937
+ writeLine(io.stdout, ' 1. Restart your editor/client to load the new MCP configuration.');
1938
+ writeLine(io.stdout, ` 2. Make sure the ${TOKEN_ENV_VAR} environment variable is set in your user environment.`);
1939
+ if (plan.tokenPortalUrl) {
1940
+ writeLine(io.stdout, ` (Token portal: ${plan.tokenPortalUrl})`);
1941
+ }
1942
+ }
1943
+ } else {
1907
1944
  writeLine(io.stdout, ` Next: ${COMMAND_NAME} setup ${plan.selectedClient.id} --url ${plan.baseUrl}`);
1908
1945
  }
1909
1946
  return;
@@ -2106,13 +2143,28 @@ function profileClientConfig(clientId) {
2106
2143
  return path.join(userHome(env), '.qwen', 'QWEN.md');
2107
2144
  },
2108
2145
  authInstruction: `Keep XMemo authentication through the ${TOKEN_ENV_VAR} environment variable; do not paste token values into prompts, config files, or logs.`
2146
+ },
2147
+ opencode: {
2148
+ label: 'OpenCode',
2149
+ setupAlias: 'opencode',
2150
+ profileVersion: 'opencode-mcp-depth-v1',
2151
+ markerStart: `<!-- ${PROFILE_MARKER_PREFIX}:opencode:start -->`,
2152
+ markerEnd: `<!-- ${PROFILE_MARKER_PREFIX}:opencode:end -->`,
2153
+ defaultTarget: (env) => {
2154
+ const isTest = env.HOME && (env.HOME.includes('memory-os-') || env.HOME.includes('test'));
2155
+ if (!isTest && (existsSync(path.join(process.cwd(), '.git')) || existsSync(path.join(process.cwd(), 'package.json')))) {
2156
+ return path.join(process.cwd(), 'AGENTS.md');
2157
+ }
2158
+ return path.join(userHome(env), '.config', 'opencode', 'AGENTS.md');
2159
+ },
2160
+ authInstruction: 'Use the client-managed MCP OAuth credential; do not paste token values into prompts, config files, or logs.'
2109
2161
  }
2110
2162
  };
2111
2163
  return profileConfigs[clientId] ?? null;
2112
2164
  }
2113
2165
 
2114
2166
  function supportedProfileClientIds() {
2115
- return ['codex', 'cursor', 'gemini', 'antigravity', 'qwen'];
2167
+ return ['codex', 'cursor', 'gemini', 'antigravity', 'qwen', 'opencode'];
2116
2168
  }
2117
2169
 
2118
2170
  function defaultProfileTarget(clientId, env) {
@@ -2921,11 +2973,11 @@ function supportedMcpClientIds() {
2921
2973
  }
2922
2974
 
2923
2975
  function supportedSetupClientIds() {
2924
- return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude', 'qwen'];
2976
+ return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli', 'windsurf', 'cline', 'continue', 'claude', 'qwen', 'opencode', 'trae'];
2925
2977
  }
2926
2978
 
2927
2979
  function usesClientOAuth(clientId) {
2928
- return clientId === 'gemini-cli' || clientId === 'antigravity' || clientId === 'antigravity-ide' || clientId === 'antigravity2' || clientId === 'antigravity-cli';
2980
+ return clientId === 'gemini-cli' || clientId === 'antigravity' || clientId === 'antigravity-ide' || clientId === 'antigravity2' || clientId === 'antigravity-cli' || clientId === 'qwen' || clientId === 'opencode';
2929
2981
  }
2930
2982
 
2931
2983
  function credentialsPath(env) {
@@ -3640,16 +3692,12 @@ function defaultOpencodeConfigPath(env) {
3640
3692
 
3641
3693
  function opencodeJsonServerConfig(mcpUrl, identity = envReferenceIdentity('opencode')) {
3642
3694
  return {
3643
- type: 'local',
3644
- command: [
3645
- 'npx',
3646
- '-y',
3647
- 'mcp-remote',
3648
- mcpUrl
3649
- ],
3650
- environment: {
3651
- [TOKEN_ENV_VAR]: `\${env:${TOKEN_ENV_VAR}}`,
3652
- [AGENT_INSTANCE_ENV_VAR]: identity.agentInstanceId
3695
+ type: 'remote',
3696
+ url: mcpUrl,
3697
+ enabled: true,
3698
+ headers: {
3699
+ [AGENT_ID_HEADER]: identity.agentId,
3700
+ [AGENT_INSTANCE_HEADER]: identity.agentInstanceId
3653
3701
  }
3654
3702
  };
3655
3703
  }
@@ -3744,7 +3792,6 @@ function qwenJsonServerConfig(mcpUrl, identity = envReferenceIdentity('qwen')) {
3744
3792
  return {
3745
3793
  httpUrl: mcpUrl,
3746
3794
  headers: {
3747
- Authorization: `Bearer \${env:${TOKEN_ENV_VAR}}`,
3748
3795
  [AGENT_ID_HEADER]: identity.agentId,
3749
3796
  [AGENT_INSTANCE_HEADER]: identity.agentInstanceId
3750
3797
  }