@helixlife-ai/xiantao 0.1.34 → 0.1.36
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 +23 -6
- package/dist/commands/config/get.js +1 -1
- package/dist/commands/config/set.js +2 -2
- package/dist/commands/plot/run.js +4 -4
- package/dist/commands/tool/inspect.js +3 -3
- package/dist/commands/tool/specific-search.js +1 -0
- package/dist/lib/config.js +2 -2
- package/dist/lib/constants.js +1 -1
- package/dist/lib/envelope.js +1 -1
- package/dist/lib/http.js +1 -1
- package/dist/lib/plot-options.js +1 -1
- package/dist/lib/storage.js +2 -2
- package/dist/lib/xiantao-plot.js +1 -1
- package/dist/lib/xiantao.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Install with `npm i -g @helixlife-ai/xiantao` and run it as `xt`.
|
|
|
6
6
|
|
|
7
7
|
`tool` is the primary product topic for bioinformatics tools. `plot` is kept as a compatibility entrypoint for the current command set and prints a migration warning when executed.
|
|
8
8
|
|
|
9
|
-
`--profile` is the primary profile selector for token lookup and config isolation. If it is omitted, the CLI resolves the profile from `AGENT_NAME`, then the host runtime (`cursor`, `opencode`, `openclaw`), then `~/.config/
|
|
9
|
+
`--profile` is the primary profile selector for token lookup and config isolation. If it is omitted, the CLI resolves the profile from `AGENT_NAME`, then the host runtime (`cursor`, `opencode`, `openclaw`), then `~/.config/helixlife/config.json`, and finally defaults to `opencode`. `--agent` is kept as a compatibility alias.
|
|
10
10
|
|
|
11
11
|
`login`, `status`, and `logout` are the primary auth entrypoints. `auth ...` is kept as a compatibility topic and prints a migration warning when executed.
|
|
12
12
|
|
|
@@ -48,6 +48,7 @@ xt tool exec km_plot_gene --profile opencode --json --cloudFilter '胆管癌'
|
|
|
48
48
|
xt tool prepare km_plot_gene --profile opencode --json --cloudDataId tcga-chol-2
|
|
49
49
|
xt tool exec km_plot_gene --profile opencode --json --cloudFilter '胆管癌' --cloudIndex 0
|
|
50
50
|
xt tool exec km_plot_gene --profile opencode --json --cloudDataId tcga-chol-2
|
|
51
|
+
xt tool specific-search km_plot_gene genes TP53 --profile opencode --json --cloudDataId tcga-brca-2
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
For machine callers, use `xt tool prepare` to fetch the final schema, then `xt tool exec` to submit. Keep `--json`, pass an explicit profile with `--profile`, and avoid interactive-only flows.
|
|
@@ -59,6 +60,17 @@ The examples below illustrate command shapes, not a fixed allowlist of tools. Ap
|
|
|
59
60
|
- demo-capable upload modules: pass `--demo`
|
|
60
61
|
- history-record modules such as `gsea_plot`: pass neither `--file` nor `--demo`; the CLI reuses the default `XTRecord` returned by `tool inspect` / `tool prepare`
|
|
61
62
|
- cloud-capable modules: use `xt tool cloud` to inspect candidates, then pass `--cloudFilter <keyword>`, `--cloudIndex <n>`, or `--cloudDataId <id>` to `tool prepare` / `tool exec`
|
|
63
|
+
- modules without returned input metadata can be submitted with `--specific` / `--set`; the CLI sends an empty `args_data.info` payload
|
|
64
|
+
|
|
65
|
+
`args_specific` defaults come from the dynamic schema returned by Xiantao. Use repeated `--specific` flags to override a whole key or a nested dotted path; array paths use numeric indexes.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
xt tool prepare km_plot_gene --profile opencode --json --cloudDataId tcga-brca-2 --specific 'genes=TP53[ENSG00000141510.17]'
|
|
69
|
+
xt tool prepare group_plot_clin --profile opencode --json --cloudDataId tcga-brca-2 --specific 'genes=["TP53[ENSG00000141510.17]"]' --specific 'clin_list_1n.0.variable=(临床)Age'
|
|
70
|
+
xt tool prepare cox_analysis_cloud --profile opencode --json --cloudDataId tcga-brca-2 --specific 'surv_list_nn.0.variable=(临床)Gender' --specific 'surv_list_nn.0.attrs_list.0.attrs=["Female [50]","Male [49]"]'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For Search-style `args_specific` fields, use `xt tool specific-search <tool> <argsKey> <query> --json` to retrieve normalized choices before setting the final value. Pass the same input selectors that the tool needs, such as `--cloudDataId`, `--cloudFilter`, `--cloudIndex`, or `--selected`.
|
|
62
74
|
|
|
63
75
|
### Cloud Data Flow
|
|
64
76
|
|
|
@@ -88,7 +100,9 @@ Current operational notes for agent-style callers:
|
|
|
88
100
|
- `tool inspect` also reports `inputs.cloud_available` and `inputs.cloud_default` for `XTCloud` modules
|
|
89
101
|
- for multi-upload modules, pass keyed uploads in the same field names returned by `tool inspect`
|
|
90
102
|
- `tool cloud` only supports `--json` and returns structured cloud candidates via `data.choices`
|
|
103
|
+
- `tool specific-search` only supports `--json` and returns normalized dynamic `args_specific` choices via `data.choices`
|
|
91
104
|
- if `tool prepare` or `tool exec` returns `code=TOOL_AMBIGUOUS` with `data.selection_type=cloud_record`, do not auto-pick; ask the user which item to use, then retry with `--cloudIndex` or `--cloudDataId`
|
|
105
|
+
- if a command returns `code=PERMISSION_REQUIRED` or `code=RATE_LIMITED`, treat it as an upstream permission or submit-capacity problem rather than changing local input files
|
|
92
106
|
- `gsea_customize` has been validated through `tool prepare` and `tool exec` with repeated `--file gene_set=... --file data=...`
|
|
93
107
|
|
|
94
108
|
For agent workflows, do not use `xt tool run`. Treat `xt tool run` as the human-first path and `xt tool exec` as the machine path.
|
|
@@ -106,10 +120,12 @@ For agent workflows, do not use `xt tool run`. Treat `xt tool run` as the human-
|
|
|
106
120
|
|
|
107
121
|
### Config
|
|
108
122
|
|
|
123
|
+
- `xt config get agent_api`
|
|
124
|
+
- `xt config set agent_api https://agent.helixlife.cn`
|
|
109
125
|
- `xt config get base-url`
|
|
110
126
|
- `xt config set base-url https://agent.helixlife.cn`
|
|
111
127
|
- `xt config get login-url`
|
|
112
|
-
- `xt config set login-url https://
|
|
128
|
+
- `xt config set login-url https://agent.helixlife.cn/`
|
|
113
129
|
|
|
114
130
|
### History
|
|
115
131
|
|
|
@@ -125,6 +141,7 @@ For agent workflows, do not use `xt tool run`. Treat `xt tool run` as the human-
|
|
|
125
141
|
- `xt tool search`
|
|
126
142
|
- `xt tool inspect`
|
|
127
143
|
- `xt tool cloud`
|
|
144
|
+
- `xt tool specific-search`
|
|
128
145
|
- `xt tool prepare`
|
|
129
146
|
- `xt tool run`
|
|
130
147
|
- `xt tool exec`
|
|
@@ -140,15 +157,15 @@ For agent workflows, do not use `xt tool run`. Treat `xt tool run` as the human-
|
|
|
140
157
|
|
|
141
158
|
## Notes
|
|
142
159
|
|
|
143
|
-
For Xiantao tool commands that accept `--toolProductUuid`, the default value is `c0b6febb-52dd-4525-970a-61bbe9e263ff`. You can override it with `--toolProductUuid`, `XIANTAO_TOOL_PRODUCT_UUID`, or `~/.config/
|
|
160
|
+
For Xiantao tool commands that accept `--toolProductUuid`, the default value is `c0b6febb-52dd-4525-970a-61bbe9e263ff`. You can override it with `--toolProductUuid`, `XIANTAO_TOOL_PRODUCT_UUID`, or `~/.config/helixlife/config.json` under `xiantao.toolProductUuid`.
|
|
144
161
|
|
|
145
|
-
The CLI also loads a project-root `.env` file on startup. You can set `XIANTAO_BASE_URL=https://agent.helixlife.cn` there to switch the API base URL without prefixing each command manually, and `XIANTAO_LOGIN_URL=https://
|
|
162
|
+
The CLI also loads a project-root `.env` file on startup. You can set `XIANTAO_BASE_URL=https://agent.helixlife.cn` there to switch the API base URL without prefixing each command manually, and `XIANTAO_LOGIN_URL=https://agent.helixlife.cn/` to override the resolved login page value. The same values can be stored with `xt config set agent_api ...` and `xt config set login-url ...`; `base-url` is kept as a compatibility alias for `agent_api`. Environment variables take precedence over `~/.config/helixlife/config.json`. Login stores the access token at `~/.config/helixlife/user-access-token.txt`. Set `DEBUG_MODE=1` to print HTTP request and response debug payloads to stderr.
|
|
146
163
|
|
|
147
|
-
`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, the full `args_data` payload in JSON mode, and the detected input source summary, including `XTCloud`, per-field `XTUpload`, and `XTRecord` defaults. `xt tool run <tool_id>` runs a Xiantao bioinformatics tool in the human-first path. `xt tool exec <tool_id>` is the agent-safe submit command and also supports `--download <path>` when a local artifact is needed. `xt tool resolve <tool_id>` remains available as the low-level UUID and route lookup. `xt tool menus` returns a concise catalog with each tool title, `module_id`, `path`, and `route`, which is useful when `tool search` finds nothing helpful or when you want to shortlist tools for recommendation.
|
|
164
|
+
`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, the full `args_data` payload in JSON mode, and the detected input source summary, including `XTCloud`, per-field `XTUpload`, and `XTRecord` defaults. `xt tool specific-search <tool_id> <argsKey> <query> --json` searches dynamic Search-style `args_specific` options and strips frontend highlight markup from returned choices. `xt tool run <tool_id>` runs a Xiantao bioinformatics tool in the human-first path. `xt tool exec <tool_id>` is the agent-safe submit command and also supports `--download <path>` when a local artifact is needed. `xt tool resolve <tool_id>` remains available as the low-level UUID and route lookup. `xt tool menus` returns a concise catalog with each tool title, `module_id`, `path`, and `route`, which is useful when `tool search` finds nothing helpful or when you want to shortlist tools for recommendation.
|
|
148
165
|
|
|
149
166
|
`xt tool cloud <tool_id>` fetches paginated cloud candidates and returns a machine-friendly payload when `--json` is used. `data.choices` contains the short selector list with 0-based `index`, `data_id`, and `label`; `records` contains the full records; `columns`, `filter`, `selected_record`, `pages_fetched`, and pagination metadata are included for callers that need the full context. Use `--page` to fetch one page, `--all` to merge every page, and `--argsKey` only when the module's cloud field cannot be auto-detected. `xt tool cloud` uses `--recordJson` / `--recordFile` for the current record seed, while `xt tool prepare` and `xt tool exec` use `--cloudRecordJson` / `--cloudRecordFile` for the final selected record.
|
|
150
167
|
|
|
151
|
-
`--demo` reuses the demo file metadata returned by `tool fetch-all`; `--file` uploads a local file first; multi-upload modules accept repeated `--file key=path`; for `XTRecord` modules the CLI can submit directly from the default history record returned by `fetch-all`; for `XTCloud` modules use `--cloudFilter`, then `--cloudIndex` or `--cloudDataId` to pin one cloud record before submit. Run `xt login` first to authorize the stored token. When cloud filtering matches multiple records, `tool prepare` and `tool exec` return `code=TOOL_AMBIGUOUS` plus `data.selection_type=cloud_record` and `data.choices`; callers should ask the user which record to use before retrying. `--cloudRecordJson` / `--cloudRecordFile` cannot be combined with `--cloudFilter` / `--cloudDataId` / `--cloudIndex`, and cloud selection flags cannot be combined with `--demo` or `--file`. When a tool exposes multiple downloadable results, `--download <path>` uses the output file extension to select the matching artifact.
|
|
168
|
+
`--demo` reuses the demo file metadata returned by `tool fetch-all`; `--file` uploads a local file first; multi-upload modules accept repeated `--file key=path`; for `XTRecord` modules the CLI can submit directly from the default history record returned by `fetch-all`; for `XTCloud` modules use `--cloudFilter`, then `--cloudIndex` or `--cloudDataId` to pin one cloud record before submit. Tools that return no input metadata can still submit in `mode=none` with `--set` / `--specific`; the CLI sends an empty `args_data.info` object. Run `xt login` first to authorize the stored token. When cloud filtering matches multiple records, `tool prepare` and `tool exec` return `code=TOOL_AMBIGUOUS` plus `data.selection_type=cloud_record` and `data.choices`; callers should ask the user which record to use before retrying. `--cloudRecordJson` / `--cloudRecordFile` cannot be combined with `--cloudFilter` / `--cloudDataId` / `--cloudIndex`, and cloud selection flags cannot be combined with `--demo` or `--file`. When a tool exposes multiple downloadable results, `--download <path>` uses the output file extension to select the matching artifact.
|
|
152
169
|
|
|
153
170
|
For the current GSEA tool family, `gsea_plot`, `gsea_plot2`, `gsea_bar`, `gsea_point`, `gsea_ridge`, `gsea_emapplot`, `gsea_tree`, and `gsea_path_cluster` are record-backed visual modules that reuse the default `gsea_analysis` history record. `gsea_analysis` itself is an upload/demo analysis module. `gsea_customize` is a custom gene-set upload module whose frontend expects two uploads, `gene_set` and `data`; submit it with `--file gene_set=... --file data=...`. A real CLI submit path has been verified with the sample files in [`docs/GSEA-基因集.csv`](/Users/chenyunjie/Desktop/xtz-cli/xiantao/docs/GSEA-基因集.csv) and [`docs/GSEA-分子.xlsx`](/Users/chenyunjie/Desktop/xtz-cli/xiantao/docs/GSEA-分子.xlsx).
|
|
154
171
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Args as i,Flags as o}from"@oclif/core";import{XtzCommand as r}from"../../base-command.js";import{resolveXiantaoConfigValue as n}from"../../lib/config.js";class t extends r{static description="Get a resolved config value";static args={key:i.string({description:"Config key, such as base-url or login-url",required:!0})};static flags={json:o.boolean({default:!1,description:"Output JSON"})};async run(){const{args:
|
|
1
|
+
import{Args as i,Flags as o}from"@oclif/core";import{XtzCommand as r}from"../../base-command.js";import{resolveXiantaoConfigValue as n}from"../../lib/config.js";class t extends r{static description="Get a resolved config value";static args={key:i.string({description:"Config key, such as agent_api, base-url, or login-url",required:!0})};static flags={json:o.boolean({default:!1,description:"Output JSON"})};async run(){const{args:s,flags:e}=await this.parse(t),a=await n(s.key);this.print(e,a,a.value)}}export{t as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Args as
|
|
2
|
-
`)}}export{
|
|
1
|
+
import{Args as s,Flags as n}from"@oclif/core";import{XtzCommand as u}from"../../base-command.js";import{resolveXiantaoConfigValue as l,setXiantaoConfigValue as c}from"../../lib/config.js";class o extends u{static description="Set a config value";static args={key:s.string({description:"Config key, such as agent_api, base-url, or login-url",required:!0}),value:s.string({description:"Config value",required:!0})};static flags={json:n.boolean({default:!1,description:"Output JSON"})};async run(){const{args:t,flags:e}=await this.parse(o),a=await c(t.key,t.value),i=await l(a.key),r={...a,active_source:i.source,active_value:i.value};this.print(e,r,this.formatSetText(a,i))}formatSetText(t,e){const a=[`${t.key}: ${t.value}`,`path: ${t.path}`];return(e.source!=="config"||e.value!==t.value)&&a.push(`active: ${e.value} (${e.source})`),a.join(`
|
|
2
|
+
`)}}export{o as default};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{readFile as L}from"node:fs/promises";import{Args as
|
|
1
|
+
import{readFile as L}from"node:fs/promises";import{Args as x,Flags as h}from"@oclif/core";import{XtzCommand as N}from"../../base-command.js";import{getAuthContext as U}from"../../lib/auth.js";import{XIANTAO_HISTORY_UUID as X}from"../../lib/constants.js";import{downloadToPath as b}from"../../lib/download.js";import{XtzChoiceRequiredError as B,XtzError as a}from"../../lib/errors.js";import{globalFlags as O,toolCloudFlags as E}from"../../lib/flags.js";import{fetchXiantaoHistoryDownloadButtons as j,getXiantaoHistoryRecordStatus as K,waitForLatestXiantaoHistoryRecord as J,waitForXiantaoHistoryRecordCompletion as V}from"../../lib/history.js";import{deepMerge as g,isJsonObject as S}from"../../lib/json.js";import{confirmPlotArgsMain as q,promptPlotArgsMain as Q,promptPlotCloudRecordSelection as G,promptPlotFilePath as M,promptPlotInputSource as Y,promptPlotMenuSelection as W,promptPlotResultSelection as Z}from"../../lib/plot-interactive.js";import{uploadFile as ee}from"../../lib/plot.js";import{applySpecificOverrides as F,parseSetOverrides as oe,plotOverrideFlags as te}from"../../lib/plot-options.js";import{buildArgsMainFromSchema as D,buildArgsSpecificFromSchema as T}from"../../lib/plot-schema.js";import{loadPlotArgsMainConfig as ie,resolveXiantaoToolProductUuid as de}from"../../lib/storage.js";import{findDefaultXiantaoCloudInput as $,findDefaultXiantaoRecord as H,listXiantaoUploadFields as v}from"../../lib/tool-inputs.js";import{fetchXiantaoCloudData as z}from"../../lib/xiantao-cloud.js";import{buildSubmitArgsData as ne,resolveXiantaoDownload as A,submitXiantaoPlot as re,verifyXiantaoPlotUpload as le}from"../../lib/xiantao-plot.js";import{fetchAllPlotArgs as ae,fetchToolMenu as ue,fetchToolMenus as se,resolveToolMenuByCode as ce,updatePlotArgs as me}from"../../lib/xiantao.js";class he extends N{resolveToolFileInputs(e,o){if(e&&o&&o.length>0)throw new a("FILE \u4E0E `--file` \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002");return e?[e]:o??[]}async prepareToolRun(e,o,t){this.validateInputSourceFlags(o,t);const i=await this.getProfile(t.profile),d=await U(i,t.token),n=await this.resolveModule(e,t,d),{moduleId:l,route:r,toolProductUuid:u,uuid:s}=n,c=await ae(d,{moduleId:l,uuid:s}),f=await this.resolveInputMode(c,{cloudRequested:!!(t.cloudDataId?.trim()||t.cloudFilter?.trim()||typeof t.cloudIndex=="number"||t.cloudKey?.trim()||t.cloudRecordFile||t.cloudRecordJson),demo:t.demo,fileInputs:o,interactive:t.interactive}),p=await ie(l,t.config),R=g(p,oe(t.set));let w=c.args_main??[],y=c.args_specific??[],_=g(D(w),R),k=F(T(y),t.specific),m=f.mode==="cloud"?await this.resolveCloudInput(c,t,l,d,s):f.mode==="demo"?this.resolveDemoInput(c,l):f.mode==="record"?this.resolveRecordInput(c,l):f.mode==="none"?this.resolveNoInput(c):await this.uploadAndVerify(i,f.fileInputs??[],{argsMain:_,argsData:c.args_data??[],moduleId:l,uuid:s},d);if(m.schema.length&&(w=m.schema,_=g(D(w),R)),m.input.kind==="cloud"){const P=await me(d,{argsData:ne(m.duid,m.input),argsKey:m.input.cloud.key,argsMain:_,argsSpecific:k,moduleId:l,uuid:s}),I=$(P.args_data??[]);I&&(m={...m,input:{kind:"cloud",cloud:{key:I.key,label:I.label,record:this.normalizeCloudRecord(I.record)}}}),w=P.args_main??w,y=P.args_specific??y,_=g(D(w),R),k=F(T(y),t.specific)}return{agent:i,argsMain:_,argsSpecific:k,argsSpecificSchema:y,auth:d,duid:m.duid,input:m.input,inputMode:f.mode,inputSummary:this.summarizePreparedInput(m.input),moduleId:l,notice:c.notice??"",route:r,schema:w,toolProductUuid:u,uuid:s}}async executeToolRun(e,o,t){this.validateDownloadFlags(t);const i=await this.prepareToolRun(e,o,t);let d=i.argsMain;const n=i.argsSpecific;t.interactive&&(d=await Q(i.schema??[],d),await q(d));const l=Date.now(),r=await re(i.auth,{argsMain:d,argsSpecific:n,duid:i.duid,input:i.input,moduleId:i.moduleId,route:i.route,uuid:i.uuid});if(r.asyncSubmission)return this.resolveAsyncToolRun(i,d,n,t,l,r.message);const u=t.download?await this.downloadResult(i.auth,{downloadPath:t.download,downloadItem:t.downloadItem,downloadLabel:t.downloadLabel,downloads:r.downloads,file:r.file,moduleId:i.moduleId,uuid:i.uuid}):await this.downloadInteractiveResults(i.auth,{choice:t.interactive?await Z({downloads:r.downloads,hasFile:!!r.file}):{downloadFile:!1,downloads:[]},file:r.file,moduleId:i.moduleId,uuid:i.uuid}),s=u[0];return{data:{agent:i.agent,args_main:d,args_specific:n,body:r.body,download_path:s,download_paths:u,downloads:r.downloads,duid:i.duid,file:r.file??null,history:null,history_hint:null,...i.inputSummary,mode:i.inputMode,module_id:i.moduleId,notice:i.notice,result_source:"direct",route:i.route,submission_message:r.message,tool_product_uuid:i.toolProductUuid,uuid:i.uuid},text:this.formatResultText(r,u,t.interactive&&!t.download)}}async resolveAsyncToolRun(e,o,t,i,d,n){const l=await J(e.auth,{intervalMs:3e3,moduleId:e.moduleId,submittedAtMs:d,timeoutMs:i.download?6e4:12e3}),r=l?this.toHistorySummary(l,e.moduleId):null;if(!i.download)return{data:{agent:e.agent,args_main:o,args_specific:t,body:"",download_path:void 0,download_paths:[],downloads:[],duid:e.duid,file:null,history:r,history_hint:this.buildHistoryHint(r),...e.inputSummary,mode:e.inputMode,module_id:e.moduleId,notice:e.notice,result_source:"history",route:e.route,submission_message:n,tool_product_uuid:e.toolProductUuid,uuid:e.uuid},text:this.formatAsyncHistoryText(r,n)};if(!l?.fuid?.trim())return{data:{agent:e.agent,args_main:o,args_specific:t,body:"",download_path:void 0,download_paths:[],downloads:[],duid:e.duid,file:null,history:r,history_hint:this.buildHistoryHint(r),...e.inputSummary,mode:e.inputMode,module_id:e.moduleId,notice:e.notice,result_source:"history",route:e.route,submission_message:n,tool_product_uuid:e.toolProductUuid,uuid:e.uuid},text:this.formatAsyncHistoryText(r,`${n}\uFF0C\u4F46\u6682\u672A\u5B9A\u4F4D\u5230\u5386\u53F2\u8BB0\u5F55\u3002`)};const u=await V(e.auth,{fuid:l.fuid.trim(),intervalMs:3e3,timeoutMs:6e4}),s=u?this.toHistorySummary(u,e.moduleId):r;if(!u?.fuid?.trim())return{data:{agent:e.agent,args_main:o,args_specific:t,body:"",download_path:void 0,download_paths:[],downloads:[],duid:e.duid,file:null,history:s,history_hint:this.buildHistoryHint(s),...e.inputSummary,mode:e.inputMode,module_id:e.moduleId,notice:e.notice,result_source:"history",route:e.route,submission_message:`${n}\uFF0C\u4F46\u7B49\u5F85\u5386\u53F2\u8BB0\u5F55\u5B8C\u6210\u8D85\u65F6\u3002`,tool_product_uuid:e.toolProductUuid,uuid:e.uuid},text:this.formatAsyncHistoryText(s,`${n}\uFF0C\u4F46\u7B49\u5F85\u5386\u53F2\u8BB0\u5F55\u5B8C\u6210\u8D85\u65F6\u3002`)};const{body:c,downloads:f,paths:p}=await this.downloadAsyncHistoryResult(e.auth,{downloadPath:i.download,downloadItem:i.downloadItem,downloadLabel:i.downloadLabel,fuid:u.fuid.trim(),moduleId:e.moduleId});return{data:{agent:e.agent,args_main:o,args_specific:t,body:c,download_path:p[0],download_paths:p,downloads:f,duid:e.duid,file:null,history:s,history_hint:this.buildHistoryHint(s),...e.inputSummary,mode:e.inputMode,module_id:e.moduleId,notice:e.notice,result_source:"history",route:e.route,submission_message:n,tool_product_uuid:e.toolProductUuid,uuid:e.uuid},text:this.formatAsyncHistoryDownloadText(s,p)}}async downloadAsyncHistoryResult(e,o){let t;for(let i=0;i<4;i+=1){const d=await j(e,{fuid:o.fuid});try{const n=await this.downloadResult(e,{downloadPath:o.downloadPath,downloadItem:o.downloadItem,downloadLabel:o.downloadLabel,downloads:d.downloads,moduleId:o.moduleId,uuid:X});return{body:d.body,downloads:d.downloads,paths:n}}catch(n){if(!(n instanceof a)||!this.isRetryableAsyncDownloadError(n)||i===3)throw n;t=n,await this.sleep(3e3)}}throw t??new a("\u4E0B\u8F7D\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")}formatResultText(e,o,t){const i=[];if(e.file&&i.push(e.file),!e.file&&(e.downloads.length>0||e.body)&&i.push("\u5206\u6790\u5B8C\u6210"),!e.file&&!e.body&&e.downloads.length===0)return"\u63D0\u4EA4\u5B8C\u6210";if(e.downloads.length>0&&!t)for(const d of e.downloads)i.push(`${d.label} (${d.device})`);for(const d of o)i.push(d);return i.join(`
|
|
2
2
|
`)}formatAsyncHistoryText(e,o){const t=[o];return e&&t.push(`\u5386\u53F2\u8BB0\u5F55: ${e.fuid} (${e.status})`),t.push(this.buildHistoryHint(e)),t.join(`
|
|
3
3
|
`)}formatAsyncHistoryDownloadText(e,o){const t=[];e&&t.push(`\u5386\u53F2\u8BB0\u5F55: ${e.fuid} (${e.status})`);for(const i of o)t.push(i);return t.join(`
|
|
4
|
-
`)}async downloadResult(e,o){if(o.downloads.length>0){const t=this.pickDownloadItem(o.downloads,{item:o.downloadItem,label:o.downloadLabel,outputPath:o.downloadPath});if(!t)throw new a(this.buildMultipleDownloadsMessage(o.downloads));const i=await A(e,{item:t,moduleId:o.moduleId,uuid:o.uuid});return[await
|
|
4
|
+
`)}async downloadResult(e,o){if(o.downloads.length>0){const t=this.pickDownloadItem(o.downloads,{item:o.downloadItem,label:o.downloadLabel,outputPath:o.downloadPath});if(!t)throw new a(this.buildMultipleDownloadsMessage(o.downloads));const i=await A(e,{item:t,moduleId:o.moduleId,uuid:o.uuid});return[await b(i.url,o.downloadPath)]}if(o.file)return[await b(o.file,o.downloadPath)];throw new a("\u5F53\u524D\u6A21\u5757\u672A\u8FD4\u56DE\u53EF\u4E0B\u8F7D\u6587\u4EF6\u3002")}pickDownloadItem(e,o){if(o.item!==void 0)return this.pickDownloadItemByIndex(e,o.item);if(o.label)return this.pickDownloadItemByLabel(e,o.label);const t=this.inferDownloadDevice(o.outputPath);if(t){const d=e.filter(n=>this.normalizeDevice(n.device)===t);if(d.length===1)return d[0];if(d.length>1)throw new a(`\u4E0B\u8F7D\u683C\u5F0F ${t} \u5339\u914D\u5230\u591A\u4E2A\u7ED3\u679C\uFF0C\u8BF7\u6539\u7528 \`--downloadItem\` \u6216 \`--downloadLabel\` \u7CBE\u786E\u9009\u62E9\u3002
|
|
5
5
|
${this.buildMultipleDownloadsMessage(e)}`)}const i=e.filter(d=>d.endpoint==="public.output.download-result");if(i.length===1)return i[0];if(e.length===1)return e[0]}pickDownloadItemByIndex(e,o){if(!Number.isInteger(o)||o<1||o>e.length)throw new a(`\u4E0B\u8F7D\u9879\u5E8F\u53F7 ${o} \u65E0\u6548\uFF0C\u53EF\u9009\u8303\u56F4\u4E3A 1-${e.length}\u3002
|
|
6
6
|
${this.buildMultipleDownloadsMessage(e)}`);return e[o-1]}pickDownloadItemByLabel(e,o){const t=o.trim().toLowerCase();if(!t)return;const i=e.filter(d=>d.label.trim().toLowerCase()===t);if(i.length===1)return i[0];if(i.length>1)throw new a(`\u4E0B\u8F7D\u9879\u540D\u79F0 ${o} \u5339\u914D\u5230\u591A\u4E2A\u7ED3\u679C\uFF0C\u8BF7\u6539\u7528 \`--downloadItem\` \u7CBE\u786E\u9009\u62E9\u3002
|
|
7
7
|
${this.buildMultipleDownloadsMessage(e)}`)}inferDownloadDevice(e){if(!e)return;const o=e.trim().split(".").pop()?.toLowerCase();if(o)return this.normalizeDevice(o)}normalizeDevice(e){const o=e.trim().toLowerCase();return o==="tif"?"tiff":o==="jpg"?"jpeg":o}buildMultipleDownloadsMessage(e){const o=["\u5F53\u524D\u6A21\u5757\u8FD4\u56DE\u591A\u4E2A\u53EF\u4E0B\u8F7D\u6587\u4EF6\uFF0C\u8BF7\u4F7F\u7528 `--downloadItem`\u3001`--downloadLabel` \u6216\u5E26\u76EE\u6807\u6269\u5C55\u540D\u7684 `--download` \u8DEF\u5F84\u660E\u786E\u9009\u62E9\u3002","\u53EF\u9009\u4E0B\u8F7D\u9879\uFF1A"];return e.forEach((t,i)=>{o.push(`${i+1}. ${t.label} (device=${t.device}, endpoint=${t.endpoint})`)}),o.join(`
|
|
8
|
-
`)}validateDownloadFlags(e){if(e.downloadItem!==void 0&&e.downloadLabel)throw new a("`--downloadItem` \u4E0E `--downloadLabel` \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002");if((e.downloadItem!==void 0||e.downloadLabel)&&!e.download)throw new a("`--downloadItem` \u548C `--downloadLabel` \u4EC5\u53EF\u4E0E `--download` \u4E00\u8D77\u4F7F\u7528\u3002")}toHistorySummary(e,o){const t=e.fuid?.trim();return t?{fuid:t,id:typeof e.id=="number"?e.id:null,module_id:e.module_id?.trim()||o,module_name:e.module_name?.trim()||"",name:e.name?.trim()||"",status:K(e),time:e.time?.trim()||"",type:e.type?.trim()||""}:null}buildHistoryHint(e){return e?`\u53EF\u4F7F\u7528 \`xt history download ${e.fuid} --device pdf\` \u6216 \`xt history list\` \u67E5\u770B\u7ED3\u679C`:"\u53EF\u4F7F\u7528 `xt history list` \u67E5\u770B\u4EFB\u52A1\u8FDB\u5EA6"}async downloadSelectedResults(e,o){const t=[];for(const i of o.downloads){const d=await A(e,{item:i,moduleId:o.moduleId,uuid:o.uuid});t.push(await
|
|
9
|
-
`)}buildCloudSelectionData(e,o){return{choices:e.map((t,i)=>{const d=typeof t.data_id=="string"?t.data_id.trim():"",n=typeof t.label=="string"?t.label.trim():"";return{data_id:d,index:i,label:n||d}}),filter:o??"",selection_type:"cloud_record"}}async uploadFiles(e,o,t,i){const d
|
|
8
|
+
`)}validateDownloadFlags(e){if(e.downloadItem!==void 0&&e.downloadLabel)throw new a("`--downloadItem` \u4E0E `--downloadLabel` \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002");if((e.downloadItem!==void 0||e.downloadLabel)&&!e.download)throw new a("`--downloadItem` \u548C `--downloadLabel` \u4EC5\u53EF\u4E0E `--download` \u4E00\u8D77\u4F7F\u7528\u3002")}toHistorySummary(e,o){const t=e.fuid?.trim();return t?{fuid:t,id:typeof e.id=="number"?e.id:null,module_id:e.module_id?.trim()||o,module_name:e.module_name?.trim()||"",name:e.name?.trim()||"",status:K(e),time:e.time?.trim()||"",type:e.type?.trim()||""}:null}buildHistoryHint(e){return e?`\u53EF\u4F7F\u7528 \`xt history download ${e.fuid} --device pdf\` \u6216 \`xt history list\` \u67E5\u770B\u7ED3\u679C`:"\u53EF\u4F7F\u7528 `xt history list` \u67E5\u770B\u4EFB\u52A1\u8FDB\u5EA6"}async downloadSelectedResults(e,o){const t=[];for(const i of o.downloads){const d=await A(e,{item:i,moduleId:o.moduleId,uuid:o.uuid});t.push(await b(d.url,d.fileName))}return t}async downloadInteractiveResults(e,o){const t=[];return o.choice.downloadFile&&o.file&&t.push(await b(o.file)),o.choice.downloads.length>0&&t.push(...await this.downloadSelectedResults(e,{downloads:o.choice.downloads,moduleId:o.moduleId,uuid:o.uuid})),t}isRetryableAsyncDownloadError(e){return e.message.includes("\u4E0B\u8F7D\u5931\u8D25")||e.message.includes("\u672A\u83B7\u53D6\u5230\u4E0B\u8F7D\u94FE\u63A5")}async sleep(e){await new Promise(o=>setTimeout(o,e))}async resolveInputMode(e,o){if(o.demo)return this.hasDemoInput(e)?{mode:"demo"}:this.hasRecordInput(e)?{mode:"record"}:this.hasCloudInput(e)?{mode:"cloud"}:{mode:"demo"};if(o.fileInputs.length>0)return{fileInputs:o.fileInputs,mode:"upload"};if(o.cloudRequested)return{mode:"cloud"};if(this.hasRecordInput(e))return{mode:"record"};if(this.hasCloudInput(e))return{mode:"cloud"};if(!o.interactive)return this.hasUploadInput(e)?{mode:"upload"}:{mode:"none"};if(!this.hasDemoInput(e))return this.hasUploadInput(e)?{fileInputs:[await M()],mode:"upload"}:{mode:"none"};const t=await Y();return t==="demo"?{mode:t}:{fileInputs:[await M()],mode:t}}resolveNoInput(e){return{duid:e.id?.duid?.trim()??"",input:{kind:"none"},schema:[]}}resolveDemoInput(e,o){const t=e.id?.duid?.trim();if(!t)throw new a(`\u6A21\u5757 ${o} \u672A\u8FD4\u56DE demo duid\uFF0C\u65E0\u6CD5\u4F7F\u7528 \`--demo\`\u3002`);const i=v(e.args_data??[]);if(!i.length||i.some(d=>!d.defaultUpload))throw new a(`\u6A21\u5757 ${o} \u672A\u8FD4\u56DE\u53EF\u7528\u7684 demo \u6587\u4EF6\u4FE1\u606F\uFF0C\u65E0\u6CD5\u4F7F\u7528 \`--demo\`\u3002`);return{duid:t,input:{kind:"upload",uploads:i.map(d=>({key:d.key,label:d.label,upload:{fileName:d.defaultUpload.fileName,fileOss:d.defaultUpload.fileOss,fileSize:d.defaultUpload.fileSize}}))},schema:[]}}hasDemoInput(e){if(!e.id?.duid?.trim())return!1;const t=v(e.args_data??[]);return t.length>0&&t.every(i=>!!i.defaultUpload)}async resolveCloudInput(e,o,t,i,d){const n=$(e.args_data??[]),l=o.cloudKey?.trim()||n?.key||"";if(!l)throw new a(`\u6A21\u5757 ${t} \u672A\u8FD4\u56DE\u53EF\u7528\u7684\u4E91\u7AEF\u6570\u636E\u53C2\u6570\uFF0C\u8BF7\u663E\u5F0F\u4F20\u5165 \`--cloudKey\`.`);const r=await this.resolveCloudRecord(i,o,{argsKey:l,defaultRecord:n?.record,moduleId:t,uuid:d});if(!r)throw new a(`\u6A21\u5757 ${t} \u672A\u8FD4\u56DE\u9ED8\u8BA4\u4E91\u7AEF\u6570\u636E\uFF0C\u8BF7\u4F20\u5165 \`--cloudRecordJson\` \u6216 \`--cloudRecordFile\`.`);return{duid:e.id?.duid?.trim()||"cloud",input:{kind:"cloud",cloud:{key:l,label:n?.label??"",record:this.normalizeCloudRecord(r)}},schema:[]}}resolveRecordInput(e,o){const t=e.id?.duid?.trim();if(!t)throw new a(`\u6A21\u5757 ${o} \u672A\u8FD4\u56DE record duid\uFF0C\u65E0\u6CD5\u4F7F\u7528\u5386\u53F2\u8BB0\u5F55\u8F93\u5165\u3002`);const i=H(e.args_data??[]);if(!i)throw new a(`\u6A21\u5757 ${o} \u672A\u8FD4\u56DE\u53EF\u7528\u7684\u6570\u636E\u8BB0\u5F55\uFF0C\u65E0\u6CD5\u76F4\u63A5\u8FD0\u884C\u3002`);return{duid:t,input:{kind:"record",record:{key:i.key,label:i.label,moduleId:i.moduleId,moduleName:i.moduleName,recordId:i.recordId,recordName:i.recordName,time:i.time}},schema:[]}}hasRecordInput(e){return!!(e.id?.duid?.trim()&&H(e.args_data??[]))}hasCloudInput(e){return!!$(e.args_data??[])}hasUploadInput(e){return v(e.args_data??[]).length>0}async uploadAndVerify(e,o,t,i){const d=await this.uploadFiles(e,o,t.argsData??[],t.moduleId),n=await le(i,{argsMain:t.argsMain,moduleId:t.moduleId,uploads:d,uuid:t.uuid});return{duid:n.duid,input:{kind:"upload",uploads:d},schema:n.schema}}summarizePreparedInput(e){if(e.kind==="cloud")return{file_name:null,file_oss:null,file_size:null,input_cloud:this.summarizeCloudInput(e.cloud),input_record:null,input_uploads:null};if(e.kind==="none")return{file_name:null,file_oss:null,file_size:null,input_cloud:null,input_record:null,input_uploads:null};if(e.kind==="record")return{file_name:null,file_oss:null,file_size:null,input_cloud:null,input_record:{label:e.record.label,module_id:e.record.moduleId,module_name:e.record.moduleName,record_id:e.record.recordId,record_name:e.record.recordName,time:e.record.time},input_uploads:null};const o=e.uploads.map(i=>({file_name:i.upload.fileName,file_oss:i.upload.fileOss,file_size:i.upload.fileSize,key:i.key,label:i.label})),t=o.length===1?o[0]:null;return{file_name:t?.file_name??null,file_oss:t?.file_oss??null,file_size:t?.file_size??null,input_cloud:null,input_record:null,input_uploads:o}}summarizeCloudInput(e){return{data_filter:this.readCloudOptionValue(e.record.data_filter),data_id:typeof e.record.data_id=="string"?e.record.data_id.trim():"",data_process:this.readCloudOptionValue(e.record.data_process),key:e.key,label:e.label,record:structuredClone(e.record),record_label:typeof e.record.label=="string"?e.record.label.trim():""}}readCloudOptionValue(e){return S(e)&&(typeof e.value=="string"?e.value.trim():"")||null}async resolveCloudRecord(e,o,t){return o.cloudRecordJson?this.parseCloudRecord(o.cloudRecordJson,"--cloudRecordJson"):o.cloudRecordFile?this.parseCloudRecord(await L(o.cloudRecordFile,"utf8"),"--cloudRecordFile"):o.cloudFilter?.trim()||o.cloudDataId?.trim()||typeof o.cloudIndex=="number"?this.resolveCloudRecordByQuery(e,o,t):t.defaultRecord}parseCloudRecord(e,o){let t;try{t=JSON.parse(e)}catch{throw new a(`${o} \u4E0D\u662F\u5408\u6CD5 JSON\u3002`)}if(!S(t))throw new a(`${o} \u5FC5\u987B\u662F JSON \u5BF9\u8C61\u3002`);return t}normalizeCloudRecord(e){const o={};for(const[t,i]of Object.entries(e))i!==void 0&&(o[t]=structuredClone(i));return(typeof o.type!="string"||!o.type.trim())&&(o.type="cloud"),o}validateInputSourceFlags(e,o){const t=!!(o.cloudRecordJson||o.cloudRecordFile),i=!!(o.cloudDataId?.trim()||o.cloudFilter?.trim()||typeof o.cloudIndex=="number"),d=t||i;if(o.cloudRecordJson&&o.cloudRecordFile)throw new a("`--cloudRecordJson` \u4E0E `--cloudRecordFile` \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002");if(t&&i)throw new a("\u663E\u5F0F\u4E91\u7AEF\u8BB0\u5F55\u53C2\u6570\u4E0D\u80FD\u4E0E `--cloudFilter` / `--cloudDataId` / `--cloudIndex` \u540C\u65F6\u4F7F\u7528\u3002");if(o.demo&&d)throw new a("`--demo` \u4E0D\u80FD\u4E0E\u4E91\u7AEF\u6570\u636E\u8BB0\u5F55\u53C2\u6570\u540C\u65F6\u4F7F\u7528\u3002");if(e.length>0&&d)throw new a("`--file` \u4E0D\u80FD\u4E0E\u4E91\u7AEF\u6570\u636E\u8BB0\u5F55\u53C2\u6570\u540C\u65F6\u4F7F\u7528\u3002")}async resolveCloudRecordByQuery(e,o,t){const i=await this.fetchCloudRecords(e,{argsKey:t.argsKey,filter:o.cloudFilter?.trim(),moduleId:t.moduleId,selectedRecord:t.defaultRecord,uuid:t.uuid});if(i.length===0){const n=o.cloudFilter?.trim();throw n?new a(`\u672A\u627E\u5230\u5339\u914D\u4E91\u7AEF\u6570\u636E: ${n}`):new a("\u5F53\u524D\u6A21\u5757\u6CA1\u6709\u53EF\u9009\u7684\u4E91\u7AEF\u6570\u636E\u8BB0\u5F55\u3002")}const d=o.cloudDataId?.trim();if(d){const n=i.find(l=>(typeof l.data_id=="string"?l.data_id.trim():"")===d);if(!n)throw new a(`\u672A\u627E\u5230 data_id=${d} \u5BF9\u5E94\u7684\u4E91\u7AEF\u6570\u636E\u3002`);return n}if(typeof o.cloudIndex=="number"){const n=i[o.cloudIndex];if(!n)throw new a(`\u4E91\u7AEF\u6570\u636E\u7D22\u5F15\u8D85\u51FA\u8303\u56F4: ${o.cloudIndex}\uFF0C\u5F53\u524D\u5171\u6709 ${i.length} \u6761\u3002`);return n}if(i.length===1)return i[0];if(o.interactive)return this.normalizeCloudRecord(await G(i));throw new B(this.buildCloudSelectionHint(i,o.cloudFilter?.trim()),this.buildCloudSelectionData(i,o.cloudFilter?.trim()))}async fetchCloudRecords(e,o){const t=await z(e,{argsKey:o.argsKey,currentPage:1,filter:o.filter,moduleId:o.moduleId,selectedRecord:o.selectedRecord,uuid:o.uuid}),i=t.records.map(d=>this.normalizeCloudRecord(d));for(let d=t.currentPage+1;d<=t.lastPage;d+=1){const n=await z(e,{argsKey:o.argsKey,currentPage:d,filter:o.filter,moduleId:o.moduleId,selectedRecord:o.selectedRecord,uuid:o.uuid});i.push(...n.records.map(l=>this.normalizeCloudRecord(l)))}return i}buildCloudSelectionHint(e,o){const t=[o?`\u5339\u914D\u5230\u591A\u4E2A\u4E91\u7AEF\u6570\u636E: ${o}`:"\u5339\u914D\u5230\u591A\u4E2A\u4E91\u7AEF\u6570\u636E","\u8BF7\u4F7F\u7528 `--cloudIndex` \u6216 `--cloudDataId` \u6307\u5B9A\u5176\u4E2D\u4E00\u6761\uFF1A"];return e.forEach((i,d)=>{const n=typeof i.data_id=="string"?i.data_id.trim():"",l=typeof i.label=="string"?i.label.trim():"";t.push(` [${d}] ${l||n}`)}),t.join(`
|
|
9
|
+
`)}buildCloudSelectionData(e,o){return{choices:e.map((t,i)=>{const d=typeof t.data_id=="string"?t.data_id.trim():"",n=typeof t.label=="string"?t.label.trim():"";return{data_id:d,index:i,label:n||d}}),filter:o??"",selection_type:"cloud_record"}}async uploadFiles(e,o,t,i){const d=v(t??[]),n=this.resolveUploadInputs(o,d,i),l=await U(e),r=[];for(const u of n){const s=await ee(l,u.filePath);r.push({key:u.key,label:u.label,upload:s})}return r}resolveUploadInputs(e,o,t){if(!o.length)throw new a(`\u6A21\u5757 ${t} \u672A\u68C0\u6D4B\u5230\u53EF\u4E0A\u4F20\u8F93\u5165\uFF0C\u4E0D\u80FD\u4F7F\u7528 \`--file\`\u3002`);if(!e.length)throw o.length===1?new a("\u901A\u7528\u6A21\u5F0F\u8BF7\u4F20\u5165 FILE / `--file <xlsx>`\uFF0C\u6216\u6539\u7528 `--demo`\u3002"):new a(`\u6A21\u5757 ${t} \u9700\u8981\u591A\u4E2A\u4E0A\u4F20\u5B57\u6BB5\uFF0C\u8BF7\u4F7F\u7528 \`--file key=path\`\u3002\u53EF\u7528\u5B57\u6BB5: ${o.map(r=>r.key).join(", ")}`);const[i]=o;if(o.length===1&&e.length===1){const r=this.parseUploadFileInput(e[0]);if(r.key&&r.key!==i.key)throw new a(`\u6A21\u5757 ${t} \u4EC5\u652F\u6301\u4E0A\u4F20\u5B57\u6BB5 ${i.key}\uFF0C\u6536\u5230 ${r.key}\u3002`);return[{filePath:r.path,key:i.key,label:i.label}]}const d=new Map(o.map(r=>[r.key,r])),n=new Map;for(const r of e){const u=this.parseUploadFileInput(r);if(!u.key){if(o.length===1){if(n.has(i.key))throw new a(`\u6A21\u5757 ${t} \u4EC5\u9700\u8981 1 \u4E2A\u4E0A\u4F20\u6587\u4EF6\uFF0C\u6536\u5230\u91CD\u590D\u8F93\u5165\u3002`);n.set(i.key,u.path);continue}throw new a(`\u6A21\u5757 ${t} \u9700\u8981\u591A\u4E2A\u4E0A\u4F20\u5B57\u6BB5\uFF0C\u8BF7\u4F7F\u7528 \`--file key=path\`\u3002\u53EF\u7528\u5B57\u6BB5: ${o.map(c=>c.key).join(", ")}`)}const s=d.get(u.key);if(!s)throw new a(`\u6A21\u5757 ${t} \u4E0D\u5B58\u5728\u4E0A\u4F20\u5B57\u6BB5 ${u.key}\u3002\u53EF\u7528\u5B57\u6BB5: ${o.map(c=>c.key).join(", ")}`);if(n.has(s.key))throw new a(`\u4E0A\u4F20\u5B57\u6BB5 ${s.key} \u91CD\u590D\u4F20\u5165\u3002`);n.set(s.key,u.path)}const l=o.filter(r=>r.required&&!n.has(r.key));if(l.length>0)throw new a(`\u6A21\u5757 ${t} \u7F3A\u5C11\u5FC5\u586B\u4E0A\u4F20\u5B57\u6BB5: ${l.map(r=>r.key).join(", ")}`);return o.flatMap(r=>{const u=n.get(r.key);return u?[{filePath:u,key:r.key,label:r.label}]:[]})}parseUploadFileInput(e){const o=e.trim();if(!o)throw new a("`--file` \u4E0D\u80FD\u4E3A\u7A7A\u3002");const t=o.indexOf("=");if(t<=0)return{path:o};const i=o.slice(0,t).trim(),d=o.slice(t+1).trim();if(!i||!d)throw new a("\u591A\u4E0A\u4F20\u6A21\u5757\u8BF7\u4F7F\u7528 `--file key=path`\u3002");return{key:i,path:d}}async resolveModule(e,o,t){const i=e?.trim(),d=o.route?.trim(),n=o.uuid?.trim(),l=await de(o.toolProductUuid);if(!i){if(!o.interactive)throw new a("\u8BF7\u4F20\u5165 `module_id`\uFF0C\u6216\u4F7F\u7528 `--interactive --file <xlsx>` \u5148\u4ECE\u83DC\u5355\u9009\u62E9\u5DE5\u5177\u3002");const u=await W(this.sortTopLevelMenus(await se(t,l)));return{moduleId:u.code,route:d??u.route,toolProductUuid:l,uuid:n??u.uuid}}if(d&&n)return{moduleId:i,route:d,toolProductUuid:l,uuid:n};const r=o.menuUuid?.trim();if(r&&l){const u=await ue(t,r,l),s=d??this.requireMenuRoute(u),c=u.code?.trim();if(c&&c!==i)throw new a(`\u83DC\u5355\u6A21\u5757 code \u4E3A ${c}\uFF0C\u4E0E\u4F20\u5165\u7684 module_id ${i} \u4E0D\u4E00\u81F4\u3002`);return{moduleId:i,route:s,toolProductUuid:l,uuid:n??r}}if(l){const u=await ce(t,l,i);return{moduleId:i,route:d??u.route,toolProductUuid:l,uuid:n??u.uuid}}if(!n)throw new a("\u901A\u7528\u6A21\u5F0F\u9700\u8981\u4F20\u5165 `--uuid`\uFF0C\u6216\u4F7F\u7528\u9ED8\u8BA4/\u663E\u5F0F `toolProductUuid` \u81EA\u52A8\u89E3\u6790\u3002");if(!d)throw new a("\u901A\u7528\u6A21\u5F0F\u9700\u8981\u4F20\u5165 `--route`\uFF0C\u6216\u4F7F\u7528\u9ED8\u8BA4/\u663E\u5F0F `toolProductUuid` \u81EA\u52A8\u89E3\u6790\u3002");return{moduleId:i,route:d,toolProductUuid:l,uuid:n}}sortTopLevelMenus(e){const o=["\u57FA\u7840\u7ED8\u56FE","\u8868\u8FBE\u5DEE\u5F02","\u529F\u80FD\u805A\u7C7B","\u4EA4\u4E92\u7F51\u7EDC","\u4E34\u5E8A\u610F\u4E49","\u5176\u4ED6"],t=new Map(o.map((i,d)=>[i,d]));return[...e].sort((i,d)=>{const n=t.get(i.title?.trim()??"")??Number.MAX_SAFE_INTEGER,l=t.get(d.title?.trim()??"")??Number.MAX_SAFE_INTEGER;return n-l})}requireMenuRoute(e){const o=e.route;if(typeof o!="string"||!o.trim())throw new a("\u83DC\u5355\u672A\u8FD4\u56DE\u53EF\u7528 route\uFF0C\u8BF7\u6539\u7528 `--route` \u663E\u5F0F\u6307\u5B9A\u3002");return o.trim()}}class C extends he{static description="Run a Xiantao bioinformatics tool";static args={tool:x.string({description:"Tool id; optional with --interactive to choose from menus"}),file:x.string({description:"Path to the local xlsx file; optional with --demo or --interactive"})};static flags={...O,...E,...te,demo:h.boolean({default:!1,description:"Prefer the module default remote input returned by fetch-all instead of uploading a local file"}),file:h.string({description:"Path to the local xlsx file; repeat or use KEY=PATH for named upload fields",multiple:!0}),download:h.string({description:"Download the generated file or preferred analysis result to this local path after submission"}),downloadItem:h.integer({description:"Select a download item by its 1-based index when --download matches multiple results"}),downloadLabel:h.string({description:"Select a download item by its label when --download matches multiple results"}),interactive:h.boolean({default:!1,description:"Prompt for dynamic args before submitting the module"}),menuUuid:h.string({description:"Tool menu UUID from /products/apply/:toolProductUuid/analyse/:uuid"}),route:h.string({description:"Tool route like app1.violin_flat in generic mode"}),token:h.string({description:"Bearer token for agent.helixlife.cn xiantao APIs; falls back to the stored agent token"}),toolProductUuid:h.string({description:"tool_product_uuid used to auto-resolve module UUID and route in generic mode; defaults to the main Xiantao product UUID"}),uuid:h.string({description:"Tool UUID used in generic mode for fetch-all and verify-upload; optional when --toolProductUuid is provided"})};async run(){this.warnIfLegacyPlotCommand();const{args:e,flags:o}=await this.parse(C);if(o.interactive&&o.json)throw new a("`--interactive` \u4E0D\u80FD\u4E0E `--json` \u540C\u65F6\u4F7F\u7528\u3002");const t=this.resolveToolFileInputs(e.file,o.file),i=await this.executeToolRun(e.tool,t,o);this.print(o,i.data,i.text,{profile:i.data.agent})}}export{he as ToolRunCommandBase,C as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{Args as
|
|
2
|
-
`);t.push(`args_main: ${f.section_count} sections, ${f.field_count} fields, ${f.required_field_count} required`);for(const
|
|
3
|
-
`)}summarizeInputs(e,
|
|
1
|
+
import{Args as y,Flags as b}from"@oclif/core";import{XtzCommand as k}from"../../base-command.js";import{getAuthContext as q}from"../../lib/auth.js";import{globalFlags as B}from"../../lib/flags.js";import{isJsonObject as $}from"../../lib/json.js";import{buildArgsMainFromSchema as x,buildArgsSpecificFromSchema as A}from"../../lib/plot-schema.js";import{resolveXiantaoToolProductUuid as C}from"../../lib/storage.js";import{findDefaultXiantaoCloudInput as v,findDefaultXiantaoRecord as F,listXiantaoUploadFields as I}from"../../lib/tool-inputs.js";import{fetchAllPlotArgs as S,resolveToolMenuByCode as U}from"../../lib/xiantao.js";class h extends k{static description="Inspect a Xiantao tool and its dynamic inputs";static args={tool:y.string({description:"Tool id, e.g. violin_flat",required:!0})};static flags={...B,token:b.string({description:"Bearer token for agent.helixlife.cn xiantao APIs; falls back to the stored agent token"}),toolProductUuid:b.string({description:"tool_product_uuid used in the menu filter payload; defaults to the main Xiantao product UUID"})};async run(){const{args:e,flags:o}=await this.parse(h),i=await this.getProfile(o.profile),n=await q(i,o.token),d=await C(o.toolProductUuid),s=await U(n,d,e.tool),l=await S(n,{moduleId:e.tool,uuid:s.uuid}),f=l.args_main??[],r=this.summarizeInputs(l.args_data??[],l.id?.duid??""),c=this.summarizeSchema(f),t={agent:i,args_data:l.args_data??[],args_main:f,args_main_defaults:x(f),args_specific:l.args_specific??[],args_specific_defaults:A(l.args_specific),duid:l.id?.duid??"",inputs:r,module_id:e.tool,notice:l.notice??"",path:s.path,route:s.route,summary:c,title:s.title,tool_product_uuid:d,uuid:s.uuid};this.print(o,t,this.formatInspectText(t.module_id,t.title,t.path,t.route,t.uuid,t.notice,r,c,l.args_specific??[],f),{profile:i})}formatInspectText(e,o,i,n,d,s,l,f,r,c){const t=[`${e} ${o}`,`path: ${i||"-"}`,`route: ${n}`,`uuid: ${d}`];s&&t.push(`notice: ${s}`),t.push("input:"),t.push(` cloud: ${l.cloud_available?this.formatCloudSummary(l.cloud_default):"unavailable"}`),t.push(` upload: ${l.upload_available?`${l.upload_fields.length} fields`:"not detected"}`);for(const a of l.upload_fields){const m=[a.label&&a.label!==a.key?a.label:void 0,a.required?"required":void 0,a.demo_upload?this.formatDemoSummary(a.demo_upload):"no demo default"].filter(Boolean);t.push(` - ${a.key}${m.length>0?` - ${m.join(", ")}`:""}`)}if(t.push(` demo: ${l.demo_available?"available":"unavailable"}`),t.push(` record: ${l.record_available?this.formatRecordSummary(l.record_default):"unavailable"}`),r.length>0){t.push(`args_specific: ${r.length} fields`);for(const a of r){const m=this.formatLabel(a.label),p=[m&&m!==a.key?m:void 0,a.type?.trim(),a.required?"required":void 0,a.multiple?"multiple":void 0,this.formatDefaultValue(a.default_value)].filter(Boolean);t.push(` ${a.key}${p.length>0?` - ${p.join(", ")}`:""}`)}}else t.push("args_specific: none");if(c.length===0)return t.push("args_main: none"),t.join(`
|
|
2
|
+
`);t.push(`args_main: ${f.section_count} sections, ${f.field_count} fields, ${f.required_field_count} required`);for(const a of c){const m=a.form??[],p=m.filter(u=>u.required).length;t.push(`- ${this.formatLabel(a.label)||a.key} (${a.key}) - ${m.length} fields, ${p} required`);for(const u of a.form??[]){const _=this.formatLabel(u.label),g=[_&&_!==u.key?_:void 0,u.type?.trim(),u.required?"required":void 0,u.multiple?"multiple":void 0,u.options?.length?`options:${u.options.length}`:void 0,this.formatDefaultValue(u.default_value)].filter(Boolean);t.push(` ${u.key}${g.length>0?` - ${g.join(", ")}`:""}`)}}return t.join(`
|
|
3
|
+
`)}summarizeInputs(e,o){const i=I(e),n=F(e),d=v(e),s=!!(o.trim()&&i.length>0&&i.every(r=>!!r.defaultUpload)),l=!!(o.trim()&&n),f=l&&n?{key:n.key,label:n.label,module_id:n.moduleId,module_name:n.moduleName,record_id:n.recordId,record_name:n.recordName,time:n.time}:null;return{cloud_available:!!d,cloud_default:d?this.toCloudSummary(d.key,d.label,d.record):null,demo_available:s,record_available:l,record_default:f,upload_available:i.length>0,upload_fields:i.map(r=>({demo_upload:r.defaultUpload?{file_name:r.defaultUpload.fileName,file_oss:r.defaultUpload.fileOss,file_size:r.defaultUpload.fileSize,key:r.key,label:r.label}:null,key:r.key,label:r.label,required:r.required}))}}summarizeSchema(e){const o=e.flatMap(i=>i.form??[]);return{field_count:o.length,required_field_count:o.filter(i=>i.required).length,section_count:e.length}}formatDemoSummary(e){return`${e.file_name} (${this.formatFileSize(e.file_size)})`}formatRecordSummary(e){return e?`${e.module_id||"-"} ${e.record_id}${e.time?` (${e.time})`:""}`:"available"}formatCloudSummary(e){if(!e)return"available";const o=[e.record_label||e.data_id,e.data_filter?`filter:${e.data_filter}`:void 0,e.data_process?`process:${e.data_process}`:void 0].filter(Boolean);return`${e.key}${o.length>0?` (${o.join(", ")})`:""}`}formatLabel(e){return typeof e=="string"?e.trim():$(e)?Object.values(e).filter(o=>typeof o=="string"&&!!o.trim()).map(o=>o.trim()).join(" / "):""}toCloudSummary(e,o,i){const n=this.readCloudOptionValue(i.data_filter),d=this.readCloudOptionValue(i.data_process);return{data_filter:n,data_id:typeof i.data_id=="string"?i.data_id.trim():"",data_process:d,key:e,label:o,record_label:typeof i.label=="string"?i.label.trim():""}}readCloudOptionValue(e){return $(e)&&(typeof e.value=="string"?e.value.trim():"")||null}formatFileSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}formatDefaultValue(e){if(!(e==null||e===""))return typeof e=="string"?`default:${e}`:typeof e=="number"||typeof e=="boolean"?`default:${String(e)}`:Array.isArray(e)?e.length>0?`default:${e.length} items`:void 0:"default:object"}}export{h as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Args as u,Flags as s}from"@oclif/core";import{createErrorEnvelope as S,createSuccessEnvelope as _}from"../../lib/envelope.js";import{XtzError as a}from"../../lib/errors.js";import{globalFlags as b,toolCloudFlags as w}from"../../lib/flags.js";import{isJsonObject as d}from"../../lib/json.js";import{buildSubmitArgsData as U}from"../../lib/xiantao-plot.js";import{searchPlotSpecificOptions as k}from"../../lib/xiantao.js";import{ToolRunCommandBase as I}from"../plot/run.js";class f extends I{static description="Search dynamic argsSpecific options for a Xiantao tool in agent mode";static usage="tool specific-search <tool> <argsKey> <query> --json [--cloudDataId <value>]";static args={tool:u.string({description:"Tool id, e.g. lollipop_cor_gene",required:!0}),argsKey:u.string({description:"argsSpecific key, e.g. genes",required:!0}),query:u.string({description:"Search text typed into the dynamic specific input",required:!0})};static flags={...b,...w,menuUuid:s.string({description:"Tool menu UUID from /products/apply/:toolProductUuid/analyse/:uuid"}),route:s.string({description:"Tool route like app1.lollipop_cor_gene in generic mode"}),selected:s.string({description:"Current selected argsSpecific value; defaults to the prepared field value"}),token:s.string({description:"Bearer token for agent.helixlife.cn xiantao APIs; falls back to the stored agent token"}),toolProductUuid:s.string({description:"tool_product_uuid used to auto-resolve module UUID and route in generic mode; defaults to the main Xiantao product UUID"}),uuid:s.string({description:"Tool UUID used in generic mode for fetch-all; optional when --toolProductUuid is provided"})};async catch(r){const e=await this.getProfile(this.readProfileFlag());this.log(JSON.stringify(S(e,"tool specific-search",this.normalizeError(r)),null,2)),this.exit(1)}async run(){const{args:r,flags:e}=await this.parse(f);if(!e.json)throw new a("`xt tool specific-search` \u4EC5\u652F\u6301 `--json` \u8F93\u51FA\u3002");const n=r.argsKey.trim(),l=r.query.trim();if(!l)throw new a("\u641C\u7D22\u5173\u952E\u8BCD\u4E0D\u80FD\u4E3A\u7A7A\u3002");const i=await this.prepareToolRun(r.tool,[],{...e,demo:!1,interactive:!1,json:e.json}),o=i.argsSpecificSchema.find(c=>c.key===n);if(!o)throw new a(`\u6A21\u5757 ${i.moduleId} \u672A\u627E\u5230 argsSpecific \u5B57\u6BB5: ${n}`);if(o.type&&!o.type.includes("Search"))throw new a(`\u5B57\u6BB5 ${n} \u4E0D\u662F\u52A8\u6001\u641C\u7D22\u7C7B\u578B: ${o.type}`);const g=e.selected??i.argsSpecific[n]??o.default_value??"",m=await k(i.auth,{argsData:U(i.duid,i.input),argsKey:n,listen:o.listen??[],moduleId:i.moduleId,searchString:l,selected:g,uuid:i.uuid}),h=await this.getProfile(e.profile);this.log(JSON.stringify(_(h,"tool specific-search",{agent:i.agent,args_key:n,choices:m.map((c,y)=>j(c,y)),default_value:o.default_value??null,field:{key:o.key,label:o.label??"",listen:o.listen??[],multiple:o.multiple??!1,type:o.type??""},input_cloud:i.inputSummary.input_cloud,input_record:i.inputSummary.input_record,input_uploads:i.inputSummary.input_uploads,mode:i.inputMode,module_id:i.moduleId,route:i.route,search_string:l,selected:g,tool_product_uuid:i.toolProductUuid,total:m.length,uuid:i.uuid}),null,2))}readProfileFlag(){for(let r=0;r<this.argv.length;r+=1){const e=this.argv[r];if((e==="--profile"||e==="--agent")&&this.argv[r+1])return this.argv[r+1];if(e.startsWith("--profile="))return e.slice(10);if(e.startsWith("--agent="))return e.slice(8)}}normalizeError(r){return r.message.replace(/\u001B\[[0-?]*[ -/]*[@-~]/g,"").includes("required arg")?new a("`xt tool specific-search` \u9700\u8981\u4F20\u5165 TOOL\u3001ARGSKEY \u548C QUERY\u3002"):r}}function P(t){return t.replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim()}function j(t,r){const e=p(t);return{index:r,label:x(e),raw:t,value:e,value_type:E(e)}}function p(t){return typeof t=="string"?P(t):Array.isArray(t)?t.map(r=>p(r)):d(t)?Object.fromEntries(Object.entries(t).map(([r,e])=>[r,p(e)])):t}function x(t){if(typeof t=="string")return t;if(d(t))for(const r of["label","variable","name","value","title"]){const e=t[r];if(typeof e=="string"&&e.trim())return e.trim()}return JSON.stringify(t)}function E(t){return Array.isArray(t)?"array":d(t)?"object":typeof t}export{f as default};
|
package/dist/lib/config.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{mkdir as
|
|
2
|
-
`,"utf8"),{key:e,path:
|
|
1
|
+
import{mkdir as A,readFile as y,writeFile as U}from"node:fs/promises";import _ from"node:os";import c from"node:path";import{DEFAULT_XIANTAO_BASE_URL as E,DEFAULT_XIANTAO_LOGIN_URL as C,XIANTAO_CONFIG_PATH as L}from"./constants.js";import{XtzError as r}from"./errors.js";import{isJsonObject as b}from"./json.js";const f=["agent_api","base-url","login-url"];function p(){return c.join(_.homedir(),L)}async function S(n,t){const e=h(n),a=d(e,t),o=p(),i=await w(o),l=x(e);return i[l]=a,l==="agent_api"&&delete i["base-url"],await A(c.dirname(o),{recursive:!0}),await U(o,`${JSON.stringify(i,null,2)}
|
|
2
|
+
`,"utf8"),{key:e,path:o,value:a}}async function g(n){const t=h(n),e=p(),a=X(t);if(a)return{key:t,path:e,source:"environment",value:a};const o=await w(e),i=$(o,t);return i?{key:t,path:e,source:"config",value:d(t,i)}:{key:t,path:e,source:"default",value:O(t)}}async function N(){return(await g("base-url")).value}async function F(){return(await g("login-url")).value}async function G(){return u("agent/skills/auth-url")}async function j(){return u("agent/skills/check-token")}async function D(){return u("agent/bio-api")}async function J(){return u("agent/tool/menus")}async function k(){const n=new URL(await u("agent/upload/config"));return n.searchParams.set("type","bio"),n.searchParams.set("oss_type","bio"),n.toString()}async function u(n){const t=await N();return`${t.endsWith("/api/v1")?t:`${t}/api/v1`}/${n}`}async function w(n){try{const t=await y(n,"utf8"),e=JSON.parse(t);if(!b(e))throw new r(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u4E0D\u6B63\u786E: ${n}`);const a=e.agent_api;if(a!==void 0&&typeof a!="string")throw new r(`\u914D\u7F6E\u9879 agent_api \u5FC5\u987B\u662F\u5B57\u7B26\u4E32: ${n}`);const o=e["base-url"];if(o!==void 0&&typeof o!="string")throw new r(`\u914D\u7F6E\u9879 base-url \u5FC5\u987B\u662F\u5B57\u7B26\u4E32: ${n}`);const i=e["login-url"];if(i!==void 0&&typeof i!="string")throw new r(`\u914D\u7F6E\u9879 login-url \u5FC5\u987B\u662F\u5B57\u7B26\u4E32: ${n}`);return e}catch(t){if(T(t)&&t.code==="ENOENT")return{};throw t}}function h(n){const t=n.trim().toLowerCase();if(f.includes(t))return t;throw new r(`\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u9879 ${n}\uFF0C\u5F53\u524D\u652F\u6301: ${f.join(", ")}`)}function d(n,t){const e=t.trim();if(!e)throw new r(`\u914D\u7F6E\u9879 ${n} \u4E0D\u80FD\u4E3A\u7A7A`);return s(n)?m(e):n==="login-url"?v(e):e}function X(n){if(s(n)){const t=process.env.XIANTAO_BASE_URL?.trim();return t?m(t):void 0}if(n==="login-url"){const t=process.env.XIANTAO_LOGIN_URL?.trim();return t?v(t):void 0}}function O(n){if(s(n))return E;if(n==="login-url")return C;throw new r(`\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u9879 ${n}`)}function x(n){return s(n)?"agent_api":n}function $(n,t){return s(t)?n.agent_api?.trim()||n["base-url"]?.trim():n[t]?.trim()}function s(n){return n==="agent_api"||n==="base-url"}function m(n){let t;try{t=new URL(n)}catch{throw new r("base-url \u5FC5\u987B\u662F\u6709\u6548\u7684\u7EDD\u5BF9 URL\uFF0C\u4F8B\u5982 https://agent.helixlife.cn")}if(t.protocol!=="http:"&&t.protocol!=="https:")throw new r("base-url \u53EA\u652F\u6301 http \u6216 https");return n.replace(/\/+$/,"")}function v(n){let t;try{t=new URL(n)}catch{throw new r("login-url \u5FC5\u987B\u662F\u6709\u6548\u7684\u7EDD\u5BF9 URL\uFF0C\u4F8B\u5982 https://www.helixlife.net/")}if(t.protocol!=="http:"&&t.protocol!=="https:")throw new r("login-url \u53EA\u652F\u6301 http \u6216 https");return n}function T(n){return n instanceof Error&&"code"in n}export{f as XIANTAO_CONFIG_KEYS,p as getXiantaoConfigPath,G as resolveAuthUrlEndpoint,j as resolveCheckTokenEndpoint,k as resolveUploadConfigEndpoint,N as resolveXiantaoBaseUrl,D as resolveXiantaoBioApiEndpoint,g as resolveXiantaoConfigValue,F as resolveXiantaoLoginUrl,J as resolveXiantaoToolMenusEndpoint,S as setXiantaoConfigValue};
|
package/dist/lib/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const o="opencode",A=".config/helixlife/config.json",t=".config/helixlife/update-check.json",c=".config/helixlife/config.json",e="https://agent.helixlife.net"?.trim(),_=process.env.XTZ_BUILD_XIANTAO_LOGIN_URL?.trim(),n=(e||"https://agent.helixlife.cn").replace(/\/+$/,""),T=_||"https://agent.helixlife.cn/",I="c0b6febb-52dd-4525-970a-61bbe9e263ff",U="2d491694-8c8d-11ee-9409-00163e118c99";export{o as DEFAULT_AGENT,n as DEFAULT_XIANTAO_BASE_URL,T as DEFAULT_XIANTAO_LOGIN_URL,I as DEFAULT_XIANTAO_TOOL_PRODUCT_UUID,c as XIANTAO_CONFIG_PATH,U as XIANTAO_HISTORY_UUID,A as XTZ_CONFIG_PATH,t as XTZ_UPDATE_CHECK_PATH};
|
package/dist/lib/envelope.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{XtzChoiceRequiredError as d}from"./errors.js";function
|
|
1
|
+
import{XtzChoiceRequiredError as d}from"./errors.js";function o(n,u,i){return{code:"OK",data:i,message:"",meta:{command:u,profile:n,version:"1"},ok:!0}}function e(n,u,i){const c=i instanceof Error?i.message:String(i),r=i instanceof d?i.data:null;return{code:l(c),data:r,message:c,meta:{command:u,profile:n,version:"1"},ok:!1}}function l(n){return n.includes("\u6388\u6743\u5DF2\u8FC7\u671F")||n.includes("\u6388\u6743\u5DF2\u8FC7\u671F\u6216\u65E0\u6548")?"AUTH_EXPIRED":n.includes("\u672A\u627E\u5230")&&n.includes("token")?"AUTH_REQUIRED":n.includes("\u672A\u627E\u5230\u6A21\u5757")?"TOOL_NOT_FOUND":n.includes("\u9700\u8D2D\u4E70")||n.includes("\u65E0\u6743\u9650")||n.includes("\u6743\u9650")?"PERMISSION_REQUIRED":n.includes("\u5339\u914D\u5230\u591A\u4E2A\u7ED3\u679C")||n.includes("\u5339\u914D\u5230\u591A\u4E2A\u4E91\u7AEF\u6570\u636E")?"TOOL_AMBIGUOUS":n.includes("Missing 1 required arg")||n.includes("Missing 2 required args")||n.includes("Missing required arg")||n.includes("\u9700\u8981\u4F20\u5165 TOOL")||n.includes("\u8BF7\u4F20\u5165 `module_id`")||n.includes("\u8BF7\u4F20\u5165 FILE")||n.includes("\u9700\u8981 `--uuid`")||n.includes("\u9700\u8981 `--route`")||n.includes("\u9700\u8981 `--file`")?"INPUT_REQUIRED":n.includes("\u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E")||n.includes("\u4E0D\u662F\u5408\u6CD5 JSON")||n.includes("Unexpected argument:")||n.includes("\u4E0D\u80FD\u540C\u65F6\u4F7F\u7528")||n.includes("\u4E0D\u80FD\u4E0E")||n.includes("\u65E0\u6548")||n.includes("\u4E0D\u4E00\u81F4")?"INPUT_INVALID":n.includes("\u672A\u8FD4\u56DE\u53EF\u4E0B\u8F7D\u6587\u4EF6")||n.includes("\u672A\u83B7\u53D6\u5230\u4E0B\u8F7D\u94FE\u63A5")?"DOWNLOAD_NOT_AVAILABLE":n.includes("\u9891\u7E41")||n.includes("\u901F\u7387\u9650\u5236")||n.includes("\u5EFA\u8BAE\u6B21\u65E5\u518D\u8BD5")?"RATE_LIMITED":n.includes("\u7F51\u7EDC")||n.includes("\u4E0B\u8F7D\u5931\u8D25")||n.includes("\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94")?"NETWORK_ERROR":"INTERNAL_ERROR"}export{e as createErrorEnvelope,o as createSuccessEnvelope};
|
package/dist/lib/http.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{XtzError as
|
|
1
|
+
import{XtzError as s,raiseApiError as c}from"./errors.js";import{debugHttpError as p,debugHttpRequest as u,debugHttpResponse as m}from"./debug.js";async function y(r,t={},o={}){let e;u(r,t);try{e=await fetch(r,t)}catch(i){throw p(r,i),new s("\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}const a=await e.text();m(r,e,a);const n=f(e,a);return o.allowErrorPayload?.(n,e)||e.ok||await c(n,o),n}function f(r,t){try{return JSON.parse(t)}catch{const o=[`HTTP ${r.status}`,r.headers.get("content-type")?.trim()].filter(Boolean).join(", "),e=l(t);throw new s(e?`\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\uFF08${o}\uFF09\uFF1A${e}`:`\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\uFF08${o}\uFF09\u3002`)}}function l(r){const t=r.trim().replace(/\s+/g," ");return t?t.length>160?`${t.slice(0,160)}...`:t:""}export{y as requestJson};
|
package/dist/lib/plot-options.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Flags as
|
|
1
|
+
import{Flags as u}from"@oclif/core";import{XtzError as f}from"./errors.js";import{isJsonObject as l}from"./json.js";const J={config:u.string({description:"Path to a JSON file with raw argsMain overrides"}),specific:u.string({description:"Override argsSpecific by key or dotted path, e.g. --specific genes=TP53 or --specific surv_list_nn.0.variable=...",multiple:!0}),set:u.string({description:"Override argsMain value by dotted path, e.g. --set title.title=My Title",multiple:!0})};function V(e){const r={};for(const n of e??[]){const t=n.indexOf("=");if(t<=0||t===n.length-1)throw new f(`--set \u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E: ${n}`);const i=n.slice(0,t).trim(),s=n.slice(t+1).trim(),o=i.split(".").filter(Boolean);if(o.length===0)throw new f(`--set \u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E: ${n}`);const c=o.at(-1)==="value"?o:[...o,"value"];g(r,c,d(s,"--set"))}return r}function b(e){return $({},e)}function $(e,r){const n=structuredClone(e);for(const t of r??[]){const i=t.indexOf("=");if(i<=0||i===t.length-1)throw new f(`--specific \u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E: ${t}`);const s=t.slice(0,i).trim(),o=t.slice(i+1).trim();if(!s)throw new f(`--specific \u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E: ${t}`);const c=s.split(".").filter(Boolean);if(c.length===0)throw new f(`--specific \u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E: ${t}`);if(c.length===1){n[c[0]]=d(o,"--specific");continue}v(n,c,d(o,"--specific"),"--specific")}return n}function P(e){const r=[];for(const[n,t]of Object.entries(e))if(l(t))for(const[i,s]of Object.entries(t)){if(!l(s)||!("value"in s))continue;const o=s.value,c=`${n}.${i}=${JSON.stringify(o)}`;r.push(`--set ${x(c)}`)}return r}function g(e,r,n){let t=e;for(const i of r.slice(0,-1)){const s=t[i];l(s)||(t[i]={}),t=t[i]}t[r.at(-1)]=n}function v(e,r,n,t){let i=e;for(let s=0;s<r.length-1;s+=1){const o=r[s],c=r[s+1],a=O(i,o,t);if(l(a)||Array.isArray(a)){i=a;continue}const p=y(c)?[]:{};h(i,o,p,t),i=p}h(i,r.at(-1),n,t)}function O(e,r,n){if(!Array.isArray(e))return e[r];const t=w(r,n);return e[t]}function h(e,r,n,t){if(!Array.isArray(e)){e[r]=n;return}const i=w(r,t);if(i>e.length)throw new f(`${t} \u6570\u7EC4\u7D22\u5F15\u8D85\u51FA\u8303\u56F4: ${r}`);e[i]=n}function w(e,r){if(!y(e))throw new f(`${r} \u6570\u7EC4\u8DEF\u5F84\u5FC5\u987B\u4F7F\u7528\u975E\u8D1F\u6574\u6570\u7D22\u5F15: ${e}`);return Number(e)}function y(e){return/^(0|[1-9]\d*)$/.test(e)}function d(e,r){if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(/^-?\d+(\.\d+)?$/.test(e))return Number(e);if(e.startsWith("{")||e.startsWith("[")||e.startsWith('"'))try{return JSON.parse(e)}catch{throw new f(`${r} \u53C2\u6570\u503C\u4E0D\u662F\u5408\u6CD5 JSON: ${e}`)}return e}function x(e){return`'${e.replaceAll("'","'\\''")}'`}export{$ as applySpecificOverrides,P as formatSetOverrides,V as parseSetOverrides,b as parseSpecificOverrides,J as plotOverrideFlags};
|
package/dist/lib/storage.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{mkdir as _,readFile as a,rm as
|
|
2
|
-
`,"utf8"),n}async function v(r){const t=m(r);try{return(await a(t,"utf8")).trim()||void 0}catch(n){if(O(n)&&n.code==="ENOENT")return;throw n}}async function L(r){const t=await v(r);if(t)return t;throw new f(`\u672A\u627E\u5230 ${r} \u7684 token\uFF0C\u8BF7\u5148\u8FD0\u884C \`xt login --profile ${r}\``)}async function G(r){const t=m(r);try{return await
|
|
1
|
+
import{mkdir as _,readFile as a,rm as g,writeFile as A}from"node:fs/promises";import T from"node:os";import u from"node:path";import{DEFAULT_AGENT as l,DEFAULT_XIANTAO_TOOL_PRODUCT_UUID as w,XTZ_CONFIG_PATH as N}from"./constants.js";import{XtzError as f}from"./errors.js";import{deepMerge as p}from"./json.js";import{isJsonObject as e}from"./json.js";function m(r){return u.join(T.homedir(),".config","helixlife","user-access-token.txt")}async function y(r,t){const n=m(r);return await _(u.dirname(n),{recursive:!0}),await A(n,`${t.trim()}
|
|
2
|
+
`,"utf8"),n}async function v(r){const t=m(r);try{return(await a(t,"utf8")).trim()||void 0}catch(n){if(O(n)&&n.code==="ENOENT")return;throw n}}async function L(r){const t=await v(r);if(t)return t;throw new f(`\u672A\u627E\u5230 ${r} \u7684 token\uFF0C\u8BF7\u5148\u8FD0\u884C \`xt login --profile ${r}\``)}async function G(r){const t=m(r);try{return await g(t),!0}catch(n){if(O(n)&&n.code==="ENOENT")return!1;throw n}}async function d(){const r=u.join(T.homedir(),N);try{const t=await a(r,"utf8"),n=JSON.parse(t);if(!e(n))throw new f(`\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F\u4E0D\u6B63\u786E: ${r}`);return n}catch(t){if(O(t)&&t.code==="ENOENT")return{};throw t}}async function X(r){const t=r?.trim();if(t)return t;const n=h();return n||(await d()).agent?.trim()||l}async function $(r){if(r?.trim())return r.trim();if(process.env.XIANTAO_TOOL_PRODUCT_UUID?.trim())return process.env.XIANTAO_TOOL_PRODUCT_UUID.trim();const n=(await d()).xiantao?.toolProductUuid?.trim();return n||w}async function F(r,t){const i=(await d()).plots?.[r],s=e(i)&&e(i.argsMain)?i.argsMain:{};if(!t)return s;const o=await C(t),c=(e(o.plots)?o.plots:void 0)?.[r];return e(c)&&e(c.argsMain)?p(s,c.argsMain):e(o.argsMain)?p(s,o.argsMain):p(s,o)}async function C(r){const t=await a(r,"utf8"),n=JSON.parse(t);if(!e(n))throw new f(`JSON \u914D\u7F6E\u683C\u5F0F\u4E0D\u6B63\u786E: ${r}`);return n}function O(r){return r instanceof Error&&"code"in r}function h(){const r=process.env.AGENT_NAME?.trim();if(r)return r;if(R())return"cursor";if(E("OPENCODE"))return"opencode";if(E("OPENCLAW"))return"openclaw"}function R(){return!!(process.env.CURSOR_TRACE_ID?.trim()||process.env.CURSOR_SESSION_ID?.trim()||process.env.CURSOR_AGENT?.trim()||process.env.VSCODE_GIT_ASKPASS_NODE?.includes("Cursor")||process.env.TERM_PROGRAM?.toLowerCase()==="cursor")}function E(r){return!!(process.env[r]?.trim()||process.env[`${r}_AGENT`]?.trim()||process.env[`${r}_SESSION_ID`]?.trim()||process.env.TERM_PROGRAM?.toLowerCase()===r.toLowerCase())}export{G as deleteToken,m as getTokenPath,F as loadPlotArgsMainConfig,v as loadToken,d as readXtzConfig,L as requireToken,X as resolveAgent,$ as resolveXiantaoToolProductUuid,y as saveToken};
|
package/dist/lib/xiantao-plot.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveXiantaoBioApiEndpoint as d}from"./config.js";import{XtzError as m}from"./errors.js";import{requestJson as n}from"./http.js";import{buildXiantaoHeaders as s}from"./xiantao.js";async function h(
|
|
1
|
+
import{resolveXiantaoBioApiEndpoint as d}from"./config.js";import{XtzError as m}from"./errors.js";import{requestJson as n}from"./http.js";import{buildXiantaoHeaders as s}from"./xiantao.js";async function h(o,e){const a=await n(await d(),{body:JSON.stringify({version:"v3",name:"public.verify.upload",args:{id:{module_id:e.moduleId,uuid:e.uuid},args_data:{duid:"",info:f(e.uploads)},args_main:e.argsMain}}),headers:await s(o,!0),method:"POST"},{agent:o.agent}),i=a.data.id?.duid;if(!i)throw new m(a.message??"\u672A\u83B7\u53D6\u5230 duid");return{duid:i,schema:a.data.args_main??[]}}async function x(o,e){const a=await n(await d(),{body:JSON.stringify({version:"v3",name:"common.module",extra_args:{name:e.route},args:{action:"submit",id:{module_id:e.moduleId,uuid:e.uuid},args_data:v(e.duid,e.input),args_main:e.argsMain,args_specific:e.argsSpecific}}),headers:await s(o,!0),method:"POST"},{agent:o.agent,allowErrorPayload:u=>c(u.message)}),i=g(a.data.data),t=typeof a.data.file=="string"&&a.data.file.trim()?a.data.file.trim():void 0,l=a.data.body??"",r=a.message??"";if(!t&&!l&&i.length===0){if(c(r))return{asyncSubmission:!0,body:l,downloads:i,file:t,message:r};throw new m(r||"\u672A\u83B7\u53D6\u5230\u53EF\u7528\u7ED3\u679C")}return{asyncSubmission:!1,body:l,downloads:i,file:t,message:r}}async function X(o,e){const a=await n(await d(),{body:JSON.stringify({version:"v3",name:e.item.endpoint,args:{tag:"download",name:e.item.endpoint,fuid:e.item.fuid,sign:e.item.sign,device:e.item.device,index:e.item.index,info:e.item.info,pos:e.item.pos,id:{uuid:e.uuid,module_id:e.moduleId}}}),headers:await s(o,!0),method:"POST"},{agent:o.agent}),i=a.data.url?.trim();if(!i)throw new m(a.message??"\u672A\u83B7\u53D6\u5230\u4E0B\u8F7D\u94FE\u63A5");return{fileName:a.data.file_name?.trim()||void 0,url:i}}function g(o){const e=[...o?.buttons??[]];for(const a of o?.tabs??[])for(const i of a.sections??[])e.push(...i.button??[]);return e.flatMap(a=>a.tag!=="download"||!a.device||!a.endpoint||!a.fuid||!a.label?[]:[{device:a.device,endpoint:a.endpoint,fuid:a.fuid,index:a.index,info:a.info,label:a.label,pos:a.pos,sign:a.sign}])}function y(o){return o.fileOssPath??o.fileOss}function w(o){return o.fileSizeForXiantao??o.fileSize}function v(o,e){return e.kind==="none"?{duid:o,info:{}}:e.kind==="cloud"?{duid:o,info:{[e.cloud.key]:_(e.cloud.record)}}:e.kind==="record"?{duid:o,info:{[e.record.key]:{label:e.record.label,module_id:e.record.moduleId,module_name:e.record.moduleName,record_id:e.record.recordId,record_name:e.record.recordName,time:e.record.time,type:"record"}}}:{duid:o,info:f(e.uploads)}}function _(o){const e=structuredClone(o);return(typeof e.type!="string"||!e.type.trim())&&(e.type="cloud"),e}function f(o){return Object.fromEntries(o.map(e=>[e.key,{file_oss:y(e.upload),file_name:e.upload.fileName,file_size:w(e.upload),type:"upload"}]))}async function I(o,e){await n(await d(),{body:JSON.stringify({version:"v3",name:"public.output.save",args:{tag:"msg-box",type:"all",name:"public.output.save",fuid:e.fuid,pos:"main",id:{uuid:e.uuid,module_id:e.moduleId},value:e.name}}),headers:await s(o,!0),method:"POST"},{agent:o.agent})}function c(o){return!!o?.includes("\u4EFB\u52A1\u63D0\u4EA4\u6210\u529F")}export{v as buildSubmitArgsData,X as resolveXiantaoDownload,I as saveXiantaoOutput,x as submitXiantaoPlot,h as verifyXiantaoPlotUpload};
|
package/dist/lib/xiantao.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveXiantaoBaseUrl as
|
|
1
|
+
import{resolveXiantaoBaseUrl as M,resolveXiantaoBioApiEndpoint as l,resolveXiantaoToolMenusEndpoint as h}from"./config.js";import{encrypt as S}from"./encrypt.js";import{XtzError as u}from"./errors.js";import{requestJson as i}from"./http.js";async function P(t,e,o){const r=await h(),n=new URL(`${r}/${e}`);n.searchParams.set("f",y({tool_product_uuid:o}));try{return(await i(n.toString(),{headers:await c(t),method:"GET"},{agent:t.agent})).data}catch(s){if(!(s instanceof u)||!s.message.includes("\u5DF2\u4E0B\u67B6"))throw s;const a=T(await g(t,o),e);if(a)return a;throw s}}async function g(t,e){const o=new URL(await h());return o.searchParams.set("f",y({is_all:1,tool_product_uuid:e})),(await i(o.toString(),{headers:await c(t),method:"GET"},{agent:t.agent})).data}async function B(t,e,o){const r=o.trim(),n=d(await g(t,e),r);if(n.length===0)throw new u(`\u672A\u627E\u5230\u6A21\u5757 ${r}\uFF0C\u8BF7\u786E\u8BA4 module_id \u6216 tool_product_uuid \u662F\u5426\u6B63\u786E\u3002`);if(n.length>1)throw new u(`\u6A21\u5757 ${r} \u5339\u914D\u5230\u591A\u4E2A\u7ED3\u679C\uFF0C\u8BF7\u6539\u7528 \`--uuid\` \u663E\u5F0F\u6307\u5B9A\u3002`);return n[0]}function m(t){return d(t)}function O(t){return m(t).map(e=>({module_id:e.code,path:e.path,route:e.route,title:e.title}))}function E(t,e){const o=e.trim().toLowerCase();return m(t).filter(r=>[r.code,r.title,r.path,r.route].some(s=>s.toLowerCase().includes(o))).sort((r,n)=>_(n,o)-_(r,o))}async function z(t,e){return(await i(await l(),{body:JSON.stringify({args:{id:{module_id:e.moduleId,uuid:e.uuid}},name:"public.args.fetch-all",version:"v3"}),headers:await c(t,!0),method:"POST"},{agent:t.agent})).data}async function A(t,e){return(await i(await l(),{body:JSON.stringify({args:{args_data:e.argsData,args_key:e.argsKey,args_main:e.argsMain,args_specific:e.argsSpecific,id:{module_id:e.moduleId,uuid:e.uuid}},name:"public.args.update-args",version:"v3"}),headers:await c(t,!0),method:"POST"},{agent:t.agent})).data}async function R(t,e){return(await i(await l(),{body:JSON.stringify({args:{args_data:e.argsData,args_key:e.argsKey,id:{module_id:e.moduleId,uuid:e.uuid},listen:e.listen,search_string:e.searchString,selected:e.selected},name:"public.search.main",version:"v3"}),headers:await c(t,!0),method:"POST"},{agent:t.agent})).data.options??[]}function w(t){return(t.children??[]).filter(e=>!!(e.title?.trim()||e.code?.trim()))}function v(t){return!!(t.code?.trim()&&t.route?.trim()&&t.title?.trim()&&t.uuid?.trim())}function d(t,e){const o=[];for(const r of t){const n=r.code?.trim();if((!e||n===e)&&v(r)){const a=r.route?.trim(),f=r.title?.trim(),p=r.uuid?.trim();n&&a&&f&&p&&o.push({code:n,path:r.path?.trim()??"",route:a,title:f,uuid:p})}const s=w(r);s.length>0&&o.push(...d(s,e))}return o}function T(t,e){const o=e.trim();for(const r of t){if(r.uuid?.trim()===o||String(r.id??"").trim()===o)return r;const n=w(r);if(n.length>0){const s=T(n,o);if(s)return s}}}function _(t,e){let o=0;const r=t.code.toLowerCase(),n=t.title.toLowerCase(),s=t.path.toLowerCase(),a=t.route.toLowerCase();return r===e?o+=500:r.startsWith(e)?o+=300:r.includes(e)&&(o+=150),n===e?o+=400:n.startsWith(e)?o+=250:n.includes(e)&&(o+=120),s.includes(e)&&(o+=80),a.includes(e)&&(o+=40),o}function y(t){return S.encryption(t)}async function c(t,e=!1){const o=await M(),r={Authorization:`Bearer ${t.token}`,origin:o,platform:"pc",referer:o,source:"PC"};return e&&(r["Content-Type"]="application/json"),r}export{c as buildXiantaoHeaders,z as fetchAllPlotArgs,P as fetchToolMenu,g as fetchToolMenus,w as getBrowsableToolMenuChildren,v as isRunnableToolMenu,m as listResolvedToolMenus,O as listToolMenuSummaries,B as resolveToolMenuByCode,R as searchPlotSpecificOptions,E as searchResolvedToolMenus,A as updatePlotArgs};
|