@helixlife-ai/xiantao 0.1.10 → 0.1.12

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
@@ -21,7 +21,7 @@ xt tool inspect violin_flat
21
21
  xt tool run violin_flat ./data.xlsx
22
22
  ```
23
23
 
24
- `xt login` is the recommended first-use entrypoint. It refreshes both the upload token and the Xiantao web token for the current profile. `xt tool login` is kept as an equivalent entrypoint under the `tool` topic.
24
+ `xt login` is the recommended first-use entrypoint. It authorizes and stores the profile token in one step. `xt tool login` is kept as an equivalent entrypoint under the `tool` topic.
25
25
 
26
26
  ### Interactive Tool Run
27
27
 
@@ -34,10 +34,13 @@ This starts a menu-driven path for choosing a tool, selecting demo data or a loc
34
34
  ### Agent Automation
35
35
 
36
36
  ```bash
37
+ xt tool prepare violin_flat --file ./data.xlsx --profile opencode --json
37
38
  xt tool exec violin_flat --file ./data.xlsx --profile opencode --json
38
39
  ```
39
40
 
40
- For machine callers, use `xt tool exec`, keep `--json`, pass an explicit profile with `--profile`, and avoid interactive-only flows.
41
+ For machine callers, use `xt tool prepare` to fetch the upload-dependent final schema, then `xt tool exec` to submit. Keep `--json`, pass an explicit profile with `--profile`, and avoid interactive-only flows.
42
+
43
+ `xt login --json` now returns the authorization link immediately and defaults to `authorized: false` until the browser step completes. Use `xt login --json --wait` when you explicitly want the command to block until authorization is confirmed. `xt status` is a probe-style check and returns `authorized: true` or `authorized: false` together with a reason such as `missing_token` or `expired_token`.
41
44
 
42
45
  ## Command Groups
43
46
 
@@ -52,6 +55,7 @@ For machine callers, use `xt tool exec`, keep `--json`, pass an explicit profile
52
55
 
53
56
  - `xt tool search`
54
57
  - `xt tool inspect`
58
+ - `xt tool prepare`
55
59
  - `xt tool run`
56
60
  - `xt tool exec`
57
61
  - `xt tool download`
@@ -67,12 +71,10 @@ For machine callers, use `xt tool exec`, keep `--json`, pass an explicit profile
67
71
 
68
72
  For the common Xiantao tool product, `tool search`, `tool inspect`, `tool run`, `tool resolve`, and `tool menu` default `toolProductUuid` to `c0b6febb-52dd-4525-970a-61bbe9e263ff`. You can override it with `--toolProductUuid`, `XIANTAO_TOOL_PRODUCT_UUID`, or `~/.config/xtz/config.json` under `xiantao.toolProductUuid`.
69
73
 
70
- `xt tool search <keyword>` searches cached or remote tool menus by tool id, title, path, and route. `xt tool inspect <tool_id>` prints resolved metadata together with the dynamic `args_main` schema used by the tool. `xt tool run <tool_id>` runs a Xiantao bioinformatics tool. `xt tool resolve <tool_id>` remains available as the low-level UUID and route lookup. `--demo` reuses the demo file metadata returned by `tool fetch-all`; otherwise `tool run` uploads the local file first and therefore also needs upload auth. Run `xt login` first to refresh both tokens in one step. When a tool exposes multiple downloadable results, `--download <path>` uses the output file extension to select the matching artifact.
74
+ `xt tool search <keyword>` searches remote tool menus by tool id, title, path, and route. `xt tool inspect <tool_id>` prints resolved metadata together with the dynamic `args_main` schema used by the tool. `xt tool run <tool_id>` runs a Xiantao bioinformatics tool. `xt tool resolve <tool_id>` remains available as the low-level UUID and route lookup. `--demo` reuses the demo file metadata returned by `tool fetch-all`; otherwise `tool run` uploads the local file first and therefore also needs token auth. Run `xt login` first to authorize the stored token. When a tool exposes multiple downloadable results, `--download <path>` uses the output file extension to select the matching artifact.
71
75
 
72
76
  `xt tool run <tool_id> ... --interactive` prompts for dynamic `args_main` values before the final submit, prints reusable `--set` flags, and supports `<` for the previous item plus `/skip` for the current section.
73
77
 
74
- When resolving tools from `--toolProductUuid`, the CLI caches the `/tool/menus?is_all=1` result locally for 12 hours per `profile + toolProductUuid` to avoid repeated full-menu fetches.
75
-
76
78
  ## Development
77
79
 
78
80
  ```bash
@@ -1,21 +1,36 @@
1
1
  import { Command } from '@oclif/core';
2
+ import { createErrorEnvelope, createSuccessEnvelope } from './lib/envelope.js';
2
3
  import { XtzError } from './lib/errors.js';
3
4
  import { resolveAgent } from './lib/storage.js';
5
+ import { getUpdateReminder } from './lib/update.js';
4
6
  export class XtzCommand extends Command {
7
+ async init() {
8
+ await super.init();
9
+ await this.warnIfUpdateAvailable();
10
+ }
5
11
  async getProfile(profileFlag) {
6
12
  return resolveAgent(profileFlag);
7
13
  }
8
14
  async getAgent(agentFlag) {
9
15
  return this.getProfile(agentFlag);
10
16
  }
11
- print(flags, data, text) {
17
+ print(flags, data, text, context) {
12
18
  if (flags.json) {
19
+ if (context) {
20
+ this.log(JSON.stringify(createSuccessEnvelope(context.profile, context.command ?? this.getCommandName(), data), null, 2));
21
+ return;
22
+ }
13
23
  this.log(JSON.stringify(data, null, 2));
14
24
  return;
15
25
  }
16
26
  this.log(text);
17
27
  }
18
28
  async catch(error) {
29
+ if (this.isJsonOutputRequested()) {
30
+ const profile = await this.getProfile(this.readProfileFlagFromArgv());
31
+ this.log(JSON.stringify(createErrorEnvelope(profile, this.getCommandName(), error), null, 2));
32
+ this.exit(1);
33
+ }
19
34
  if (error instanceof XtzError) {
20
35
  this.error(error.message, { exit: 1 });
21
36
  }
@@ -37,4 +52,52 @@ export class XtzCommand extends Command {
37
52
  const replacement = command.replace(/^auth /, '');
38
53
  this.warn(`\`xt ${command}\` 已兼容保留,建议改用 \`xt ${replacement}\``);
39
54
  }
55
+ async warnIfUpdateAvailable() {
56
+ if (this.argv.includes('--json') || !process.stdout.isTTY || this.shouldSkipUpdateReminder()) {
57
+ return;
58
+ }
59
+ const reminder = await getUpdateReminder(this.config.version);
60
+ if (!reminder) {
61
+ return;
62
+ }
63
+ this.warn(reminder);
64
+ }
65
+ getCommandName() {
66
+ return this.id?.replaceAll(':', ' ') ?? 'unknown';
67
+ }
68
+ isJsonOutputRequested() {
69
+ return this.argv.includes('--json');
70
+ }
71
+ readProfileFlagFromArgv() {
72
+ for (let index = 0; index < this.argv.length; index += 1) {
73
+ const token = this.argv[index];
74
+ if ((token === '--profile' || token === '--agent') && this.argv[index + 1]) {
75
+ return this.argv[index + 1];
76
+ }
77
+ if (token.startsWith('--profile=')) {
78
+ return token.slice('--profile='.length);
79
+ }
80
+ if (token.startsWith('--agent=')) {
81
+ return token.slice('--agent='.length);
82
+ }
83
+ }
84
+ return undefined;
85
+ }
86
+ shouldSkipUpdateReminder() {
87
+ const commandId = this.id ?? '';
88
+ return [
89
+ 'login',
90
+ 'logout',
91
+ 'status',
92
+ 'auth:login',
93
+ 'auth:logout',
94
+ 'auth:status',
95
+ 'plot:login',
96
+ 'plot:run',
97
+ 'tool:exec',
98
+ 'tool:login',
99
+ 'tool:prepare',
100
+ 'tool:run',
101
+ ].includes(commandId);
102
+ }
40
103
  }
@@ -1,10 +1,11 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
3
  import { globalFlags } from '../../lib/flags.js';
4
+ import { loginAuth } from '../../lib/auth.js';
4
5
  import { loginAll } from '../../lib/login-flow.js';
5
- import { getTokenPath, getXiantaoTokenPath } from '../../lib/storage.js';
6
+ import { getTokenPath } from '../../lib/storage.js';
6
7
  export default class AuthLogin extends XtzCommand {
7
- static description = 'Sign in for the current profile and refresh both the upload token and the Xiantao web token';
8
+ static description = 'Authorize the current profile token';
8
9
  static flags = {
9
10
  ...globalFlags,
10
11
  open: Flags.boolean({
@@ -12,52 +13,64 @@ export default class AuthLogin extends XtzCommand {
12
13
  default: true,
13
14
  description: 'Open the authorization link in the browser',
14
15
  }),
16
+ wait: Flags.boolean({
17
+ allowNo: true,
18
+ default: true,
19
+ description: 'Wait until the browser authorization is confirmed before exiting',
20
+ }),
15
21
  };
16
22
  async run() {
17
23
  this.warnIfLegacyAuthCommand();
18
24
  const { flags } = await this.parse(AuthLogin);
19
25
  const agent = await this.getProfile(flags.profile);
20
- const result = await loginAll(agent, flags.open, ({ auth, phase }) => {
21
- if (flags.json) {
22
- return;
23
- }
24
- if (phase === 'auth_started') {
25
- if (auth.authorizedWithStoredXiantao) {
26
- this.log('已使用现有仙桃网页登录自动完成上传授权,等待确认...');
26
+ const waitForAuthorization = this.shouldWait(flags);
27
+ const result = waitForAuthorization
28
+ ? await loginAll(agent, flags.open, ({ auth, phase }) => {
29
+ if (flags.json) {
30
+ return;
31
+ }
32
+ if (phase === 'auth_started') {
33
+ this.log(auth.browserOpened ? '浏览器已打开授权链接,等待授权完成...' : `请先在浏览器中打开授权链接: ${auth.linkUrl}`);
27
34
  return;
28
35
  }
29
- this.log(auth.browserOpened ? '浏览器已打开上传授权链接,等待授权完成...' : `请先在浏览器中打开上传授权链接: ${auth.linkUrl}`);
30
- return;
31
- }
32
- this.log(auth.authorizedWithStoredXiantao ? '上传授权已确认,已复用现有仙桃网页登录。' : '上传授权已确认,继续仙桃网页登录...');
33
- });
36
+ this.log('授权已确认。');
37
+ })
38
+ : { auth: await loginAuth(agent, flags.open) };
39
+ const authorized = waitForAuthorization;
34
40
  this.print(flags, {
35
41
  agent,
36
- auto_authorized: result.auth.authorizedWithStoredXiantao,
42
+ authorization_pending: !authorized,
43
+ authorized,
37
44
  browser_opened: result.auth.browserOpened,
38
45
  link_url: result.auth.linkUrl,
39
46
  token_path: result.auth.tokenPath,
40
- xiantao: {
41
- browser_opened: result.xiantao.browserOpened,
42
- callback_url: result.xiantao.callbackUrl,
43
- jump_url: result.xiantao.jumpUrl,
44
- reused: result.xiantao.reused,
45
- token_path: result.xiantao.tokenPath,
46
- },
47
- }, [
48
- `profile: ${agent}`,
49
- `token: ${getTokenPath(agent)}`,
50
- `xiantao_token: ${getXiantaoTokenPath(agent)}`,
51
- result.xiantao.reused
52
- ? '已复用现有仙桃网页登录 token。'
53
- : result.xiantao.browserOpened
54
- ? '仙桃网页登录成功,token 已刷新。'
55
- : `请在浏览器中打开: ${result.xiantao.jumpUrl}`,
56
- result.auth.authorizedWithStoredXiantao
57
- ? '已使用现有仙桃网页登录自动完成授权。'
58
- : result.auth.browserOpened
59
- ? '浏览器已打开授权链接,请完成授权后运行 `xt status`。'
60
- : `请在浏览器中打开: ${result.auth.linkUrl}`,
61
- ].join('\n'));
47
+ wait: waitForAuthorization,
48
+ }, this.formatLoginText({
49
+ agent,
50
+ authorized,
51
+ browserOpened: result.auth.browserOpened,
52
+ linkUrl: result.auth.linkUrl,
53
+ }), { profile: agent });
54
+ }
55
+ shouldWait(flags) {
56
+ if (!this.hasExplicitWaitFlag()) {
57
+ return !flags.json;
58
+ }
59
+ return flags.wait;
60
+ }
61
+ hasExplicitWaitFlag() {
62
+ return this.argv.includes('--wait') || this.argv.includes('--no-wait');
63
+ }
64
+ formatLoginText(input) {
65
+ const lines = [
66
+ `profile: ${input.agent}`,
67
+ `token: ${getTokenPath(input.agent)}`,
68
+ `authorized: ${input.authorized}`,
69
+ ];
70
+ if (input.authorized) {
71
+ return lines.join('\n');
72
+ }
73
+ lines.push(input.browserOpened ? '浏览器已打开授权链接,请完成授权后运行 `xt status`。' : `请在浏览器中打开: ${input.linkUrl}`);
74
+ return lines.join('\n');
62
75
  }
63
76
  }
@@ -15,6 +15,6 @@ export default class AuthLogout extends XtzCommand {
15
15
  agent,
16
16
  removed,
17
17
  token_path: getTokenPath(agent),
18
- }, removed ? `已删除 token: ${getTokenPath(agent)}` : `未找到 token: ${getTokenPath(agent)}`);
18
+ }, removed ? `已删除 token: ${getTokenPath(agent)}` : `未找到 token: ${getTokenPath(agent)}`, { profile: agent });
19
19
  }
20
20
  }
@@ -1,9 +1,10 @@
1
1
  import { XtzCommand } from '../../base-command.js';
2
+ import { XtzError } from '../../lib/errors.js';
2
3
  import { checkToken } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
- import { getTokenPath, requireToken } from '../../lib/storage.js';
5
+ import { getTokenPath, loadToken } from '../../lib/storage.js';
5
6
  export default class AuthStatus extends XtzCommand {
6
- static description = 'Check whether the current profile token is authorized';
7
+ static description = 'Show token auth status for the current profile';
7
8
  static flags = {
8
9
  ...globalFlags,
9
10
  };
@@ -11,12 +12,49 @@ export default class AuthStatus extends XtzCommand {
11
12
  this.warnIfLegacyAuthCommand();
12
13
  const { flags } = await this.parse(AuthStatus);
13
14
  const agent = await this.getProfile(flags.profile);
14
- const token = await requireToken(agent);
15
- await checkToken(agent, token);
15
+ const tokenPath = getTokenPath(agent);
16
+ const token = await loadToken(agent);
17
+ const status = !token
18
+ ? {
19
+ authorized: false,
20
+ reason: 'missing_token',
21
+ }
22
+ : await this.resolveAuthorization(agent, token);
16
23
  this.print(flags, {
17
24
  agent,
18
- authorized: true,
19
- token_path: getTokenPath(agent),
20
- }, `profile: ${agent}\nauthorized: true\ntoken: ${getTokenPath(agent)}`);
25
+ authorized: status.authorized,
26
+ reason: status.reason,
27
+ token_path: tokenPath,
28
+ }, this.formatStatusText(agent, tokenPath, status), { profile: agent });
29
+ }
30
+ async resolveAuthorization(agent, token) {
31
+ try {
32
+ await checkToken(agent, token);
33
+ return {
34
+ authorized: true,
35
+ reason: null,
36
+ };
37
+ }
38
+ catch (error) {
39
+ if (!(error instanceof XtzError) || !error.message.includes('授权已过期')) {
40
+ throw error;
41
+ }
42
+ return {
43
+ authorized: false,
44
+ reason: 'expired_token',
45
+ };
46
+ }
47
+ }
48
+ formatStatusText(agent, tokenPath, status) {
49
+ const lines = [
50
+ `profile: ${agent}`,
51
+ `authorized: ${status.authorized}`,
52
+ `token: ${tokenPath}`,
53
+ ];
54
+ if (!status.authorized && status.reason) {
55
+ lines.push(`reason: ${status.reason}`);
56
+ lines.push(`run: xt login --profile ${agent}`);
57
+ }
58
+ return lines.join('\n');
21
59
  }
22
60
  }
@@ -1,8 +1,8 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
+ import { getAuthContext } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
5
  import { buildArgsMainFromSchema } from '../../lib/plot-schema.js';
5
- import { getXiantaoAuthContext } from '../../lib/xiantao-auth.js';
6
6
  import { fetchAllPlotArgs } from '../../lib/xiantao.js';
7
7
  export default class PlotFetchAll extends XtzCommand {
8
8
  static description = 'Fetch raw dynamic args for a Xiantao tool via public.args.fetch-all';
@@ -15,7 +15,7 @@ export default class PlotFetchAll extends XtzCommand {
15
15
  static flags = {
16
16
  ...globalFlags,
17
17
  token: Flags.string({
18
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
18
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
19
19
  }),
20
20
  uuid: Flags.string({
21
21
  description: 'Tool UUID used in the public.args.fetch-all payload',
@@ -26,7 +26,7 @@ export default class PlotFetchAll extends XtzCommand {
26
26
  this.warnIfLegacyPlotCommand();
27
27
  const { args, flags } = await this.parse(PlotFetchAll);
28
28
  const agent = await this.getProfile(flags.profile);
29
- const auth = await getXiantaoAuthContext(agent, flags.token);
29
+ const auth = await getAuthContext(agent, flags.token);
30
30
  const result = await fetchAllPlotArgs(auth, {
31
31
  moduleId: args.moduleId,
32
32
  uuid: flags.uuid,
@@ -42,6 +42,6 @@ export default class PlotFetchAll extends XtzCommand {
42
42
  notice: result.notice ?? '',
43
43
  uuid: flags.uuid,
44
44
  };
45
- this.print(flags, output, JSON.stringify(output, null, 2));
45
+ this.print(flags, output, JSON.stringify(output, null, 2), { profile: agent });
46
46
  }
47
47
  }
@@ -1,10 +1,11 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
+ import { loginAuth } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
5
  import { loginAll } from '../../lib/login-flow.js';
5
- import { getTokenPath, getXiantaoTokenPath } from '../../lib/storage.js';
6
+ import { getTokenPath } from '../../lib/storage.js';
6
7
  export default class PlotLogin extends XtzCommand {
7
- static description = 'Sign in for the current profile and refresh both the upload token and the Xiantao web token';
8
+ static description = 'Authorize the current profile token';
8
9
  static flags = {
9
10
  ...globalFlags,
10
11
  open: Flags.boolean({
@@ -12,52 +13,64 @@ export default class PlotLogin extends XtzCommand {
12
13
  default: true,
13
14
  description: 'Open the authorization link in the browser',
14
15
  }),
16
+ wait: Flags.boolean({
17
+ allowNo: true,
18
+ default: true,
19
+ description: 'Wait until the browser authorization is confirmed before exiting',
20
+ }),
15
21
  };
16
22
  async run() {
17
23
  this.warnIfLegacyPlotCommand();
18
24
  const { flags } = await this.parse(PlotLogin);
19
25
  const agent = await this.getProfile(flags.profile);
20
- const result = await loginAll(agent, flags.open, ({ auth, phase }) => {
21
- if (flags.json) {
22
- return;
23
- }
24
- if (phase === 'auth_started') {
25
- if (auth.authorizedWithStoredXiantao) {
26
- this.log('已使用现有仙桃网页登录自动完成上传授权,等待确认...');
26
+ const waitForAuthorization = this.shouldWait(flags);
27
+ const result = waitForAuthorization
28
+ ? await loginAll(agent, flags.open, ({ auth, phase }) => {
29
+ if (flags.json) {
30
+ return;
31
+ }
32
+ if (phase === 'auth_started') {
33
+ this.log(auth.browserOpened ? '浏览器已打开授权链接,等待授权完成...' : `请先在浏览器中打开授权链接: ${auth.linkUrl}`);
27
34
  return;
28
35
  }
29
- this.log(auth.browserOpened ? '浏览器已打开上传授权链接,等待授权完成...' : `请先在浏览器中打开上传授权链接: ${auth.linkUrl}`);
30
- return;
31
- }
32
- this.log(auth.authorizedWithStoredXiantao ? '上传授权已确认,已复用现有仙桃网页登录。' : '上传授权已确认,继续仙桃网页登录...');
33
- });
36
+ this.log('授权已确认。');
37
+ })
38
+ : { auth: await loginAuth(agent, flags.open) };
39
+ const authorized = waitForAuthorization;
34
40
  this.print(flags, {
35
41
  agent,
36
- auto_authorized: result.auth.authorizedWithStoredXiantao,
42
+ authorization_pending: !authorized,
43
+ authorized,
37
44
  browser_opened: result.auth.browserOpened,
38
45
  link_url: result.auth.linkUrl,
39
46
  token_path: result.auth.tokenPath,
40
- xiantao: {
41
- browser_opened: result.xiantao.browserOpened,
42
- callback_url: result.xiantao.callbackUrl,
43
- jump_url: result.xiantao.jumpUrl,
44
- reused: result.xiantao.reused,
45
- token_path: result.xiantao.tokenPath,
46
- },
47
- }, [
48
- `profile: ${agent}`,
49
- `token: ${getTokenPath(agent)}`,
50
- `xiantao_token: ${getXiantaoTokenPath(agent)}`,
51
- result.xiantao.reused
52
- ? '已复用现有仙桃网页登录 token。'
53
- : result.xiantao.browserOpened
54
- ? '仙桃网页登录成功,token 已刷新。'
55
- : `请在浏览器中打开: ${result.xiantao.jumpUrl}`,
56
- result.auth.authorizedWithStoredXiantao
57
- ? '已使用现有仙桃网页登录自动完成授权。'
58
- : result.auth.browserOpened
59
- ? '浏览器已打开授权链接,请完成授权后运行 `xt status`。'
60
- : `请在浏览器中打开: ${result.auth.linkUrl}`,
61
- ].join('\n'));
47
+ wait: waitForAuthorization,
48
+ }, this.formatLoginText({
49
+ agent,
50
+ authorized,
51
+ browserOpened: result.auth.browserOpened,
52
+ linkUrl: result.auth.linkUrl,
53
+ }), { profile: agent });
54
+ }
55
+ shouldWait(flags) {
56
+ if (!this.hasExplicitWaitFlag()) {
57
+ return !flags.json;
58
+ }
59
+ return flags.wait;
60
+ }
61
+ hasExplicitWaitFlag() {
62
+ return this.argv.includes('--wait') || this.argv.includes('--no-wait');
63
+ }
64
+ formatLoginText(input) {
65
+ const lines = [
66
+ `profile: ${input.agent}`,
67
+ `token: ${getTokenPath(input.agent)}`,
68
+ `authorized: ${input.authorized}`,
69
+ ];
70
+ if (input.authorized) {
71
+ return lines.join('\n');
72
+ }
73
+ lines.push(input.browserOpened ? '浏览器已打开授权链接,请完成授权后运行 `xt status`。' : `请在浏览器中打开: ${input.linkUrl}`);
74
+ return lines.join('\n');
62
75
  }
63
76
  }
@@ -1,8 +1,8 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
+ import { getAuthContext } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
5
  import { resolveXiantaoToolProductUuid } from '../../lib/storage.js';
5
- import { getXiantaoAuthContext } from '../../lib/xiantao-auth.js';
6
6
  import { fetchToolMenu } from '../../lib/xiantao.js';
7
7
  export default class PlotMenu extends XtzCommand {
8
8
  static description = 'Fetch Xiantao menu metadata for a tool menu UUID';
@@ -15,7 +15,7 @@ export default class PlotMenu extends XtzCommand {
15
15
  static flags = {
16
16
  ...globalFlags,
17
17
  token: Flags.string({
18
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
18
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
19
19
  }),
20
20
  toolProductUuid: Flags.string({
21
21
  description: 'tool_product_uuid used in the menu filter payload; defaults to the main Xiantao product UUID',
@@ -25,13 +25,13 @@ export default class PlotMenu extends XtzCommand {
25
25
  this.warnIfLegacyPlotCommand();
26
26
  const { args, flags } = await this.parse(PlotMenu);
27
27
  const agent = await this.getProfile(flags.profile);
28
- const auth = await getXiantaoAuthContext(agent, flags.token);
28
+ const auth = await getAuthContext(agent, flags.token);
29
29
  const toolProductUuid = await resolveXiantaoToolProductUuid(flags.toolProductUuid);
30
30
  const menu = await fetchToolMenu(auth, args.menuUuid, toolProductUuid);
31
31
  this.print(flags, {
32
32
  agent,
33
33
  menu,
34
34
  tool_product_uuid: toolProductUuid,
35
- }, JSON.stringify(menu, null, 2));
35
+ }, JSON.stringify(menu, null, 2), { profile: agent });
36
36
  }
37
37
  }
@@ -1,15 +1,15 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
+ import { getAuthContext } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
5
  import { resolveXiantaoToolProductUuid } from '../../lib/storage.js';
5
- import { getXiantaoAuthContext } from '../../lib/xiantao-auth.js';
6
6
  import { fetchToolMenus } from '../../lib/xiantao.js';
7
7
  export default class PlotMenus extends XtzCommand {
8
8
  static description = 'Fetch all Xiantao menu metadata for a tool product';
9
9
  static flags = {
10
10
  ...globalFlags,
11
11
  token: Flags.string({
12
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
12
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
13
13
  }),
14
14
  toolProductUuid: Flags.string({
15
15
  description: 'tool_product_uuid used in the menu filter payload; defaults to the main Xiantao product UUID',
@@ -19,13 +19,13 @@ export default class PlotMenus extends XtzCommand {
19
19
  this.warnIfLegacyPlotCommand();
20
20
  const { flags } = await this.parse(PlotMenus);
21
21
  const agent = await this.getProfile(flags.profile);
22
- const auth = await getXiantaoAuthContext(agent, flags.token);
22
+ const auth = await getAuthContext(agent, flags.token);
23
23
  const toolProductUuid = await resolveXiantaoToolProductUuid(flags.toolProductUuid);
24
24
  const menus = await fetchToolMenus(auth, toolProductUuid);
25
25
  this.print(flags, {
26
26
  agent,
27
27
  menus,
28
28
  tool_product_uuid: toolProductUuid,
29
- }, JSON.stringify(menus, null, 2));
29
+ }, JSON.stringify(menus, null, 2), { profile: agent });
30
30
  }
31
31
  }
@@ -1,8 +1,8 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import { XtzCommand } from '../../base-command.js';
3
+ import { getAuthContext } from '../../lib/auth.js';
3
4
  import { globalFlags } from '../../lib/flags.js';
4
5
  import { resolveXiantaoToolProductUuid } from '../../lib/storage.js';
5
- import { getXiantaoAuthContext } from '../../lib/xiantao-auth.js';
6
6
  import { resolveToolMenuByCode } from '../../lib/xiantao.js';
7
7
  export default class PlotResolve extends XtzCommand {
8
8
  static description = 'Resolve a Xiantao tool id to its UUID and route';
@@ -15,7 +15,7 @@ export default class PlotResolve extends XtzCommand {
15
15
  static flags = {
16
16
  ...globalFlags,
17
17
  token: Flags.string({
18
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
18
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
19
19
  }),
20
20
  toolProductUuid: Flags.string({
21
21
  description: 'tool_product_uuid from the /products/apply/:uuid URL; defaults to the main Xiantao product UUID',
@@ -25,7 +25,7 @@ export default class PlotResolve extends XtzCommand {
25
25
  this.warnIfLegacyPlotCommand();
26
26
  const { args, flags } = await this.parse(PlotResolve);
27
27
  const agent = await this.getProfile(flags.profile);
28
- const auth = await getXiantaoAuthContext(agent, flags.token);
28
+ const auth = await getAuthContext(agent, flags.token);
29
29
  const toolProductUuid = await resolveXiantaoToolProductUuid(flags.toolProductUuid);
30
30
  const resolved = await resolveToolMenuByCode(auth, toolProductUuid, args.moduleId);
31
31
  this.print(flags, {
@@ -43,6 +43,6 @@ export default class PlotResolve extends XtzCommand {
43
43
  title: resolved.title,
44
44
  tool_product_uuid: toolProductUuid,
45
45
  uuid: resolved.uuid,
46
- }, null, 2));
46
+ }, null, 2), { profile: agent });
47
47
  }
48
48
  }
@@ -11,15 +11,14 @@ import { parseSetOverrides, plotOverrideFlags } from '../../lib/plot-options.js'
11
11
  import { buildArgsMainFromSchema } from '../../lib/plot-schema.js';
12
12
  import { loadPlotArgsMainConfig, resolveXiantaoToolProductUuid } from '../../lib/storage.js';
13
13
  import { resolveXiantaoDownload, submitXiantaoPlot, verifyXiantaoPlotUpload } from '../../lib/xiantao-plot.js';
14
- import { getXiantaoAuthContext } from '../../lib/xiantao-auth.js';
15
14
  import { fetchAllPlotArgs, fetchToolMenu, fetchToolMenus, resolveToolMenuByCode } from '../../lib/xiantao.js';
16
15
  export class ToolRunCommandBase extends XtzCommand {
17
16
  async prepareToolRun(requestedModuleId, filePath, flags) {
18
17
  const agent = await this.getProfile(flags.profile);
19
- const xiantaoAuth = await getXiantaoAuthContext(agent, flags.token);
20
- const resolved = await this.resolveModule(requestedModuleId, flags, xiantaoAuth);
18
+ const auth = await getAuthContext(agent, flags.token);
19
+ const resolved = await this.resolveModule(requestedModuleId, flags, auth);
21
20
  const { moduleId, route, toolProductUuid, uuid } = resolved;
22
- const fetchAllResult = await fetchAllPlotArgs(xiantaoAuth, { moduleId, uuid });
21
+ const fetchAllResult = await fetchAllPlotArgs(auth, { moduleId, uuid });
23
22
  const inputMode = await this.resolveInputMode(fetchAllResult, {
24
23
  demo: flags.demo,
25
24
  filePath,
@@ -35,7 +34,7 @@ export class ToolRunCommandBase extends XtzCommand {
35
34
  argsMain,
36
35
  moduleId,
37
36
  uuid,
38
- }, xiantaoAuth);
37
+ }, auth);
39
38
  if (verifiedSchema.length) {
40
39
  schema = verifiedSchema;
41
40
  argsMain = deepMerge(buildArgsMainFromSchema(schema), overrides);
@@ -43,7 +42,7 @@ export class ToolRunCommandBase extends XtzCommand {
43
42
  return {
44
43
  agent,
45
44
  argsMain,
46
- auth: xiantaoAuth,
45
+ auth,
47
46
  duid,
48
47
  inputMode: inputMode.mode,
49
48
  moduleId,
@@ -409,7 +408,7 @@ export default class PlotRun extends ToolRunCommandBase {
409
408
  description: 'Tool route like app1.violin_flat in generic mode',
410
409
  }),
411
410
  token: Flags.string({
412
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
411
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
413
412
  }),
414
413
  toolProductUuid: Flags.string({
415
414
  description: 'tool_product_uuid used to auto-resolve module UUID and route in generic mode; defaults to the main Xiantao product UUID',
@@ -428,6 +427,6 @@ export default class PlotRun extends ToolRunCommandBase {
428
427
  throw new XtzError('FILE 与 `--file` 不能同时使用。');
429
428
  }
430
429
  const result = await this.executeToolRun(args.tool, args.file ?? flags.file, flags);
431
- this.print(flags, result.data, result.text);
430
+ this.print(flags, result.data, result.text, { profile: result.data.agent });
432
431
  }
433
432
  }
@@ -40,7 +40,7 @@ export default class ToolExec extends ToolRunCommandBase {
40
40
  description: 'Tool route like app1.violin_flat in generic mode',
41
41
  }),
42
42
  token: Flags.string({
43
- description: 'Bearer token for api.helixlife.net xiantao APIs; falls back to XIANTAO_TOKEN or the stored Xiantao web token',
43
+ description: 'Bearer token for agent.helixlife.net xiantao APIs; falls back to the stored agent token',
44
44
  }),
45
45
  toolProductUuid: Flags.string({
46
46
  description: 'tool_product_uuid used to auto-resolve module UUID and route in generic mode; defaults to the main Xiantao product UUID',