bailian-cli 1.0.0 → 1.0.1

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 ADDED
@@ -0,0 +1,128 @@
1
+ <div align="center">
2
+
3
+ <img src="https://img.alicdn.com/imgextra/i1/O1CN01RSQFUD1jN5IBzHORt_!!6000000004535-2-tps-2440-521.png" alt="Aliyun Model Studio CLI" width="420" />
4
+
5
+ # >\_ Aliyun Model Studio CLI
6
+
7
+ **The official command-line interface for Aliyun Model Studio (DashScope) AI Platform**
8
+
9
+ [![npm version](https://img.shields.io/npm/v/bailian-cli?color=0969da&label=npm)](https://www.npmjs.com/package/bailian-cli)
10
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D22.12-brightgreen)](https://nodejs.org)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6)](https://www.typescriptlang.org)
12
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
13
+
14
+ [Aliyun Model Studio CLI Site](https://bailian.console.aliyun.com/cli) · [中文文档](README_CN.md) · [API Documentation](https://help.aliyun.com/zh/model-studio/) · [Get API Key](https://bailian.console.aliyun.com/cn-beijing/?tab=app#/api-key)
15
+
16
+ ---
17
+
18
+ _Chat with Qwen, generate images & videos, understand images, call agents,_
19
+ _manage memory, search the web — all from your terminal._
20
+
21
+ _Built for AI Agents. Every command works as a structured tool call._
22
+
23
+ </div>
24
+
25
+ ## Features
26
+
27
+ Equip your AI Agent out-of-the-box with these capabilities, composable across complex tasks:
28
+
29
+ - **Text chat** — Qwen3.6-plus: major gains in agentic coding, frontend coding, and vibe coding
30
+ - **Multimodal (Omni)** — Full omni-modal support across text + image + audio + video
31
+ - **Image generation & editing** — Qwen-Image 2.0: pro text rendering, photorealism, strong semantic adherence, multi-image composition
32
+ - **Video generation & editing** — HappyHorse-1.0 series: text-/image-/reference-to-video and natural-language video editing (up to 9-image reference)
33
+ - **Speech synthesis & recognition** — CosyVoice streaming TTS, voice cloning from 5–20s samples; FunAudio-ASR covers 30 languages including 7 Chinese dialects and 20+ Mandarin accents
34
+ - **Image & video understanding** — Qwen-VL: long-form video analysis, chart/document parsing, visual reasoning, multilingual OCR
35
+ - **Knowledge base & memory** — Multimodal RAG retrieval and cross-session memory for personalized, coherent dialogue
36
+ - **App calls** — Invoke agents and workflows already published on Aliyun Model Studio
37
+ - **Web search** — Real-time internet retrieval for up-to-date, accurate answers
38
+ - **Local file auto-upload** — Every URL parameter accepts a local path; uploaded to free temp storage with 48-hour validity
39
+
40
+ <p align="center">
41
+ <img src="https://img.alicdn.com/imgextra/i1/O1CN01Df2LiL1IcCkXJROYz_!!6000000000913-2-tps-759-426.png" alt="bl --help" width="720" />
42
+ </p>
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ npm install -g bailian-cli
48
+ ```
49
+
50
+ > Requires Node.js >= 22.12.
51
+
52
+ ## Quick Start
53
+
54
+ ```bash
55
+ # Authenticate
56
+ bl auth login --api-key sk-xxxxx
57
+
58
+ # Chat with Qwen
59
+ bl text chat --message "What is DashScope?"
60
+
61
+ # Multimodal chat (text + image + audio + video)
62
+ bl omni --message "Describe this image" --image ./photo.jpg
63
+
64
+ # Generate an image
65
+ bl image generate --prompt "A cat in a spacesuit" --out-dir ./images/
66
+
67
+ # Generate a video from local image
68
+ bl video generate --image ./cat.png --prompt "Make the cat move" --download cat.mp4
69
+ ```
70
+
71
+ > More examples and scenarios: [Aliyun Model Studio CLI Site](https://bailian.console.aliyun.com/cli)
72
+
73
+ ## Authentication
74
+
75
+ ### DashScope API Key
76
+
77
+ Required for most commands. Get your key from the [DashScope Console](https://bailian.console.aliyun.com/cn-beijing/?tab=app#/api-key).
78
+
79
+ ```bash
80
+ # Option 1: Environment variable
81
+ export DASHSCOPE_API_KEY=sk-xxxxx
82
+
83
+ # Option 2: Login command (persisted to ~/.bailian/config.json)
84
+ bl auth login --api-key sk-xxxxx
85
+
86
+ # Option 3: Per-command flag
87
+ bl text chat --api-key sk-xxxxx --message "Hello"
88
+ ```
89
+
90
+ ### Alibaba Cloud AK/SK (Knowledge Base only)
91
+
92
+ Required for `knowledge retrieve`. Get your AccessKey from [RAM Console](https://ram.console.aliyun.com/manage/ak).
93
+
94
+ > Recommended: create a RAM sub-account with minimum privileges instead of using the root account's AK/SK.
95
+
96
+ ```bash
97
+ export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5t...
98
+ export ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
99
+ export BAILIAN_WORKSPACE_ID=ws-...
100
+ ```
101
+
102
+ ## Configuration
103
+
104
+ ```bash
105
+ # View current config
106
+ bl config show
107
+
108
+ # Set defaults
109
+ bl config set --key region --value us
110
+ bl config set --key default_text_model --value qwen-turbo
111
+ bl config set --key timeout --value 600
112
+
113
+ # Self-update to latest version
114
+ bl update
115
+ ```
116
+
117
+ Config file location: `~/.bailian/config.json`
118
+
119
+ ## Links
120
+
121
+ | Resource | URL |
122
+ | :--------------------------- | :-------------------------------------------------------------- |
123
+ | Aliyun Model Studio CLI Site | https://bailian.console.aliyun.com/cli |
124
+ | DashScope API Docs | https://help.aliyun.com/zh/model-studio/ |
125
+ | Qwen Model List | https://help.aliyun.com/zh/model-studio/getting-started/models |
126
+ | Aliyun Model Studio Console | https://bailian.console.aliyun.com/ |
127
+ | Get API Key | https://bailian.console.aliyun.com/cn-beijing/?tab=app#/api-key |
128
+ | Get AccessKey | https://ram.console.aliyun.com/manage/ak |
package/dist/bailian.mjs CHANGED
@@ -130,7 +130,7 @@ This process keeps the local port open for the console; press Ctrl+C when finish
130
130
  `),process.exit(1)),Ai(e)?a.push(e):i=e}else throw new e(`Missing required argument --image or --video.`,n.USAGE,`bl vision describe --image <path-or-url>
131
131
  bl vision describe --video <url-or-path>`);let f=u(t.output);if(t.dryRun){M({request:{prompt:d,image:i,video:a.length?a:void 0,model:o}},f);return}let p=[];if(a.length>0)for(let r of a){let i=r;if(y(r)){if(!Te(r))throw new e(`Video file not found: ${r}`,n.USAGE);i=await D(r,(await E(t)).token,o)}p.push({type:`video_url`,video_url:{url:i}})}if(i){let e=await ji(i),n=e;if(y(i)&&e.startsWith(`data:`)){let{statSync:e}=await import(`fs`);if(e(i).size>5*1024*1024){let e=await E(t);n=await D(i,e.token,o)}}p.push({type:`image_url`,image_url:{url:n}})}p.push({type:`text`,text:d});let m={model:o,messages:[{role:`user`,content:p}]},h=await T(t,{url:s(t.baseUrl),method:`POST`,body:m}),g=h.choices?.[0]?.message?.content;if(f!==`text`){M(h,f);return}N(g||``)}})})),Ii,Li=j((()=>{P(),Ii=l({name:`config show`,description:`Display current configuration`,usage:`bl config show`,examples:[`bl config show`,`bl config show --output json`],async run(e,t){let n=w(),r=u(e.output),i={region:e.region,base_url:e.baseUrl,output:e.output,timeout:e.timeout,config_file:h()};n.api_key&&(i.api_key=x(n.api_key)),n.access_token&&(i.access_token=x(n.access_token)),n.default_text_model&&(i.default_text_model=n.default_text_model),n.default_video_model&&(i.default_video_model=n.default_video_model),n.default_image_model&&(i.default_image_model=n.default_image_model),M(i,r)}})})),Ri,zi,Bi,Vi=j((()=>{P(),Ri=[`region`,`base_url`,`output`,`output_dir`,`timeout`,`api_key`,`access_token`,`default_text_model`,`default_video_model`,`default_image_model`,`default_speech_model`,`default_omni_model`,`access_key_id`,`access_key_secret`,`workspace_id`],zi={"base-url":`base_url`,"output-dir":`output_dir`,"api-key":`api_key`,"access-token":`access_token`,"default-text-model":`default_text_model`,"default-video-model":`default_video_model`,"default-image-model":`default_image_model`,"default-speech-model":`default_speech_model`,"default-omni-model":`default_omni_model`,"access-key-id":`access_key_id`,"access-key-secret":`access_key_secret`,"workspace-id":`workspace_id`},Bi=l({name:`config set`,description:`Set a config value`,usage:`bl config set --key <key> --value <value>`,options:[{flag:`--key <key>`,description:`Config key (region, base_url, output, output_dir, timeout, api_key, access_token, default_*_model, access_key_id, access_key_secret, workspace_id)`},{flag:`--value <value>`,description:`Value to set`}],examples:[`bl config set --key output --value json`,`bl config set --key timeout --value 600`,`bl config set --key base_url --value https://dashscope.aliyuncs.com`],async run(t,r){let i=r.key,a=r.value;if(!i||a===void 0)throw new e(`--key and --value are required.`,n.USAGE,`bl config set --key <key> --value <value>`);let o=zi[i]||i;if(!Ri.includes(o))throw new e(`Invalid config key "${i}". Valid keys: ${Ri.join(`, `)}`,n.USAGE);if(o===`region`&&![`cn`,`us`,`intl`].includes(a))throw new e(`Invalid region "${a}". Valid values: cn, us, intl`,n.USAGE);if(o===`output`&&![`text`,`json`].includes(a))throw new e(`Invalid output format "${a}". Valid values: text, json`,n.USAGE);if(o===`timeout`){let t=Number(a);if(isNaN(t)||t<=0)throw new e(`Invalid timeout "${a}". Must be a positive number.`,n.USAGE)}let s=u(t.output);if(t.dryRun){M({would_set:{[o]:a}},s);return}let c=w();c[o]=o===`timeout`?Number(a):a,await he(c),t.quiet||M({[o]:c[o]},s)}})})),Hi,Ui,Wi=j((()=>{Hi=[`auth `,`config `,`update`],Ui=l({name:`config export-schema`,description:`Export all (or one) CLI command(s) as Anthropic/OpenAI-compatible JSON tool schemas`,usage:`bl config export-schema [--command "<name>"]`,options:[{flag:`--command <name>`,description:`Export schema for a specific command only (e.g. "image generate")`}],examples:[`bl config export-schema`,`bl config export-schema --command "video generate"`],async run(t,r){let{commands:i}=await Promise.resolve().then(()=>(ro(),to)),a=r.command;if(a){let t=i[a];if(!t)throw new e(`Command "${a}" not found.`,n.USAGE);let r=p(t);process.stdout.write(JSON.stringify(r,null,2)+`
132
132
  `);return}let o=Object.values(i).filter(e=>!Hi.some(t=>e.name.startsWith(t))).map(e=>p(e));process.stdout.write(JSON.stringify(o,null,2)+`
133
- `)}})}));Pr(),Ir(),zr(),Hr(),Kr(),pi(),_i(),xi(),Ci(),Ti(),Di(),ki(),Fi(),Li(),Vi(),Wi();var Gi=`1.0.0`,Z,Ki=j((()=>{Z=Gi}));function qi(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}function Ji(){try{let e=De(ta(),`utf-8`);return JSON.parse(e)}catch{return null}}function Yi(e){try{ke(ta(),JSON.stringify(e))}catch{}}async function Xi(e=ra){try{let t=ea.replace(`/`,`%2f`),n=await fetch(`${$i}/${t}/latest`,{headers:{Accept:`application/json`,...de()},signal:AbortSignal.timeout(e)});return n.ok?(await n.json()).version??null:null}catch{return null}}function Zi(){return ia}async function Qi(e){if(process.env.CI||!process.stderr.isTTY)return;let t=Ji(),n=Date.now();if(t&&n-t.lastChecked<na){t.latestVersion&&qi(t.latestVersion,e)&&(ia=t.latestVersion);return}let r=await Xi();r&&(Yi({lastChecked:n,latestVersion:r}),r&&qi(r,e)&&(ia=r))}var $i,ea,ta,na,ra,ia,aa=j((()=>{$i=`https://registry.npmjs.org`,ea=`bailian-cli`,ta=()=>Me(m(),`update-state.json`),na=14400*1e3,ra=3e3,ia=null}));function oa(){return{cmd:`npm install -g ${ea}@latest`,label:`npm`}}var sa,ca=j((()=>{Ki(),aa(),sa=l({name:`update`,description:`Update bl to the latest version`,usage:`bl update`,examples:[`bl update`],async run(){let e=process.stderr.isTTY,t=e?`\x1B[32m`:``,n=e?`\x1B[33m`:``,r=e?`\x1B[0m`:``;process.stderr.write(`Current version: ${n}${Z}${r}\n`),process.stderr.write(`Checking for updates...
133
+ `)}})}));Pr(),Ir(),zr(),Hr(),Kr(),pi(),_i(),xi(),Ci(),Ti(),Di(),ki(),Fi(),Li(),Vi(),Wi();var Gi=`1.0.1`,Z,Ki=j((()=>{Z=Gi}));function qi(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}function Ji(){try{let e=De(ta(),`utf-8`);return JSON.parse(e)}catch{return null}}function Yi(e){try{ke(ta(),JSON.stringify(e))}catch{}}async function Xi(e=ra){try{let t=ea.replace(`/`,`%2f`),n=await fetch(`${$i}/${t}/latest`,{headers:{Accept:`application/json`,...de()},signal:AbortSignal.timeout(e)});return n.ok?(await n.json()).version??null:null}catch{return null}}function Zi(){return ia}async function Qi(e){if(process.env.CI||!process.stderr.isTTY)return;let t=Ji(),n=Date.now();if(t&&n-t.lastChecked<na){t.latestVersion&&qi(t.latestVersion,e)&&(ia=t.latestVersion);return}let r=await Xi();r&&(Yi({lastChecked:n,latestVersion:r}),r&&qi(r,e)&&(ia=r))}var $i,ea,ta,na,ra,ia,aa=j((()=>{$i=`https://registry.npmjs.org`,ea=`bailian-cli`,ta=()=>Me(m(),`update-state.json`),na=14400*1e3,ra=3e3,ia=null}));function oa(){return{cmd:`npm install -g ${ea}@latest`,label:`npm`}}var sa,ca=j((()=>{Ki(),aa(),sa=l({name:`update`,description:`Update bl to the latest version`,usage:`bl update`,examples:[`bl update`],async run(){let e=process.stderr.isTTY,t=e?`\x1B[32m`:``,n=e?`\x1B[33m`:``,r=e?`\x1B[0m`:``;process.stderr.write(`Current version: ${n}${Z}${r}\n`),process.stderr.write(`Checking for updates...
134
134
  `);let i=await Xi(5e3);if(i&&i===Z){process.stderr.write(`${t}\u2713 Already up to date (${Z}).${r}\n`);return}i&&process.stderr.write(`Latest version: ${t}${i}${r}\n\n`);let{cmd:a,label:o}=oa();process.stderr.write(`Updating ${ea} via ${o}...\n\n`);try{Ne(a,{stdio:`inherit`});try{let e=Ne(`bl --version 2>/dev/null`,{encoding:`utf-8`}).trim().replace(/^bl\s+/,``);process.stderr.write(`\n${t}\u2713 Update complete: ${Z} \u2192 ${e}${r}\n`);try{ke(Me(m(),`update-state.json`),JSON.stringify({lastChecked:Date.now(),latestVersion:e}))}catch{}}catch{process.stderr.write(`\n${t}\u2713 Update complete.${r}\n`)}}catch{process.stderr.write(`
135
135
  Automatic update failed. Please run manually:
136
136
  `),process.stderr.write(` ${a}\n\n`)}}})})),la,ua=j((()=>{J(),P(),la=l({name:`app call`,description:`Call a Bailian application (agent or workflow)`,usage:`bl app call --app-id <id> --prompt <text> [flags]`,options:[{flag:`--app-id <id>`,description:`Application ID (required)`,required:!0},{flag:`--prompt <text>`,description:`Input prompt text`,required:!0},{flag:`--image <url>`,description:`Image URL(s) to pass to the app (repeatable)`,type:`array`},{flag:`--file-id <id>`,description:`Pre-uploaded file ID(s) (repeatable)`,type:`array`},{flag:`--session-id <id>`,description:`Session ID for multi-turn conversation`},{flag:`--stream`,description:`Stream response (default: on in TTY)`},{flag:`--pipeline-ids <ids>`,description:`Knowledge base pipeline IDs (comma-separated)`},{flag:`--memory-id <id>`,description:`Memory ID for long-term memory`},{flag:`--biz-params <json>`,description:`Business parameters JSON (workflow variables)`},{flag:`--has-thoughts`,description:`Show agent thinking process`}],examples:[`bl app call --app-id abc123 --prompt "你好"`,`bl app call --app-id abc123 --prompt "描述这张图片" --image https://example.com/photo.jpg`,`bl app call --app-id abc123 --prompt "分析图片" --image img1.jpg --image img2.jpg`,`bl app call --app-id abc123 --prompt "继续" --session-id sess_xxx --stream`,`bl app call --app-id abc123 --prompt "搜索资料" --pipeline-ids pipe1,pipe2`,`bl app call --app-id abc123 --prompt "开始" --biz-params '{"key":"value"}'`],async run(e,t){let n=t.appId;n||q(`app-id`,`bl app call --app-id <id> --prompt <text>`);let r=t.prompt;r||q(`prompt`,`bl app call --app-id <id> --prompt <text>`);let i=t.stream===!0||t.stream===void 0&&process.stdout.isTTY,o=u(e.output),s={input:{prompt:r},parameters:{incremental_output:i}};t.sessionId&&(s.input.session_id=t.sessionId);let c=t.image;c&&c.length>0&&(s.input.image_list=c);let l=t.fileId;if(l&&l.length>0&&(s.input.file_ids=l),t.hasThoughts&&(s.parameters.has_thoughts=!0),t.pipelineIds){let e=t.pipelineIds.split(`,`).map(e=>e.trim()).filter(Boolean);s.parameters.rag_options={pipeline_ids:e}}if(t.memoryId&&(s.parameters.memory_id=t.memoryId),t.bizParams)try{s.input.biz_params=JSON.parse(t.bizParams)}catch{process.stderr.write(`Error: --biz-params must be valid JSON
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bailian-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "CLI for Aliyun Model Studio (DashScope) AI Platform.",
5
5
  "homepage": "https://bailian.console.aliyun.com/cli",
6
6
  "license": "Apache-2.0",
@@ -23,7 +23,7 @@
23
23
  "registry": "https://registry.npmjs.org/"
24
24
  },
25
25
  "dependencies": {
26
- "bailian-cli-core": "1.0.0"
26
+ "bailian-cli-core": "1.0.1"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@clack/prompts": "^0.7.0",