@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 +7 -5
- package/dist/base-command.js +64 -1
- package/dist/commands/auth/login.js +50 -37
- package/dist/commands/auth/logout.js +1 -1
- package/dist/commands/auth/status.js +45 -7
- package/dist/commands/plot/fetch-all.js +4 -4
- package/dist/commands/plot/login.js +50 -37
- package/dist/commands/plot/menu.js +4 -4
- package/dist/commands/plot/menus.js +4 -4
- package/dist/commands/plot/resolve.js +4 -4
- package/dist/commands/plot/run.js +7 -8
- package/dist/commands/tool/exec.js +1 -1
- package/dist/commands/tool/inspect.js +4 -4
- package/dist/commands/tool/prepare.js +2 -2
- package/dist/commands/tool/search.js +4 -4
- package/dist/lib/auth.js +25 -11
- package/dist/lib/constants.js +4 -6
- package/dist/lib/errors.js +5 -11
- package/dist/lib/login-flow.js +1 -10
- package/dist/lib/storage.js +0 -70
- package/dist/lib/update.js +151 -0
- package/dist/lib/xiantao-plot.js +3 -3
- package/dist/lib/xiantao.js +38 -18
- package/dist/xtz-help.js +5 -5
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
package/dist/base-command.js
CHANGED
|
@@ -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
|
|
6
|
+
import { getTokenPath } from '../../lib/storage.js';
|
|
6
7
|
export default class AuthLogin extends XtzCommand {
|
|
7
|
-
static description = '
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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(
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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,
|
|
5
|
+
import { getTokenPath, loadToken } from '../../lib/storage.js';
|
|
5
6
|
export default class AuthStatus extends XtzCommand {
|
|
6
|
-
static description = '
|
|
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
|
|
15
|
-
await
|
|
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:
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
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
|
|
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
|
|
6
|
+
import { getTokenPath } from '../../lib/storage.js';
|
|
6
7
|
export default class PlotLogin extends XtzCommand {
|
|
7
|
-
static description = '
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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(
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
20
|
-
const resolved = await this.resolveModule(requestedModuleId, flags,
|
|
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(
|
|
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
|
-
},
|
|
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
|
|
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
|
|
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
|
|
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',
|