@xmemo/client 0.4.154 → 0.4.156
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 +2 -2
- package/src/args.js +63 -0
- package/src/auth.js +199 -0
- package/src/base-url.js +12 -0
- package/src/cli.js +23 -3962
- package/src/commands/auth.js +229 -0
- package/src/commands/diagnostics.js +196 -0
- package/src/commands/mcp.js +187 -0
- package/src/commands/profile.js +56 -0
- package/src/commands/setup.js +190 -0
- package/src/commands/update.js +57 -0
- package/src/constants.js +32 -0
- package/src/discovery.js +102 -0
- package/src/env.js +81 -0
- package/src/errors.js +6 -0
- package/src/help.js +58 -0
- package/src/http.js +160 -0
- package/src/io.js +16 -0
- package/src/mcp/clients.js +80 -0
- package/src/mcp/codex.js +147 -0
- package/src/mcp/copilot-proxy.js +43 -0
- package/src/mcp/detect.js +50 -0
- package/src/mcp/hermes.js +71 -0
- package/src/mcp/identity.js +62 -0
- package/src/mcp/json-clients.js +354 -0
- package/src/mcp/names.js +12 -0
- package/src/mcp/paths.js +154 -0
- package/src/mcp/proxy.js +111 -0
- package/src/mcp/registry.js +67 -0
- package/src/mcp/templates.js +155 -0
- package/src/path-config.js +25 -0
- package/src/profile.js +532 -0
- package/src/runtime.js +144 -0
- package/src/setup.js +243 -0
- package/src/version.js +1 -0
package/src/setup.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { optionValue } from './args.js';
|
|
2
|
+
import {
|
|
3
|
+
COMMAND_NAME,
|
|
4
|
+
DEFAULT_PROXY_HOST,
|
|
5
|
+
MCP_SERVER_NAME,
|
|
6
|
+
PRODUCT_NAME,
|
|
7
|
+
TOKEN_ENV_VAR
|
|
8
|
+
} from './constants.js';
|
|
9
|
+
import { UsageError } from './errors.js';
|
|
10
|
+
import { writeLine } from './io.js';
|
|
11
|
+
import { supportedMcpClientIds, usesClientOAuth } from './mcp/registry.js';
|
|
12
|
+
import { mcpLocalProxyTemplate } from './mcp/templates.js';
|
|
13
|
+
import { defaultCopilotConfigPath } from './path-config.js';
|
|
14
|
+
import { profileClientConfig } from './profile.js';
|
|
15
|
+
|
|
16
|
+
const SETUP_CLIENT_ALIASES = new Map([
|
|
17
|
+
['codex', 'codex'],
|
|
18
|
+
['cursor', 'cursor'],
|
|
19
|
+
['copilot', 'copilot-cli'],
|
|
20
|
+
['copilot-cli', 'copilot-cli'],
|
|
21
|
+
['gemini', 'gemini-cli'],
|
|
22
|
+
['gemini-cli', 'gemini-cli'],
|
|
23
|
+
['antigravity', 'antigravity'],
|
|
24
|
+
['antigravity-ide', 'antigravity-ide'],
|
|
25
|
+
['antigravity2', 'antigravity2'],
|
|
26
|
+
['antigravity-cli', 'antigravity-cli'],
|
|
27
|
+
['windsurf', 'windsurf'],
|
|
28
|
+
['cline', 'cline'],
|
|
29
|
+
['continue', 'continue'],
|
|
30
|
+
['claude', 'claude-desktop'],
|
|
31
|
+
['claude-desktop', 'claude-desktop'],
|
|
32
|
+
['openclaw', 'openclaw'],
|
|
33
|
+
['kiro', 'kiro'],
|
|
34
|
+
['zed', 'zed'],
|
|
35
|
+
['jetbrains', 'jetbrains'],
|
|
36
|
+
['opencode', 'opencode'],
|
|
37
|
+
['hermes', 'hermes'],
|
|
38
|
+
['qwen', 'qwen'],
|
|
39
|
+
['qwencli', 'qwen'],
|
|
40
|
+
['qwen-cli', 'qwen'],
|
|
41
|
+
['trae', 'trae'],
|
|
42
|
+
['traesolo', 'trae-solo'],
|
|
43
|
+
['trae-solo', 'trae-solo'],
|
|
44
|
+
['claude-code', 'claude-code'],
|
|
45
|
+
['claudecode', 'claude-code'],
|
|
46
|
+
['claude-cli', 'claude-code'],
|
|
47
|
+
['claudecode-cli', 'claude-code']
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
export function supportedSetupClientIds(mcpClients) {
|
|
51
|
+
return [...supportedMcpClientIds(mcpClients), 'copilot-cli'];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function requiredOption(args, name) {
|
|
55
|
+
const value = optionValue(args, name);
|
|
56
|
+
if (!value) {
|
|
57
|
+
throw new UsageError(`Missing required option ${name}.`);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function positionalClientArg(args, mcpClients) {
|
|
63
|
+
const candidate = args[0];
|
|
64
|
+
if (!candidate || candidate.startsWith('--')) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return normalizeSetupClientId(candidate, mcpClients);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function normalizeSetupClientId(candidate, mcpClients) {
|
|
72
|
+
if (!candidate) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const normalized = SETUP_CLIENT_ALIASES.get(candidate);
|
|
77
|
+
if (!normalized) {
|
|
78
|
+
throw new UsageError(`Unsupported setup client: ${candidate}. Supported clients: ${supportedSetupClientIds(mcpClients).join(', ')}.`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return normalized;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function clientSetupPlan(clientId, client, mcpUrl, env, identity) {
|
|
85
|
+
return {
|
|
86
|
+
id: clientId,
|
|
87
|
+
label: client.label,
|
|
88
|
+
configKind: client.configKind,
|
|
89
|
+
configPath: client.defaultConfigPath(env),
|
|
90
|
+
serverName: MCP_SERVER_NAME,
|
|
91
|
+
mcpUrl,
|
|
92
|
+
tokenEnvVar: TOKEN_ENV_VAR,
|
|
93
|
+
agentId: identity.agentId,
|
|
94
|
+
agentInstanceId: identity.agentInstanceId,
|
|
95
|
+
agentInstanceIdPath: identity.path,
|
|
96
|
+
writesTokenValue: false,
|
|
97
|
+
written: false
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function copilotSetupPlan(mcpUrl, proxyPort, env) {
|
|
102
|
+
const proxyUrl = `http://${DEFAULT_PROXY_HOST}:${proxyPort}/mcp`;
|
|
103
|
+
const template = mcpLocalProxyTemplate('copilot-cli', proxyUrl);
|
|
104
|
+
return {
|
|
105
|
+
id: 'copilot-cli',
|
|
106
|
+
label: 'Copilot CLI',
|
|
107
|
+
configKind: 'local-proxy',
|
|
108
|
+
configPath: defaultCopilotConfigPath(env),
|
|
109
|
+
serverName: template.serverName,
|
|
110
|
+
mcpUrl,
|
|
111
|
+
proxyUrl,
|
|
112
|
+
tokenEnvVar: TOKEN_ENV_VAR,
|
|
113
|
+
requiresCredential: template.requiresCredential,
|
|
114
|
+
requiresLocalCommand: template.requiresLocalCommand,
|
|
115
|
+
template: template.snippet,
|
|
116
|
+
agentId: template.agentIdentity.agentId,
|
|
117
|
+
writesTokenValue: false,
|
|
118
|
+
writeSupported: true,
|
|
119
|
+
written: false
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function writeSetupSummary(plan, io) {
|
|
124
|
+
writeLine(io.stdout, `${PRODUCT_NAME} setup discovery: ${plan.baseUrl}`);
|
|
125
|
+
writeLine(io.stdout, ` API: ${plan.apiBase}`);
|
|
126
|
+
writeLine(io.stdout, ` MCP: ${plan.mcpUrl}`);
|
|
127
|
+
writeLine(io.stdout, ` Guide: ${plan.guideUrl}`);
|
|
128
|
+
if (plan.docsUrl) {
|
|
129
|
+
writeLine(io.stdout, ` Docs: ${plan.docsUrl}`);
|
|
130
|
+
}
|
|
131
|
+
if (plan.tokenPortalUrl) {
|
|
132
|
+
writeLine(io.stdout, ` Token portal: ${plan.tokenPortalUrl}`);
|
|
133
|
+
}
|
|
134
|
+
writeLine(io.stdout, ` Token env var: ${plan.tokenEnvVar}`);
|
|
135
|
+
writeLine(io.stdout, ` Onboarding ready: ${plan.onboardingReady === null ? 'unknown' : plan.onboardingReady}`);
|
|
136
|
+
writeLine(io.stdout, 'Privacy: telemetry disabled; no token sent; generated config references env vars only.');
|
|
137
|
+
|
|
138
|
+
if (plan.boundaries.adminRequired.length > 0) {
|
|
139
|
+
writeLine(io.stdout, `Admin-only actions: ${plan.boundaries.adminRequired.join(', ')}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (plan.detectedClients) {
|
|
143
|
+
writeLine(io.stdout, '');
|
|
144
|
+
if (plan.detectedClients.length === 0) {
|
|
145
|
+
writeLine(io.stdout, 'No local IDE or CLI client configurations were detected.');
|
|
146
|
+
writeLine(io.stdout, `Run \`${COMMAND_NAME} setup <client>\` to configure a client manually.`);
|
|
147
|
+
} else {
|
|
148
|
+
writeLine(io.stdout, `Auto-detected ${plan.detectedClients.length} client(s):`);
|
|
149
|
+
for (const client of plan.detectedClients) {
|
|
150
|
+
writeLine(io.stdout, ` [${client.written ? '✔' : ' '}] ${client.label}`);
|
|
151
|
+
writeLine(io.stdout, ` Config: ${client.configPath}`);
|
|
152
|
+
writeLine(io.stdout, ` Agent ID: ${client.agentId}`);
|
|
153
|
+
}
|
|
154
|
+
if (plan.detectedClients.some(c => c.written)) {
|
|
155
|
+
writeLine(io.stdout, '');
|
|
156
|
+
writeLine(io.stdout, 'Successfully applied XMemo MCP configuration to all detected clients!');
|
|
157
|
+
writeLine(io.stdout, 'Restart your IDEs or reload their MCP configurations to apply the changes.');
|
|
158
|
+
} else {
|
|
159
|
+
writeLine(io.stdout, '');
|
|
160
|
+
writeLine(io.stdout, `Run \`${COMMAND_NAME} setup --all --write\` to write configurations for all detected clients.`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (plan.selectedClient) {
|
|
167
|
+
writeLine(io.stdout, '');
|
|
168
|
+
writeLine(io.stdout, `Selected client: ${plan.selectedClient.label}`);
|
|
169
|
+
writeLine(io.stdout, ` Config path: ${plan.selectedClient.configPath}`);
|
|
170
|
+
writeLine(io.stdout, ` Written: ${plan.selectedClient.written}`);
|
|
171
|
+
writeLine(io.stdout, ` Token value embedded: ${plan.selectedClient.writesTokenValue}`);
|
|
172
|
+
writeLine(io.stdout, ` Agent ID: ${plan.selectedClient.agentId}`);
|
|
173
|
+
if (plan.selectedClient.agentInstanceIdPath) {
|
|
174
|
+
writeLine(io.stdout, ` Agent instance ID stored: ${plan.selectedClient.agentInstanceIdPath}`);
|
|
175
|
+
}
|
|
176
|
+
if (plan.selectedClient.configKind === 'local-proxy') {
|
|
177
|
+
writeLine(io.stdout, ` Local proxy: ${plan.selectedClient.requiresLocalCommand}`);
|
|
178
|
+
if (plan.selectedClient.written) {
|
|
179
|
+
writeLine(io.stdout, ` Next: keep \`${plan.selectedClient.requiresLocalCommand}\` running while you use Copilot CLI.`);
|
|
180
|
+
writeLine(io.stdout, ' If Copilot CLI is already open, reload MCP config or restart Copilot CLI.');
|
|
181
|
+
} else {
|
|
182
|
+
writeLine(io.stdout, ' MCP template:');
|
|
183
|
+
writeLine(io.stdout, JSON.stringify(plan.selectedClient.template, null, 2));
|
|
184
|
+
writeLine(io.stdout, ` Next: ${COMMAND_NAME} setup copilot --url ${plan.baseUrl}`);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (plan.selectedClient.behaviorProfile) {
|
|
189
|
+
const profile = plan.selectedClient.behaviorProfile;
|
|
190
|
+
const profileClient = profileClientConfig(profile.client);
|
|
191
|
+
writeLine(io.stdout, ` Behavior profile target: ${profile.targetPath}`);
|
|
192
|
+
writeLine(io.stdout, ` Behavior profile client: ${profileClient?.label ?? profile.client}`);
|
|
193
|
+
writeLine(io.stdout, ` Behavior profile installed: ${profile.written}`);
|
|
194
|
+
writeLine(io.stdout, ` Behavior profile changed: ${profile.changed}`);
|
|
195
|
+
if (!profile.written) {
|
|
196
|
+
writeLine(io.stdout, ` Profile preview: ${COMMAND_NAME} profile install ${profile.client} --target ${profile.targetPath}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (plan.selectedClient.written) {
|
|
200
|
+
writeLine(io.stdout, '');
|
|
201
|
+
const cid = plan.selectedClient.id;
|
|
202
|
+
if (cid === 'opencode') {
|
|
203
|
+
writeLine(io.stdout, '💡 Next steps for OpenCode:');
|
|
204
|
+
writeLine(io.stdout, ' 1. Open or restart OpenCode.');
|
|
205
|
+
writeLine(io.stdout, ' 2. Trigger any XMemo tool call, or manually run `opencode mcp auth XMemo` in your terminal.');
|
|
206
|
+
writeLine(io.stdout, ' 3. A browser window will automatically pop up requesting XMemo OAuth authorization.');
|
|
207
|
+
writeLine(io.stdout, ' 4. Log in or register on the webpage, then click "Authorize" to link OpenCode.');
|
|
208
|
+
} else if (cid === 'qwen') {
|
|
209
|
+
writeLine(io.stdout, '💡 Next steps for Qwen:');
|
|
210
|
+
writeLine(io.stdout, ' 1. Open or restart Qwen.');
|
|
211
|
+
writeLine(io.stdout, ' 2. When Qwen connects to XMemo MCP, a browser window will automatically pop up requesting OAuth authorization.');
|
|
212
|
+
writeLine(io.stdout, ' 3. Follow the page prompts to sign in and click "Authorize" to link Qwen.');
|
|
213
|
+
} else if (cid === 'trae' || cid === 'trae-solo') {
|
|
214
|
+
writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
|
|
215
|
+
writeLine(io.stdout, ` 1. Restart ${plan.selectedClient.label} to load the new MCP configuration.`);
|
|
216
|
+
writeLine(io.stdout, ` 2. Make sure the ${TOKEN_ENV_VAR} environment variable is set in your user environment.`);
|
|
217
|
+
if (plan.tokenPortalUrl) {
|
|
218
|
+
writeLine(io.stdout, ` (Token portal: ${plan.tokenPortalUrl})`);
|
|
219
|
+
}
|
|
220
|
+
} else if (usesClientOAuth(cid)) {
|
|
221
|
+
writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
|
|
222
|
+
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.');
|
|
223
|
+
writeLine(io.stdout, ' 2. Follow the page prompts to sign in and click "Authorize".');
|
|
224
|
+
} else {
|
|
225
|
+
writeLine(io.stdout, `💡 Next steps for ${plan.selectedClient.label}:`);
|
|
226
|
+
writeLine(io.stdout, ' 1. Restart your editor/client to load the new MCP configuration.');
|
|
227
|
+
writeLine(io.stdout, ` 2. Make sure the ${TOKEN_ENV_VAR} environment variable is set in your user environment.`);
|
|
228
|
+
if (plan.tokenPortalUrl) {
|
|
229
|
+
writeLine(io.stdout, ` (Token portal: ${plan.tokenPortalUrl})`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
writeLine(io.stdout, ` Next: ${COMMAND_NAME} setup ${plan.selectedClient.id} --url ${plan.baseUrl}`);
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
writeLine(io.stdout, '');
|
|
239
|
+
writeLine(io.stdout, 'Next steps:');
|
|
240
|
+
writeLine(io.stdout, ` 1. Create a scoped token in the token portal and store it in ${plan.tokenEnvVar}.`);
|
|
241
|
+
writeLine(io.stdout, ` 2. Configure a client, for example: ${COMMAND_NAME} setup codex --url ${plan.baseUrl}`);
|
|
242
|
+
writeLine(io.stdout, ` 3. Run ${COMMAND_NAME} status to smoke-test the service without sending the token.`);
|
|
243
|
+
}
|
package/src/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CLI_VERSION = '0.4.156';
|