patchxnote-agent 0.2.7 → 0.2.8

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/README.md CHANGED
@@ -9,7 +9,23 @@ PatchXNote Agent is the local AI assistant connector for PatchXNote. It lets an
9
9
  Give this one-line prompt to a local-command-capable AI assistant:
10
10
 
11
11
  ```text
12
- Connect PatchXNote Agent by following the public guide at https://patchx2025.feishu.cn/wiki/PnVRwYT7IirFPckairGcWPnHnCd: run npx -y patchxnote-agent@latest mcp config, add the printed MCP JSON config to this AI assistant, then guide me through npx -y patchxnote-agent@latest login in the editor terminal. Do not ask me to paste OTP codes, access tokens, or refresh tokens into chat. GitHub repository: https://github.com/ZsTs119/patchxnote-agent
12
+ Connect PatchXNote Agent by following the public guide at https://patchx2025.feishu.cn/wiki/PnVRwYT7IirFPckairGcWPnHnCd: run npx -y patchxnote-agent@latest setup --client <my-client>, keep MCP config secret-free, and guide me through login in the same runtime that will launch the MCP server. Do not ask me to paste OTP codes, access tokens, or refresh tokens into chat. GitHub repository: https://github.com/ZsTs119/patchxnote-agent
13
+ ```
14
+
15
+ Run setup for a supported local client:
16
+
17
+ ```sh
18
+ npx -y patchxnote-agent@latest setup --client cursor
19
+ npx -y patchxnote-agent@latest setup --client vscode
20
+ npx -y patchxnote-agent@latest setup --client codex
21
+ ```
22
+
23
+ Log in with browser OAuth, then check or clear the MCP login state:
24
+
25
+ ```sh
26
+ npx -y patchxnote-agent@latest mcp login
27
+ npx -y patchxnote-agent@latest mcp status
28
+ npx -y patchxnote-agent@latest mcp logout --local-only
13
29
  ```
14
30
 
15
31
  Print the generic MCP config manually:
@@ -24,12 +40,18 @@ The generated config uses this universal local stdio MCP command:
24
40
  npx -y patchxnote-agent@latest mcp serve
25
41
  ```
26
42
 
27
- Log in from the editor terminal:
43
+ The older terminal Agent login remains available for legacy local CLI/MCP fallback:
28
44
 
29
45
  ```sh
30
46
  npx -y patchxnote-agent@latest login
31
47
  ```
32
48
 
49
+ `setup` reuses the same `mcp login` browser OAuth flow. The GoServer website owns phone OTP input; the local Agent owns the loopback callback, token exchange, secure storage, and stdio bridge. `mcp serve` never opens a browser during editor startup. It stores credentials in the OS-native keychain and keeps MCP config free of phone numbers, OTP codes, access tokens, and refresh tokens.
50
+
51
+ P0 local client IDs: `vscode`, `cursor`, `codex`, `claude-code`, `claude-desktop`, `windsurf`, `trae`, `qoder`, `workbuddy`.
52
+
53
+ Platform clients such as Feishu Aily, Doubao Work Partner, Tencent Agent Development Platform, and enterprise WorkBuddy need the hosted remote MCP gateway plus platform-console acceptance; local `npx` setup is for desktop and terminal clients.
54
+
33
55
  If a client rejects `npx` or times out during first binary download, run the stable absolute-path fallback:
34
56
 
35
57
  ```sh
@@ -29,10 +29,18 @@ async function main(argv) {
29
29
  await runLogin(parsed);
30
30
  return;
31
31
  }
32
+ if (parsed.command === "setup") {
33
+ await runSetup(parsed);
34
+ return;
35
+ }
32
36
  if (parsed.command === "mcp" && parsed.subcommand === "config") {
33
37
  printUniversalMCPConfig();
34
38
  return;
35
39
  }
40
+ if (parsed.command === "mcp" && ["login", "status", "logout"].includes(parsed.subcommand)) {
41
+ await runMCPSubcommand(parsed);
42
+ return;
43
+ }
36
44
  if (parsed.command === "mcp" && parsed.subcommand === "serve") {
37
45
  await runMCPServe(parsed);
38
46
  return;
@@ -74,6 +82,14 @@ async function runLogin(parsed) {
74
82
  process.exitCode = code;
75
83
  }
76
84
 
85
+ async function runSetup(parsed) {
86
+ const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
87
+ const code = await spawnAndWait(plan.install_path, ["setup", ...parsed.passthroughArgs], {
88
+ stdio: "inherit"
89
+ });
90
+ process.exitCode = code;
91
+ }
92
+
77
93
  async function runMCPServe(parsed) {
78
94
  const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
79
95
  const code = await spawnAndWait(plan.install_path, ["mcp", "serve", ...parsed.passthroughArgs], {
@@ -83,6 +99,14 @@ async function runMCPServe(parsed) {
83
99
  process.exitCode = code;
84
100
  }
85
101
 
102
+ async function runMCPSubcommand(parsed) {
103
+ const plan = await ensureBinary(parsed.options, { stderr: process.stderr });
104
+ const code = await spawnAndWait(plan.install_path, ["mcp", parsed.subcommand, ...parsed.passthroughArgs], {
105
+ stdio: "inherit"
106
+ });
107
+ process.exitCode = code;
108
+ }
109
+
86
110
  function createInstallPlan(command, options = {}) {
87
111
  const target = resolveTarget(options.platform || process.platform, options.arch || process.arch);
88
112
  const installDir = options.installDir || defaultInstallDir(process.platform);
@@ -371,13 +395,21 @@ function parseArgs(argv) {
371
395
  const launcher = parseLauncherOptions(rest, { allowPassthrough: true, rejectPrintConfig: true });
372
396
  return { command, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
373
397
  }
398
+ if (command === "setup") {
399
+ const launcher = parseLauncherOptions(rest, {
400
+ allowPassthrough: true,
401
+ passThroughDryRun: true,
402
+ passThroughPrintConfig: true
403
+ });
404
+ return { command, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
405
+ }
374
406
  if (command === "mcp") {
375
407
  const [subcommand, ...subcommandArgs] = rest;
376
- if (!["serve", "config"].includes(subcommand)) {
408
+ if (!["serve", "config", "login", "status", "logout"].includes(subcommand)) {
377
409
  throw new Error(mcpUsage());
378
410
  }
379
411
  const launcher = parseLauncherOptions(subcommandArgs, {
380
- allowPassthrough: subcommand === "serve",
412
+ allowPassthrough: subcommand !== "config",
381
413
  rejectPrintConfig: true
382
414
  });
383
415
  return { command, subcommand, options: launcher.options, passthroughArgs: launcher.passthroughArgs };
@@ -432,8 +464,16 @@ function parseLauncherOptions(rest, settings = {}) {
432
464
  }
433
465
  throw new Error(`unknown option ${arg}`);
434
466
  case "--dry-run":
467
+ if (settings.passThroughDryRun) {
468
+ passthroughArgs.push(arg);
469
+ break;
470
+ }
435
471
  throw new Error("--dry-run is only valid for install/update/uninstall");
436
472
  case "--print-config":
473
+ if (settings.passThroughPrintConfig) {
474
+ passthroughArgs.push(arg);
475
+ break;
476
+ }
437
477
  if (settings.rejectPrintConfig) {
438
478
  throw new Error("--print-config is not valid for this command");
439
479
  }
@@ -629,11 +669,11 @@ function verifyChecksum(binary, assetName, checksumsText) {
629
669
  }
630
670
 
631
671
  function usage() {
632
- return "usage: patchxnote-agent <install|update|uninstall|login|mcp> [options]";
672
+ return "usage: patchxnote-agent <install|update|uninstall|login|setup|mcp> [options]";
633
673
  }
634
674
 
635
675
  function mcpUsage() {
636
- return "usage: patchxnote-agent mcp <serve|config> [options]";
676
+ return "usage: patchxnote-agent mcp <serve|config|login|status|logout> [options]";
637
677
  }
638
678
 
639
679
  if (require.main === module) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchxnote-agent",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Installer wrapper for the PatchXNote Agent CLI and local MCP server.",
5
5
  "repository": {
6
6
  "type": "git",