bailian-cli-commands 1.12.0 → 1.13.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/dist/index.mjs +2587 -245
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,133 +1,1161 @@
|
|
|
1
|
-
import{ASYNC_FLAG as e,BailianError as t,CONCURRENT_FLAG as n,DEFAULT_TRAINING_TYPE as r,DOCS_HOSTS as i,ExitCode as a,MAX_DATASET_BYTES as o,MAX_MEDIA_ZIP_BYTES as s,MODEL_LIST_API as c,REGIONS as l,SEMANTIC_TOP_K as u,STRATEGIES as d,TRAINING_TYPES_CLI as f,UsageError as p,analyzeIntent as m,appCompletionPath as h,bailianMcpPath as g,buildAcsCanonicalQuery as _,buildDocLink as v,callConsoleGateway as y,cancelFineTune as b,chatPath as x,createBailianControlUser as S,createDeployment as C,createFineTune as ee,createInstrumentedFetch as te,defaultDeployPlan as
|
|
1
|
+
import{ASYNC_FLAG as e,BailianError as t,CONCURRENT_FLAG as n,DEFAULT_TRAINING_TYPE as r,DOCS_HOSTS as i,ExitCode as a,MAX_DATASET_BYTES as o,MAX_MEDIA_ZIP_BYTES as s,MODEL_LIST_API as c,REGIONS as l,SEMANTIC_TOP_K as u,STRATEGIES as d,TRAINING_TYPES_CLI as f,UsageError as p,analyzeIntent as m,appCompletionPath as h,bailianMcpPath as g,buildAcsCanonicalQuery as _,buildDocLink as v,callConsoleGateway as y,cancelFineTune as b,chatPath as x,createBailianControlUser as S,createDeployment as C,createFineTune as ee,createInstrumentedFetch as te,defaultDeployPlan as ne,defineCommand as w,deleteConfigProfile as re,deleteDataset as ie,deleteDeployment as ae,deleteFineTune as oe,detectModality as se,detectOutputFormat as T,effectiveConsoleGatewayConfig as ce,exportCheckpoint as le,fetchModelCapability as ue,fetchModelDetail as de,fetchModelGroups as fe,fetchModelList as pe,fetchPredictConfig as me,formatIssue as he,generateCLIAccessToken as ge,generateFilename as _e,getConfigDir as ve,getDataset as ye,getDeployment as be,getFineTune as xe,getFineTuneLogs as Se,getModelProfilePreset as Ce,getModels as we,getProfile as Te,imageFileToDataUri as Ee,isLocalFile as De,isTrainingTypeCli as Oe,knowledgeChatEndpoint as ke,knowledgeRetrievePath as Ae,knowledgeSearchEndpoint as je,listBailianControlWorkspaces as Me,listCheckpoints as Ne,listDatasets as Pe,listDeployableModels as Fe,listDeployments as Ie,listFineTunes as Le,listSupportedTrainingTypes as Re,mapApiError as ze,maskToken as E,mcpWebSearchPath as Be,memoryAddPath as Ve,memoryListPath as He,memoryNodePath as Ue,memorySearchPath as We,modelSupportsTrainingType as Ge,normalizeConfigName as Ke,normalizeModelBaseUrl as qe,parseDatasetSchemaFlag as Je,parseSSE as Ye,pickPlanStrategy as Xe,preflightBatchSizeGate as Ze,profileSchemaPath as Qe,rankModels as $e,readConfigFile as et,readTextFromPathOrStdin as tt,recallSemantic as nt,redactDataUri as D,requestJson as rt,resetBailianControlPolicies4Agent as it,resolveBooleanFlag as at,resolveImageEditApi as ot,resolveImageGenerateApi as st,resolveOutputDir as ct,resolveWatermark as lt,scaleDeployment as ut,speechRecognizePath as dt,speechSynthesizePath as ft,stripUndefined as pt,taskPath as O,trackingHeaders as mt,trainingTypeMethodVariant as ht,unwrapResponse as gt,updateDeployment as _t,uploadDataset as vt,userProfilePath as yt,validateDataset as bt,videoGeneratePath as xt,writeConfigFile as St}from"bailian-cli-core";import{API_KEY_PAGE as Ct,BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT as wt,BOOL_FLAG_PROMPT_EXTEND_CLI_TRUE as Tt,BOOL_FLAG_PROMPT_EXTEND_IMAGE_GENERATE as Et,BOOL_FLAG_WATERMARK as Dt,VOICE_TTS_PAGE as Ot,ansi as k,collectPipelineHints as kt,collectPipelineIssues as At,createSpinner as jt,displayWidth as Mt,downloadFile as A,downloadParallel as Nt,emitBare as j,emitResult as M,executePipeline as Pt,fetchLatestVersion as Ft,formatBytes as It,formatTable as N,getConcurrency as Lt,initPipelineSteps as Rt,mcpMarketplaceDetailPage as zt,padEnd as P,poll as Bt,renderBoxTable as Vt,resolveImageSize as Ht,runConcurrent as Ut,streamPipelineEvents as Wt,supportsColor as Gt}from"bailian-cli-runtime";import{randomBytes as Kt,timingSafeEqual as qt}from"node:crypto";import Jt from"node:http";import{execFile as Yt}from"node:child_process";import{copyFileSync as Xt,createWriteStream as Zt,existsSync as Qt,mkdirSync as $t,readFileSync as en,renameSync as tn,statSync as nn,writeFileSync as rn}from"fs";import{basename as an,dirname as on,extname as sn,join as F}from"path";import{createReadStream as cn,existsSync as I,mkdirSync as ln,readFileSync as un,readdirSync as dn,statSync as fn,unlinkSync as pn,writeFileSync as mn}from"node:fs";import{basename as hn,dirname as gn,extname as _n,join as L,relative as vn,resolve as R,sep as yn}from"node:path";import{homedir as z}from"node:os";import{inflateRawSync as bn}from"node:zlib";import xn from"yaml";import{parse as Sn,stringify as Cn}from"smol-toml";import{homedir as B,platform as wn}from"os";import{execSync as Tn}from"child_process";import{readFile as En,writeFile as Dn}from"node:fs/promises";import On from"boxen";import kn,{Chalk as An}from"chalk";import*as jn from"@openagentpack/sdk";import{AGENTS_PROVIDER_FIELDS as Mn,LocalFileStateBackend as Nn,StateManager as Pn,UserError as Fn,bootstrapRuntimeCredentialsSync as In,createProjectRuntime as Ln,createSessionForAgent as Rn,deleteSession as zn,destroyPlannedProjectResources as Bn,executePlannedProject as Vn,getSession as Hn,importResource as Un,isTerminalSessionStatus as Wn,listSessionEvents as Gn,listSessionSummaries as Kn,listSkills as qn,parseStateAddress as Jn,planDestroyProjectContext as Yn,planProjectContext as Xn,resolveProjectConfig as Zn,sendSessionMessagePolling as Qn,sendSessionMessageStreaming as $n,startSessionRun as er,startSessionRunPolling as tr,validateProjectConfig as nr}from"@openagentpack/sdk";import{sanitizeSessionEvents as rr}from"@openagentpack/sdk/session-events";function ir(e){if(e instanceof t){if(e.exitCode===a.NETWORK||e.exitCode===a.TIMEOUT)return!0;let t=e.api?.httpStatus;return t===401||t!==void 0&&t>=500}return e instanceof Error?e.name===`AbortError`||e.name===`TimeoutError`||e.message.includes(`timed out`)||e.message===`fetch failed`:!1}async function ar(e,t,n){process.stderr.write(`Testing key... `);let r={identity:e.identity,settings:e.settings},i=qe(n.baseUrl),a=n.persistBaseUrl?qe(n.persistBaseUrl):void 0,o={url:i+x(),method:`POST`,headers:{Authorization:`Bearer ${t}`},timeout:Math.min(e.settings.timeout,30),body:{model:`qwen3.8-max`,messages:[{role:`user`,content:`hi`}],max_tokens:1,stream:!1}};for(let e=1;e<=3;e++)try{await rt(r,o);break}catch(t){if(e>=3||!ir(t))throw process.stderr.write(`Failed
|
|
2
2
|
`),t;let n=500*2**(e-1);await new Promise(e=>setTimeout(e,n))}process.stderr.write(`Valid
|
|
3
|
-
`),await e.authStore.login({...n.persistPatch,api_key:t,base_url:a,default_text_model:n.defaultTextModel,default_video_model:n.defaultVideoModel,default_image_to_video_model:n.defaultImageToVideoModel,default_reference_to_video_model:n.defaultReferenceToVideoModel,default_image_model:n.defaultImageModel})}function
|
|
3
|
+
`),await e.authStore.login({...n.persistPatch,api_key:t,base_url:a,default_text_model:n.defaultTextModel,default_video_model:n.defaultVideoModel,default_image_to_video_model:n.defaultImageToVideoModel,default_reference_to_video_model:n.defaultReferenceToVideoModel,default_image_model:n.defaultImageModel})}function or(e,t=0){return new Promise((n,r)=>{let i=e=>r(e);e.once(`error`,i),e.listen({port:t,host:`127.0.0.1`,exclusive:!0},()=>{e.off(`error`,i);let t=e.address();if(!t||typeof t==`string`){r(Error(`Expected TCP socket address`));return}n(t.port)})})}function sr(e){let t=process.platform,n=t===`darwin`?`open`:t===`win32`?`cmd`:`xdg-open`,r=t===`win32`?[`/c`,`start`,``,e]:[e];return new Promise((e,t)=>{Yt(n,r,{windowsHide:!0},n=>{n?t(n):e()})})}function cr(e){return sr(e)}const lr=RegExp(`\r
|
|
4
4
|
\r
|
|
5
5
|
|
|
|
6
6
|
|
|
7
|
-
`),
|
|
8
|
-
`);return}let{accessToken:r,apiKey:a,baseUrl:c,consoleSite:l,consoleRegion:u,consoleSwitchAgent:d,workspaceId:f}=await
|
|
7
|
+
`),ur={domestic:`https://bailian.console.aliyun.com`,international:`https://modelstudio.console.alibabacloud.com`};function dr(e){return e&&ur[e]||ur.domestic}function fr(e){return new Promise((t,n)=>{let r=0,i=[];e.on(`data`,e=>{if(r+=e.length,r>65536){n(Error(`payload too large`));return}i.push(e)}),e.on(`end`,()=>t(Buffer.concat(i).toString(`utf8`))),e.on(`error`,n)})}function pr(e){let t=e.headers[`content-type`];return Array.isArray(t)?t[0]??``:typeof t==`string`?t:``}function mr(e){let t=e.split(`;`);for(let e of t){let t=e.trim();if(!t.toLowerCase().startsWith(`boundary=`))continue;let n=t.slice(9).trim();return(n.startsWith(`"`)&&n.endsWith(`"`)||n.startsWith(`'`)&&n.endsWith(`'`))&&(n=n.slice(1,-1)),n.length>0?n:null}return null}function hr(e,t){let n=`--${t}`,r=e.split(n);for(let e=1;e<r.length;e++){let t=r[e];if(!/name\s*=\s*["'](?:access_token|accessToken)["']/i.test(t))continue;let n=t.match(lr);if(!n||n.index===void 0)continue;let i=t.slice(n.index+n[0].length);if(i=i.replace(/(?:\r\n)+$/g,``).replace(/\n+$/g,``).trim(),i)return i}return null}function gr(e){for(let t of[`access_token`,`accessToken`]){let n=e[t];if(typeof n==`string`&&n.trim())return n.trim()}return null}function _r(e){for(let t of[`api_key`,`apiKey`]){let n=e[t];if(typeof n==`string`&&n.trim())return n.trim()}return null}function vr(e){let t=e.trim();if(t.charCodeAt(0)===65279&&(t=t.slice(1)),!t)return null;let n;try{n=JSON.parse(t)}catch{return null}if(!n||typeof n!=`object`||Array.isArray(n))return null;let r=n,i=gr(r);if(i)return i;let a=r.data;if(a&&typeof a==`object`&&!Array.isArray(a)){let e=gr(a);if(e)return e}return null}function yr(e,t){let n=t.toLowerCase();if(!e.trim())return null;if(n.includes(`multipart/form-data`)){let n=mr(t);if(n){let t=hr(e,n);if(t)return t}}if(n.includes(`application/json`)||n.includes(`text/json`)){let t=vr(e);if(t)return t}if(n.includes(`application/x-www-form-urlencoded`))try{let t=new URLSearchParams(e.trim()),n=t.get(`access_token`)??t.get(`accessToken`);if(n?.trim())return n.trim()}catch{}let r=vr(e);if(r)return r;try{let t=new URLSearchParams(e.trim()),n=t.get(`access_token`)??t.get(`accessToken`);if(n?.trim())return n.trim()}catch{}let i=mr(t);if(i){let t=hr(e,i);if(t)return t}return null}function br(e){let t=e.trim();if(t.charCodeAt(0)===65279&&(t=t.slice(1)),!t)return null;let n;try{n=JSON.parse(t)}catch{return null}if(!n||typeof n!=`object`||Array.isArray(n))return null;let r=n,i=_r(r);if(i)return i;let a=r.data;if(a&&typeof a==`object`&&!Array.isArray(a)){let e=_r(a);if(e)return e}return null}function xr(e,t){let n=t.toLowerCase();if(!e.trim())return null;if(n.includes(`application/json`)||n.includes(`text/json`)){let t=br(e);if(t)return t}if(n.includes(`application/x-www-form-urlencoded`))try{let t=new URLSearchParams(e.trim()),n=t.get(`api_key`)??t.get(`apiKey`);if(n?.trim())return n.trim()}catch{}let r=br(e);if(r)return r;try{let t=new URLSearchParams(e.trim()),n=t.get(`api_key`)??t.get(`apiKey`);if(n?.trim())return n.trim()}catch{}return null}function Sr(e,...t){for(let n of t){let t=e[n];if(typeof t==`string`&&t.trim())return t.trim()}return null}function Cr(e,t){let n={baseUrl:null,consoleSite:null,consoleRegion:null,consoleSwitchAgent:null,workspaceId:null};if(!e.trim())return n;let r=null,i=t.toLowerCase();if(i.includes(`application/json`)||i.includes(`text/json`))try{let t=JSON.parse(e.trim());t&&typeof t==`object`&&!Array.isArray(t)&&(r=t)}catch{}if(!r&&i.includes(`application/x-www-form-urlencoded`))try{let t=new URLSearchParams(e.trim());r=Object.fromEntries(t)}catch{}if(!r)try{let t=JSON.parse(e.trim());t&&typeof t==`object`&&!Array.isArray(t)&&(r=t)}catch{}return r?{baseUrl:Sr(r,`base_url`,`baseUrl`),consoleSite:Sr(r,`console_site`,`consoleSite`),consoleRegion:Sr(r,`console_region`,`consoleRegion`),consoleSwitchAgent:Sr(r,`console_switch_agent`,`consoleSwitchAgent`),workspaceId:Sr(r,`workspace_id`,`workspaceId`)}:n}async function wr(e){let t=new URL(e.url??`/`,`http://127.0.0.1`),n=t.searchParams.get(`access_token`)??t.searchParams.get(`accessToken`),r=t.searchParams.get(`api_key`)??t.searchParams.get(`apiKey`),i=t.searchParams.get(`base_url`)??t.searchParams.get(`baseUrl`),a=t.searchParams.get(`console_site`)??t.searchParams.get(`consoleSite`),o=t.searchParams.get(`console_region`)??t.searchParams.get(`consoleRegion`),s=t.searchParams.get(`console_switch_agent`)??t.searchParams.get(`consoleSwitchAgent`),c=t.searchParams.get(`workspace_id`)??t.searchParams.get(`workspaceId`),l={baseUrl:i?.trim()||null,consoleSite:a?.trim()||null,consoleRegion:o?.trim()||null,consoleSwitchAgent:s?.trim()||null,workspaceId:c?.trim()||null},u=e.method??`GET`;if(u!==`POST`&&u!==`PUT`&&u!==`PATCH`)return{accessToken:n?.trim()||null,apiKey:r?.trim()||null,...l};let d=pr(e),f;try{f=await fr(e)}catch{return{accessToken:n?.trim()||null,apiKey:r?.trim()||null,...l}}let p=n?.trim()||yr(f,d),m=r?.trim()||xr(f,d),h=Cr(f,d);return{accessToken:p,apiKey:m,baseUrl:l.baseUrl||h.baseUrl,consoleSite:l.consoleSite||h.consoleSite,consoleRegion:l.consoleRegion||h.consoleRegion,consoleSwitchAgent:l.consoleSwitchAgent||h.consoleSwitchAgent,workspaceId:l.workspaceId||h.workspaceId}}function Tr(e){return or(e)}async function Er(e,n,r){let i=Kt(16).toString(`hex`),o,s=Jt.createServer(async(e,t)=>{try{if(e.method===`OPTIONS`){t.writeHead(204,{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`GET, POST, PUT, PATCH, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type`}),t.end();return}if(new URL(e.url??`/`,`http://127.0.0.1`).searchParams.get(`state`)!==i){t.writeHead(400,{"Content-Type":`text/plain; charset=utf-8`}),t.end(`bad state
|
|
8
|
+
`);return}let{accessToken:r,apiKey:a,baseUrl:c,consoleSite:l,consoleRegion:u,consoleSwitchAgent:d,workspaceId:f}=await wr(e),p=r||c||l||u||d||f;if(p||a)try{let e={access_token:r||void 0,console_site:l||void 0,console_region:u||void 0,console_switch_agent:d?Number(d):void 0,workspace_id:f||void 0};a?(await ar(n,a,{baseUrl:c||n.authStore.resolveBaseUrl(),persistBaseUrl:c||void 0,persistPatch:e}),process.stderr.write(`Config saved to ${n.authStore.path}\n`)):p&&(await n.authStore.login({...e,base_url:c||void 0}),process.stderr.write(`Config saved to ${n.authStore.path}\n`))}catch(e){o=e,t.writeHead(500,{"Content-Type":`text/plain; charset=utf-8`}),t.end(`Failed to save credentials
|
|
9
9
|
`),s.close();return}t.writeHead(200,{"Content-Type":`text/plain; charset=utf-8`,"Access-Control-Allow-Origin":`*`}),t.end(`OK
|
|
10
|
-
`),(p||a)&&s.close()}catch{t.statusCode=500,t.end()}}),c;try{c=await
|
|
10
|
+
`),(p||a)&&s.close()}catch{t.statusCode=500,t.end()}}),c;try{c=await Tr(s)}catch(e){throw new t(`Could not bind to 127.0.0.1 (no free port or permission denied): ${e instanceof Error?e.message:String(e)}`,a.USAGE)}let l=`${e}/console-login?notice=127.0.0.1:${c}?state=${encodeURIComponent(i)}`;r?.needApiKey&&(l+=`&needapikey=true`);try{await cr(l),process.stderr.write(`Opened the login page in your default browser. This process keeps the local port open for the console; press Ctrl+C when finished (or wait for idle timeout).
|
|
11
11
|
`)}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`Could not open the default browser (${t}). Open this URL manually:\n\n`),process.stdout.write(`${l}\n`),process.stderr.write(`
|
|
12
12
|
This process keeps the local port open for the console; press Ctrl+C when finished (or wait for idle timeout).
|
|
13
|
-
`)}if(await new Promise((e,t)=>{let n=!1,r=()=>{n||(n=!0,clearTimeout(i),e())},i=setTimeout(()=>{s.close()},9e5);s.once(`close`,r),s.once(`error`,e=>{clearTimeout(i),n||(n=!0,t(e))})}),o)throw o}function
|
|
14
|
-
`)},r);return}if(r!==`text`){
|
|
13
|
+
`)}if(await new Promise((e,t)=>{let n=!1,r=()=>{n||(n=!0,clearTimeout(i),e())},i=setTimeout(()=>{s.close()},9e5);s.once(`close`,r),s.once(`error`,e=>{clearTimeout(i),n||(n=!0,t(e))})}),o)throw o}function Dr(e){return typeof e==`string`&&e.trim().length>0}var Or=w({description:`Authenticate with API key, console browser login, or OpenAPI AK/SK (credentials can coexist)`,auth:`none`,usageArgs:`--api-key <key> | --console | --open-api --access-key-id <id> --access-key-secret <secret>`,flags:{apiKey:{type:`string`,valueHint:`<key>`,description:`Model API key to store`},baseUrl:{type:`string`,valueHint:`<url>`,description:`Model API base URL (used with --api-key for validation)`},console:{type:`switch`,description:`Sign in via browser; use --console-site to choose domestic (default) or international`},consoleSite:{type:`string`,valueHint:`<site>`,description:`Console site: domestic, international`},openApi:{type:`switch`,description:`Store Alibaba Cloud OpenAPI AK/SK credentials`},accessKeyId:{type:`string`,valueHint:`<id>`,description:`Alibaba Cloud Access Key ID to store`},accessKeySecret:{type:`string`,valueHint:`<secret>`,description:`Alibaba Cloud Access Key Secret to store`}},exampleArgs:[`--api-key sk-xxxxx`,`--config token-plan --api-key sk-sp-xxxxx`,`--console`,`--open-api --access-key-id LTAIxxxxx --access-key-secret xxxxx`],validate:e=>{let t=Dr(e.apiKey),n=e.console===!0,r=e.openApi===!0;if(!t&&Dr(e.baseUrl))return`Use --base-url only with --api-key`;if(!n&&Dr(e.consoleSite))return`Use --console-site only with --console`;if(!r&&(Dr(e.accessKeyId)||Dr(e.accessKeySecret)))return`Use --open-api with --access-key-id and --access-key-secret`;if([t,n,r].filter(Boolean).length!==1)return`Choose exactly one login mode: --api-key, --console, or --open-api`;if(r&&(!Dr(e.accessKeyId)||!Dr(e.accessKeySecret)))return`Provide --access-key-id and --access-key-secret with --open-api`},async run(e){let{identity:t,settings:n,flags:r}=e,i=e.authStore,a={identity:t,settings:n,authStore:i},o=r.apiKey,s=r.baseUrl?qe(r.baseUrl):void 0;if(r.console){if(n.dryRun){j(`Would bind a free port on 127.0.0.1 and open the console login URL in your browser.`);return}let e=!!(o||i.stored().apiKey);await Er(dr(r.consoleSite||n.consoleSite||`domestic`),a,{needApiKey:!e});return}if(r.openApi){if(n.dryRun){j(`Would save OpenAPI AK/SK credentials and generate CLI access token.`);return}let e=i.resolveBaseUrl();process.stderr.write(`Generating CLI access token... `);let a=(await ge({identity:t,settings:n,baseUrl:e,accessKeyId:r.accessKeyId,accessKeySecret:r.accessKeySecret})).cliAccessToken;await i.login({access_key_id:r.accessKeyId,access_key_secret:r.accessKeySecret,access_token:a}),process.stderr.write(`OpenAPI credentials saved to ${i.path}\n`);return}if(!o)return;if(n.dryRun){j(`Would validate and save API key.`);return}let c=Ce(n.configName),l=i.stored().baseUrl;await ar(a,o,{baseUrl:s||i.resolveBaseUrl(c?.baseUrl),persistBaseUrl:s||(l?void 0:c?.baseUrl),defaultTextModel:c?.defaultTextModel,defaultVideoModel:c?.defaultVideoModel,defaultImageToVideoModel:c?.defaultImageToVideoModel,defaultReferenceToVideoModel:c?.defaultReferenceToVideoModel,defaultImageModel:c?.defaultImageModel})}}),kr=w({description:`Show current authentication state`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let{identity:t,settings:n}=e,r=T(n.output),i=e.authStore.describe(),a=i.apiKey?{source:i.apiKey.source,masked:E(i.apiKey.token),base_url:i.apiKey.baseUrl}:void 0,o=i.console?{source:i.console.source,masked:E(i.console.token),region:i.console.region,site:i.console.site}:void 0,s=i.openapi?{source:i.openapi.source,access_key_id:E(i.openapi.accessKeyId),access_key_secret:E(i.openapi.accessKeySecret)}:void 0,c=!!(a||o||s),l=n.configName??`default`,u=e.authStore.path;if(!c){M({authenticated:!1,config:l,config_file:u,message:`Not authenticated.`,hint:[`API key (model): ${t.binName} auth login --api-key <key> or DASHSCOPE_API_KEY`,`Console gateway: ${t.binName} auth login --console`,`OpenAPI (AK/SK): ${t.binName} auth login --open-api --access-key-id <id> --access-key-secret <secret>`,`Get API Key: ${Ct}`].join(`
|
|
14
|
+
`)},r);return}if(r!==`text`){M({authenticated:!0,config:l,config_file:u,api_key:a,console:o,openapi:s},r);return}j(`Config: ${l}`),j(`Config file: ${u}`),j(`Authentication Status:`),j(a?` API key (model): ${a.source} ${a.masked}`:` API key (model): not configured`),j(o?` Console gateway: ${o.source} ${o.masked} (${o.region}, ${o.site})`:` Console gateway: not configured (run ${t.binName} auth login --console)`),j(s?` OpenAPI (AK/SK): ${s.source} ${s.access_key_id}`:` OpenAPI (AK/SK): not configured (run ${t.binName} auth login --open-api)`)}}),Ar=w({description:`Clear stored credentials; full logout also clears the model Base URL`,auth:`none`,usageArgs:`[--console | --open-api] [--dry-run]`,flags:{console:{type:`switch`,description:`Only clear the console access_token, keep api_key intact`},openApi:{type:`switch`,description:`Only clear OpenAPI AK/SK/STS credentials, keep other credentials intact`}},exampleArgs:[``,`--console`,`--open-api`,`--dry-run`],validate:e=>e.console&&e.openApi?`Use only one scope: --console or --open-api`:void 0,async run(e){let{settings:t,flags:n}=e,r=e.authStore,i=r.stored();if(n.console){if(t.dryRun){i.console?j(`Would clear access_token from ${r.path}`):j(`No console access_token to clear.`),j(`No changes made.`);return}await r.logout(`console`)?(process.stderr.write(`Cleared access_token from ${r.path}\n`),i.apiKey&&process.stderr.write(`api_key is still configured and will be used for authentication.
|
|
15
15
|
`)):process.stderr.write(`No console access_token to clear.
|
|
16
|
-
`);return}if(n.openApi){if(t.dryRun){i.openapi?
|
|
16
|
+
`);return}if(n.openApi){if(t.dryRun){i.openapi?j(`Would clear access_key_id / access_key_secret / security_token from ${r.path}`):j(`No OpenAPI AK/SK credentials to clear.`),j(`No changes made.`);return}await r.logout(`openapi`)?(process.stderr.write(`Cleared access_key_id / access_key_secret / security_token from ${r.path}\n`),(i.apiKey||i.console)&&process.stderr.write(`Other credentials are still configured and will be used for authentication.
|
|
17
17
|
`)):process.stderr.write(`No OpenAPI AK/SK credentials to clear.
|
|
18
|
-
`);return}let a=i.apiKey||i.console||i.openapi||!!i.baseUrl;if(t.dryRun){
|
|
19
|
-
`)}}),
|
|
20
|
-
`))),i&&o.write(t.reasoning_content)),t.content&&(i&&r&&(o.write(`${u.reset}\n\nResponse:\n`),r=!1),n+=t.content,i&&c.write(t.content))}}catch{}}r&&o.write(u.reset),s===`json`?
|
|
21
|
-
`)}else{let n=await e.client.requestJson({path:x(),method:`POST`,body:l}),r=n.choices?.[0]?.message?.content??``;t.quiet||s===`text`?
|
|
18
|
+
`);return}let a=i.apiKey||i.console||i.openapi||!!i.baseUrl;if(t.dryRun){j(a?`Would clear api_key / base_url / access_token / access_key_id / access_key_secret / security_token from ${r.path}`:`No credentials or model Base URL to clear.`),j(`No changes made.`);return}await r.logout(`all`)?process.stderr.write(`Cleared api_key / base_url / access_token / access_key_id / access_key_secret / security_token from ${r.path}\n`):process.stderr.write(`No credentials or model Base URL to clear.
|
|
19
|
+
`)}}),jr=w({description:`Generate a CLI access token using OpenAPI AK/SK`,auth:`none`,usageArgs:`--access-key-id <id> --access-key-secret <secret> --security-token <token>`,flags:{accessKeyId:{type:`string`,valueHint:`<id>`,description:`Alibaba Cloud Access Key ID`,required:!0},accessKeySecret:{type:`string`,valueHint:`<secret>`,description:`Alibaba Cloud Access Key Secret`,required:!0},securityToken:{type:`string`,valueHint:`<token>`,description:`Alibaba Cloud STS Security Token to store (optional)`}},exampleArgs:[`--access-key-id LTAIxxxxx --access-key-secret xxxxx --security-token <token>`],async run(e){let{identity:t,settings:n,flags:r}=e,i=T(n.output);M(await ge({identity:t,settings:n,baseUrl:e.client.baseUrl,accessKeyId:r.accessKeyId,accessKeySecret:r.accessKeySecret,securityToken:r.securityToken||void 0}),i)}});const Mr={model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: qwen3.8-max)`},message:{type:`array`,valueHint:`<text>`,description:`Message text (repeatable, prefix role: to set role); or use --messages-file`},messagesFile:{type:`string`,valueHint:`<path>`,description:`JSON file with messages array (use - for stdin)`},system:{type:`string`,valueHint:`<text>`,description:`System prompt`},maxTokens:{type:`number`,valueHint:`<n>`,description:`Maximum tokens to generate (default: 4096)`},temperature:{type:`number`,valueHint:`<n>`,description:`Sampling temperature (0.0, 2.0]`},topP:{type:`number`,valueHint:`<n>`,description:`Nucleus sampling threshold`},stream:{type:`switch`,description:`Stream response tokens (default: on in TTY)`},tool:{type:`array`,valueHint:`<json-or-path>`,description:`Tool definition as JSON or file path (repeatable)`},enableThinking:{type:`switch`,description:`Enable thinking/reasoning mode (for qwen3/qwq models)`},thinkingBudget:{type:`number`,valueHint:`<n>`,description:`Max tokens for thinking (default: 4096)`}};function Nr(e){let t=[],n;if(e.system&&(n=e.system),e.messagesFile){let r=tt(e.messagesFile),i=JSON.parse(r);for(let e of i)e.role===`system`?n=typeof e.content==`string`?e.content:``:t.push(e)}if(e.message){let r=new Set([`system`,`user`,`assistant`]),i=e.message;for(let e of i){let i=e.indexOf(`:`),a=i===-1?``:e.slice(0,i);if(r.has(a)){let r=e.slice(i+1);a===`system`?n=r:t.push({role:a,content:r})}else t.push({role:`user`,content:e})}}return{system:n,messages:t}}var Pr=w({description:`Send a chat completion (OpenAI compatible, DashScope)`,auth:`apiKey`,usageArgs:`--message <text> [flags]`,flags:Mr,exampleArgs:[`--message "What is Qwen?"`,`--model qwen-max --system "You are a coding assistant." --message "Write fizzbuzz in Python"`,`--message "Hello" --message "assistant:Hi!" --message "How are you?"`,`--messages-file - --stream`,`--message "Hello" --output json`,`--model qwq-plus --message "Solve 1+1" --enable-thinking`],validate:e=>!e.message&&!e.messagesFile?`Provide --message or --messages-file.`:void 0,async run(e){let{settings:t,flags:n}=e,{system:r,messages:i}=Nr(n),a=n.model||t.defaultTextModel||`qwen3.8-max`,o=n.stream||process.stdout.isTTY,s=T(t.output),c=[];r&&c.push({role:`system`,content:r}),c.push(...i);let l={model:a,messages:c,max_tokens:n.maxTokens??4096,stream:o};if(n.temperature!==void 0&&(l.temperature=n.temperature),n.topP!==void 0&&(l.top_p=n.topP),n.enableThinking&&(l.enable_thinking=!0,n.thinkingBudget!==void 0&&(l.thinking_budget=n.thinkingBudget)),n.tool&&(l.tools=n.tool.map(e=>{try{return JSON.parse(e)}catch{let t=en(e,`utf-8`);return JSON.parse(t)}})),t.dryRun){M({request:l},s);return}if(o){let t=await e.client.request({path:x(),method:`POST`,body:l,stream:!0}),n=``,r=!1,i=s===`text`,a=process.stdout.isTTY,o=s===`json`?process.stderr:a?process.stdout:process.stderr,c=process.stdout,u=k(o);for await(let e of Ye(t)){if(e.data===`[DONE]`)break;try{let t=JSON.parse(e.data);for(let e of t.choices){let t=e.delta;t.reasoning_content&&(i&&!r&&(r=!0,o.write(u.dim(`Thinking:
|
|
20
|
+
`))),i&&o.write(t.reasoning_content)),t.content&&(i&&r&&(o.write(`${u.reset}\n\nResponse:\n`),r=!1),n+=t.content,i&&c.write(t.content))}}catch{}}r&&o.write(u.reset),s===`json`?M({content:n},s):c.write(`
|
|
21
|
+
`)}else{let n=await e.client.requestJson({path:x(),method:`POST`,body:l}),r=n.choices?.[0]?.message?.content??``;t.quiet||s===`text`?j(r):M(n,s)}}});const Fr=[{voice:`Tina`,name:`甜妹`,desc:`甜美亲切`,lang:`中文/英文`},{voice:`Dylan`,name:`北京-晓东`,desc:`胡同少年`,lang:`中文/北京`},{voice:`Kiki`,name:`粤语-阿清`,desc:`甜美港妹`,lang:`中文/英文`},{voice:`Li`,name:`南京-老李`,desc:`南京大叔`,lang:`中文/英文`},{voice:`Sunny`,name:`四川-晴儿`,desc:`甜飒川妹`,lang:`中文`},{voice:`Marcus`,name:`陕西-秦川`,desc:`陕北汉子`,lang:`中文/英文`},{voice:`Eric`,name:`四川-程川`,desc:`成都大哥`,lang:`中文/英文`},{voice:`Rocky`,name:`粤语-阿强`,desc:`幽默港仔`,lang:`中文/英文`},{voice:`Jennifer`,name:`詹妮弗`,desc:`美剧大女主`,lang:`中文/英文`},{voice:`Ryan`,name:`甜茶`,desc:`美剧张力男`,lang:`中文/英文`},{voice:`Katerina`,name:`卡捷琳娜`,desc:`御姐深情女`,lang:`中文/英文`},{voice:`Peter`,name:`天津-李彼得`,desc:`天津捧哏`,lang:`中文/英文`},{voice:`Ethan`,name:`晨煦`,desc:`北方口音男`,lang:`中文/英文`}];function Ir(){let e=(e,t)=>e.padEnd(t);process.stdout.write(`
|
|
22
22
|
Omni output voices:
|
|
23
|
-
`),process.stdout.write(`${e(`VOICE ID`,12)} ${e(`NAME`,14)} ${e(`DESCRIPTION`,14)} LANGUAGE\n`),process.stdout.write(`${`-`.repeat(12)} ${`-`.repeat(14)} ${`-`.repeat(14)} ${`-`.repeat(12)}\n`);for(let t of
|
|
24
|
-
`);let ee;if(b&&!s){let e=Buffer.from(b,`base64`),r=
|
|
25
|
-
`));else{let t={urls:e,saved:l,total:e.length};i&&(t.task_id=i),a&&a.length>1&&(t.task_ids=a),
|
|
26
|
-
`)):
|
|
27
|
-
`)),r.async){
|
|
28
|
-
`)),r.async){F(g.length===1?{task_id:g[0]}:{task_ids:g},d);return}let _=r.pollInterval??15,v=Math.max(n.timeout,600),y=await Promise.all(g.map(t=>Lt(e.client,n,{url:e.client.url(A(t)),intervalSec:_,timeoutSec:v,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}}))),b=[];for(let e=0;e<y.length;e++){let t=y[e],n=t.output.video_url||t.output.results&&t.output.results[0]?.url;n&&b.push({taskId:g[e],videoUrl:n})}if(b.length===0)throw new t(`All tasks completed but no video URLs returned.`,a.GENERAL);if(r.download){let e=r.download,{size:t}=await N(b[0].videoUrl,e,{quiet:n.quiet});n.quiet?P(e):F({task_id:b[0].taskId,video_url:b[0].videoUrl,status:`SUCCEEDED`,saved:e,size:Nt(t)},d);return}let{join:x}=await import(`path`),S=k(n,{subDir:`videos`}),C=[];await Promise.all(b.map(async({taskId:e,videoUrl:t})=>{let r=x(S,`${e}.mp4`);await N(t,r,{quiet:n.quiet}),C.push({task_id:e,video_url:t,saved:r})})),C.length===1?F(C[0],d):F({videos:C,total:C.length},d)}}),Lr=T({description:`Query async task status`,auth:`apiKey`,usageArgs:`--task-id <id>`,flags:{taskId:{type:`string`,valueHint:`<id>`,description:`Async task ID`,required:!0}},exampleArgs:[`--task-id 3b256896-3e70-xxxx-xxxx-xxxxxxxxxxxx`,`--task-id 3b256896-3e70-xxxx --output json`],async run(e){let{settings:t,flags:n}=e,r=n.taskId,i=E(t.output);if(t.dryRun){F({task_id:r},i);return}let a=await e.client.requestJson({path:A(r)});if(t.quiet){P(a.output.task_status);return}F({task_id:a.output.task_id,task_status:a.output.task_status,video_url:a.output.video_url,results:a.output.results,submit_time:a.output.submit_time,end_time:a.output.end_time},i)}}),Rr=T({description:`Download a completed video by task ID`,auth:`apiKey`,usageArgs:`--task-id <id> --out <path>`,flags:{taskId:{type:`string`,valueHint:`<id>`,description:`Task ID to download from`,required:!0},out:{type:`string`,valueHint:`<path>`,description:`Output file path`,required:!0}},exampleArgs:[`--task-id 3b256896-xxxx --out video.mp4`,`--task-id 3b256896-xxxx --out video.mp4 --quiet`],async run(e){let{settings:n,flags:r}=e,i=r.taskId,o=r.out,s=E(n.output);if(n.dryRun){F({task_id:i,action:`download`,out:o},s);return}let c=await e.client.requestJson({path:A(i)});if(c.output.task_status!==`SUCCEEDED`)throw new t(`Task is not complete (status: ${c.output.task_status}).`,a.GENERAL,`Wait for the task to complete before downloading.`);let l=c.output.video_url||c.output.results&&c.output.results[0]?.url;if(!l)throw new t(`No download URL available for this task.`,a.GENERAL);let{size:u}=await N(l,o,{quiet:n.quiet});if(n.quiet){P(o);return}F({saved:o,size:Nt(u)},s)}});const zr=new Set([`.mp4`,`.mov`,`.avi`,`.mkv`,`.webm`,`.flv`,`.wmv`]);function Br(e){let t=en(e).toLowerCase().split(`?`)[0];return!!(zr.has(t)||/\.(mp4|mov|avi|mkv|webm|flv|wmv)(\?|$)/i.test(e))}async function Vr(e){return e.startsWith(`data:`)||e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`oss://`)?e:Te(e)}var Hr=T({description:`Describe an image or video using Qwen-VL`,auth:`apiKey`,usageArgs:`--image <path-or-url> [--video <url>] [--prompt <text>]`,flags:{image:{type:`string`,valueHint:`<path-or-url>`,description:`Local image path or URL`},video:{type:`array`,valueHint:`<url>`,description:`Video file URL or local path (mp4/mov/avi/mkv/webm)`},prompt:{type:`string`,valueHint:`<text>`,description:`Question about the content (default: auto-detected)`},model:{type:`string`,valueHint:`<model>`,description:`Vision model (default: qwen3-vl-plus)`}},exampleArgs:[`--image photo.jpg`,`--image https://example.com/photo.jpg --prompt "What breed is this dog?"`,`--video https://example.com/video.mp4 --prompt "Summarize the video content"`,`--video ./local-video.mp4`,`--image photo.png --prompt "Extract the text" --model qwen3-vl-plus`],validate:e=>!e.image&&!e.video?.length?`Provide --image or --video.`:void 0,async run(e){let{settings:n,flags:r}=e,i=r.image,o=r.video??[],s=r.model||(e.client.usesTokenPlanEndpoint()?n.defaultTextModel:void 0)||`qwen3-vl-plus`;i&&Br(i)&&(o.push(i),i=void 0);let c=o.length>0?`Describe the video.`:`Describe the image.`,l=r.prompt||c,u=E(n.output);if(n.dryRun){F({request:{prompt:l,image:i?O(i):void 0,video:o.length?o.map(O):void 0,model:s}},u);return}let d=[];if(o.length>0)for(let n of o){let r=n;if(Ee(n)){if(!z(n))throw new t(`Video file not found: ${n}`,a.USAGE);r=await e.client.uploadFile(n,s)}d.push({type:`video_url`,video_url:{url:r}})}if(i){let t=await Vr(i),n=t;Ee(i)&&t.startsWith(`data:`)&&Xt(i).size>5*1024*1024&&(n=await e.client.resolveImageInput(i,s)),d.push({type:`image_url`,image_url:{url:n}})}d.push({type:`text`,text:l});let f={model:s,messages:[{role:`user`,content:d}]},p=await e.client.requestJson({path:x(),method:`POST`,body:f}),m=p.choices?.[0]?.message?.content;if(u!==`text`){F(p,u);return}P(m||``)}});const Ur=[`base_url`,`output`,`output_dir`,`timeout`,`api_key`,`access_token`,`access_key_id`,`access_key_secret`,`security_token`,`default_text_model`,`default_video_model`,`default_image_to_video_model`,`default_reference_to_video_model`,`default_image_model`,`default_speech_model`,`default_omni_model`,`workspace_id`],Wr=new Set([`api_key`,`access_token`,`access_key_id`,`access_key_secret`,`security_token`]),Gr={"base-url":`base_url`,"output-dir":`output_dir`,"api-key":`api_key`,"access-token":`access_token`,"access-key-id":`access_key_id`,"access-key-secret":`access_key_secret`,"security-token":`security_token`,"default-text-model":`default_text_model`,"default-video-model":`default_video_model`,"default-image-to-video-model":`default_image_to_video_model`,"default-reference-to-video-model":`default_reference_to_video_model`,"default-image-model":`default_image_model`,"default-speech-model":`default_speech_model`,"default-omni-model":`default_omni_model`,"workspace-id":`workspace_id`};function Kr(e){return Gr[e]||e}function qr(e,n){let r=Kr(e);if(!Ur.includes(r))throw new t(`Invalid config key "${e}". Valid keys: ${Ur.join(`, `)}`,a.USAGE);if(r===`output`&&![`text`,`json`].includes(n))throw new t(`Invalid output format "${n}". Valid values: text, json`,a.USAGE);if(r===`timeout`){let e=Number(n);if(isNaN(e)||e<=0)throw new t(`Invalid timeout "${n}". Must be a positive number.`,a.USAGE);return e}return r===`base_url`?Ke(n):n}var Jr=T({description:`Display current configuration`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let{settings:t,client:n}=e,r=e.configStore,i=r.read(),a=E(t.output),o={...i,base_url:n.baseUrl,output:t.output,timeout:t.timeout,config:t.configName??`default`,config_file:r.path};for(let e of Wr)typeof o[e]==`string`&&(o[e]=D(o[e]));F(o,a)}}),Yr=T({description:`Set a config value`,auth:`none`,usageArgs:`--key <key> --value <value>`,flags:{key:{type:`string`,valueHint:`<key>`,description:`Config key (base_url, output, output_dir, timeout, api_key, access_token, access_key_id, access_key_secret, security_token, default_*_model, workspace_id)`,required:!0},value:{type:`string`,valueHint:`<value>`,description:`Value to set`,required:!0}},exampleArgs:[`--key output --value json`,`--key timeout --value 600`,`--key base_url --value https://dashscope.aliyuncs.com`],async run(e){let{settings:t,flags:n}=e,r=n.key,i=n.value,a=Kr(r),o=qr(r,i),s=E(t.output);if(t.dryRun){F({would_set:{[a]:o},config:t.configName??`default`,config_file:e.configStore.path},s);return}if(await e.configStore.write({[a]:o}),!t.quiet){let n=Wr.has(a)?D(String(o)):o;F({[a]:n,config:t.configName??`default`,config_file:e.configStore.path},s)}}}),Xr=T({description:`List config profiles and show the active profile`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let t=e.configStore.profiles(),n=[`default`,...Object.keys(t.named).sort()],r=E(e.settings.output);if(r===`json`){F({active_config:t.active,profiles:n,config_file:e.configStore.path},r);return}let i=Math.max(4,...n.map(e=>e.length));P(`${`NAME`.padEnd(i)} ACTIVE`);for(let e of n)P(`${e.padEnd(i)} ${e===t.active?`*`:``}`)}}),Zr=T({description:`Set the active config profile`,auth:`none`,usageArgs:`--name <name>`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Existing profile name, or default`,required:!0}},exampleArgs:[`--name token-plan`,`--name default`],async run(e){let t=E(e.settings.output);if(e.settings.dryRun){F({would_activate:e.configStore.validateActivation(e.flags.name),config_file:e.configStore.path},t);return}let n=await e.configStore.activate(e.flags.name);e.settings.quiet||F({active_config:n,config_file:e.configStore.path},t)}});const Qr={port:{type:`number`,valueHint:`<port>`,description:`Port to listen on (default: random free port)`},noOpen:{type:`switch`,description:`Do not open the browser automatically`}};function $r(e){return e instanceof t||e instanceof Error?e.message:String(e)}function U(e,t,n){e.writeHead(t,{"Content-Type":`application/json; charset=utf-8`}),e.end(JSON.stringify(n))}function ei(e){return new Promise((t,n)=>{let r=0,i=[];e.on(`data`,e=>{if(r+=e.length,r>1048576){n(Error(`payload too large`));return}i.push(e)}),e.on(`end`,()=>t(Buffer.concat(i).toString(`utf8`))),e.on(`error`,n)})}function ti(e){let t={};for(let[n,r]of Object.entries(e)){let e=``;typeof r==`string`?e=r:(typeof r==`number`||typeof r==`boolean`)&&(e=String(r)),e!==``&&(t[Kr(n)]=qr(n,e))}return t}function ni(e,t){let n=new Set(Ur),r={};for(let[t,i]of Object.entries(e))n.has(t)||(r[t]=i);return{...r,...t}}function ri(e,t){return Ut.createServer(async(n,r)=>{try{let i=(n.headers.host||``).split(`:`)[0];if(i!==`127.0.0.1`&&i!==`localhost`){r.writeHead(403,{"Content-Type":`text/plain; charset=utf-8`}),r.end(`forbidden host
|
|
29
|
-
`)
|
|
30
|
-
`);return}let o=n.method??`GET`,s=a.pathname;if(s===`/`&&o===`GET`){r.writeHead(200,{"Content-Type":`text/html; charset=utf-8`}),r.end(`<!doctype html>
|
|
23
|
+
`),process.stdout.write(`${e(`VOICE ID`,12)} ${e(`NAME`,14)} ${e(`DESCRIPTION`,14)} LANGUAGE\n`),process.stdout.write(`${`-`.repeat(12)} ${`-`.repeat(14)} ${`-`.repeat(14)} ${`-`.repeat(12)}\n`);for(let t of Fr)process.stdout.write(`${e(t.voice,12)} ${e(t.name,14)} ${e(t.desc,14)} ${t.lang}\n`);process.stdout.write(`\nTotal: ${Fr.length} voices\n`)}const Lr={wav:`wav`,mp3:`mp3`,amr:`amr`,aac:`aac`,m4a:`aac`,ogg:`ogg`,"3gp":`3gp`,"3gpp":`3gpp`},Rr=Object.keys(Lr);function zr(e){let n=e.split(`?`)[0].split(`#`)[0],r=sn(n).slice(1).toLowerCase();if(!r)throw new t(`Cannot infer audio format from "${e}". Use a file/URL whose path ends with: ${Rr.join(`, `)}.`,a.USAGE);let i=Lr[r];if(!i)throw new t(`Unsupported audio extension ".${r}" for "${e}". Supported extensions: ${Rr.join(`, `)}.`,a.USAGE);return i}function Br(e){let t=Buffer.alloc(44);return t.write(`RIFF`,0),t.writeUInt32LE(36+e,4),t.write(`WAVE`,8),t.write(`fmt `,12),t.writeUInt32LE(16,16),t.writeUInt16LE(1,20),t.writeUInt16LE(1,22),t.writeUInt32LE(24e3,24),t.writeUInt32LE(48e3,28),t.writeUInt16LE(2,32),t.writeUInt16LE(16,34),t.write(`data`,36),t.writeUInt32LE(e,40),t}var Vr=w({description:`Multimodal chat with text + audio output (Qwen-Omni)`,auth:`apiKey`,usageArgs:`--message <text> [flags]`,flags:{message:{type:`array`,valueHint:`<text>`,description:`Message text (repeatable, prefix role: to set role)`},model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: qwen3.5-omni-plus)`},system:{type:`string`,valueHint:`<text>`,description:`System prompt`},image:{type:`array`,valueHint:`<url>`,description:`Image URL or local file (repeatable)`},audio:{type:`array`,valueHint:`<url>`,description:`Audio URL or local file (.wav/.mp3/.amr/.aac/.m4a/.ogg/.3gp/.3gpp)`},video:{type:`array`,valueHint:`<url>`,description:`Video file URL / local path, or comma-separated frame URLs`},voice:{type:`string`,valueHint:`<voice>`,description:`Output voice ID (default: Tina). Use --list-voices to see all options`},listVoices:{type:`switch`,description:`List available output voices and exit`},audioFormat:{type:`string`,valueHint:`<fmt>`,description:`Audio output format (default: wav)`},audioOut:{type:`string`,valueHint:`<path>`,description:`Save audio to file (default: auto-generate)`},textOnly:{type:`switch`,description:`Output text only, no audio generation`},maxTokens:{type:`number`,valueHint:`<n>`,description:`Maximum tokens to generate`},temperature:{type:`number`,valueHint:`<n>`,description:`Sampling temperature (0.0, 2.0]`}},exampleArgs:[`--list-voices`,`--message "Hello, who are you?"`,`--message "Describe this image" --image ./photo.jpg`,`--message "What is this audio saying?" --audio https://example.com/audio.wav`,`--message "Summarize this video" --video https://example.com/video.mp4`,`--message "What is this video about?" --video ./local-video.mp4 --text-only`,`--message "Answer in Sichuan dialect: How's the weather today?" --voice Sunny`,`--message "Hello" --text-only --output json`,`--message "Read this passage aloud" --audio-out greeting.wav`],validate:e=>e.listVoices||e.message?void 0:`Missing required flag: --message`,async run(e){let{settings:t,flags:n}=e;if(n.listVoices){Ir();return}let r=n.message??[],i=n.model||t.defaultOmniModel||`qwen3.5-omni-plus`,a=n.voice||`Tina`,o=n.audioFormat||`wav`,s=n.textOnly===!0,c=T(t.output),l=[];n.system&&l.push({role:`system`,content:n.system});let u=new Set([`system`,`user`,`assistant`]);for(let e of r){let t=e.indexOf(`:`),n=t===-1?``:e.slice(0,t);if(u.has(n)){let r=e.slice(t+1);n===`system`?l.push({role:`system`,content:r}):l.push({role:n,content:r})}else l.push({role:`user`,content:e})}let d=n.image||[],f=n.audio||[],p=n.video||[],m=[],h=[],g=[];if(d.length>0||f.length>0||p.length>0){for(let t of d){let n=await e.client.uploadFile(t,i);m.push(n)}for(let t of f){let n=await e.client.uploadFile(t,i);h.push({source:t,data:n})}for(let t of p)if(t.includes(`,`)){let n=t.split(`,`).map(e=>e.trim()).filter(Boolean);for(let t of n){let n=await e.client.uploadFile(t,i);g.push(`frame:${n}`)}}else{let n=await e.client.uploadFile(t,i);g.push(n)}}if(m.length>0||h.length>0||g.length>0){for(let e=l.length-1;e>=0;e--)if(l[e].role===`user`){let t=l[e].content,n=[];typeof t==`string`?n.push({type:`text`,text:t}):Array.isArray(t)&&n.push(...t);for(let e of m)n.push({type:`image_url`,image_url:{url:e}});for(let{source:e,data:t}of h)n.push({type:`input_audio`,input_audio:{data:t,format:zr(e)}});let r=g.filter(e=>e.startsWith(`frame:`)).map(e=>e.slice(6)),i=g.filter(e=>!e.startsWith(`frame:`));r.length>0&&n.push({type:`video`,video:r});for(let e of i)n.push({type:`video_url`,video_url:{url:e}});l[e]={role:`user`,content:n};break}}let _={model:i,messages:l,stream:!0,stream_options:{include_usage:!0}};if(s||(_.modalities=[`text`,`audio`],_.audio={voice:a,format:o}),n.maxTokens!==void 0&&(_.max_tokens=n.maxTokens),n.temperature!==void 0&&(_.temperature=n.temperature),t.dryRun){M({request:_},c);return}if(!t.quiet){let e=s?`text-only`:`text+audio, voice: ${a}`;process.stderr.write(`[Model: ${i}] [${e}]\n`)}let v=await e.client.request({path:x(),method:`POST`,body:_,stream:!0}),y=``,b=``,S=process.stdout.isTTY,C=process.stdout;for await(let e of Ye(v)){if(e.data===`[DONE]`)break;try{let t=JSON.parse(e.data);for(let e of t.choices){let t=e.delta;t.content&&(y+=t.content,S&&C.write(t.content)),t.audio?.data&&(b+=t.audio.data)}}catch{}}S&&y&&C.write(`
|
|
24
|
+
`);let ee;if(b&&!s){let e=Buffer.from(b,`base64`),r=Br(e.length),i=Buffer.concat([r,e]),a=n.audioOut;if(!a){let{join:e}=await import(`path`);a=e(ct(t,{subDir:`omni`}),`omni_${Date.now()}.wav`)}rn(a,i),ee=a,t.quiet||process.stderr.write(`Audio saved: ${a}\n`)}if(!S||c===`json`){let e={content:y};ee&&(e.audio_saved=ee,e.voice=a),M(e,c)}}}),Hr=w({description:`Generate images (Qwen-Image / wan2.x)`,auth:`apiKey`,usageArgs:`--prompt <text> [flags]`,flags:{prompt:{type:`string`,valueHint:`<text>`,description:`Image description`,required:!0},model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: qwen-image-2.0)`},size:{type:`string`,valueHint:`<W*H>`,description:`Image size: ratio (3:4, 16:9, 1:1) or pixels (2048*2048)`},n:{type:`number`,valueHint:`<count>`,description:`Number of images per request (default: 1, max: 6)`},seed:{type:`number`,valueHint:`<n>`,description:`Random seed for reproducible generation`},negativePrompt:{type:`string`,valueHint:`<text>`,description:`Negative prompt to exclude unwanted content`},promptExtend:{type:`boolean`,valueHint:`<bool>`,description:Et},watermark:{type:`boolean`,valueHint:`<bool>`,description:Dt},...e,...n,outDir:{type:`string`,valueHint:`<dir>`,description:`Download images to directory`},outPrefix:{type:`string`,valueHint:`<prefix>`,description:`Filename prefix (default: image)`},pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval when waiting (default: 3)`}},exampleArgs:[`--prompt "A cat in a spacesuit on Mars"`,`--prompt "Logo design" --n 3 --out-dir ./generated/`,`--prompt "Mountain landscape" --size 2688*1536`,`--prompt "A castle" --seed 42 --prompt-extend false`,`--prompt "Logo" --watermark false`,`--prompt "An alien in the space" --watermark false`,`--prompt "sunset" --model wan2.6-t2i --async --quiet`,`--prompt "plush doll" --model z-image-turbo --size 1024*1024`,`--prompt "sunset" --model wanx2.0-t2i-turbo --size 1024*1024`,`--prompt "Pro quality" --model qwen-image-2.0-pro`,`--prompt "Product shots" --n 2 --concurrent 3 # 6 images in parallel`],async run(e){let{settings:t,flags:n}=e,r=n.prompt,i=n.model||t.defaultImageModel||`qwen-image-2.0`,a=st(i),o=Ht(n.size||`1:1`,a.sizeProfile),s=n.n??1,c=Lt(n),l=at(n.promptExtend,a.promptExtendDefault,`prompt-extend`),u=lt(n.watermark),d={size:o,n:s,seed:n.seed,prompt_extend:l,watermark:u},f=a.inputStyle===`prompt`?{model:i,input:{prompt:r,negative_prompt:n.negativePrompt||void 0},parameters:d}:{model:i,input:{messages:[{role:`user`,content:[{text:r}]}]},parameters:{...d,negative_prompt:n.negativePrompt||void 0}},p=T(t.output);if(t.dryRun){M({request:f,mode:a.useSync?`sync`:`async`,path:a.path},p);return}t.quiet||process.stderr.write(`[Model: ${i}] [Mode: ${a.useSync?`sync`:`async`}]\n`),a.useSync?await Ur(e.client,t,a.path,f,n,p,c):await Wr(e.client,t,a.path,f,n,p,c)}});async function Ur(e,n,r,i,o,s,c){let l=(await Ut(c,n,()=>e.requestJson({path:r,method:`POST`,body:i}))).flatMap(e=>e.output.choices||[]).flatMap(e=>e.message?.content||[]).map(e=>e.image).filter(Boolean);if(l.length===0)throw new t(`Generation completed but no images returned.`,a.GENERAL);await Gr(l,o,n,s)}async function Wr(e,n,r,i,o,s,c){let l=(await Ut(c,n,()=>e.requestJson({path:r,method:`POST`,body:i,async:!0}),`tasks`)).map(e=>e.output.task_id);if(o.async){M({task_ids:l},s);return}let u=o.pollInterval??3,d=l.map(t=>Bt(e,n,{url:e.url(O(t)),intervalSec:u,timeoutSec:n.timeout,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}})),f=await Promise.all(d),p=[];for(let e of f){if(e.output.choices){let t=e.output.choices.flatMap(e=>e.message?.content||[]).map(e=>e.image).filter(Boolean);p.push(...t)}if(e.output.results){let t=e.output.results.map(e=>e.url).filter(Boolean);t.length>0&&p.length===0&&p.push(...t)}}if(p.length===0)throw new t(`All tasks completed but no images returned.`,a.GENERAL);await Gr(p,o,n,s,l.length===1?l[0]:void 0,l)}async function Gr(e,t,n,r,i,a){let o=ct(n,{flagDir:t.outDir,subDir:t.outDir?void 0:`images`}),s=t.prompt||``,c=t.outPrefix||_e(`image`,s),l=await Nt(e.length>1?e.map((e,t)=>({url:e,destPath:F(o,`${c}_${String(t+1).padStart(3,`0`)}.png`)})):[{url:e[0],destPath:F(o,`${c}.png`)}],A,{quiet:n.quiet});if(n.quiet)j(l.join(`
|
|
25
|
+
`));else{let t={urls:e,saved:l,total:e.length};i&&(t.task_id=i),a&&a.length>1&&(t.task_ids=a),M(t,r)}}var Kr=w({description:`Edit an existing image with text instructions (Qwen-Image / Wan 2.7)`,auth:`apiKey`,usageArgs:`--image <url> --prompt <text> [flags]`,flags:{image:{type:`array`,valueHint:`<url>`,description:`Source image URL or local file path (repeatable for multi-image merge)`,required:!0},prompt:{type:`string`,valueHint:`<text>`,description:`Edit instruction text`,required:!0},model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: qwen-image-2.0)`},size:{type:`string`,valueHint:`<W*H>`,description:`Output image size: ratio (3:4, 16:9) or pixels (2048*2048)`},n:{type:`number`,valueHint:`<count>`,description:`Number of images (default: 1, max: 6)`},seed:{type:`number`,valueHint:`<n>`,description:`Random seed for reproducible results`},negativePrompt:{type:`string`,valueHint:`<text>`,description:`Negative prompt to exclude unwanted content`},function:{type:`string`,valueHint:`<name>`,description:`wanx*-imageedit function (default: description_edit). Examples: stylization_all, description_edit`},promptExtend:{type:`boolean`,valueHint:`<bool>`,description:Tt},watermark:{type:`boolean`,valueHint:`<bool>`,description:Dt},outDir:{type:`string`,valueHint:`<dir>`,description:`Download images to directory`},outPrefix:{type:`string`,valueHint:`<prefix>`,description:`Filename prefix (default: edited)`},...e,...n,pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval when waiting (default: 3)`}},exampleArgs:[`--image ./photo.png --prompt "Replace the background with a beach"`,`--image https://example.com/logo.png --prompt "Change color to blue" --n 3`,`--image ./a.png --image ./b.png --prompt "Merge two images into one collage"`,`--image https://example.com/photo.png --prompt "Remove the person" --model qwen-image-2.0-pro`,`--image ./photo.png --prompt "Change the style" --model wan2.7-image`,`--image ./photo.png --prompt "Place the subject on a table" --model wan2.5-i2i-preview`,`--image ./photo.png --prompt "转换成绘本风格" --model wanx2.1-imageedit --function stylization_all`,`--image ./photo.png --prompt "Replace the background with a beach" --watermark false`],async run(e){let{settings:n,flags:r}=e,i=[];Array.isArray(r.image)?i=r.image:typeof r.image==`string`&&(i=[r.image]);let o=r.prompt,s=r.model||n.defaultImageModel||`qwen-image-2.0`,c=ot(s),l=await Promise.all(i.map(t=>e.client.resolveImageInput(t,s))),u=r.n??1,d=at(r.promptExtend,c.promptExtendDefault,`prompt-extend`),f=lt(r.watermark),p={size:Ht(r.size,c.sizeProfile),n:u,seed:r.seed,prompt_extend:d,watermark:f},m;if(c.inputStyle===`function-base-image`){let e=l[0];if(!e)throw new t(`wanx*-imageedit requires at least one --image as base_image_url.`,a.USAGE);m={model:s,input:{function:r.function||`description_edit`,prompt:o,base_image_url:e},parameters:p}}else if(c.inputStyle===`prompt-images`)m={model:s,input:{prompt:o,images:l,negative_prompt:r.negativePrompt||void 0},parameters:p};else{let e=l.map(e=>({image:e}));e.push({text:o}),m={model:s,input:{messages:[{role:`user`,content:e}]},parameters:{...p,negative_prompt:r.negativePrompt||void 0}}}pt(m.parameters);let h=T(n.output);if(n.dryRun){let e=m;`messages`in m.input?e={...m,input:{messages:m.input.messages.map(e=>({...e,content:e.content.map(e=>e.image?{...e,image:D(e.image)}:e)}))}}:`images`in m.input?e={...m,input:{...m.input,images:m.input.images?.map(e=>D(e))}}:`base_image_url`in m.input&&(e={...m,input:{...m.input,base_image_url:D(m.input.base_image_url),mask_image_url:m.input.mask_image_url?D(m.input.mask_image_url):void 0}}),M({request:e,mode:c.useSync?`sync`:`async`,path:c.path},h);return}n.quiet||process.stderr.write(`[Model: ${s}] [Mode: ${c.useSync?`sync`:`async`}] [Images: ${l.length}]\n`);let g=Lt(r);c.useSync?await qr(e.client,n,c.path,m,r,h,g):await Jr(e.client,n,c.path,m,r,h,g)}});async function qr(e,n,r,i,o,s,c){let l=(await Ut(c,n,()=>e.requestJson({path:r,method:`POST`,body:i}))).flatMap(e=>e.output.choices||[]).flatMap(e=>e.message?.content||[]).map(e=>e.image).filter(Boolean);if(l.length===0)throw new t(`Edit completed but no images returned.`,a.GENERAL);await Yr(l,o,n,s)}async function Jr(e,n,r,i,o,s,c){let l=(await Ut(c,n,()=>e.requestJson({path:r,method:`POST`,body:i,async:!0}),`tasks`)).map(e=>e.output.task_id);if(o.async){M({task_ids:l},s);return}let u=o.pollInterval??3,d=l.map(t=>Bt(e,n,{url:e.url(O(t)),intervalSec:u,timeoutSec:n.timeout,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}})),f=await Promise.all(d),p=[];for(let e of f){if(e.output.choices){let t=e.output.choices.flatMap(e=>e.message?.content||[]).map(e=>e.image).filter(Boolean);p.push(...t)}if(e.output.results){let t=e.output.results.map(e=>e.url).filter(Boolean);t.length>0&&p.length===0&&p.push(...t)}}if(p.length===0)throw new t(`All tasks completed but no images returned.`,a.GENERAL);await Yr(p,o,n,s)}async function Yr(e,t,n,r){let i=ct(n,{flagDir:t.outDir,subDir:t.outDir?void 0:`images`}),a=t.outPrefix||_e(`edited`,t.prompt),o=await Nt(e.length>1?e.map((e,t)=>({url:e,destPath:F(i,`${a}_${String(t+1).padStart(3,`0`)}.png`)})):[{url:e[0],destPath:F(i,`${a}.png`)}],A,{quiet:n.quiet});n.quiet?j(o.join(`
|
|
26
|
+
`)):M({urls:e,saved:o,total:e.length},r)}var Xr=w({description:`Generate a video from text or image (happyhorse-1.1-t2v / happyhorse-1.1-i2v / wan2.6-t2v)`,auth:`apiKey`,usageArgs:`--prompt <text> [--image <url>] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: happyhorse-1.1-t2v, or happyhorse-1.1-i2v with --image)`},prompt:{type:`string`,valueHint:`<text>`,description:`Video description`,required:!0},image:{type:`string`,valueHint:`<url>`,description:`Input image URL for image-to-video generation`},negativePrompt:{type:`string`,valueHint:`<text>`,description:`Negative prompt to exclude unwanted content`},resolution:{type:`string`,valueHint:`<res>`,description:`Resolution: 720P or 1080P (default: 1080P)`},ratio:{type:`string`,valueHint:`<ratio>`,description:`Aspect ratio (e.g. 16:9, 9:16, 1:1)`},duration:{type:`number`,valueHint:`<seconds>`,description:`Video duration in seconds (default: 5)`},promptExtend:{type:`boolean`,valueHint:`<bool>`,description:wt},watermark:{type:`boolean`,valueHint:`<bool>`,description:Dt},seed:{type:`number`,valueHint:`<n>`,description:`Random seed for reproducible generation`},download:{type:`string`,valueHint:`<path>`,description:`Save video to file on completion`},...e,...n,pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval when waiting (default: 5)`}},exampleArgs:[`--prompt "A person reading a book, static shot"`,`--prompt "Ocean waves at sunset." --download sunset.mp4`,`--image https://example.com/cat.png --prompt "Make the cat in the scene move"`,`--prompt "Mountain landscape" --resolution 720P --duration 5`,`--prompt "A cat playing with a ball" --watermark false`],async run(e){let{settings:n,flags:r}=e,i=r.prompt,o=r.model||(r.image?n.defaultImageToVideoModel||`happyhorse-1.1-i2v`:n.defaultVideoModel||`happyhorse-1.1-t2v`),s=T(n.output),c=r.image,l;c&&(l=await e.client.resolveImageInput(c,o));let u=lt(r.watermark),d=at(r.promptExtend,void 0,`prompt-extend`),f={model:o,input:{prompt:i,negative_prompt:r.negativePrompt||void 0,...l?{media:[{type:`first_frame`,url:l}]}:{}},parameters:{resolution:r.resolution||void 0,ratio:r.ratio||void 0,duration:r.duration||void 0,prompt_extend:d,watermark:u,seed:r.seed}};if(n.dryRun){M({request:l?{...f,input:{...f.input,media:[{type:`first_frame`,url:D(l)}]}}:f},s);return}let p=(await Ut(Lt(r),n,()=>e.client.requestJson({path:xt(),method:`POST`,body:f,async:!0}),`tasks`)).map(e=>e.output.task_id);if(n.quiet||process.stderr.write(`[Model: ${o}]\n`),r.async){M(p.length===1?{task_id:p[0]}:{task_ids:p},s);return}let m=r.pollInterval??5,h=p.map(t=>{let r=e.client.url(O(t));return Bt(e.client,n,{url:r,intervalSec:m,timeoutSec:n.timeout,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}})}),g=await Promise.all(h),_=[];for(let e=0;e<g.length;e++){let t=g[e],n=t.output.video_url||t.output.results&&t.output.results[0]?.url;n&&_.push({taskId:p[e],videoUrl:n})}if(_.length===0)throw new t(`All tasks completed but no video URLs returned.`,a.GENERAL);if(r.download){let e=r.download,{size:t}=await A(_[0].videoUrl,e,{quiet:n.quiet});n.quiet?j(e):M({task_id:_[0].taskId,video_url:_[0].videoUrl,status:`SUCCEEDED`,saved:e,size:It(t)},s);return}let v=ct(n,{subDir:`videos`}),{join:y}=await import(`path`),b=[];await Promise.all(_.map(async({taskId:e,videoUrl:t})=>{let r=y(v,`${e}.mp4`);await A(t,r,{quiet:n.quiet}),b.push({task_id:e,video_url:t,saved:r})})),b.length===1?M(b[0],s):M({videos:b,total:b.length},s)}}),Zr=w({description:`Edit a video with happyhorse-1.0-video-edit (style transfer, object replacement, etc.)`,auth:`apiKey`,usageArgs:`--video <url> --prompt <text> [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: happyhorse-1.0-video-edit)`},video:{type:`string`,valueHint:`<url>`,description:`Input video URL or local file (mp4/mov, 2-10s)`,required:!0},prompt:{type:`string`,valueHint:`<text>`,description:`Edit instruction (e.g. "Convert the scene to a claymation style")`},refImage:{type:`string`,valueHint:`<url>`,description:`Reference image URL (up to 4, comma-separated)`},negativePrompt:{type:`string`,valueHint:`<text>`,description:`Negative prompt to exclude unwanted content`},resolution:{type:`string`,valueHint:`<res>`,description:`Resolution: 720P or 1080P (default: 1080P)`},ratio:{type:`string`,valueHint:`<ratio>`,description:`Aspect ratio (16:9, 9:16, 1:1, 4:3, 3:4)`},duration:{type:`number`,valueHint:`<seconds>`,description:`Output video duration in seconds (2-10)`},audioSetting:{type:`string`,valueHint:`<mode>`,description:`Audio: auto (default) or origin (keep original)`,choices:[`auto`,`origin`]},promptExtend:{type:`boolean`,valueHint:`<bool>`,description:wt},watermark:{type:`boolean`,valueHint:`<bool>`,description:Dt},seed:{type:`number`,valueHint:`<n>`,description:`Random seed for reproducible generation`},download:{type:`string`,valueHint:`<path>`,description:`Save video to file on completion`},...e,...n,pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval when waiting (default: 15)`}},exampleArgs:[`--video https://example.com/input.mp4 --prompt "Convert the entire scene to claymation style"`,`--video https://example.com/input.mp4 --prompt "Replace the outfit with the style shown in the image" --ref-image https://example.com/clothes.png`,`--video https://example.com/input.mp4 --prompt "Convert to anime style" --resolution 720P --download output.mp4`,`--video https://example.com/input.mp4 --prompt "Put clothes on the kitten in the video" --watermark false`],async run(e){let{settings:n,flags:r}=e,i=r.video,o=r.prompt,s=r.model||`happyhorse-1.0-video-edit`,c=T(n.output),l=[{type:`video`,url:await e.client.uploadFile(i,s)}],u=r.refImage;if(u){let t=u.split(`,`).map(e=>e.trim()).filter(Boolean);for(let n of t){let t=await e.client.uploadFile(n,s);l.push({type:`reference_image`,url:t})}}let d=at(r.promptExtend,void 0,`prompt-extend`),f=lt(r.watermark),p={model:s,input:{prompt:o||void 0,negative_prompt:r.negativePrompt||void 0,media:l},parameters:{resolution:r.resolution||void 0,ratio:r.ratio||void 0,duration:r.duration||void 0,audio_setting:r.audioSetting||void 0,prompt_extend:d,watermark:f,seed:r.seed}};if(n.dryRun){M({request:p},c);return}let m=(await Ut(Lt(r),n,()=>e.client.requestJson({path:xt(),method:`POST`,body:p,async:!0}),`tasks`)).map(e=>e.output.task_id);if(n.quiet||(process.stderr.write(`[Model: ${s}]\n`),process.stderr.write(`Note: Video editing typically takes 5-8 minutes. Please be patient.
|
|
27
|
+
`)),r.async){M(m.length===1?{task_id:m[0]}:{task_ids:m},c);return}let h=r.pollInterval??15,g=Math.max(n.timeout,600),_=await Promise.all(m.map(t=>Bt(e.client,n,{url:e.client.url(O(t)),intervalSec:h,timeoutSec:g,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}}))),v=[];for(let e=0;e<_.length;e++){let t=_[e],n=t.output.video_url||t.output.results&&t.output.results[0]?.url;n&&v.push({taskId:m[e],videoUrl:n})}if(v.length===0)throw new t(`All tasks completed but no video URLs returned.`,a.GENERAL);if(r.download){let e=r.download,{size:t}=await A(v[0].videoUrl,e,{quiet:n.quiet});n.quiet?j(e):M({task_id:v[0].taskId,video_url:v[0].videoUrl,status:`SUCCEEDED`,saved:e,size:It(t)},c);return}let y=await import(`path`),b=ct(n,{subDir:`videos`}),x=[];await Promise.all(v.map(async({taskId:e,videoUrl:t})=>{let r=y.join(b,`${e}.mp4`);await A(t,r,{quiet:n.quiet}),x.push({task_id:e,video_url:t,saved:r})})),x.length===1?M(x[0],c):M({videos:x,total:x.length},c)}}),Qr=w({description:`Reference-to-video generation (happyhorse-1.1-r2v / wan2.6-r2v): multi-subject, multi-shot with voice`,auth:`apiKey`,usageArgs:`--prompt <text> --image <url>... [--ref-video <url>...] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: happyhorse-1.1-r2v)`},prompt:{type:`string`,valueHint:`<text>`,description:`Video description with reference markers (image1, video1, etc.)`,required:!0},image:{type:`array`,valueHint:`<url>`,description:`Reference image URL or local file (repeatable for multiple subjects)`},refVideo:{type:`array`,valueHint:`<url>`,description:`Reference video URL or local file (repeatable)`},imageVoice:{type:`array`,valueHint:`<url>`,description:`Voice URL for corresponding image (pairs by position)`},videoVoice:{type:`array`,valueHint:`<url>`,description:`Voice URL for corresponding ref-video (pairs by position)`},resolution:{type:`string`,valueHint:`<res>`,description:`Resolution: 720P or 1080P (default: 1080P)`},ratio:{type:`string`,valueHint:`<ratio>`,description:`Aspect ratio (16:9, 9:16, 1:1)`},duration:{type:`number`,valueHint:`<seconds>`,description:`Video duration in seconds (default: 5)`},promptExtend:{type:`boolean`,valueHint:`<bool>`,description:wt},watermark:{type:`boolean`,valueHint:`<bool>`,description:Dt},seed:{type:`number`,valueHint:`<n>`,description:`Random seed for reproducible generation`},download:{type:`string`,valueHint:`<path>`,description:`Save video to file on completion`},...e,...n,pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval when waiting (default: 15)`}},exampleArgs:[`--prompt "Image1 running on the grass" --image person.jpg`,`--prompt "Video 1 plays guitar, Image 1 walks over" --ref-video scene.mp4 --image person.jpg`,`--prompt "Image 1 speaks" --image person.jpg --image-voice voice.mp3 --resolution 1080P`,`--prompt "Image 1 and Image 2 have a conversation" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3`,`--prompt "Image 1 drinks water" --image person.jpg --watermark false`],validate:e=>!e.image?.length&&!e.refVideo?.length?`Provide at least one --image or --ref-video.`:void 0,async run(e){let{settings:n,flags:r}=e,i=r.prompt,o=r.image||[],s=r.refVideo||[],c=r.imageVoice||[],l=r.videoVoice||[],u=r.model||n.defaultReferenceToVideoModel||`happyhorse-1.1-r2v`,d=T(n.output),f=[];for(let t=0;t<o.length;t++){let n={type:`reference_image`,url:await e.client.resolveImageInput(o[t],u)};c[t]&&(n.reference_voice=await e.client.uploadFile(c[t],u)),f.push(n)}for(let t=0;t<s.length;t++){let n={type:`reference_video`,url:await e.client.uploadFile(s[t],u)};l[t]&&(n.reference_voice=await e.client.uploadFile(l[t],u)),f.push(n)}let p=at(r.promptExtend,void 0,`prompt-extend`),m=lt(r.watermark),h={model:u,input:{prompt:i,media:f},parameters:{resolution:r.resolution||void 0,ratio:r.ratio||void 0,duration:r.duration||void 0,prompt_extend:p,watermark:m,seed:r.seed}};if(n.dryRun){M({request:{...h,input:{...h.input,media:h.input.media.map(e=>({...e,url:D(e.url),reference_voice:e.reference_voice?D(e.reference_voice):void 0}))}}},d);return}let g=(await Ut(Lt(r),n,()=>e.client.requestJson({path:xt(),method:`POST`,body:h,async:!0}),`tasks`)).map(e=>e.output.task_id);if(n.quiet||(process.stderr.write(`[Model: ${u}]\n`),process.stderr.write(`Note: Reference-to-video typically takes 5-10 minutes. Please be patient.
|
|
28
|
+
`)),r.async){M(g.length===1?{task_id:g[0]}:{task_ids:g},d);return}let _=r.pollInterval??15,v=Math.max(n.timeout,600),y=await Promise.all(g.map(t=>Bt(e.client,n,{url:e.client.url(O(t)),intervalSec:_,timeoutSec:v,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>{let t=e.output;return t.message||t.code||void 0}}))),b=[];for(let e=0;e<y.length;e++){let t=y[e],n=t.output.video_url||t.output.results&&t.output.results[0]?.url;n&&b.push({taskId:g[e],videoUrl:n})}if(b.length===0)throw new t(`All tasks completed but no video URLs returned.`,a.GENERAL);if(r.download){let e=r.download,{size:t}=await A(b[0].videoUrl,e,{quiet:n.quiet});n.quiet?j(e):M({task_id:b[0].taskId,video_url:b[0].videoUrl,status:`SUCCEEDED`,saved:e,size:It(t)},d);return}let{join:x}=await import(`path`),S=ct(n,{subDir:`videos`}),C=[];await Promise.all(b.map(async({taskId:e,videoUrl:t})=>{let r=x(S,`${e}.mp4`);await A(t,r,{quiet:n.quiet}),C.push({task_id:e,video_url:t,saved:r})})),C.length===1?M(C[0],d):M({videos:C,total:C.length},d)}}),$r=w({description:`Query async task status`,auth:`apiKey`,usageArgs:`--task-id <id>`,flags:{taskId:{type:`string`,valueHint:`<id>`,description:`Async task ID`,required:!0}},exampleArgs:[`--task-id 3b256896-3e70-xxxx-xxxx-xxxxxxxxxxxx`,`--task-id 3b256896-3e70-xxxx --output json`],async run(e){let{settings:t,flags:n}=e,r=n.taskId,i=T(t.output);if(t.dryRun){M({task_id:r},i);return}let a=await e.client.requestJson({path:O(r)});if(t.quiet){j(a.output.task_status);return}M({task_id:a.output.task_id,task_status:a.output.task_status,video_url:a.output.video_url,results:a.output.results,submit_time:a.output.submit_time,end_time:a.output.end_time},i)}}),ei=w({description:`Download a completed video by task ID`,auth:`apiKey`,usageArgs:`--task-id <id> --out <path>`,flags:{taskId:{type:`string`,valueHint:`<id>`,description:`Task ID to download from`,required:!0},out:{type:`string`,valueHint:`<path>`,description:`Output file path`,required:!0}},exampleArgs:[`--task-id 3b256896-xxxx --out video.mp4`,`--task-id 3b256896-xxxx --out video.mp4 --quiet`],async run(e){let{settings:n,flags:r}=e,i=r.taskId,o=r.out,s=T(n.output);if(n.dryRun){M({task_id:i,action:`download`,out:o},s);return}let c=await e.client.requestJson({path:O(i)});if(c.output.task_status!==`SUCCEEDED`)throw new t(`Task is not complete (status: ${c.output.task_status}).`,a.GENERAL,`Wait for the task to complete before downloading.`);let l=c.output.video_url||c.output.results&&c.output.results[0]?.url;if(!l)throw new t(`No download URL available for this task.`,a.GENERAL);let{size:u}=await A(l,o,{quiet:n.quiet});if(n.quiet){j(o);return}M({saved:o,size:It(u)},s)}});const ti=new Set([`.mp4`,`.mov`,`.avi`,`.mkv`,`.webm`,`.flv`,`.wmv`]);function ni(e){let t=sn(e).toLowerCase().split(`?`)[0];return!!(ti.has(t)||/\.(mp4|mov|avi|mkv|webm|flv|wmv)(\?|$)/i.test(e))}async function ri(e){return e.startsWith(`data:`)||e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`oss://`)?e:Ee(e)}var ii=w({description:`Describe an image or video using Qwen-VL`,auth:`apiKey`,usageArgs:`--image <path-or-url> [--video <url>] [--prompt <text>]`,flags:{image:{type:`string`,valueHint:`<path-or-url>`,description:`Local image path or URL`},video:{type:`array`,valueHint:`<url>`,description:`Video file URL or local path (mp4/mov/avi/mkv/webm)`},prompt:{type:`string`,valueHint:`<text>`,description:`Question about the content (default: auto-detected)`},model:{type:`string`,valueHint:`<model>`,description:`Vision model (default: qwen3-vl-plus)`}},exampleArgs:[`--image photo.jpg`,`--image https://example.com/photo.jpg --prompt "What breed is this dog?"`,`--video https://example.com/video.mp4 --prompt "Summarize the video content"`,`--video ./local-video.mp4`,`--image photo.png --prompt "Extract the text" --model qwen3-vl-plus`],validate:e=>!e.image&&!e.video?.length?`Provide --image or --video.`:void 0,async run(e){let{settings:n,flags:r}=e,i=r.image,o=r.video??[],s=r.model||(e.client.usesTokenPlanEndpoint()?n.defaultTextModel:void 0)||`qwen3-vl-plus`;i&&ni(i)&&(o.push(i),i=void 0);let c=o.length>0?`Describe the video.`:`Describe the image.`,l=r.prompt||c,u=T(n.output);if(n.dryRun){M({request:{prompt:l,image:i?D(i):void 0,video:o.length?o.map(D):void 0,model:s}},u);return}let d=[];if(o.length>0)for(let n of o){let r=n;if(De(n)){if(!Qt(n))throw new t(`Video file not found: ${n}`,a.USAGE);r=await e.client.uploadFile(n,s)}d.push({type:`video_url`,video_url:{url:r}})}if(i){let t=await ri(i),n=t;De(i)&&t.startsWith(`data:`)&&nn(i).size>5*1024*1024&&(n=await e.client.resolveImageInput(i,s)),d.push({type:`image_url`,image_url:{url:n}})}d.push({type:`text`,text:l});let f={model:s,messages:[{role:`user`,content:d}]},p=await e.client.requestJson({path:x(),method:`POST`,body:f}),m=p.choices?.[0]?.message?.content;if(u!==`text`){M(p,u);return}j(m||``)}});const ai=[`base_url`,`output`,`output_dir`,`timeout`,`api_key`,`access_token`,`access_key_id`,`access_key_secret`,`security_token`,`default_text_model`,`default_video_model`,`default_image_to_video_model`,`default_reference_to_video_model`,`default_image_model`,`default_speech_model`,`default_omni_model`,`workspace_id`],oi=new Set([`api_key`,`access_token`,`access_key_id`,`access_key_secret`,`security_token`]),si=[`console_site`,`console_region`,`console_switch_agent`,`telemetry`],ci=[...ai,...si],li={output:[`text`,`json`],console_site:[`domestic`,`international`]},ui=new Set([`telemetry`]),di={default_text_model:`qwen3.8-max`,default_image_model:`qwen-image-2.0`,default_video_model:`happyhorse-1.1-t2v`,default_speech_model:`cosyvoice-v3-flash`,default_omni_model:`qwen3.5-omni-plus`},fi={default_text_model:[{id:`qwen3.8-max`,role:`text/chat default`},{id:`qwen3-coder-plus`,role:`coding-oriented (agent config)`},{id:`qwen-flash`,role:`fast · advisor ranking`},{id:`qwen3.6-flash`,role:`fast · advisor intent`}],default_image_model:[{id:`qwen-image-2.0`,role:`image/generate default · sync`},{id:`qwen-image-max`,role:`image/generate · sync`},{id:`qwen-image-edit-2.0`,role:`image/edit · sync`},{id:`wanx2.x`,role:`image/generate · async series`}],default_video_model:[{id:`happyhorse-1.1-t2v`,role:`video/generate default · text-to-video`},{id:`happyhorse-1.1-i2v`,role:`video/generate · image-to-video`}],default_speech_model:[{id:`cosyvoice-v3-flash`,role:`speech/synthesize (TTS) default`},{id:`fun-asr`,role:`speech/recognize (ASR)`}],default_omni_model:[{id:`qwen3.5-omni-plus`,role:`omni/chat default`},{id:`qwen3-vl-plus`,role:`vision/describe · multimodal input`}]},pi={"base-url":`base_url`,"output-dir":`output_dir`,"api-key":`api_key`,"access-token":`access_token`,"access-key-id":`access_key_id`,"access-key-secret":`access_key_secret`,"security-token":`security_token`,"default-text-model":`default_text_model`,"default-video-model":`default_video_model`,"default-image-to-video-model":`default_image_to_video_model`,"default-reference-to-video-model":`default_reference_to_video_model`,"default-image-model":`default_image_model`,"default-speech-model":`default_speech_model`,"default-omni-model":`default_omni_model`,"workspace-id":`workspace_id`};function mi(e){return pi[e]||e}function hi(e,n){let r=mi(e);if(!ai.includes(r))throw new t(`Invalid config key "${e}". Valid keys: ${ai.join(`, `)}`,a.USAGE);if(r===`output`&&![`text`,`json`].includes(n))throw new t(`Invalid output format "${n}". Valid values: text, json`,a.USAGE);if(r===`timeout`){let e=Number(n);if(isNaN(e)||e<=0)throw new t(`Invalid timeout "${n}". Must be a positive number.`,a.USAGE);return e}return r===`base_url`?qe(n):n}function gi(e,n){let r=mi(e);if(ai.includes(r))return hi(e,n);if(r===`console_site`){if(![`domestic`,`international`].includes(n))throw new t(`Invalid console_site "${n}". Valid values: domestic, international`,a.USAGE);return n}if(r===`console_region`)return n;if(r===`console_switch_agent`){let e=Number(n);if(!Number.isFinite(e)||e<=0)throw new t(`Invalid console_switch_agent "${n}". Must be a positive number.`,a.USAGE);return e}if(r===`telemetry`){if(n!==`true`&&n!==`false`)throw new t(`Invalid telemetry "${n}". Valid values: true, false`,a.USAGE);return n===`true`}throw new t(`Invalid config key "${e}". Valid keys: ${ci.join(`, `)}`,a.USAGE)}var _i=w({description:`Display current configuration`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let{settings:t,client:n}=e,r=e.configStore,i=r.read(),a=T(t.output),o={...i,base_url:n.baseUrl,output:t.output,timeout:t.timeout,config:t.configName??`default`,config_file:r.path};for(let e of oi)typeof o[e]==`string`&&(o[e]=E(o[e]));M(o,a)}}),vi=w({description:`Set a config value`,auth:`none`,usageArgs:`--key <key> --value <value>`,flags:{key:{type:`string`,valueHint:`<key>`,description:`Config key (base_url, output, output_dir, timeout, api_key, access_token, access_key_id, access_key_secret, security_token, default_*_model, workspace_id)`,required:!0},value:{type:`string`,valueHint:`<value>`,description:`Value to set`,required:!0}},exampleArgs:[`--key output --value json`,`--key timeout --value 600`,`--key base_url --value https://dashscope.aliyuncs.com`],async run(e){let{settings:t,flags:n}=e,r=n.key,i=n.value,a=mi(r),o=hi(r,i),s=T(t.output);if(t.dryRun){M({would_set:{[a]:o},config:t.configName??`default`,config_file:e.configStore.path},s);return}if(await e.configStore.write({[a]:o}),!t.quiet){let n=oi.has(a)?E(String(o)):o;M({[a]:n,config:t.configName??`default`,config_file:e.configStore.path},s)}}}),yi=w({description:`List config profiles and show the active profile`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let t=e.configStore.profiles(),n=[`default`,...Object.keys(t.named).sort()],r=T(e.settings.output);if(r===`json`){M({active_config:t.active,profiles:n,config_file:e.configStore.path},r);return}let i=Math.max(4,...n.map(e=>e.length));j(`${`NAME`.padEnd(i)} ACTIVE`);for(let e of n)j(`${e.padEnd(i)} ${e===t.active?`*`:``}`)}}),bi=w({description:`Set the active config profile`,auth:`none`,usageArgs:`--name <name>`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Existing profile name, or default`,required:!0}},exampleArgs:[`--name token-plan`,`--name default`],async run(e){let t=T(e.settings.output);if(e.settings.dryRun){M({would_activate:e.configStore.validateActivation(e.flags.name),config_file:e.configStore.path},t);return}let n=await e.configStore.activate(e.flags.name);e.settings.quiet||M({active_config:n,config_file:e.configStore.path},t)}});function V(e){try{return un(e,`utf-8`)}catch{return}}function H(e){let t=V(e);if(t!==void 0)try{let e=JSON.parse(t);return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}catch{return}}function U(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:void 0}function xi(e){let t=/^---\s*\n([\s\S]*?)\n---/.exec(e);if(!t)return{};try{return U(xn.parse(t[1]))??{}}catch{return{}}}function Si(e,t=500){let n=0,r=e=>{if(n>=t)return;let i;try{i=dn(e,{withFileTypes:!0})}catch{return}for(let a of i){if(n>=t)return;let i=L(e,a.name);a.isDirectory()?r(i):n+=1}};return r(e),n}function Ci(e){return[{source:`global`,dir:L(e,`.agents`,`skills`)},{source:`claude-code`,dir:L(e,`.claude`,`skills`)},{source:`cursor`,dir:L(e,`.cursor`,`skills`)},{source:`qwen-code`,dir:L(e,`.qwen`,`skills`)},{source:`codex`,dir:L(e,`.codex`,`skills`)},{source:`opencode`,dir:L(e,`.config`,`opencode`,`skills`)},{source:`openclaw`,dir:L(e,`.openclaw`,`skills`)},{source:`openclaw`,dir:L(e,`.openclaw`,`workspace`,`skills`)},{source:`hermes`,dir:L(e,`.hermes`,`skills`)},{source:`gemini`,dir:L(e,`.gemini`,`skills`)},{source:`antigravity`,dir:L(e,`.gemini`,`antigravity`,`skills`)},{source:`windsurf`,dir:L(e,`.windsurf`,`skills`)},{source:`windsurf`,dir:L(e,`.codeium`,`windsurf`,`skills`)},{source:`qoderwork`,dir:L(e,`.qoderwork`,`skills`)},{source:`workbuddy`,dir:L(e,`.workbuddy`,`skills`)}]}function wi(e=z()){let t=new Map;for(let{source:n,dir:r}of Ci(e)){let e;try{e=dn(r,{withFileTypes:!0})}catch{continue}for(let i of e){if(!i.isDirectory()&&!i.isSymbolicLink())continue;let e=L(r,i.name),a=L(e,`SKILL.md`);if(!I(a))continue;let o=t.get(i.name);if(o){o.sources.includes(n)||o.sources.push(n);continue}let s=xi(V(a)??``),c=U(s.metadata),l=typeof s.description==`string`?s.description.trim():``,u=c&&typeof c.version==`string`?c.version:typeof s.version==`string`?s.version:void 0;t.set(i.name,{id:i.name,name:typeof s.name==`string`&&s.name?s.name:i.name,description:l,version:u,fileCount:Si(e),path:e,sources:[n],origin:`local`})}}return[...t.values()].sort((e,t)=>e.name.localeCompare(t.name))}function Ti(e,t=z()){let n=wi(t).find(t=>t.id===e);if(!n)return null;let r=V(L(n.path,`SKILL.md`))??``;return{...n,content:r}}const Ei=[{source:`global`,label:`All agents (~/.agents/skills)`,sub:[`.agents`,`skills`]},{source:`claude-code`,label:`Claude Code`,sub:[`.claude`,`skills`]},{source:`qwen-code`,label:`Qwen Code`,sub:[`.qwen`,`skills`]},{source:`codex`,label:`Codex`,sub:[`.codex`,`skills`]},{source:`opencode`,label:`OpenCode`,sub:[`.config`,`opencode`,`skills`]},{source:`openclaw`,label:`OpenClaw`,sub:[`.openclaw`,`skills`]},{source:`qoderwork`,label:`QoderWork`,sub:[`.qoderwork`,`skills`]},{source:`windsurf`,label:`Windsurf`,sub:[`.codeium`,`windsurf`,`skills`]},{source:`gemini`,label:`Gemini`,sub:[`.gemini`,`skills`]}];function Di(e,t){let n=Ei.find(t=>t.source===e);return n?L(t,...n.sub):null}function Oi(e){let t=-1,n=Math.max(0,e.length-22-65535);for(let r=e.length-22;r>=n;r--)if(e.readUInt32LE(r)===101010256){t=r;break}if(t<0)throw Error(`Not a valid .zip archive.`);let r=e.readUInt16LE(t+10),i=e.readUInt32LE(t+16),a=[];for(let t=0;t<r&&!(i+46>e.length||e.readUInt32LE(i)!==33639248);t++){let t=e.readUInt16LE(i+10),n=e.readUInt32LE(i+20),r=e.readUInt16LE(i+28),o=e.readUInt16LE(i+30),s=e.readUInt16LE(i+32),c=e.readUInt32LE(i+42),l=e.toString(`utf8`,i+46,i+46+r);if(i+=46+r+o+s,l.endsWith(`/`)||c+30>e.length||e.readUInt32LE(c)!==67324752)continue;let u=e.readUInt16LE(c+26),d=e.readUInt16LE(c+28),f=c+30+u+d,p=e.subarray(f,f+n),m;if(t===0)m=Buffer.from(p);else if(t===8)m=bn(p);else throw Error(`Unsupported compression in archive (entry: `+l+`).`);a.push({name:l,data:m})}return a}function ki(e,t,n,r=z()){let i=Di(e,r);if(!i)throw Error(`Unknown skill install target.`);let a=Oi(t).map(e=>({name:e.name.replace(/\\/g,`/`).replace(/^\.\//,``).replace(/^\/+/,``),data:e.data})).filter(e=>e.name&&!e.name.endsWith(`/`)&&!e.name.split(`/`).includes(`..`));if(!a.length)throw Error(`The archive contains no usable files.`);let o=a.find(e=>e.name===`SKILL.md`||e.name.endsWith(`/SKILL.md`));if(!o)throw Error(`No SKILL.md found in the archive (root or a top-level folder).`);let s=o.name.lastIndexOf(`/`),c,l;if(s<0){if(c=(n||``).trim(),!c)throw Error(`SKILL.md is at the archive root — please provide a skill name.`);l=``}else l=o.name.slice(0,s+1),c=(n||``).trim()||l.split(`/`)[0];if(!/^[A-Za-z0-9._-]+$/.test(c))throw Error(`Invalid skill name: `+c);let u=L(i,c),d=R(u),f=0;for(let e of a){let t=e.name;if(l){if(!e.name.startsWith(l))continue;t=e.name.slice(l.length)}if(!t)continue;let n=R(L(u,t));n!==d&&!n.startsWith(d+yn)||(ln(gn(n),{recursive:!0}),mn(n,e.data),f++)}if(f===0)throw Error(`Nothing was extracted from the archive.`);return{installed:c,files:f,dir:u}}function Ai(e){if(typeof e.command==`string`){let t=Array.isArray(e.args)?e.args.join(` `):``;return{transport:`stdio`,detail:`${e.command} ${t}`.trim()}}let t=typeof e.url==`string`?e.url:void 0;return t?{transport:(typeof e.type==`string`?e.type.toLowerCase():``)===`sse`?`sse`:`http`,detail:t}:{transport:`unknown`,detail:``}}function W(e,t,n,r,i){let a=U(e);if(a)for(let[e,o]of Object.entries(a)){let a=U(o)??{},{transport:s,detail:c}=Ai(a);r.push({name:e,source:t,transport:s,detail:c,scope:n,origin:`local`,config:Hi(a),editable:i})}}function ji(e=z()){let t=[],n=H(L(e,`.claude.json`));if(n){W(n.mcpServers,`claude-code`,`global`,t,!0);let e=U(n.projects);if(e)for(let[n,r]of Object.entries(e)){let e=U(r);e?.mcpServers&&W(e.mcpServers,`claude-code`,n,t,!0)}}let r=H(L(e,`.qwen`,`settings.json`));r&&W(r.mcpServers,`qwen-code`,`global`,t,!0);let i=H(L(e,`.config`,`opencode`,`opencode.json`));i&&W(i.mcp,`opencode`,`global`,t,!0);let a=H(L(e,`.cursor`,`mcp.json`));a&&W(a.mcpServers,`cursor`,`global`,t,!0);let o=H(L(e,`.codeium`,`windsurf`,`mcp_config.json`));o&&W(o.mcpServers,`windsurf`,`global`,t,!0);let s=H(L(e,`.gemini`,`settings.json`));s&&W(s.mcpServers,`gemini`,`global`,t,!0);let c=H(L(e,`.qoderwork`,`mcp.json`));c&&W(c.mcpServers,`qoderwork`,`global`,t,!0);let l=H(L(e,`.openclaw`,`openclaw.json`));l&&W(l.mcpServers,`openclaw`,`global`,t,!0);let u=H(Mi(e));u&&W(u.mcpServers,`claude-desktop`,`global`,t,!0);let d=V(L(e,`.codex`,`config.toml`));if(d)try{W(Sn(d).mcp_servers,`codex`,`global`,t,!1)}catch{}return t.sort((e,t)=>e.name.localeCompare(t.name)||e.source.localeCompare(t.source))}function Mi(e){return process.platform===`darwin`?L(e,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`):process.platform===`win32`?L(process.env.APPDATA??L(e,`AppData`,`Roaming`),`Claude`,`claude_desktop_config.json`):L(e,`.config`,`Claude`,`claude_desktop_config.json`)}function Ni(e,t,n){return e===`claude-code`?{file:L(n,`.claude.json`),mapKey:`mcpServers`,projectScoped:t!==`global`}:e===`qwen-code`?{file:L(n,`.qwen`,`settings.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`opencode`?{file:L(n,`.config`,`opencode`,`opencode.json`),mapKey:`mcp`,projectScoped:!1}:e===`cursor`?{file:L(n,`.cursor`,`mcp.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`windsurf`?{file:L(n,`.codeium`,`windsurf`,`mcp_config.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`gemini`?{file:L(n,`.gemini`,`settings.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`qoderwork`?{file:L(n,`.qoderwork`,`mcp.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`openclaw`?{file:L(n,`.openclaw`,`openclaw.json`),mapKey:`mcpServers`,projectScoped:!1}:e===`claude-desktop`?{file:Mi(n),mapKey:`mcpServers`,projectScoped:!1}:null}function Pi(e,t){if(typeof e==`string`){if(e.includes(`•`)){if(typeof t==`string`)return t;throw Error(`Replace masked values (•••) with the real value before saving.`)}return e}if(Array.isArray(e)){let n=Array.isArray(t)?t:[];return e.map((e,t)=>Pi(e,n[t]))}let n=U(e);if(n){let e=U(t)??{},r={};for(let[t,i]of Object.entries(n))r[t]=Pi(i,e[t]);return r}return e}function Fi(e,t,n,r,i=z()){let a=Ni(e,t,i);if(!a)throw Error(`This MCP source is read-only and cannot be edited here.`);let o=n.trim();if(!o)throw Error(`Server name is required.`);let s=U(r);if(!s)throw Error(`Config must be a JSON object.`);let c=H(a.file)??{},l=c;if(a.projectScoped){let e=U(c.projects)??{};c.projects=e;let n=U(e[t])??{};e[t]=n,l=n}let u=U(l[a.mapKey])??{};l[a.mapKey]=u,u[o]=Pi(s,U(u[o])),ln(gn(a.file),{recursive:!0}),mn(a.file,JSON.stringify(c,null,2)+`
|
|
29
|
+
`,`utf-8`)}function Ii(e,t,n,r=z()){let i=Ni(e,t,r);if(!i)throw Error(`This MCP source is read-only and cannot be edited here.`);let a=H(i.file);if(!a)throw Error(`Config file not found.`);let o=a;if(i.projectScoped){let e=U(a.projects);o=e?U(e[t]):void 0}let s=o?U(o[i.mapKey]):void 0;if(!s||!(n in s))throw Error(`Server not found: `+n);delete s[n],o&&Object.keys(s).length===0&&delete o[i.mapKey],mn(i.file,JSON.stringify(a,null,2)+`
|
|
30
|
+
`,`utf-8`)}const Li=[{id:`claude-code`,label:`Claude Code`,paths:e=>[L(process.env.CLAUDE_CONFIG_DIR||L(e,`.claude`),`settings.json`),L(e,`.claude.json`)],detect:e=>{let t=U(H(L(process.env.CLAUDE_CONFIG_DIR||L(e,`.claude`),`settings.json`))?.env),n=t&&typeof t.ANTHROPIC_BASE_URL==`string`?t.ANTHROPIC_BASE_URL:void 0,r=t&&typeof t.ANTHROPIC_MODEL==`string`?t.ANTHROPIC_MODEL:void 0;return{configured:!!n,model:r}}},{id:`qwen-code`,label:`Qwen Code`,paths:e=>[L(e,`.qwen`,`settings.json`)],detect:e=>{let t=H(L(e,`.qwen`,`settings.json`)),n=U(t?.modelProviders),r=n?Object.values(n).some(e=>Array.isArray(e)&&e.some(e=>{let t=U(e)?.name;return typeof t==`string`&&(t===`bailian-cli`||t.startsWith(`[Bailian]`))})):!1,i=U(t?.model);return{configured:r,model:i&&typeof i.name==`string`?i.name:void 0}}},{id:`opencode`,label:`OpenCode`,paths:e=>[L(e,`.config`,`opencode`,`opencode.json`)],detect:e=>{let t=U(U(H(L(e,`.config`,`opencode`,`opencode.json`))?.provider)?.[`bailian-cli`]),n=U(t?.models);return{configured:!!t,model:n?Object.keys(n)[0]:void 0}}},{id:`openclaw`,label:`OpenClaw`,paths:e=>[L(e,`.openclaw`,`openclaw.json`)],detect:e=>{let t=U(U(U(H(L(e,`.openclaw`,`openclaw.json`))?.models)?.providers)?.[`bailian-cli`]),n=U((Array.isArray(t?.models)?t.models:[])[0]);return{configured:!!t,model:n&&typeof n.id==`string`?n.id:void 0}}},{id:`hermes`,label:`Hermes Agent`,paths:e=>[L(e,`.hermes`,`config.yaml`)],detect:e=>{let t=V(L(e,`.hermes`,`config.yaml`));if(!t)return{configured:!1};let n;try{n=U(xn.parse(t))}catch{return{configured:!1}}let r=(Array.isArray(n?.custom_providers)?n.custom_providers:[]).some(e=>U(e)?.name===`bailian-cli`),i=U(n?.model),a=!!(i&&i.provider===`custom`&&typeof i.base_url==`string`&&i.base_url.includes(`aliyuncs.com`));return{configured:r||a,model:i&&typeof i.default==`string`?i.default:void 0}}},{id:`codex`,label:`Codex`,paths:e=>[L(e,`.codex`,`config.toml`),L(e,`.codex`,`auth.json`)],detect:e=>{let t=V(L(e,`.codex`,`config.toml`));if(!t)return{configured:!1};let n={};try{n=Sn(t)}catch{return{configured:!1}}return{configured:!!U(n.model_providers)?.[`bailian-cli`],model:typeof n.model==`string`?n.model:void 0}}}];function Ri(e=z()){return Li.map(t=>{let n=t.paths(e),r=n.some(e=>I(e)),{configured:i,model:a}=r?t.detect(e):{configured:!1,model:void 0};return{id:t.id,label:t.label,installed:r,configured:i,model:a,paths:n,origin:`local`}})}function G(e,t,n,r=!1){typeof n==`string`&&n.trim()&&e.push({label:t,value:n.trim(),secret:r})}function zi(e,t){let n=[];if(e===`claude-code`){let e=U(H(L(t,`.claude`,`settings.json`))?.env);G(n,`Model`,e?.ANTHROPIC_MODEL),G(n,`Base URL`,e?.ANTHROPIC_BASE_URL),G(n,`Auth Token`,e?.ANTHROPIC_AUTH_TOKEN,!0)}else if(e===`qwen-code`){let e=H(L(t,`.qwen`,`settings.json`)),r=U(e?.model),i=U(U(e?.security)?.auth),a=U(e?.env);G(n,`Model`,r?.name),G(n,`Base URL`,i?.baseUrl??r?.baseUrl),G(n,`Protocol`,i?.selectedType),G(n,`API Key`,i?.apiKey??a?.BAILIAN_CLI_API_KEY,!0)}else if(e===`opencode`){let e=U(U(H(L(t,`.config`,`opencode`,`opencode.json`))?.provider)?.[`bailian-cli`]),r=U(e?.options),i=U(e?.models);G(n,`Model`,i?Object.keys(i)[0]:void 0),G(n,`Base URL`,r?.baseURL),G(n,`Provider`,e?.npm),G(n,`API Key`,r?.apiKey,!0)}else if(e===`openclaw`){let e=U(U(U(H(L(t,`.openclaw`,`openclaw.json`))?.models)?.providers)?.[`bailian-cli`]);G(n,`Model`,U((Array.isArray(e?.models)?e.models:[])[0])?.id),G(n,`Base URL`,e?.baseUrl),G(n,`API`,e?.api),G(n,`API Key`,e?.apiKey,!0)}else if(e===`hermes`){let e=V(L(t,`.hermes`,`config.yaml`)),r;if(e)try{r=U(xn.parse(e))}catch{r=void 0}let i=U((Array.isArray(r?.custom_providers)?r.custom_providers:[]).find(e=>U(e)?.name===`bailian-cli`));G(n,`Model`,U((Array.isArray(i?.models)?i.models:[])[0])?.id??U(r?.model)?.default),G(n,`Base URL`,i?.base_url),G(n,`API Mode`,i?.api_mode),G(n,`API Key`,i?.api_key,!0)}else if(e===`codex`){let e=V(L(t,`.codex`,`config.toml`)),r={};if(e)try{r=Sn(e)}catch{r={}}let i=U(U(r.model_providers)?.[`bailian-cli`]),a=H(L(t,`.codex`,`auth.json`));G(n,`Model`,r.model),G(n,`Base URL`,i?.base_url),G(n,`Wire API`,i?.wire_api),G(n,`API Key`,a?.OPENAI_API_KEY,!0)}return n}function Bi(e){let t=e.trim();return t.length<=8?`•`.repeat(Math.max(t.length,4)):t.slice(0,3)+`•`.repeat(Math.min(t.length-3,16))}const Vi=/key|token|secret|password|passwd|auth|credential/i;function Hi(e,t=``){if(typeof e==`string`)return t&&Vi.test(t)&&e.trim()?Bi(e):e;if(Array.isArray(e))return e.map(e=>Hi(e));let n=U(e);if(n){let e={};for(let[t,r]of Object.entries(n))e[t]=Hi(r,t);return e}return e}function Ui(e){return e.endsWith(`.json`)?`json`:e.endsWith(`.yaml`)||e.endsWith(`.yml`)?`yaml`:e.endsWith(`.toml`)?`toml`:`text`}function Wi(e,t=z()){let n=Li.find(t=>t.id===e);if(!n)return null;let r=n.paths(t),i=r.some(e=>I(e)),{configured:a,model:o}=i?n.detect(t):{configured:!1,model:void 0},s=i?zi(e,t).map(e=>e.secret?{...e,raw:e.value,value:Bi(e.value)}:e):[],c=r.map(e=>({path:e,exists:I(e)})),l=i?r.filter(e=>I(e)).map(e=>({path:e,lang:Ui(e),text:V(e)??``})).filter(e=>e.text.trim()):[];return{id:n.id,label:n.label,installed:i,configured:a,model:o,paths:r,origin:`local`,fields:s,files:c,settings:l}}const Gi={"claude-code":`claude`,"qwen-code":`qwen`,opencode:`opencode`,openclaw:`openclaw`,hermes:`hermes`,codex:`codex`};function Ki(e){return Object.prototype.hasOwnProperty.call(Gi,e)?Gi[e]:void 0}const qi={"qwen-code":e=>[`-i`,e],"claude-code":e=>[e],codex:e=>[e]};function Ji(e){return Object.prototype.hasOwnProperty.call(qi,e)}function Yi(e){let t=process.platform===`win32`?`where`:`which`;return new Promise(n=>{Yt(t,[e],{windowsHide:!0},e=>n(!e))})}function Xi(e){let t=Ki(e);return t?Yi(t):Promise.resolve(!1)}function Zi(e){return`'${e.replace(/'/g,`'\\''`)}'`}function Qi(e,t){let n=process.platform;return new Promise((r,i)=>{if(n===`darwin`){Yt(`osascript`,[`-e`,`tell application "Terminal" to do script "${`cd ${Zi(t)} && ${e}`.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`,`-e`,`tell application "Terminal" to activate`],{windowsHide:!0},e=>e?i(e):r());return}if(n===`win32`){Yt(`cmd`,[`/c`,`start`,``,`cmd`,`/k`,`cd /d ${t} && ${e}`],{windowsHide:!0},e=>e?i(e):r());return}Yt(`x-terminal-emulator`,[`-e`,`bash`,`-lc`,`cd ${Zi(t)} && ${e}; exec $SHELL`],{windowsHide:!0},e=>e?i(Error(`No supported terminal emulator was found`)):r())})}async function $i(e,t=process.cwd(),n){let r=Ki(e);if(!r)throw Error(`Unknown agent: ${e}`);if(!await Yi(r))throw Error(`\`${r}\` was not found on your PATH — install ${e} first.`);let i=r,a=(n??``).trim();if(a){let t=qi[e];if(!t)throw Error(`${e} does not support dispatching a task prompt.`);i=[r,...t(a).map(Zi)].join(` `)}return await Qi(i,t),{launched:!0,command:i}}const ea=[{id:`image-generate`,title:`文生图`,description:`一键生成一张示例图片并保存到输出目录。`,category:`图像`,prompt:"请使用 bl 的图像生成能力(如 `bl image generate` 命令)生成一张示例图片:一只在雨中撑伞的柯基,水彩风格,光线柔和。保存到输出目录后告诉我文件路径。"},{id:`image-describe`,title:`图片理解`,description:`从输出目录任选一张图片,详细描述内容与风格。`,category:`图像`,prompt:`请在输出目录(默认 output/images)中任选一张图片,用中文详细描述它的内容、主体、构图、色彩与风格,并推测它适合的使用场景。若目录为空请说明。`},{id:`image-alt-batch`,title:`批量 Alt 文本`,description:`为输出目录下的图片批量生成无障碍 alt 文本。`,category:`图像`,prompt:`请扫描输出目录(默认 output/images)下的所有图片,逐张生成简洁、准确的 alt 无障碍描述,最后以「文件名 → alt 文本」的表格汇总。若目录为空请说明。`},{id:`image-to-code`,title:`截图转代码`,description:`把输出目录里的界面截图还原成 HTML+CSS。`,category:`图像`,prompt:`请在输出目录(默认 output/images)中查找一张界面截图,用 HTML + CSS 尽可能还原它的布局、间距与配色,输出为一个可直接在浏览器打开的单文件,并简述还原思路。若没有找到截图请说明。`},{id:`speech-generate`,title:`文字转语音`,description:`把一句示例文字合成为自然语音。`,category:`音频`,prompt:"请使用 bl 的语音合成能力(如 `bl speech` 相关命令)把下面这句话合成为自然语音,保存到输出目录,并告诉我音频文件路径:欢迎使用阿里云百炼命令行工具,让多模态创作更简单。"},{id:`audio-summarize`,title:`音频转写总结`,description:`转写输出目录里的音频并提炼要点。`,category:`音频`,prompt:`请在输出目录(默认 output/speech)中找到一个音频文件,转写其内容,先给出完整文字,再用要点列表总结关键信息。若目录为空或缺少转写能力,请说明并尝试用可用的能力完成。`},{id:`video-generate`,title:`文生视频`,description:`一键生成一段示例短视频。`,category:`视频`,prompt:"请使用 bl 的视频生成能力(如 `bl video generate` 命令)生成一段示例短视频:日落时分海边奔跑的少年,电影质感,慢动作。保存到输出目录后告诉我视频文件路径。"},{id:`video-storyboard`,title:`视频分镜脚本`,description:`围绕示例主题产出可用于文生视频的分镜。`,category:`视频`,prompt:`围绕主题「城市清晨的第一杯咖啡」,为一支 15-30 秒的短视频撰写分镜脚本:逐镜头给出画面描述、时长、字幕或旁白,并为每个镜头附上可直接用于文生视频的英文 prompt。`},{id:`media-prompt-craft`,title:`多模态提示词`,description:`把一个示例创意扩展成图/视频/语音提示词。`,category:`多模态`,prompt:`把创意「未来赛博城市的夜市」扩展成三组高质量生成提示词:1) 文生图;2) 文生视频;3) 语音风格描述。每组给出中英对照,并简要说明关键参数建议。`},{id:`image-story-narration`,title:`图片配音文案`,description:`为输出目录里的图片写解说词并给出可合成文本。`,category:`多模态`,prompt:`请在输出目录(默认 output/images)中任选一张图片,为它撰写一段 60 秒左右的中文解说词(适合配音),语气生动。随后给出可直接用于语音合成的纯文本版本。若目录为空请说明。`},{id:`summarize-project`,title:`总结当前项目`,description:`让 agent 阅读当前目录,总结架构、技术栈与主要模块。`,category:`代码`,prompt:`请阅读当前工作目录的项目结构和关键源码,用简洁的中文总结:1) 它是做什么的;2) 技术栈;3) 主要模块及其职责;4) 值得注意的设计。先浏览再下结论,不要臆测。`},{id:`write-tests`,title:`为核心模块写单测`,description:`自动挑选缺测试的核心模块并补全单元测试。`,category:`代码`,prompt:`请在当前项目中挑选一个核心且缺少测试(或测试薄弱)的模块,为它编写全面的单元测试,覆盖主要逻辑分支和边界情况,并遵循本项目现有的测试框架与风格。先阅读相关文件及其依赖,再编写测试。`},{id:`code-review`,title:`代码审查`,description:`审查当前项目核心代码,指出问题与改进建议。`,category:`代码`,prompt:`请审查当前项目的核心源码,指出潜在的 bug、安全隐患、性能与可维护性问题,并给出具体、可操作的改进建议,按严重程度排序。先浏览项目结构,选取关键文件再审查。`},{id:`explain-code`,title:`解释核心代码`,description:`挑选入口或核心模块,解释其实现与依赖。`,category:`代码`,prompt:`请挑选当前项目的入口文件或核心模块,解释它的实现:职责是什么、关键流程如何运转、依赖了哪些模块。用清晰的中文说明,必要时给出调用关系。`},{id:`generate-readme`,title:`生成 README`,description:`阅读代码后生成结构清晰、与实现一致的 README.md。`,category:`文档`,prompt:`为当前工作目录的项目生成一个结构清晰的 README.md,包含:项目简介、安装步骤、使用示例、目录结构说明。请先阅读现有代码与配置再撰写,内容必须与实际实现一致。`}];function ta(e){return ea.find(t=>t.id===e)}function na(e,t){return e.prompt.replace(/\{\{(\w+)\}\}/g,(e,n)=>{let r=t[n];return typeof r==`string`?r.trim():``})}const ra=new Uint8Array(512),ia=new Uint8Array(256);(()=>{let e=1;for(let t=0;t<255;t++)ra[t]=e,ia[e]=t,e<<=1,e&256&&(e^=285);for(let e=255;e<512;e++)ra[e]=ra[e-255]})();function aa(e,t){return e===0||t===0?0:ra[ia[e]+ia[t]]}function oa(e){let t=[1];for(let n=0;n<e;n++){let e=Array.from({length:t.length+1},()=>0);for(let r=0;r<t.length;r++)e[r]^=t[r],e[r+1]^=aa(t[r],ra[n]);t=e}return t.map(e=>ia[e])}function sa(e,t){let n=oa(t),r=new Uint8Array(e.length+t);r.set(e,0);for(let t=0;t<e.length;t++){let e=r[t];if(e!==0){let i=ia[e];for(let e=0;e<n.length;e++)r[t+e]^=ra[(n[e]+i)%255]}}return Array.from(r.slice(e.length))}const ca=[[19,7],[34,10],[55,15],[80,20],[108,26]];function la(e){let t=12+e*8;for(let e=0;e<ca.length;e++)if(ca[e][0]*8>=t)return e+1;throw Error(`qr: data too large for supported versions (max 108 bytes)`)}function ua(e,t){let[n]=ca[t-1],r=[],i=(e,t)=>{for(let n=t-1;n>=0;n--)r.push(e>>n&1)};i(4,4),i(e.length,8);for(let t of e)i(t,8);let a=n*8;for(i(0,Math.min(4,a-r.length));r.length%8!=0;)r.push(0);let o=[];for(let e=0;e<r.length;e+=8){let t=0;for(let n=0;n<8;n++)t=t<<1|r[e+n];o.push(t)}let s=[236,17];for(let e=0;o.length<n;e++)o.push(s[e%2]);return o.concat(sa(o,ca[t-1][1]))}function da(e){return{size:e,mod:new Uint8Array(e*e),fn:new Uint8Array(e*e)}}function fa(e,t,n,r){e.mod[t*e.size+n]=r,e.fn[t*e.size+n]=1}function pa(e,t,n){for(let r=-1;r<=7;r++)for(let i=-1;i<=7;i++){let a=t+r,o=n+i;a<0||a>=e.size||o<0||o>=e.size||fa(e,a,o,+(r>=0&&r<=6&&i>=0&&i<=6&&(r===0||r===6||i===0||i===6||r>=2&&r<=4&&i>=2&&i<=4)))}}function ma(e,t,n){for(let r=-2;r<=2;r++)for(let i=-2;i<=2;i++){let a=Math.max(Math.abs(r),Math.abs(i));fa(e,t+r,n+i,a===1?0:1)}}function ha(e,t){let n=e.size;for(let t=0;t<n;t++)fa(e,6,t,+(t%2==0)),fa(e,t,6,+(t%2==0));if(pa(e,0,0),pa(e,0,n-7),pa(e,n-7,0),t>=2){let t=n-7;ma(e,t,t)}for(let t=0;t<9;t++)t!==6&&(e.fn[8*n+t]=1),t!==6&&(e.fn[t*n+8]=1);e.fn[8*n+6]=1,e.fn[6*n+8]=1;for(let t=0;t<8;t++)e.fn[(n-1-t)*n+8]=1;for(let t=0;t<8;t++)e.fn[8*n+(n-1-t)]=1;fa(e,n-8,8,1)}function ga(e,t){let n=e.size,r=[];for(let e of t)for(let t=7;t>=0;t--)r.push(e>>t&1);let i=0,a=!0;for(let t=n-1;t>=1;t-=2){t===6&&(t=5);for(let o=0;o<n;o++){let s=a?n-1-o:o;for(let a of[0,1]){let o=t-a;e.fn[s*n+o]||(e.mod[s*n+o]=i<r.length?r[i++]:0)}}a=!a}}const _a=[(e,t)=>(e+t)%2==0,e=>e%2==0,(e,t)=>t%3==0,(e,t)=>(e+t)%3==0,(e,t)=>(Math.floor(e/2)+Math.floor(t/3))%2==0,(e,t)=>e*t%2+e*t%3==0,(e,t)=>(e*t%2+e*t%3)%2==0,(e,t)=>((e+t)%2+e*t%3)%2==0];function va(e,t){let n=_a[t];for(let t=0;t<e.size;t++)for(let r=0;r<e.size;r++)!e.fn[t*e.size+r]&&n(t,r)&&(e.mod[t*e.size+r]^=1)}function ya(e){let t=e.size,n=(n,r)=>e.mod[n*t+r],r=0;for(let e=0;e<t;e++){let i=1,a=1;for(let o=1;o<t;o++)n(e,o)===n(e,o-1)?i++:(i>=5&&(r+=i-2),i=1),n(o,e)===n(o-1,e)?a++:(a>=5&&(r+=a-2),a=1);i>=5&&(r+=i-2),a>=5&&(r+=a-2)}for(let e=0;e<t-1;e++)for(let i=0;i<t-1;i++){let t=n(e,i);t===n(e,i+1)&&t===n(e+1,i)&&t===n(e+1,i+1)&&(r+=3)}let i=[1,0,1,1,1,0,1,0,0,0,0],a=[0,0,0,0,1,0,1,1,1,0,1],o=(e,t,n)=>{for(let r=0;r<n.length;r++)if(e(t+r)!==n[r])return!1;return!0};for(let e=0;e<t;e++)for(let s=0;s<=t-11;s++)(o(t=>n(e,t),s,i)||o(t=>n(e,t),s,a))&&(r+=40),(o(t=>n(t,e),s,i)||o(t=>n(t,e),s,a))&&(r+=40);let s=0;for(let n=0;n<t*t;n++)s+=e.mod[n];let c=s*100/(t*t),l=Math.floor(Math.abs(c-50)/5);return r+=l*10,r}function ba(e){let t=8|e,n=t<<10;for(let e=14;e>=10;e--)n>>e&1&&(n^=1335<<e-10);return(t<<10|n)^21522}function xa(e,t){let n=e.size,r=ba(t),i=e=>r>>e&1;for(let t=0;t<=5;t++)e.mod[t*n+8]=i(t);e.mod[7*n+8]=i(6),e.mod[8*n+8]=i(7),e.mod[8*n+7]=i(8);for(let t=9;t<15;t++)e.mod[8*n+(14-t)]=i(t);for(let t=0;t<8;t++)e.mod[(n-1-t)*n+8]=i(t);for(let t=8;t<15;t++)e.mod[8*n+(n-15+t)]=i(t);e.mod[(n-8)*n+8]=1}function Sa(e){let t=new TextEncoder().encode(e),n=la(t.length),r=ua(t,n),i=da(17+4*n);ha(i,n),ga(i,r);let a=0,o=1/0;for(let e=0;e<8;e++){va(i,e),xa(i,e);let t=ya(i);t<o&&(o=t,a=e),va(i,e)}va(i,a),xa(i,a);let s=[];for(let e=0;e<i.size;e++){let t=[];for(let n=0;n<i.size;n++)t.push(i.mod[e*i.size+n]===1);s.push(t)}return s}function Ca(e){let t=Sa(e),n=t.length,r=n+8,i=``;for(let e=0;e<n;e++)for(let r=0;r<n;r++)t[e][r]&&(i+=`<rect x="${r+4}" y="${e+4}" width="1" height="1"/>`);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${r} ${r}" shape-rendering="crispEdges" role="img" aria-label="QR code"><rect width="${r}" height="${r}" fill="#ffffff"/><g fill="#000000">${i}</g></svg>`}function wa(e){let{identity:t,settings:n,authStore:r}=e;return{status(){let e=r.describe(),t={apiKey:!!e.apiKey,console:!!e.console,openapi:!!e.openapi},n;e.console?n=E(e.console.token):e.apiKey?n=E(e.apiKey.token):e.openapi&&(n=E(e.openapi.accessKeyId));let i=e.console?`console`:e.apiKey?`apiKey`:e.openapi?`openapi`:null;return{authenticated:t.apiKey||t.console||t.openapi,methods:t,primary:i,region:e.console?.region,site:e.console?.site,masked:n}},startConsoleLogin(){let e=dr(r.describe().console?.site),i=!!r.stored().apiKey;Er(e,{identity:t,settings:n,authStore:r},{needApiKey:!i}).catch(e=>{let t=e instanceof Error?e.message:String(e);process.stderr.write(`console login failed: ${t}\n`)})},logout(){return r.logout(`all`)}}}const Ta={".png":`image`,".jpg":`image`,".jpeg":`image`,".webp":`image`,".gif":`image`,".bmp":`image`,".svg":`image`,".mp4":`video`,".mov":`video`,".webm":`video`,".mkv":`video`,".avi":`video`,".mp3":`audio`,".wav":`audio`,".m4a":`audio`,".aac":`audio`,".flac":`audio`,".ogg":`audio`},Ea={".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".webp":`image/webp`,".gif":`image/gif`,".bmp":`image/bmp`,".svg":`image/svg+xml`,".mp4":`video/mp4`,".mov":`video/quicktime`,".webm":`video/webm`,".mkv":`video/x-matroska`,".avi":`video/x-msvideo`,".mp3":`audio/mpeg`,".wav":`audio/wav`,".m4a":`audio/mp4`,".aac":`audio/aac`,".flac":`audio/flac`,".ogg":`audio/ogg`};function Da(e=z()){return L(e,`bailian-output`)}function Oa(e){return Ta[e.toLowerCase()]??`other`}function ka(e){return Ea[e.toLowerCase()]??`application/octet-stream`}function Aa(e,t,n){let r;try{r=dn(e,{withFileTypes:!0})}catch{return}for(let i of r){let r=L(e,i.name);i.isDirectory()?t>0&&Aa(r,t-1,n):(i.isFile()||i.isSymbolicLink())&&n.push(r)}}function ja(e=Da()){let t=[];if(!I(e))return{base:e,assets:t};let n=[];Aa(e,8,n);for(let r of n){let n;try{n=fn(r)}catch{continue}if(!n.isFile())continue;let i=vn(e,r),a=i.split(yn),o=a.length>1?a[0]:`other`,s=_n(r);t.push({name:r.split(yn).pop()??r,category:o,kind:Oa(s),relPath:i,size:n.size,mtime:n.mtimeMs,ext:s.replace(/^\./,``).toLowerCase()})}return t.sort((e,t)=>t.mtime-e.mtime),{base:e,assets:t}}function Ma(e,t){if(typeof t!=`string`||t.length===0)return null;let n=R(e),r=R(n,t);return r!==n&&!r.startsWith(n+yn)?null:r}const Na={port:{type:`number`,valueHint:`<port>`,description:`Port to listen on (default: random free port)`},noOpen:{type:`switch`,description:`Do not open the browser automatically`}};function K(e){return e instanceof t||e instanceof Error?e.message:String(e)}function q(e,t,n){e.writeHead(t,{"Content-Type":`application/json; charset=utf-8`}),e.end(JSON.stringify(n))}function Pa(e){return new Promise((t,n)=>{let r=0,i=[];e.on(`data`,t=>{if(r+=t.length,r>1048576){n(Error(`payload too large`)),e.destroy();return}i.push(t)}),e.on(`end`,()=>t(Buffer.concat(i).toString(`utf8`))),e.on(`error`,n)})}function Fa(e,t){return new Promise((n,r)=>{let i=0,a=[];e.on(`data`,n=>{if(i+=n.length,i>t){r(Error(`payload too large`)),e.destroy();return}a.push(n)}),e.on(`end`,()=>n(Buffer.concat(a))),e.on(`error`,r)})}function Ia(e,t){if(!e)return!1;let n=Buffer.from(e),r=Buffer.from(t);return n.length===r.length&&qt(n,r)}function La(e){let t={};for(let[n,r]of Object.entries(e)){let e=``;typeof r==`string`?e=r:(typeof r==`number`||typeof r==`boolean`)&&(e=String(r)),e!==``&&(t[mi(n)]=gi(n,e))}return t}function Ra(e,t){let n=new Set(ci),r={};for(let[t,i]of Object.entries(e))n.has(t)||(r[t]=i);return{...r,...t}}function za(e,t,n=Da(),r){return Jt.createServer(async(i,a)=>{try{let o=(i.headers.host||``).split(`:`)[0];if(o!==`127.0.0.1`&&o!==`localhost`){a.writeHead(403,{"Content-Type":`text/plain; charset=utf-8`}),a.end(`forbidden host
|
|
31
|
+
`);return}let s=new URL(i.url??`/`,`http://127.0.0.1`);if(!Ia(s.searchParams.get(`token`),e)){a.writeHead(401,{"Content-Type":`text/plain; charset=utf-8`}),a.end(`unauthorized
|
|
32
|
+
`);return}let c=i.method??`GET`,u=s.pathname;if(u===`/`&&c===`GET`){a.writeHead(200,{"Content-Type":`text/html; charset=utf-8`,"Cache-Control":`no-store`,"X-Content-Type-Options":`nosniff`,"Content-Security-Policy":`default-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src 'self' data: https://img.alicdn.com https://oss.aliyuncs.com; media-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'`}),a.end(`<!doctype html>
|
|
31
33
|
<html lang="en">
|
|
32
34
|
<head>
|
|
33
35
|
<meta charset="utf-8" />
|
|
34
36
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
35
|
-
<title>
|
|
37
|
+
<title>Config - Alibaba Cloud Model Studio CLI</title>
|
|
38
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
39
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
40
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
36
41
|
<style>
|
|
42
|
+
:root {
|
|
43
|
+
--font: "Inter", "PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
44
|
+
--mono: "Geist Mono", "SF Mono", "Roboto Mono", monospace;
|
|
45
|
+
--ink: #111111; --muted: #696969; --muted-2: #888888;
|
|
46
|
+
--line: #dddee3; --line-soft: #ededf1; --surface: #ffffff;
|
|
47
|
+
--surface-soft: #f8fafb; --chip: #eff3fa;
|
|
48
|
+
--blue: #4b73ff; --violet: #653aff; --cyan: #49dad1;
|
|
49
|
+
--grad-text: linear-gradient(106deg, #4a7dff 10%, #41ffd3 97%);
|
|
50
|
+
--grad-dot: linear-gradient(135deg, #03ffd9 0%, #0054ff 90%);
|
|
51
|
+
--ok: #1f883d; --ok-soft: #eaf6ee; --warn: #b25c00; --danger: #cf222e;
|
|
52
|
+
--r-card: 18px; --r-btn: 10px; --r-pill: 999px;
|
|
53
|
+
--shadow-card: 0 8px 30px rgba(17,17,17,.06);
|
|
54
|
+
--shadow-lift: 0 16px 48px rgba(40,52,90,.12);
|
|
55
|
+
--t-lift: .3s cubic-bezier(.2,.7,.2,1); --t-fast: .15s ease;
|
|
56
|
+
}
|
|
37
57
|
* { box-sizing: border-box; }
|
|
38
|
-
body { margin: 0; font:
|
|
58
|
+
body { margin: 0; font-family: var(--font); font-size: 14px; line-height: 1.5;
|
|
59
|
+
color: var(--ink); background: #fafafc; -webkit-font-smoothing: antialiased; }
|
|
39
60
|
#app { display: flex; min-height: 100vh; }
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
.
|
|
61
|
+
|
|
62
|
+
/* Sidebar */
|
|
63
|
+
#sidebar { width: 236px; flex: none; background: var(--surface); border-right: 1px solid var(--line-soft);
|
|
64
|
+
padding: 22px 16px; display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
|
|
65
|
+
transition: width .28s cubic-bezier(.2,.7,.2,1), padding .28s cubic-bezier(.2,.7,.2,1); }
|
|
66
|
+
.nav-brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 4px; text-decoration: none; }
|
|
67
|
+
.nav-logo { height: 24px; width: auto; display: block; }
|
|
68
|
+
.nav-logo-mini { height: 26px; width: auto; display: none; }
|
|
69
|
+
.nav-wordmark { font-weight: 400; font-size: 17px; line-height: 1; letter-spacing: -.3px; color: #1a1a19; white-space: nowrap; }
|
|
70
|
+
.nav { display: flex; flex-direction: column; gap: 4px; margin-top: 18px; }
|
|
71
|
+
.nav-group { display: flex; flex-direction: column; gap: 2px; }
|
|
72
|
+
.nav-group + .nav-group { margin-top: 16px; }
|
|
73
|
+
.nav-group-label { font-size: 11px; font-weight: 600; letter-spacing: .4px; text-transform: uppercase;
|
|
74
|
+
color: var(--muted-2); padding: 0 12px 4px; white-space: nowrap; overflow: hidden; }
|
|
75
|
+
.nav-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
|
|
76
|
+
padding: 9px 12px; border: 0; background: none; border-radius: var(--r-btn); cursor: pointer;
|
|
77
|
+
font: inherit; font-weight: 500; color: var(--muted); transition: background var(--t-fast), color var(--t-fast); }
|
|
78
|
+
.nav-item:hover { background: rgba(0,0,0,.04); color: var(--ink); }
|
|
79
|
+
.nav-item.is-active { background: var(--chip); color: var(--ink); }
|
|
80
|
+
.nav-ic { flex: none; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; }
|
|
81
|
+
.nav-ic svg { width: 20px; height: 20px; display: block; }
|
|
82
|
+
.nav-text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
83
|
+
.nav-item .badge { flex: none; margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--muted-2);
|
|
84
|
+
background: var(--surface-soft); border: 1px solid var(--line-soft); border-radius: var(--r-pill); padding: 1px 7px; min-width: 20px; text-align: center; }
|
|
85
|
+
.nav-item.is-active .badge { color: var(--blue); border-color: transparent; background: #fff; }
|
|
86
|
+
/* Collapse toggle pinned to the vertical center of the right edge */
|
|
87
|
+
.sidebar-toggle { position: absolute; top: 50%; right: -12px; z-index: 5; transform: translateY(-50%);
|
|
88
|
+
width: 22px; height: 46px; display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer;
|
|
89
|
+
border: 1px solid var(--line-soft); border-radius: 999px; background: var(--surface); color: var(--muted-2);
|
|
90
|
+
box-shadow: 0 2px 8px rgba(20,30,60,.10);
|
|
91
|
+
transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast); }
|
|
92
|
+
.sidebar-toggle:hover { color: var(--blue); border-color: var(--blue); background: #fff; box-shadow: 0 4px 14px rgba(28,84,228,.18); }
|
|
93
|
+
.sidebar-toggle .chev { width: 16px; height: 16px; transition: transform .28s cubic-bezier(.2,.7,.2,1); }
|
|
94
|
+
/* Collapsed: icon-only rail */
|
|
95
|
+
#sidebar.is-collapsed { width: 66px; padding: 22px 12px; }
|
|
96
|
+
#sidebar.is-collapsed .nav-brand { justify-content: center; padding: 0 0 4px; }
|
|
97
|
+
#sidebar.is-collapsed .nav-logo-full { display: none; }
|
|
98
|
+
#sidebar.is-collapsed .nav-logo-mini { display: block; }
|
|
99
|
+
#sidebar.is-collapsed .nav-wordmark { display: none; }
|
|
100
|
+
#sidebar.is-collapsed .nav-text { display: none; }
|
|
101
|
+
#sidebar.is-collapsed .nav-item { justify-content: center; padding: 9px 0; gap: 0; }
|
|
102
|
+
#sidebar.is-collapsed .nav-item .badge { display: none; }
|
|
103
|
+
#sidebar.is-collapsed .nav-group + .nav-group { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
|
|
104
|
+
#sidebar.is-collapsed .nav-group-label { height: 0; padding: 0; margin: 0; font-size: 0; }
|
|
105
|
+
#sidebar.is-collapsed .sidebar-toggle .chev { transform: rotate(180deg); }
|
|
106
|
+
.side-foot { margin-top: auto; padding-top: 14px; }
|
|
107
|
+
.acct-session { margin-bottom: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
|
|
108
|
+
.qr { display: block; width: 100%; max-width: 148px; margin: 0 auto 10px; border: 1px solid var(--line-soft);
|
|
109
|
+
border-radius: 10px; background: #fff; padding: 8px; }
|
|
110
|
+
.url-row { display: flex; align-items: center; gap: 6px; padding: 5px 6px 5px 10px;
|
|
111
|
+
border: 1px solid var(--line); border-radius: 10px; background: var(--surface-soft); }
|
|
112
|
+
.url-link { flex: 1; min-width: 0; font-family: var(--mono); font-size: 10.5px; color: var(--blue);
|
|
113
|
+
text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
114
|
+
.url-link:hover { text-decoration: underline; }
|
|
115
|
+
.copy-btn { flex: none; font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: var(--r-pill);
|
|
116
|
+
border: 1px solid var(--line); background: #fff; color: var(--ink); cursor: pointer;
|
|
117
|
+
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast); }
|
|
118
|
+
.copy-btn:hover { border-color: var(--blue); color: var(--blue); background: #fff; }
|
|
119
|
+
.copy-btn.copied { border-color: var(--ok); color: var(--ok); background: var(--ok-soft); }
|
|
120
|
+
|
|
121
|
+
/* Account (top-right) */
|
|
122
|
+
.account { position: fixed; top: 18px; right: 22px; z-index: 40; }
|
|
123
|
+
.acct-login { display: inline-flex; align-items: center; justify-content: center; gap: 7px; font: inherit; font-size: 14px; font-weight: 700;
|
|
124
|
+
padding: 9px 22px; border-radius: var(--r-pill); border: none; background: var(--ink); color: #fff;
|
|
125
|
+
cursor: pointer; box-shadow: var(--shadow-lift); transition: transform var(--t-fast), box-shadow var(--t-fast), background var(--t-fast); }
|
|
126
|
+
.acct-login:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(0,0,0,.24); }
|
|
127
|
+
.acct-login[disabled] { opacity: .65; cursor: default; transform: none; box-shadow: var(--shadow-lift); }
|
|
128
|
+
.avatar { width: 40px; height: 40px; border-radius: 50%; border: 2px solid #fff; cursor: pointer; padding: 0; overflow: hidden;
|
|
129
|
+
display: inline-flex; align-items: center; justify-content: center; color: #fff; box-shadow: var(--shadow-lift); }
|
|
130
|
+
.avatar svg { width: 20px; height: 20px; }
|
|
131
|
+
.avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
|
|
132
|
+
.acct-login[hidden], .avatar[hidden] { display: none; }
|
|
133
|
+
.acct-menu { position: absolute; top: 50px; right: 0; width: 270px; background: #fff; border: 1px solid var(--line);
|
|
134
|
+
border-radius: 14px; box-shadow: var(--shadow-lift); padding: 14px; }
|
|
135
|
+
.acct-menu-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
|
|
136
|
+
.avatar-lg { width: 44px; height: 44px; flex: none; border-width: 0; }
|
|
137
|
+
.avatar-lg svg { width: 22px; height: 22px; }
|
|
138
|
+
.acct-id { min-width: 0; }
|
|
139
|
+
.acct-method { font-size: 14px; font-weight: 600; color: var(--ink); }
|
|
140
|
+
.acct-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }
|
|
141
|
+
.acct-token { font-family: var(--mono); font-size: 11.5px; color: var(--muted-2); background: var(--surface-soft);
|
|
142
|
+
border: 1px solid var(--line-soft); border-radius: 8px; padding: 7px 10px; word-break: break-all; margin-bottom: 12px; }
|
|
143
|
+
.acct-logout { width: 100%; font: inherit; font-size: 13px; font-weight: 600; padding: 8px; border-radius: var(--r-btn);
|
|
144
|
+
border: 1px solid var(--line); background: var(--surface-soft); color: var(--ink); cursor: pointer;
|
|
145
|
+
transition: border-color var(--t-fast), color var(--t-fast); }
|
|
146
|
+
.acct-logout:hover { border-color: #e5484d; color: #e5484d; }
|
|
147
|
+
|
|
148
|
+
/* Toolbar (search) + pagination */
|
|
149
|
+
.toolbar { display: flex; align-items: center; gap: 10px; margin: 0 0 16px; }
|
|
150
|
+
.search { flex: 1; max-width: 340px; font: inherit; font-size: 13px; padding: 8px 14px; border-radius: var(--r-pill);
|
|
151
|
+
border: 1px solid var(--line); background: #fff; color: var(--ink); transition: border-color var(--t-fast); }
|
|
152
|
+
.search:focus { outline: none; border-color: var(--blue); }
|
|
153
|
+
.search::placeholder { color: var(--muted-2); }
|
|
154
|
+
.pager { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px; margin-top: 24px; }
|
|
155
|
+
.pager .pg { min-width: 32px; height: 32px; padding: 0 6px; display: inline-flex; align-items: center; justify-content: center;
|
|
156
|
+
font: inherit; font-size: 13px; font-weight: 500; border-radius: var(--r-btn); border: 1px solid var(--line);
|
|
157
|
+
background: #fff; color: var(--ink); cursor: pointer; font-variant-numeric: tabular-nums;
|
|
158
|
+
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast); }
|
|
159
|
+
.pager .pg:hover:not(:disabled):not(.is-active) { border-color: var(--blue); color: var(--blue); }
|
|
160
|
+
.pager .pg.is-active { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 700; }
|
|
161
|
+
.pager .pg:disabled { opacity: .4; cursor: not-allowed; }
|
|
162
|
+
.pager .pg-nav { font-size: 15px; line-height: 1; }
|
|
163
|
+
.pager .pg-jump { border-color: transparent; background: transparent; color: var(--muted-2); letter-spacing: 1px; }
|
|
164
|
+
.pager .pg-jump:hover { color: var(--blue); }
|
|
165
|
+
.pager .pg-size { height: 32px; margin-left: 4px; font: inherit; font-size: 13px; border-radius: var(--r-btn);
|
|
166
|
+
border: 1px solid var(--line); background: #fff; color: var(--ink); padding: 0 8px; cursor: pointer; }
|
|
167
|
+
.pager .pg-size:hover { border-color: var(--blue); }
|
|
168
|
+
|
|
169
|
+
/* Main */
|
|
170
|
+
main { flex: 1; min-width: 0; padding: 34px 40px 60px; max-width: 1600px; }
|
|
171
|
+
.view { display: none; animation: rise .34s cubic-bezier(.2,.7,.2,1); }
|
|
172
|
+
.view.is-active { display: block; }
|
|
173
|
+
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
|
174
|
+
.view-head { position: sticky; top: 0; z-index: 20; margin: 0 0 22px; padding: 6px 0 14px;
|
|
175
|
+
background: #fafafc; border-bottom: 1px solid var(--line-soft); }
|
|
176
|
+
.view-title { margin: 0; font-weight: 600; font-size: 26px; letter-spacing: -.8px; }
|
|
177
|
+
.view-title .grad { background: none; -webkit-background-clip: border-box; background-clip: border-box; -webkit-text-fill-color: currentColor; color: inherit; }
|
|
178
|
+
.view-sub { margin: 8px 0 0; font-size: 14px; color: var(--muted); max-width: 620px; }
|
|
179
|
+
|
|
180
|
+
/* Buttons */
|
|
181
|
+
.btn-soft, .btn-primary, .btn-danger, .btn-danger-solid { padding: 8px 14px; border-radius: var(--r-btn); font: inherit;
|
|
182
|
+
font-weight: 500; cursor: pointer; border: 1px solid var(--line); background: var(--surface); transition: background var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast); }
|
|
183
|
+
.btn-soft:hover { background: var(--surface-soft); }
|
|
184
|
+
.btn-primary { background: var(--ink); color: #fff; border-color: var(--ink); }
|
|
185
|
+
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0,0,0,.18); }
|
|
186
|
+
.btn-danger { color: var(--danger); border-color: transparent; background: transparent; padding: 8px 10px; }
|
|
187
|
+
.btn-danger:hover { background: #fdeef0; }
|
|
188
|
+
.btn-danger-solid { color: #fff; background: var(--danger); border-color: var(--danger); font-weight: 600; }
|
|
189
|
+
.btn-danger-solid:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(220,50,60,.28); }
|
|
190
|
+
button:disabled { opacity: .5; cursor: default; box-shadow: none; transform: none; }
|
|
191
|
+
|
|
192
|
+
/* Profiles */
|
|
193
|
+
.profile-tile.selected { border-color: #dfe6f5; background: var(--chip); }
|
|
194
|
+
.profile-tile .tile-name { flex: 1; }
|
|
195
|
+
.profile-tile .star { color: var(--blue); font-size: 12px; }
|
|
196
|
+
.profile-tile .chev { color: var(--muted-2); font-size: 15px; }
|
|
197
|
+
.tile-add { align-items: center; justify-content: center; border-style: dashed; color: var(--muted);
|
|
198
|
+
font-weight: 600; cursor: pointer; text-align: center; }
|
|
199
|
+
.tile-add:hover { border-color: var(--blue); color: var(--blue); transform: translateY(-4px);
|
|
200
|
+
box-shadow: var(--shadow-lift); }
|
|
201
|
+
.card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r-card);
|
|
202
|
+
box-shadow: var(--shadow-card); padding: 22px 24px; }
|
|
203
|
+
.editor-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
|
|
204
|
+
.editor-head h3 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.3px; }
|
|
205
|
+
.row { display: flex; flex-direction: column; margin: 14px 0; }
|
|
206
|
+
.model-cat { margin-top: 8px; }
|
|
207
|
+
.model-cat-hint { font-size: 11px; color: var(--muted); margin-bottom: 6px; }
|
|
208
|
+
.model-cat-note { font-size: 11px; color: var(--muted-2); margin-top: 7px; line-height: 1.5; }
|
|
209
|
+
.model-cat-note code { font-family: var(--mono); font-size: 10.5px; background: var(--chip);
|
|
210
|
+
border: 1px solid var(--line-soft); border-radius: 5px; padding: 1px 5px; color: #33383f; }
|
|
211
|
+
.model-chips { display: flex; flex-wrap: wrap; gap: 7px; }
|
|
212
|
+
.mchip { font-family: var(--mono); font-size: 11.5px; color: #33383f; background: var(--surface-soft);
|
|
213
|
+
border: 1px solid var(--line); border-radius: var(--r-pill); padding: 4px 11px; cursor: pointer;
|
|
214
|
+
transition: background .12s, border-color .12s, color .12s; white-space: nowrap; }
|
|
215
|
+
.mchip:hover { border-color: var(--blue); color: var(--blue); }
|
|
216
|
+
.mchip.active { background: var(--blue); border-color: var(--blue); color: #fff; }
|
|
217
|
+
.row label { font-weight: 500; margin-bottom: 5px; font-size: 13px; color: #33383f; font-family: var(--mono); }
|
|
51
218
|
.inputwrap { display: flex; gap: 6px; }
|
|
52
|
-
input { flex: 1; padding:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
.
|
|
58
|
-
.toggle { flex: none;
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
.
|
|
219
|
+
input { flex: 1; width: 100%; padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-btn);
|
|
220
|
+
font: inherit; background: var(--surface-soft); transition: border-color var(--t-fast), background var(--t-fast); }
|
|
221
|
+
input:focus { outline: none; border-color: var(--blue); background: #fff; }
|
|
222
|
+
select.select { width: 100%; padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-btn);
|
|
223
|
+
font: inherit; background: var(--surface-soft); cursor: pointer; }
|
|
224
|
+
select.select:focus { outline: none; border-color: var(--blue); background: #fff; }
|
|
225
|
+
.toggle { flex: none; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-btn);
|
|
226
|
+
background: var(--surface); cursor: pointer; font: inherit; font-size: 12px; color: var(--muted); }
|
|
227
|
+
.toggle:hover { background: var(--surface-soft); }
|
|
228
|
+
.actions { margin-top: 22px; display: flex; align-items: center; gap: 12px; }
|
|
229
|
+
.muted { color: var(--muted); font-size: 12px; word-break: break-all; }
|
|
230
|
+
.err { color: var(--danger); font-size: 12px; }
|
|
231
|
+
|
|
232
|
+
/* Card grids (skills / mcp / agents) */
|
|
233
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); gap: 14px; }
|
|
234
|
+
.tile { position: relative; display: flex; flex-direction: column; background: var(--surface);
|
|
235
|
+
border: 1px solid var(--line-soft); border-radius: var(--r-card); padding: 15px 17px; min-height: 96px;
|
|
236
|
+
transition: transform var(--t-lift), box-shadow var(--t-lift), border-color var(--t-lift); }
|
|
237
|
+
.tile:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: transparent; }
|
|
238
|
+
.tile-top { display: flex; align-items: center; gap: 10px; }
|
|
239
|
+
.tile-name { font-weight: 600; font-size: 15px; letter-spacing: -.3px; min-width: 0; flex: 0 1 auto;
|
|
240
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
241
|
+
.tile-meta { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
|
|
242
|
+
.tile-desc { margin: 9px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--muted);
|
|
243
|
+
display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
244
|
+
.tile-foot { margin-top: auto; padding-top: 12px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
245
|
+
font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
|
|
246
|
+
.tile-path { font-family: var(--mono); font-size: 11px; color: var(--muted-2); word-break: break-all;
|
|
247
|
+
margin-top: 9px; line-height: 1.5; }
|
|
248
|
+
.tile-actions { margin-top: auto; padding-top: 14px; display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
|
|
249
|
+
.btn-launch { flex: none; min-width: 140px; text-align: center; white-space: nowrap; padding: 7px 14px; font-size: 12.5px; font-weight: 600; border-radius: var(--r-btn);
|
|
250
|
+
border: 1px solid var(--line); background: var(--surface-soft); cursor: pointer; color: var(--ink);
|
|
251
|
+
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast); }
|
|
252
|
+
.btn-launch:hover { border-color: var(--blue); color: var(--blue); background: #fff; }
|
|
253
|
+
.btn-launch:disabled { opacity: .5; cursor: not-allowed; }
|
|
254
|
+
.btn-launch:disabled:hover { border-color: var(--line); color: var(--ink); background: var(--surface-soft); }
|
|
255
|
+
/* Round icon-only run/launch button (bottom-right of a tile) */
|
|
256
|
+
.icon-run { flex: none; width: 38px; height: 38px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
|
|
257
|
+
border-radius: 50%; border: 1px solid var(--line); background: var(--surface-soft); color: var(--ink); cursor: pointer;
|
|
258
|
+
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast); }
|
|
259
|
+
.icon-run svg { width: 15px; height: 15px; margin-left: 1px; display: block; }
|
|
260
|
+
.icon-run:hover { border-color: var(--blue); color: var(--blue); background: #fff; box-shadow: 0 3px 10px rgba(28,84,228,.16); transform: translateY(-1px); }
|
|
261
|
+
.icon-run:active { transform: none; }
|
|
262
|
+
.icon-run:disabled { opacity: .45; cursor: not-allowed; }
|
|
263
|
+
.icon-run:disabled:hover { border-color: var(--line); color: var(--ink); background: var(--surface-soft); box-shadow: none; transform: none; }
|
|
264
|
+
.launch-status { font-size: 11.5px; color: var(--muted); }
|
|
265
|
+
.launch-status.ok { color: #16a34a; }
|
|
266
|
+
.launch-status.err { color: var(--danger); }
|
|
267
|
+
.scn-desc { margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: var(--muted); }
|
|
268
|
+
#playgroundBody .tile-actions { margin-top: auto; padding-top: 14px; }
|
|
269
|
+
/* Quick Start stepper */
|
|
270
|
+
.qs-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 16px; }
|
|
271
|
+
.qs-step { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; padding: 20px; border: 1px solid var(--line-soft);
|
|
272
|
+
border-radius: var(--r-card); background: var(--surface); transition: border-color var(--t-fast), background var(--t-fast); }
|
|
273
|
+
.qs-step.done { border-color: #bbf7d0; background: #f6fef9; }
|
|
274
|
+
.qs-step.locked { opacity: .6; }
|
|
275
|
+
.qs-head { display: flex; align-items: center; gap: 10px; }
|
|
276
|
+
.qs-ic { flex: none; width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center;
|
|
277
|
+
justify-content: center; font-size: 13px; font-weight: 700; border: 2px solid var(--line); color: var(--muted-2);
|
|
278
|
+
background: #fff; }
|
|
279
|
+
.qs-step.done .qs-ic { border-color: #16a34a; background: #16a34a; color: #fff; }
|
|
280
|
+
.qs-title { font-size: 15px; font-weight: 600; color: var(--ink); }
|
|
281
|
+
.qs-done-tag { font-size: 11px; font-weight: 600; color: #16a34a; background: var(--ok-soft, #ecfdf5);
|
|
282
|
+
border: 1px solid #bbf7d0; border-radius: var(--r-pill); padding: 1px 9px; }
|
|
283
|
+
.qs-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.55; word-break: break-word;
|
|
284
|
+
display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
285
|
+
.qs-desc code { font-family: var(--mono); font-size: 12px; background: var(--chip); padding: 1px 6px; border-radius: 5px; color: #242933; }
|
|
286
|
+
.qs-act { margin: 0; margin-top: auto; padding-top: 4px; }
|
|
287
|
+
.pg-warn { margin-bottom: 14px; padding: 10px 14px; border-radius: 10px; font-size: 13px;
|
|
288
|
+
color: #92400e; background: #fffbeb; border: 1px solid #fde68a; }
|
|
289
|
+
.dispatch-preview { white-space: pre-wrap; word-break: break-word; font-family: var(--mono); font-size: 12px;
|
|
290
|
+
line-height: 1.55; background: var(--surface-soft); border: 1px solid var(--line-soft); border-radius: 8px;
|
|
291
|
+
padding: 10px 12px; max-height: 168px; overflow: auto; margin: 4px 0 0; color: var(--ink); }
|
|
292
|
+
.chip { display: inline-block; font-family: var(--mono); font-size: 11px; color: #242933;
|
|
293
|
+
background: var(--chip); border-radius: 6px; padding: 3px 8px; }
|
|
294
|
+
.chip.blue { color: var(--blue); }
|
|
295
|
+
.pill { margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 6px;
|
|
296
|
+
font-size: 11px; font-weight: 600; border-radius: var(--r-pill); padding: 3px 10px; white-space: nowrap; }
|
|
297
|
+
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
298
|
+
.pill.ok { color: var(--ok); background: var(--ok-soft); }
|
|
299
|
+
.pill.neutral { color: var(--blue); background: var(--chip); }
|
|
300
|
+
.pill.off { color: var(--muted-2); background: var(--surface-soft); }
|
|
301
|
+
.ver { margin-left: auto; flex: none; font-family: var(--mono); font-size: 11px; color: var(--violet);
|
|
302
|
+
background: #f1edff; border-radius: var(--r-pill); padding: 2px 9px; }
|
|
303
|
+
.origin { flex: none; font-family: var(--mono); font-size: 10px; font-weight: 600; text-transform: uppercase;
|
|
304
|
+
letter-spacing: .4px; padding: 2px 8px; border-radius: var(--r-pill); }
|
|
305
|
+
.origin.local { color: var(--muted); background: var(--surface-soft); border: 1px solid var(--line-soft); }
|
|
306
|
+
.origin.remote { color: #fff; background: var(--blue); border: 1px solid transparent; }
|
|
307
|
+
.empty { padding: 44px 24px; text-align: center; color: var(--muted); border: 1px dashed var(--line);
|
|
308
|
+
border-radius: var(--r-card); background: var(--surface-soft); }
|
|
309
|
+
.empty code { font-family: var(--mono); background: var(--chip); padding: 2px 7px; border-radius: 6px; color: #242933; }
|
|
310
|
+
.loading { color: var(--muted); font-size: 13px; padding: 8px 2px; }
|
|
311
|
+
|
|
312
|
+
/* Drawer (profile editor) */
|
|
313
|
+
.drawer-overlay { position: fixed; inset: 0; z-index: 50; background: rgba(17,17,17,.28);
|
|
314
|
+
display: flex; justify-content: flex-end; animation: fade .2s ease; }
|
|
315
|
+
.drawer-overlay[hidden] { display: none; }
|
|
316
|
+
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
|
|
317
|
+
.drawer-panel { width: min(560px, 94vw); height: 100%; background: var(--surface); display: flex;
|
|
318
|
+
flex-direction: column; box-shadow: -20px 0 60px rgba(20,30,60,.18); animation: slidein .28s cubic-bezier(.2,.7,.2,1); }
|
|
319
|
+
@keyframes slidein { from { transform: translateX(36px); opacity: .5; } to { transform: none; opacity: 1; } }
|
|
320
|
+
.drawer-head { flex: none; display: flex; align-items: center; justify-content: space-between;
|
|
321
|
+
padding: 20px 24px; border-bottom: 1px solid var(--line-soft); }
|
|
322
|
+
.drawer-head h3 { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -.3px; }
|
|
323
|
+
.drawer-head-actions { display: flex; align-items: center; gap: 8px; }
|
|
324
|
+
.drawer-close { border: 0; background: none; font-size: 24px; line-height: 1; cursor: pointer;
|
|
325
|
+
color: var(--muted); padding: 0 4px; border-radius: var(--r-btn); }
|
|
326
|
+
.drawer-close:hover { color: var(--ink); background: var(--surface-soft); }
|
|
327
|
+
.drawer-body { flex: 1; overflow-y: auto; padding: 4px 24px 16px; }
|
|
328
|
+
.drawer-foot { flex: none; margin-top: 0; padding: 16px 24px; border-top: 1px solid var(--line-soft);
|
|
329
|
+
background: var(--surface); }
|
|
330
|
+
.drawer-foot[hidden] { display: none; }
|
|
331
|
+
.drawer-foot-end { display: flex; justify-content: flex-end; align-items: center; gap: 10px; }
|
|
332
|
+
.tile.clickable { cursor: pointer; }
|
|
333
|
+
/* Detail drawer sections */
|
|
334
|
+
.detail-sec { margin: 16px 0 0; }
|
|
335
|
+
.detail-label { font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
|
|
336
|
+
color: var(--muted-2); margin-bottom: 7px; }
|
|
337
|
+
.detail-desc { font-size: 14px; line-height: 1.7; color: var(--ink); }
|
|
338
|
+
.detail-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
339
|
+
.detail-path { font-family: var(--mono); font-size: 12px; color: var(--muted); word-break: break-all; line-height: 1.6; }
|
|
340
|
+
.detail-kv { display: flex; flex-direction: column; }
|
|
341
|
+
.kv-row { display: flex; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line-soft); align-items: baseline; }
|
|
342
|
+
.kv-row:last-child { border-bottom: 0; }
|
|
343
|
+
.kv-key { flex: none; width: 88px; font-family: var(--mono); font-size: 11px; text-transform: uppercase;
|
|
344
|
+
letter-spacing: .5px; color: var(--muted-2); }
|
|
345
|
+
.kv-val { flex: 1; font-family: var(--mono); font-size: 12.5px; color: var(--ink); word-break: break-all; line-height: 1.5; }
|
|
346
|
+
.kv-val.secret { color: var(--muted); letter-spacing: 1px; }
|
|
347
|
+
.kv-reveal { flex: none; align-self: center; border: 1px solid var(--line); background: var(--surface);
|
|
348
|
+
color: var(--muted); font: inherit; font-size: 11px; padding: 3px 9px; border-radius: var(--r-btn);
|
|
349
|
+
cursor: pointer; white-space: nowrap; }
|
|
350
|
+
.kv-reveal:hover { color: var(--ink); background: var(--surface-soft); }
|
|
351
|
+
.settings-item { margin-bottom: 12px; }
|
|
352
|
+
.settings-item:last-child { margin-bottom: 0; }
|
|
353
|
+
.settings-item .detail-path { margin-bottom: 6px; }
|
|
354
|
+
.settings-item .detail-code { max-height: 340px; overflow: auto; white-space: pre; }
|
|
355
|
+
.detail-label-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
|
|
356
|
+
.detail-code { font-family: var(--mono); font-size: 12px; line-height: 1.6; background: var(--surface-soft);
|
|
357
|
+
border: 1px solid var(--line-soft); border-radius: var(--r-btn); padding: 14px 16px; white-space: pre-wrap;
|
|
358
|
+
word-break: break-word; color: #242933; margin: 0; }
|
|
359
|
+
textarea.code-edit { display: block; width: 100%; min-height: 220px; resize: vertical; white-space: pre;
|
|
360
|
+
overflow: auto; tab-size: 2; }
|
|
361
|
+
textarea.code-edit:focus { outline: none; border-color: var(--blue); background: #fff; }
|
|
362
|
+
.mcp-note { margin: 10px 0 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
|
|
363
|
+
.file-picker { display: flex; align-items: center; gap: 12px; }
|
|
364
|
+
.file-pick-btn { flex: none; font: inherit; font-size: 13px; font-weight: 600; padding: 8px 16px; border-radius: var(--r-btn);
|
|
365
|
+
border: 1px solid var(--line); background: var(--surface); color: var(--ink); cursor: pointer; white-space: nowrap;
|
|
366
|
+
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast); }
|
|
367
|
+
.file-pick-btn:hover { border-color: var(--blue); color: var(--blue); background: #fff; }
|
|
368
|
+
.file-name { min-width: 0; font-size: 13px; color: var(--muted-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
369
|
+
.file-name.has-file { color: var(--ink); font-weight: 500; }
|
|
370
|
+
.detail-preview { width: 100%; margin-top: 4px; border-radius: var(--r-card); overflow: hidden;
|
|
371
|
+
background: var(--surface-soft); border: 1px solid var(--line-soft); display: flex;
|
|
372
|
+
align-items: center; justify-content: center; }
|
|
373
|
+
.detail-preview img, .detail-preview video { max-width: 100%; max-height: 50vh; width: auto; height: auto;
|
|
374
|
+
object-fit: contain; display: block; }
|
|
375
|
+
.detail-preview audio { width: 100%; display: block; }
|
|
376
|
+
.detail-preview .asset-icon-lg { font-size: 64px; padding: 44px 0; }
|
|
377
|
+
/* Rendered Markdown (SKILL.md) */
|
|
378
|
+
.md-body { font-size: 13.5px; line-height: 1.7; color: var(--ink); word-break: break-word; }
|
|
379
|
+
.md-body > :first-child { margin-top: 0; }
|
|
380
|
+
.md-body h1, .md-body h2, .md-body h3, .md-body h4, .md-body h5, .md-body h6 {
|
|
381
|
+
font-weight: 600; line-height: 1.3; margin: 18px 0 8px; letter-spacing: -.2px; }
|
|
382
|
+
.md-body h1 { font-size: 20px; } .md-body h2 { font-size: 17px; }
|
|
383
|
+
.md-body h3 { font-size: 15px; } .md-body h4 { font-size: 14px; }
|
|
384
|
+
.md-body p { margin: 10px 0; }
|
|
385
|
+
.md-body ul, .md-body ol { margin: 10px 0; padding-left: 22px; }
|
|
386
|
+
.md-body li { margin: 4px 0; }
|
|
387
|
+
.md-body code { font-family: var(--mono); font-size: 12px; background: var(--chip); padding: 2px 6px;
|
|
388
|
+
border-radius: 5px; color: #242933; }
|
|
389
|
+
.md-body pre.md-pre { background: var(--surface-soft); border: 1px solid var(--line-soft);
|
|
390
|
+
border-radius: var(--r-btn); padding: 14px 16px; overflow: auto; margin: 12px 0; }
|
|
391
|
+
.md-body pre.md-pre code { background: none; padding: 0; font-size: 12px; line-height: 1.6;
|
|
392
|
+
color: #242933; white-space: pre; }
|
|
393
|
+
.md-body blockquote { margin: 12px 0; padding: 6px 14px; border-left: 3px solid var(--line);
|
|
394
|
+
color: var(--muted); background: var(--surface-soft); border-radius: 0 8px 8px 0; }
|
|
395
|
+
.md-body a { color: var(--blue); text-decoration: none; }
|
|
396
|
+
.md-body a:hover { text-decoration: underline; }
|
|
397
|
+
.md-body hr { border: 0; border-top: 1px solid var(--line-soft); margin: 18px 0; }
|
|
398
|
+
.md-body table.md-table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 12.5px; display: block; overflow-x: auto; }
|
|
399
|
+
.md-body table.md-table th, .md-body table.md-table td { border: 1px solid var(--line-soft); padding: 6px 10px; text-align: left; vertical-align: top; }
|
|
400
|
+
.md-body table.md-table th { background: var(--surface-soft); font-weight: 600; white-space: nowrap; }
|
|
401
|
+
|
|
402
|
+
/* Modal (new profile) */
|
|
403
|
+
.modal-overlay { position: fixed; inset: 0; z-index: 60; background: rgba(17,17,17,.32);
|
|
404
|
+
display: flex; align-items: center; justify-content: center; padding: 24px; animation: fade .18s ease; }
|
|
405
|
+
.modal-overlay[hidden] { display: none; }
|
|
406
|
+
.modal-card { width: min(420px, 100%); background: var(--surface); border-radius: var(--r-card);
|
|
407
|
+
box-shadow: 0 24px 70px rgba(20,30,60,.28); padding: 26px 26px 20px;
|
|
408
|
+
animation: pop .22s cubic-bezier(.2,.7,.2,1); }
|
|
409
|
+
@keyframes pop { from { transform: translateY(10px) scale(.98); opacity: .5; } to { transform: none; opacity: 1; } }
|
|
410
|
+
.modal-card h3 { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -.4px; }
|
|
411
|
+
.modal-sub { margin: 8px 0 18px; font-size: 13px; color: var(--muted); line-height: 1.5; }
|
|
412
|
+
.modal-label { display: block; font-family: var(--mono); font-size: 11px; text-transform: uppercase;
|
|
413
|
+
letter-spacing: .5px; color: var(--muted-2); margin-top: 18px; margin-bottom: 9px; }
|
|
414
|
+
.modal-err { min-height: 16px; margin-top: 8px; font-size: 12px; color: var(--danger); }
|
|
415
|
+
.btn-dark { margin-left: auto; border: 0; background: var(--ink); color: #fff; font-weight: 600;
|
|
416
|
+
font-size: 13px; padding: 9px 18px; border-radius: var(--r-pill); cursor: pointer; white-space: nowrap; }
|
|
417
|
+
.btn-dark:hover { opacity: .88; }
|
|
418
|
+
.btn-xs { padding: 5px 10px; font-size: 12px; }
|
|
419
|
+
.btn-mini { border: 1px solid var(--line); background: var(--surface); color: var(--muted);
|
|
420
|
+
font: inherit; font-size: 12px; padding: 6px 10px; border-radius: var(--r-btn); cursor: pointer; }
|
|
421
|
+
.btn-mini:hover { color: var(--ink); background: var(--surface-soft); }
|
|
422
|
+
.scn-textarea { width: 100%; min-height: 120px; resize: vertical; font: inherit; font-size: 13px;
|
|
423
|
+
line-height: 1.5; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-btn);
|
|
424
|
+
background: var(--surface); color: var(--ink); }
|
|
425
|
+
.scn-textarea:focus { outline: none; border-color: var(--blue); background: #fff; }
|
|
426
|
+
.scn-inputs-head { display: flex; align-items: center; justify-content: space-between; margin: 16px 0 8px; }
|
|
427
|
+
.scn-input-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
|
|
428
|
+
.scn-input-row .scn-k { max-width: 130px; }
|
|
429
|
+
.scn-hint { margin: 10px 0 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
|
|
430
|
+
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px; }
|
|
431
|
+
|
|
432
|
+
/* Assets */
|
|
433
|
+
.filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
|
|
434
|
+
.filter { padding: 6px 14px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--surface);
|
|
435
|
+
font: inherit; font-size: 13px; font-weight: 500; color: var(--muted); cursor: pointer; transition: all var(--t-fast); }
|
|
436
|
+
.filter:hover { background: var(--surface-soft); color: var(--ink); }
|
|
437
|
+
.filter.is-active { background: var(--ink); color: #fff; border-color: var(--ink); }
|
|
438
|
+
.filter .n { margin-left: 6px; font-family: var(--mono); font-size: 11px; opacity: .7; }
|
|
439
|
+
.filter.sort-toggle { margin-left: auto; font-family: var(--mono); font-size: 12px; }
|
|
440
|
+
.asset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
|
|
441
|
+
.asset { position: relative; display: flex; flex-direction: column; cursor: pointer; background: var(--surface);
|
|
442
|
+
border: 1px solid var(--line-soft); border-radius: var(--r-card); overflow: hidden;
|
|
443
|
+
transition: transform var(--t-lift), box-shadow var(--t-lift), border-color var(--t-lift); }
|
|
444
|
+
.asset:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); border-color: transparent; }
|
|
445
|
+
.asset-media { aspect-ratio: 4 / 3; background: var(--surface-soft); display: flex; align-items: center;
|
|
446
|
+
justify-content: center; overflow: hidden; border-bottom: 1px solid var(--line-soft); }
|
|
447
|
+
.asset-media img, .asset-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
448
|
+
.asset-media audio { width: 90%; }
|
|
449
|
+
.asset-icon { font-size: 34px; color: var(--muted-2); }
|
|
450
|
+
.asset-cat { position: absolute; top: 10px; left: 10px; font-family: var(--mono); font-size: 10px;
|
|
451
|
+
font-weight: 600; text-transform: uppercase; letter-spacing: .4px; color: #fff; background: rgba(17,17,17,.66);
|
|
452
|
+
border-radius: var(--r-pill); padding: 3px 9px; backdrop-filter: blur(4px); }
|
|
453
|
+
.asset-del { position: absolute; top: 8px; right: 8px; width: 26px; height: 26px; border: 0; border-radius: 50%;
|
|
454
|
+
background: rgba(17,17,17,.6); color: #fff; cursor: pointer; font-size: 15px; line-height: 1; opacity: 0;
|
|
455
|
+
transition: opacity var(--t-fast), background var(--t-fast); }
|
|
456
|
+
.asset:hover .asset-del { opacity: 1; }
|
|
457
|
+
.asset-del:hover { background: var(--danger); }
|
|
458
|
+
.asset-body { padding: 12px 14px; }
|
|
459
|
+
.asset-name { font-size: 13px; font-weight: 500; word-break: break-all; line-height: 1.4; }
|
|
460
|
+
.asset-name.link { cursor: pointer; }
|
|
461
|
+
.asset-name.link:hover { color: var(--blue); text-decoration: underline; }
|
|
462
|
+
.asset-folder { margin-top: 5px; display: inline-block; max-width: 100%; font-family: var(--mono);
|
|
463
|
+
font-size: 10.5px; color: var(--muted-2); background: var(--surface-soft); border-radius: 6px;
|
|
464
|
+
padding: 2px 7px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
465
|
+
.asset-meta { margin-top: 7px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
466
|
+
font-family: var(--mono); font-size: 11px; color: var(--muted-2); }
|
|
467
|
+
|
|
468
|
+
/* Narrow screens: sidebar becomes a top bar, content stacks and shrinks */
|
|
469
|
+
@media (max-width: 800px) {
|
|
470
|
+
#app { flex-direction: column; }
|
|
471
|
+
#sidebar, #sidebar.is-collapsed { width: 100%; height: auto; position: static; flex-direction: row; align-items: center;
|
|
472
|
+
gap: 10px; padding: 10px 110px 10px 14px; border-right: 0; border-bottom: 1px solid var(--line-soft);
|
|
473
|
+
overflow-x: auto; }
|
|
474
|
+
.nav { flex-direction: row; margin-top: 0; gap: 2px; }
|
|
475
|
+
.nav-group, #sidebar.is-collapsed .nav-group { flex-direction: row; gap: 2px; }
|
|
476
|
+
.nav-group + .nav-group, #sidebar.is-collapsed .nav-group + .nav-group { margin-top: 0; margin-left: 4px; padding-top: 0; border-top: 0; }
|
|
477
|
+
.nav-group-label { display: none; }
|
|
478
|
+
.nav-item, #sidebar.is-collapsed .nav-item { flex: none; width: auto; white-space: nowrap; padding: 7px 10px; justify-content: flex-start; gap: 8px; }
|
|
479
|
+
.nav-text { flex: none; }
|
|
480
|
+
#sidebar.is-collapsed .nav-text { display: inline; }
|
|
481
|
+
#sidebar.is-collapsed .nav-logo-full { display: block; }
|
|
482
|
+
#sidebar.is-collapsed .nav-logo-mini { display: none; }
|
|
483
|
+
.nav-item .badge { display: none; }
|
|
484
|
+
.sidebar-toggle { display: none; }
|
|
485
|
+
.side-foot { display: none; }
|
|
486
|
+
main { padding: 18px 16px 48px; max-width: none; }
|
|
487
|
+
.view-head { position: static; }
|
|
488
|
+
.view-title { font-size: 22px; }
|
|
489
|
+
.account { position: absolute; top: 11px; right: 12px; }
|
|
490
|
+
.acct-login { padding: 7px 16px; font-size: 13px; }
|
|
491
|
+
.avatar { width: 34px; height: 34px; }
|
|
492
|
+
.filter.sort-toggle { margin-left: 0; }
|
|
493
|
+
}
|
|
62
494
|
</style>
|
|
63
495
|
</head>
|
|
64
496
|
<body>
|
|
65
497
|
<div id="app">
|
|
498
|
+
<div id="account" class="account" hidden>
|
|
499
|
+
<button id="loginBtn" class="acct-login" type="button" hidden><span>Log in</span></button>
|
|
500
|
+
<button id="avatarBtn" class="avatar" type="button" hidden aria-haspopup="true" aria-expanded="false"></button>
|
|
501
|
+
<div id="acctMenu" class="acct-menu" hidden>
|
|
502
|
+
<div class="acct-menu-head">
|
|
503
|
+
<span id="acctAvatarLg" class="avatar avatar-lg"></span>
|
|
504
|
+
<div class="acct-id">
|
|
505
|
+
<div id="acctMethod" class="acct-method"></div>
|
|
506
|
+
<div id="acctMeta" class="acct-meta"></div>
|
|
507
|
+
</div>
|
|
508
|
+
</div>
|
|
509
|
+
<div id="acctToken" class="acct-token"></div>
|
|
510
|
+
<div class="acct-session">
|
|
511
|
+
<img id="qrImg" class="qr" alt="QR code for this session URL">
|
|
512
|
+
<div class="url-row">
|
|
513
|
+
<a id="urlLink" class="url-link" target="_blank" rel="noopener" title=""></a>
|
|
514
|
+
<button id="copyUrl" class="copy-btn" type="button" title="Copy this URL">Copy</button>
|
|
515
|
+
</div>
|
|
516
|
+
</div>
|
|
517
|
+
<button id="logoutBtn" class="acct-logout" type="button">Log out</button>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
66
520
|
<aside id="sidebar">
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
521
|
+
<a class="nav-brand" href="#" aria-label="Model Studio CLI home">
|
|
522
|
+
<img class="nav-logo nav-logo-full" src="https://img.alicdn.com/imgextra/i1/O1CN01IU2US71Ciicsi3Br3_!!6000000000115-55-tps-357-76.svg" alt="Alibaba Cloud Model Studio">
|
|
523
|
+
<img class="nav-logo-mini" src="data:image/svg+xml,%3csvg%20width='19'%20height='20'%20viewBox='0%200%2019%2020'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20clip-path='url(%23clip0_0_83)'%3e%3cmask%20id='mask0_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask0_0_83)'%3e%3cpath%20d='M14.0801%202.27495L17.7505%204.38125C18.1117%204.58817%2018.1117%205.10742%2017.7505%205.31629L9.59706%209.99739L5.11401%207.42259L14.0801%202.27299V2.27495Z'%20fill='%23AB9BFF'/%3e%3c/g%3e%3cmask%20id='mask1_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask1_0_83)'%3e%3cpath%20d='M9.59523%209.99637L14.0802%2012.5712L5.11219%2017.7188L0.62915%2015.146L9.59523%209.99637Z'%20fill='%2300EBD2'/%3e%3c/g%3e%3cmask%20id='mask2_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask2_0_83)'%3e%3cpath%20d='M18.5651%2015.1461L14.0821%2012.5713L5.11401%2017.719L9.59706%2020.2938L18.5651%2015.1461Z'%20fill='%2300CFCA'/%3e%3c/g%3e%3cmask%20id='mask3_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask3_0_83)'%3e%3cpath%20d='M0.62915%204.85219L5.11219%207.42504L14.0802%202.27739L9.59523%20-0.297405'%20fill='%237347FF'/%3e%3c/g%3e%3cmask%20id='mask4_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask4_0_83)'%3e%3cpath%20d='M5.11401%207.42445V12.5741L9.59706%209.99925L5.11401%207.42445Z'%20fill='%231C54E4'/%3e%3c/g%3e%3cmask%20id='mask5_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask5_0_83)'%3e%3cpath%20d='M18.5516%2010.9186L18.5634%2015.1468L14.0803%2012.572L17.737%2010.454C18.0982%2010.2451%2018.5516%2010.5028%2018.5516%2010.9186Z'%20fill='%2300EBD2'/%3e%3c/g%3e%3cmask%20id='mask6_0_83'%20style='mask-type:luminance'%20maskUnits='userSpaceOnUse'%20x='0'%20y='0'%20width='19'%20height='20'%3e%3cpath%20d='M18.5633%2014.0364V5.96256C18.5633%205.27347%2018.1943%204.63904%2017.5956%204.29352L10.5649%200.258564C9.96621%20-0.0850029%209.22623%20-0.0850029%208.62757%200.258564L1.59681%204.29547C0.998157%204.63904%200.62915%205.27542%200.62915%205.96256V14.0364C0.62915%2014.7235%200.998157%2015.3599%201.59681%2015.7054L8.62757%2019.7423C9.22623%2020.0859%209.96621%2020.0859%2010.5649%2019.7423L17.5956%2015.7054C18.1943%2015.3618%2018.5633%2014.7255%2018.5633%2014.0364Z'%20fill='white'/%3e%3c/mask%3e%3cg%20mask='url(%23mask6_0_83)'%3e%3cpath%20d='M0.62915%204.84948L5.11219%207.42233V12.5719L0.62915%2015.1467V4.84948Z'%20fill='%230423DB'/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='clip0_0_83'%3e%3crect%20width='19'%20height='20'%20fill='white'/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e" alt="Model Studio" aria-hidden="true">
|
|
524
|
+
<span class="nav-wordmark">CLI</span>
|
|
525
|
+
</a>
|
|
526
|
+
<nav class="nav">
|
|
527
|
+
<div class="nav-group">
|
|
528
|
+
<span class="nav-group-label">Get Started</span>
|
|
529
|
+
<button class="nav-item" data-view="start" title="Quick Start"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M13 3 4 14h7l-1 7 9-11h-7z"/></svg></span><span class="nav-text">Quick Start</span></button>
|
|
530
|
+
<button class="nav-item is-active" data-view="playground" title="Playground"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M9 3h6M10 3v5.5L5.2 17A2 2 0 0 0 7 20h10a2 2 0 0 0 1.8-3L14 8.5V3"/></svg></span><span class="nav-text">Playground</span></button>
|
|
531
|
+
</div>
|
|
532
|
+
<div class="nav-group">
|
|
533
|
+
<span class="nav-group-label">Extensions</span>
|
|
534
|
+
<button class="nav-item" data-view="skills" title="Skills"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M7 10h3V7L6.5 3.5a6 6 0 0 1 8 8l6 6a2.121 2.121 0 1 1-3 3l-6-6a6 6 0 0 1-8-8z"/></svg></span><span class="nav-text">Skills</span><span class="badge" id="cnt-skills"></span></button>
|
|
535
|
+
<button class="nav-item" data-view="mcp" title="MCPs"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="m4 12 8 4 8-4M4 16l8 4 8-4M12 4 4 8l8 4 8-4z"/></svg></span><span class="nav-text">MCPs</span><span class="badge" id="cnt-mcp"></span></button>
|
|
536
|
+
<button class="nav-item" data-view="agents" title="Agents"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M9 3v2m6-2v2M9 19v2m6-2v2M3 9h2m-2 6h2m14-6h2m-2 6h2M6 6h12v12H6zM9.5 9.5h5v5h-5z"/></svg></span><span class="nav-text">Agents</span><span class="badge" id="cnt-agents"></span></button>
|
|
537
|
+
</div>
|
|
538
|
+
<div class="nav-group">
|
|
539
|
+
<span class="nav-group-label">Workspace</span>
|
|
540
|
+
<button class="nav-item" data-view="assets" title="Assets"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M4 5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zM4 16l4.5-4.5 3 3 4-4L20 15M8.5 9.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2"/></svg></span><span class="nav-text">Assets</span><span class="badge" id="cnt-assets"></span></button>
|
|
541
|
+
<button class="nav-item" data-view="profiles" title="Config"><span class="nav-ic"><svg viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M10.3 4.3a1 1 0 0 1 1-.8h1.4a1 1 0 0 1 1 .8l.3 1.5q.8.3 1.5.9l1.5-.6a1 1 0 0 1 1.2.4l.7 1.2a1 1 0 0 1-.2 1.3l-1.2 1a6.5 6.5 0 0 1 0 1.8l1.2 1a1 1 0 0 1 .2 1.3l-.7 1.2a1 1 0 0 1-1.2.4l-1.5-.6q-.7.6-1.5.9l-.3 1.5a1 1 0 0 1-1 .8h-1.4a1 1 0 0 1-1-.8l-.3-1.5a6.5 6.5 0 0 1-1.5-.9l-1.5.6a1 1 0 0 1-1.2-.4l-.7-1.2a1 1 0 0 1 .2-1.3l1.2-1a6.5 6.5 0 0 1 0-1.8l-1.2-1a1 1 0 0 1-.2-1.3l.7-1.2a1 1 0 0 1 1.2-.4l1.5.6q.7-.6 1.5-.9z"/><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.65" d="M10 12a2 2 0 1 0 4 0 2 2 0 0 0-4 0"/></svg></span><span class="nav-text">Config</span><span class="badge" id="cnt-profiles"></span></button>
|
|
542
|
+
</div>
|
|
543
|
+
</nav>
|
|
544
|
+
<button id="sidebarToggle" class="sidebar-toggle" type="button" aria-label="Collapse sidebar" title="Collapse sidebar"><svg class="chev" viewBox="0 0 24 24" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m14 8-4 4 4 4"/></svg></button>
|
|
71
545
|
</aside>
|
|
72
|
-
<main
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
|
|
546
|
+
<main>
|
|
547
|
+
<section id="view-start" class="view">
|
|
548
|
+
<div class="view-head">
|
|
549
|
+
<h2 class="view-title"><span class="grad">Quick Start</span></h2>
|
|
550
|
+
<p class="view-sub">Complete a few steps to check your local environment and finish first-time setup: sign in to Bailian, connect a local coding agent, and run your first task. Each circle turns from gray to green as you go.</p>
|
|
551
|
+
</div>
|
|
552
|
+
<div id="qsBody"><div class="loading">Loading…</div></div>
|
|
553
|
+
</section>
|
|
554
|
+
<section id="view-playground" class="view is-active">
|
|
555
|
+
<div class="view-head">
|
|
556
|
+
<h2 class="view-title"><span class="grad">Playground</span></h2>
|
|
557
|
+
<p class="view-sub">Pick a scenario to dispatch a preset task to a connected local coding agent, running in a new terminal. Tasks run in the directory where <code style="font-family:var(--mono)">bl config ui</code> was started.</p>
|
|
558
|
+
</div>
|
|
559
|
+
<div class="toolbar"><input id="scenarioSearch" class="search" type="search" placeholder="Search scenarios…" autocomplete="off"><button id="customScnBtn" class="btn-dark" type="button">+ Custom scenario</button></div>
|
|
560
|
+
<div id="scenarioFilters" class="filters"></div>
|
|
561
|
+
<div id="playgroundBody"><div class="loading">Loading…</div></div>
|
|
562
|
+
<div id="playgroundPager" class="pager"></div>
|
|
563
|
+
</section>
|
|
564
|
+
|
|
565
|
+
<section id="view-profiles" class="view">
|
|
566
|
+
<div class="view-head">
|
|
567
|
+
<h2 class="view-title"><span class="grad">Config</span></h2>
|
|
568
|
+
<p class="view-sub">Credentials and default models. The active profile (marked with a star) is used by every bl command. Click a profile to edit its settings.</p>
|
|
569
|
+
</div>
|
|
570
|
+
<div id="profileList" class="grid"></div>
|
|
571
|
+
</section>
|
|
572
|
+
|
|
573
|
+
<section id="view-skills" class="view">
|
|
574
|
+
<div class="view-head">
|
|
575
|
+
<h2 class="view-title">Installed <span class="grad">Skills</span></h2>
|
|
576
|
+
<p class="view-sub">Agent skills discovered across every local agent module (~/.agents/skills plus each agent's skills folder). Installed via <code style="font-family:var(--mono)">npx skills add</code>.</p>
|
|
577
|
+
</div>
|
|
578
|
+
<div class="toolbar"><input id="skillSearch" class="search" type="search" placeholder="Search skills…" autocomplete="off"><button id="addSkillBtn" class="btn-dark" type="button">+ Add skill</button></div>
|
|
579
|
+
<div id="skillsBody"><div class="loading">Loading…</div></div>
|
|
580
|
+
<div id="skillsPager" class="pager"></div>
|
|
581
|
+
</section>
|
|
582
|
+
|
|
583
|
+
<section id="view-mcp" class="view">
|
|
584
|
+
<div class="view-head">
|
|
585
|
+
<h2 class="view-title"><span class="grad">MCPs</span></h2>
|
|
586
|
+
<p class="view-sub">Model Context Protocol servers declared in your local coding-agent configs.</p>
|
|
587
|
+
</div>
|
|
588
|
+
<div class="toolbar"><input id="mcpSearch" class="search" type="search" placeholder="Search MCP servers…" autocomplete="off"><button id="addMcpBtn" class="btn-dark" type="button">+ Add MCP</button></div>
|
|
589
|
+
<div id="mcpBody"><div class="loading">Loading…</div></div>
|
|
590
|
+
<div id="mcpPager" class="pager"></div>
|
|
591
|
+
</section>
|
|
592
|
+
|
|
593
|
+
<section id="view-agents" class="view">
|
|
594
|
+
<div class="view-head">
|
|
595
|
+
<h2 class="view-title">Coding <span class="grad">Agents</span></h2>
|
|
596
|
+
<p class="view-sub">Frameworks bl can configure. "Connected" means the bailian-cli provider is wired into that agent.</p>
|
|
597
|
+
</div>
|
|
598
|
+
<div class="toolbar"><input id="agentSearch" class="search" type="search" placeholder="Search agents…" autocomplete="off"></div>
|
|
599
|
+
<div id="agentFilters" class="filters"></div>
|
|
600
|
+
<div id="agentsBody"><div class="loading">Loading…</div></div>
|
|
601
|
+
<div id="agentsPager" class="pager"></div>
|
|
602
|
+
</section>
|
|
603
|
+
|
|
604
|
+
<section id="view-assets" class="view">
|
|
605
|
+
<div class="view-head">
|
|
606
|
+
<h2 class="view-title">Generated <span class="grad">Assets</span></h2>
|
|
607
|
+
<p class="view-sub">Media that bl writes into the output directory, grouped by type (images, videos, audio, files) and generation time. <span id="assetsBase" class="muted"></span></p>
|
|
608
|
+
</div>
|
|
609
|
+
<div class="toolbar"><input id="assetSearch" class="search" type="search" placeholder="Search assets…" autocomplete="off"></div>
|
|
610
|
+
<div id="assetFilters" class="filters"></div>
|
|
611
|
+
<div id="assetsBody"><div class="loading">Loading…</div></div>
|
|
612
|
+
<div id="assetsPager" class="pager"></div>
|
|
613
|
+
</section>
|
|
614
|
+
</main>
|
|
615
|
+
<div id="drawer" class="drawer-overlay" hidden>
|
|
616
|
+
<aside class="drawer-panel" role="dialog" aria-modal="true">
|
|
617
|
+
<div class="drawer-head">
|
|
618
|
+
<h3 id="currentName"></h3>
|
|
619
|
+
<div class="drawer-head-actions">
|
|
620
|
+
<button id="deleteBtn" class="btn-danger">Delete</button>
|
|
621
|
+
<button id="closeBtn" class="drawer-close" aria-label="Close">×</button>
|
|
622
|
+
</div>
|
|
623
|
+
</div>
|
|
624
|
+
<div class="drawer-body">
|
|
625
|
+
<form id="form" onsubmit="return false" autocomplete="off"></form>
|
|
626
|
+
</div>
|
|
627
|
+
<div class="drawer-foot actions">
|
|
628
|
+
<button id="saveBtn" class="btn-primary">Save</button>
|
|
629
|
+
<button id="useBtn" class="btn-soft">Save & Activate</button>
|
|
630
|
+
<span id="status" class="muted"></span>
|
|
631
|
+
</div>
|
|
632
|
+
</aside>
|
|
633
|
+
</div>
|
|
634
|
+
<div id="infoDrawer" class="drawer-overlay" hidden>
|
|
635
|
+
<aside class="drawer-panel" role="dialog" aria-modal="true">
|
|
636
|
+
<div class="drawer-head">
|
|
637
|
+
<h3 id="infoTitle"></h3>
|
|
638
|
+
<div class="drawer-head-actions">
|
|
639
|
+
<button id="infoClose" class="drawer-close" aria-label="Close">×</button>
|
|
640
|
+
</div>
|
|
641
|
+
</div>
|
|
642
|
+
<div class="drawer-body" id="infoBody"></div>
|
|
643
|
+
<div class="drawer-foot drawer-foot-end" id="infoFoot" hidden></div>
|
|
644
|
+
</aside>
|
|
645
|
+
</div>
|
|
646
|
+
<div id="scnDrawer" class="drawer-overlay" hidden>
|
|
647
|
+
<aside class="drawer-panel" role="dialog" aria-modal="true">
|
|
648
|
+
<div class="drawer-head">
|
|
649
|
+
<h3 id="scnDrawerTitle">Custom scenario</h3>
|
|
650
|
+
<div class="drawer-head-actions">
|
|
651
|
+
<button id="scnDelete" class="btn-danger" hidden>Delete</button>
|
|
652
|
+
<button id="scnDrawerClose" class="drawer-close" aria-label="Close">×</button>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
<div class="drawer-body">
|
|
656
|
+
<label class="modal-label" for="scnTitle">Title</label>
|
|
657
|
+
<input id="scnTitle" type="text" autocomplete="off" placeholder="e.g. Translate docs to English">
|
|
658
|
+
<label class="modal-label" for="scnCategory">Category</label>
|
|
659
|
+
<input id="scnCategory" type="text" autocomplete="off" placeholder="e.g. Image / Custom" list="scnCatList">
|
|
660
|
+
<datalist id="scnCatList"></datalist>
|
|
661
|
+
<label class="modal-label" for="scnDesc">Description</label>
|
|
662
|
+
<input id="scnDesc" type="text" autocomplete="off" placeholder="One-line description (optional)">
|
|
663
|
+
<label class="modal-label" for="scnPrompt">Prompt template</label>
|
|
664
|
+
<textarea id="scnPrompt" class="scn-textarea" placeholder="Use {{key}} placeholders for inputs"></textarea>
|
|
665
|
+
<div class="scn-inputs-head">
|
|
666
|
+
<span class="modal-label" style="margin:0">Inputs</span>
|
|
667
|
+
<button id="scnAddInput" class="btn-soft btn-xs" type="button">+ Add input</button>
|
|
668
|
+
</div>
|
|
669
|
+
<div id="scnInputRows"></div>
|
|
670
|
+
<p class="scn-hint">Inputs become fillable fields when dispatching. Reference each one in the prompt as {{key}}.</p>
|
|
671
|
+
<div id="scnDrawerErr" class="modal-err"></div>
|
|
672
|
+
</div>
|
|
673
|
+
<div class="drawer-foot drawer-foot-end">
|
|
674
|
+
<button id="scnDrawerSave" class="btn-primary">Save scenario</button>
|
|
675
|
+
</div>
|
|
676
|
+
</aside>
|
|
677
|
+
</div>
|
|
678
|
+
<div id="modal" class="modal-overlay" hidden>
|
|
679
|
+
<div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
|
|
680
|
+
<h3 id="modalTitle">New profile</h3>
|
|
681
|
+
<p class="modal-sub">Create a named profile with its own credentials and default models.</p>
|
|
682
|
+
<label class="modal-label" for="modalInput">Profile name</label>
|
|
683
|
+
<input id="modalInput" type="text" placeholder="e.g. work, intl, test" autocomplete="off" spellcheck="false">
|
|
684
|
+
<div id="modalErr" class="modal-err"></div>
|
|
685
|
+
<div class="modal-foot">
|
|
686
|
+
<button id="modalCancel" class="btn-soft">Cancel</button>
|
|
687
|
+
<button id="modalCreate" class="btn-primary">Create</button>
|
|
688
|
+
</div>
|
|
76
689
|
</div>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
<
|
|
690
|
+
</div>
|
|
691
|
+
<div id="confirm" class="modal-overlay" hidden>
|
|
692
|
+
<div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="confirmTitle">
|
|
693
|
+
<h3 id="confirmTitle"></h3>
|
|
694
|
+
<p class="modal-sub" id="confirmMsg"></p>
|
|
695
|
+
<div class="modal-foot">
|
|
696
|
+
<button id="confirmCancel" class="btn-soft">Cancel</button>
|
|
697
|
+
<button id="confirmOk" class="btn-danger-solid">Delete</button>
|
|
698
|
+
</div>
|
|
82
699
|
</div>
|
|
83
|
-
</
|
|
700
|
+
</div>
|
|
701
|
+
<div id="dispatch" class="modal-overlay" hidden>
|
|
702
|
+
<div class="modal-card" role="dialog" aria-modal="true" aria-labelledby="dispatchTitle">
|
|
703
|
+
<h3 id="dispatchTitle"></h3>
|
|
704
|
+
<p class="modal-sub" id="dispatchDesc"></p>
|
|
705
|
+
<label class="modal-label" for="dispatchAgent">Target agent</label>
|
|
706
|
+
<select id="dispatchAgent" class="select"></select>
|
|
707
|
+
<div id="dispatchInputs"></div>
|
|
708
|
+
<label class="modal-label">Task to dispatch</label>
|
|
709
|
+
<pre id="dispatchPreview" class="dispatch-preview"></pre>
|
|
710
|
+
<div id="dispatchErr" class="modal-err"></div>
|
|
711
|
+
<div class="modal-foot">
|
|
712
|
+
<button id="dispatchCancel" class="btn-soft">Cancel</button>
|
|
713
|
+
<button id="dispatchGo" class="btn-primary">Run it</button>
|
|
714
|
+
</div>
|
|
715
|
+
</div>
|
|
716
|
+
</div>
|
|
84
717
|
</div>
|
|
85
718
|
<script>
|
|
86
719
|
var token = new URLSearchParams(location.search).get('token') || '';
|
|
87
|
-
var KEYS = [], SECRETS = [], DATA = { default: {}, named: {} }, CURRENT = '', ACTIVE = 'default';
|
|
720
|
+
var KEYS = [], SECRETS = [], ENUMS = {}, BOOLEANS = [], FIELD_DEFAULTS = {}, MODEL_CATALOG = {}, DATA = { default: {}, named: {} }, CURRENT = '', ACTIVE = 'default';
|
|
721
|
+
var loaded = { skills: false, mcp: false, agents: false, assets: false, playground: false, start: false };
|
|
722
|
+
var SCENARIOS = [], BUILTIN_SCENARIOS = [], DISPATCH_AGENTS = [], SCN_Q = '', SCN_FILTER = 'all', SCN_PAGE = 1, DISPATCH_SCN = null;
|
|
723
|
+
var ASSETS = [], ASSET_FILTER = 'all', ASSET_SORT = 'new', ASSET_Q = '', ASSET_PAGE = 1;
|
|
724
|
+
var AGENTS = [], AGENT_FILTER = 'all', AGENT_Q = '', AGENT_PAGE = 1;
|
|
725
|
+
var SKILLS = [], SKILL_Q = '', SKILL_PAGE = 1;
|
|
726
|
+
var MCPS = [], MCP_Q = '', MCP_PAGE = 1;
|
|
727
|
+
var PAGE_SIZES = [10, 20, 50];
|
|
728
|
+
var PAGE_SIZE_KEY = 'bl.pageSize.';
|
|
729
|
+
function getPageSize(view) {
|
|
730
|
+
try {
|
|
731
|
+
var v = parseInt(localStorage.getItem(PAGE_SIZE_KEY + view), 10);
|
|
732
|
+
if (PAGE_SIZES.indexOf(v) >= 0) return v;
|
|
733
|
+
} catch (e) { /* ignore */ }
|
|
734
|
+
return 20;
|
|
735
|
+
}
|
|
736
|
+
function setPageSize(view, n) { try { localStorage.setItem(PAGE_SIZE_KEY + view, String(n)); } catch (e) { /* ignore */ } }
|
|
737
|
+
var AUTH = null, authPoll = null, HEALTH = null, AUTO_START_CHECKED = false, QS_LOGIN_BTN = null;
|
|
738
|
+
var FIRST_RUN_KEY = 'bl.firstRunDone';
|
|
739
|
+
var SIDEBAR_KEY = 'bl.sidebarCollapsed';
|
|
740
|
+
var PERSON_SVG = '<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 12a5 5 0 1 0 0-10 5 5 0 0 0 0 10Zm0 2c-4.42 0-8 2.24-8 5v1h16v-1c0-2.76-3.58-5-8-5Z"/></svg>';
|
|
741
|
+
var PLAY_SVG = '<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8 5v14l11-7z"/></svg>';
|
|
742
|
+
// Signed-in avatar photo. The generated colour + person icon stay as the
|
|
743
|
+
// background fallback while the image loads or if it fails.
|
|
744
|
+
var AVATAR_URL = 'https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg';
|
|
745
|
+
function setAvatar(elm, seed) {
|
|
746
|
+
elm.style.background = avatarStyle(seed);
|
|
747
|
+
elm.innerHTML = PERSON_SVG;
|
|
748
|
+
var img = document.createElement('img');
|
|
749
|
+
img.alt = '';
|
|
750
|
+
img.onload = function () { elm.innerHTML = ''; elm.appendChild(img); };
|
|
751
|
+
img.src = AVATAR_URL;
|
|
752
|
+
}
|
|
88
753
|
|
|
89
754
|
function api(path, opts) {
|
|
90
755
|
var sep = path.indexOf('?') >= 0 ? '&' : '?';
|
|
91
756
|
return fetch(path + sep + 'token=' + encodeURIComponent(token), opts || {});
|
|
92
757
|
}
|
|
93
|
-
|
|
758
|
+
function el(tag, cls, text) {
|
|
759
|
+
var e = document.createElement(tag);
|
|
760
|
+
if (cls) e.className = cls;
|
|
761
|
+
if (text !== undefined && text !== null) e.textContent = text;
|
|
762
|
+
return e;
|
|
763
|
+
}
|
|
764
|
+
function originBadge(origin) {
|
|
765
|
+
var o = origin === 'remote' ? 'remote' : 'local';
|
|
766
|
+
return el('span', 'origin ' + o, o === 'remote' ? 'Remote' : 'Local');
|
|
767
|
+
}
|
|
94
768
|
function setStatus(msg, isErr) {
|
|
95
|
-
var
|
|
96
|
-
|
|
97
|
-
|
|
769
|
+
var s = document.getElementById('status');
|
|
770
|
+
s.textContent = msg || '';
|
|
771
|
+
s.className = isErr ? 'err' : 'muted';
|
|
772
|
+
}
|
|
773
|
+
function setCount(view, n) {
|
|
774
|
+
var b = document.getElementById('cnt-' + view);
|
|
775
|
+
if (b) b.textContent = n === undefined || n === null ? '' : String(n);
|
|
98
776
|
}
|
|
99
777
|
|
|
100
|
-
|
|
101
|
-
|
|
778
|
+
/* ---------- view switching ---------- */
|
|
779
|
+
function showView(name) {
|
|
780
|
+
var items = document.querySelectorAll('.nav-item');
|
|
781
|
+
for (var i = 0; i < items.length; i++) {
|
|
782
|
+
items[i].classList.toggle('is-active', items[i].getAttribute('data-view') === name);
|
|
783
|
+
}
|
|
784
|
+
var views = document.querySelectorAll('.view');
|
|
785
|
+
for (var j = 0; j < views.length; j++) {
|
|
786
|
+
views[j].classList.toggle('is-active', views[j].id === 'view-' + name);
|
|
787
|
+
}
|
|
788
|
+
if (name === 'skills' && !loaded.skills) loadSkills();
|
|
789
|
+
if (name === 'mcp' && !loaded.mcp) loadMcp();
|
|
790
|
+
if (name === 'agents' && !loaded.agents) loadAgents();
|
|
791
|
+
if (name === 'assets' && !loaded.assets) loadAssets();
|
|
792
|
+
if (name === 'playground' && !loaded.playground) loadPlayground();
|
|
793
|
+
if (name === 'start') loadQuickStart();
|
|
102
794
|
}
|
|
103
795
|
|
|
104
|
-
|
|
796
|
+
/* ---------- quick start ---------- */
|
|
797
|
+
function firstRunDone() { try { return localStorage.getItem(FIRST_RUN_KEY) === '1'; } catch (e) { return false; } }
|
|
798
|
+
function markFirstRun() { try { localStorage.setItem(FIRST_RUN_KEY, '1'); } catch (e) {} }
|
|
799
|
+
function loadQuickStart() {
|
|
800
|
+
loaded.start = true;
|
|
801
|
+
var body = document.getElementById('qsBody');
|
|
802
|
+
Promise.all([
|
|
803
|
+
api('/api/health').then(function (r) { return r.json(); }).catch(function () { return null; }),
|
|
804
|
+
api('/api/auth/status').then(function (r) { return r.json(); }).catch(function () { return null; }),
|
|
805
|
+
api('/api/agents').then(function (r) { return r.json(); }).catch(function () { return null; })
|
|
806
|
+
]).then(function (res) {
|
|
807
|
+
HEALTH = res[0];
|
|
808
|
+
var auth = res[1] || AUTH || { authenticated: false };
|
|
809
|
+
AUTH = auth;
|
|
810
|
+
var agents = (res[2] && res[2].agents) || [];
|
|
811
|
+
renderQuickStart(HEALTH, auth, agents);
|
|
812
|
+
}).catch(function (e) { renderError(body, e); });
|
|
813
|
+
}
|
|
814
|
+
function qsDesc(html) { var p = el('p', 'qs-desc'); p.innerHTML = html; return p; }
|
|
815
|
+
function qsBtn(label, onclick, primary) {
|
|
816
|
+
var b = el('button', primary ? 'btn-primary' : 'btn-soft', label);
|
|
817
|
+
b.type = 'button'; b.onclick = onclick; return b;
|
|
818
|
+
}
|
|
819
|
+
function qsStep(n, done, locked, title, descNode, actNode) {
|
|
820
|
+
var step = el('div', 'qs-step' + (done ? ' done' : '') + (locked ? ' locked' : ''));
|
|
821
|
+
var head = el('div', 'qs-head');
|
|
822
|
+
head.appendChild(el('span', 'qs-ic', done ? '✓' : String(n)));
|
|
823
|
+
if (done) head.appendChild(el('span', 'qs-done-tag', 'Done'));
|
|
824
|
+
step.appendChild(head);
|
|
825
|
+
step.appendChild(el('div', 'qs-title', title));
|
|
826
|
+
if (descNode) step.appendChild(descNode);
|
|
827
|
+
if (actNode && !done) { var wrap = el('div', 'qs-act'); wrap.appendChild(actNode); step.appendChild(wrap); }
|
|
828
|
+
return step;
|
|
829
|
+
}
|
|
830
|
+
function renderQuickStart(health, auth, agents) {
|
|
831
|
+
var body = document.getElementById('qsBody');
|
|
832
|
+
body.innerHTML = '';
|
|
833
|
+
var steps = el('div', 'qs-steps');
|
|
834
|
+
var envOk = !!(health && health.nodeOk);
|
|
835
|
+
var envDesc = health
|
|
836
|
+
? qsDesc('Runtime Node <code>' + escapeHtml(health.node || '') + '</code> · platform <code>' + escapeHtml(health.platform || '') + '</code>' + (envOk ? '' : '<br>Node 18 or newer is recommended.'))
|
|
837
|
+
: qsDesc('Could not read runtime environment info.');
|
|
838
|
+
steps.appendChild(qsStep(1, envOk, false, 'Environment check', envDesc, null));
|
|
839
|
+
var authed = !!(auth && auth.authenticated);
|
|
840
|
+
var loginDesc;
|
|
841
|
+
if (authed) {
|
|
842
|
+
var meta = [];
|
|
843
|
+
if (auth.primary) meta.push(authMethodLabel(auth.primary));
|
|
844
|
+
if (auth.region) meta.push(auth.region);
|
|
845
|
+
if (auth.site) meta.push(auth.site);
|
|
846
|
+
loginDesc = qsDesc('Signed in: ' + escapeHtml(meta.join(' · ') || 'Authenticated'));
|
|
847
|
+
} else {
|
|
848
|
+
loginDesc = qsDesc('Sign in to the Bailian console to obtain credentials (opens a login page in your browser).');
|
|
849
|
+
}
|
|
850
|
+
QS_LOGIN_BTN = qsBtn('Log in', function () { startLogin(); }, true);
|
|
851
|
+
steps.appendChild(qsStep(2, authed, false, 'Sign in to Bailian', loginDesc, QS_LOGIN_BTN));
|
|
852
|
+
var connectedAgents = agents.filter(function (a) { return a.installed && a.configured; });
|
|
853
|
+
var installedAgents = agents.filter(function (a) { return a.installed; });
|
|
854
|
+
var connected = connectedAgents.length > 0;
|
|
855
|
+
var agentDesc;
|
|
856
|
+
if (connected) {
|
|
857
|
+
agentDesc = qsDesc('Connected: ' + escapeHtml(connectedAgents.map(function (a) { return a.label; }).join(', ')));
|
|
858
|
+
} else if (installedAgents.length) {
|
|
859
|
+
agentDesc = qsDesc('Installed but not wired into bl: ' + escapeHtml(installedAgents.map(function (a) { return a.label; }).join(', ')) + '. Open the Agents page to finish connecting.');
|
|
860
|
+
} else {
|
|
861
|
+
agentDesc = qsDesc('No connected local coding agent detected (e.g. qwen-code). Open the Agents page to install and connect one.');
|
|
862
|
+
}
|
|
863
|
+
steps.appendChild(qsStep(3, connected, false, 'Connect a local agent', agentDesc, qsBtn('Go to Agents', function () { showView('agents'); }, false)));
|
|
864
|
+
var dispatchable = agents.some(function (a) { return a.dispatchable; });
|
|
865
|
+
var ran = firstRunDone();
|
|
866
|
+
var runDesc;
|
|
867
|
+
if (ran) {
|
|
868
|
+
runDesc = qsDesc('You have dispatched at least one task.');
|
|
869
|
+
} else if (!dispatchable) {
|
|
870
|
+
runDesc = qsDesc('Finish the previous step first (connect a dispatchable agent), then come back to Playground to run your first scenario.');
|
|
871
|
+
} else {
|
|
872
|
+
runDesc = qsDesc('Go to Playground, pick a scenario and click Run it to complete your first dispatch.');
|
|
873
|
+
}
|
|
874
|
+
var runBtn = qsBtn('Go to Playground', function () { showView('playground'); }, true);
|
|
875
|
+
if (!dispatchable) runBtn.disabled = true;
|
|
876
|
+
steps.appendChild(qsStep(4, ran, !ran && !dispatchable, 'Run your first task', runDesc, runBtn));
|
|
877
|
+
body.appendChild(steps);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/* ---------- profiles ---------- */
|
|
881
|
+
function profileData(name) { return name === '' ? DATA.default : (DATA.named[name] || {}); }
|
|
882
|
+
|
|
883
|
+
function loadConfig() {
|
|
105
884
|
api('/api/config').then(function (r) { return r.json(); }).then(function (j) {
|
|
106
|
-
KEYS = j.keys || [];
|
|
107
|
-
|
|
885
|
+
KEYS = j.keys || []; SECRETS = j.secretKeys || [];
|
|
886
|
+
ENUMS = j.enums || {}; BOOLEANS = j.booleanKeys || [];
|
|
887
|
+
FIELD_DEFAULTS = j.fieldDefaults || {};
|
|
888
|
+
MODEL_CATALOG = j.modelCatalog || {};
|
|
108
889
|
DATA = { default: j.default || {}, named: j.named || {} };
|
|
109
890
|
ACTIVE = j.activeProfile || 'default';
|
|
110
|
-
document.getElementById('cfgFile').textContent = j.configFile || '';
|
|
111
891
|
CURRENT = ACTIVE === 'default' ? '' : ACTIVE;
|
|
112
|
-
|
|
113
|
-
renderForm();
|
|
892
|
+
setCount('profiles', 1 + Object.keys(DATA.named).length);
|
|
893
|
+
renderProfiles(); renderForm();
|
|
114
894
|
}).catch(function (e) { setStatus('Load failed: ' + e, true); });
|
|
115
895
|
}
|
|
116
896
|
|
|
117
897
|
function renderProfiles() {
|
|
118
|
-
var
|
|
119
|
-
|
|
898
|
+
var grid = document.getElementById('profileList');
|
|
899
|
+
grid.innerHTML = '';
|
|
120
900
|
var names = [''].concat(Object.keys(DATA.named));
|
|
121
901
|
names.forEach(function (name) {
|
|
122
|
-
var li = document.createElement('li');
|
|
123
902
|
var displayName = name === '' ? 'default' : name;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
903
|
+
var t = el('div', 'tile clickable profile-tile' + (name === CURRENT ? ' selected' : ''));
|
|
904
|
+
var top = el('div', 'tile-top');
|
|
905
|
+
top.appendChild(el('span', 'tile-name', displayName));
|
|
906
|
+
if (displayName === ACTIVE) top.appendChild(el('span', 'star', '★'));
|
|
907
|
+
top.appendChild(el('span', 'chev', '›'));
|
|
908
|
+
t.appendChild(top);
|
|
909
|
+
t.onclick = function () { CURRENT = name; renderProfiles(); renderForm(); setStatus(''); openDrawer(); };
|
|
910
|
+
grid.appendChild(t);
|
|
911
|
+
});
|
|
912
|
+
var add = el('div', 'tile tile-add', '+ New profile');
|
|
913
|
+
add.onclick = newProfile;
|
|
914
|
+
grid.appendChild(add);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function openDrawer() {
|
|
918
|
+
var d = document.getElementById('drawer');
|
|
919
|
+
d.hidden = false;
|
|
920
|
+
document.body.style.overflow = 'hidden';
|
|
921
|
+
}
|
|
922
|
+
function closeDrawer() {
|
|
923
|
+
document.getElementById('drawer').hidden = true;
|
|
924
|
+
document.body.style.overflow = '';
|
|
925
|
+
setStatus('');
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/* ---------- read-only detail drawer (skills, ...) ---------- */
|
|
929
|
+
function openInfoDrawer() {
|
|
930
|
+
var f = document.getElementById('infoFoot');
|
|
931
|
+
if (f) { f.innerHTML = ''; f.hidden = true; }
|
|
932
|
+
document.getElementById('infoDrawer').hidden = false;
|
|
933
|
+
document.body.style.overflow = 'hidden';
|
|
934
|
+
}
|
|
935
|
+
function closeInfoDrawer() {
|
|
936
|
+
document.getElementById('infoDrawer').hidden = true;
|
|
937
|
+
document.body.style.overflow = '';
|
|
938
|
+
}
|
|
939
|
+
function detailSection(label, node, action) {
|
|
940
|
+
var sec = el('div', 'detail-sec');
|
|
941
|
+
var head = el('div', 'detail-label', label);
|
|
942
|
+
if (action) { head.classList.add('detail-label-row'); head.appendChild(action); }
|
|
943
|
+
sec.appendChild(head);
|
|
944
|
+
sec.appendChild(node);
|
|
945
|
+
return sec;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/* Minimal, XSS-safe Markdown renderer (escape first, then wrap in tags). */
|
|
949
|
+
var BT = String.fromCharCode(96);
|
|
950
|
+
function escapeHtml(s) {
|
|
951
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
952
|
+
}
|
|
953
|
+
function mdSpans(s) {
|
|
954
|
+
s = s.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');
|
|
955
|
+
s = s.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');
|
|
956
|
+
s = s.replace(/\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g, function (m, txt, url) {
|
|
957
|
+
var safe = /^(https?:|mailto:|#|\\/|\\.)/i.test(url) ? url : '#';
|
|
958
|
+
return '<a href="' + safe + '" target="_blank" rel="noopener">' + txt + '</a>';
|
|
959
|
+
});
|
|
960
|
+
return s;
|
|
961
|
+
}
|
|
962
|
+
function mdInline(text) {
|
|
963
|
+
var segs = text.split(BT);
|
|
964
|
+
var out = '';
|
|
965
|
+
for (var k = 0; k < segs.length; k++) {
|
|
966
|
+
if (k % 2 === 1) out += '<code>' + segs[k] + '</code>';
|
|
967
|
+
else out += mdSpans(segs[k]);
|
|
968
|
+
}
|
|
969
|
+
return out;
|
|
970
|
+
}
|
|
971
|
+
function splitTableRow(line) {
|
|
972
|
+
var s = line.trim().replace(/^\\|/, '').replace(/\\|$/, '');
|
|
973
|
+
return s.split('|').map(function (c) { return c.trim(); });
|
|
974
|
+
}
|
|
975
|
+
function renderMarkdown(md) {
|
|
976
|
+
md = md.replace(/^---\\n[\\s\\S]*?\\n---\\n?/, '');
|
|
977
|
+
var lines = md.split(/\\r?\\n/);
|
|
978
|
+
var html = '';
|
|
979
|
+
var i = 0;
|
|
980
|
+
var listType = null;
|
|
981
|
+
function closeList() { if (listType) { html += '</' + listType + '>'; listType = null; } }
|
|
982
|
+
while (i < lines.length) {
|
|
983
|
+
var line = lines[i];
|
|
984
|
+
if (line.indexOf(BT + BT + BT) === 0) {
|
|
985
|
+
closeList();
|
|
986
|
+
var buf = [];
|
|
987
|
+
i++;
|
|
988
|
+
while (i < lines.length && lines[i].indexOf(BT + BT + BT) !== 0) { buf.push(lines[i]); i++; }
|
|
989
|
+
i++;
|
|
990
|
+
html += '<pre class="md-pre"><code>' + escapeHtml(buf.join('\\n')) + '</code></pre>';
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
var h = line.match(/^(#{1,6})\\s+(.*)$/);
|
|
994
|
+
if (h) { closeList(); var lvl = h[1].length; html += '<h' + lvl + '>' + mdInline(escapeHtml(h[2])) + '</h' + lvl + '>'; i++; continue; }
|
|
995
|
+
if (/^\\s*(-{3,}|\\*{3,}|_{3,})\\s*$/.test(line)) { closeList(); html += '<hr>'; i++; continue; }
|
|
996
|
+
if (/^>\\s?/.test(line)) {
|
|
997
|
+
closeList();
|
|
998
|
+
var q = [];
|
|
999
|
+
while (i < lines.length && /^>\\s?/.test(lines[i])) { q.push(lines[i].replace(/^>\\s?/, '')); i++; }
|
|
1000
|
+
html += '<blockquote>' + mdInline(escapeHtml(q.join(' '))) + '</blockquote>';
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
var ul = line.match(/^\\s*[-*+]\\s+(.*)$/);
|
|
1004
|
+
if (ul) {
|
|
1005
|
+
if (listType !== 'ul') { closeList(); html += '<ul>'; listType = 'ul'; }
|
|
1006
|
+
html += '<li>' + mdInline(escapeHtml(ul[1])) + '</li>';
|
|
1007
|
+
i++; continue;
|
|
1008
|
+
}
|
|
1009
|
+
var ol = line.match(/^\\s*\\d+\\.\\s+(.*)$/);
|
|
1010
|
+
if (ol) {
|
|
1011
|
+
if (listType !== 'ol') { closeList(); html += '<ol>'; listType = 'ol'; }
|
|
1012
|
+
html += '<li>' + mdInline(escapeHtml(ol[1])) + '</li>';
|
|
1013
|
+
i++; continue;
|
|
1014
|
+
}
|
|
1015
|
+
// GFM table: a header row followed by a |---|---| separator line.
|
|
1016
|
+
if (line.indexOf('|') >= 0 && i + 1 < lines.length &&
|
|
1017
|
+
/^\\s*\\|?\\s*:?-{1,}:?\\s*(\\|\\s*:?-{1,}:?\\s*)+\\|?\\s*$/.test(lines[i + 1])) {
|
|
1018
|
+
closeList();
|
|
1019
|
+
var headCells = splitTableRow(line);
|
|
1020
|
+
i += 2;
|
|
1021
|
+
var bodyRows = [];
|
|
1022
|
+
while (i < lines.length && lines[i].indexOf('|') >= 0 && !/^\\s*$/.test(lines[i])) {
|
|
1023
|
+
bodyRows.push(splitTableRow(lines[i])); i++;
|
|
1024
|
+
}
|
|
1025
|
+
var thtml = '<table class="md-table"><thead><tr>';
|
|
1026
|
+
for (var hc = 0; hc < headCells.length; hc++) thtml += '<th>' + mdInline(escapeHtml(headCells[hc])) + '</th>';
|
|
1027
|
+
thtml += '</tr></thead><tbody>';
|
|
1028
|
+
for (var br = 0; br < bodyRows.length; br++) {
|
|
1029
|
+
thtml += '<tr>';
|
|
1030
|
+
for (var td = 0; td < headCells.length; td++) thtml += '<td>' + mdInline(escapeHtml(bodyRows[br][td] || '')) + '</td>';
|
|
1031
|
+
thtml += '</tr>';
|
|
1032
|
+
}
|
|
1033
|
+
thtml += '</tbody></table>';
|
|
1034
|
+
html += thtml;
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
if (/^\\s*$/.test(line)) { closeList(); i++; continue; }
|
|
1038
|
+
closeList();
|
|
1039
|
+
var para = [line];
|
|
1040
|
+
i++;
|
|
1041
|
+
while (i < lines.length && !/^\\s*$/.test(lines[i]) && lines[i].indexOf(BT + BT + BT) !== 0 && !/^(#{1,6}\\s|>|\\s*[-*+]\\s|\\s*\\d+\\.\\s)/.test(lines[i]) && !/^\\s*(-{3,}|\\*{3,}|_{3,})\\s*$/.test(lines[i])) {
|
|
1042
|
+
para.push(lines[i]); i++;
|
|
1043
|
+
}
|
|
1044
|
+
html += '<p>' + mdInline(escapeHtml(para.join(' '))) + '</p>';
|
|
1045
|
+
}
|
|
1046
|
+
closeList();
|
|
1047
|
+
return html;
|
|
1048
|
+
}
|
|
1049
|
+
function renderMarkdownInto(container, md) {
|
|
1050
|
+
if (!md) { container.appendChild(el('div', 'loading', '(empty)')); return; }
|
|
1051
|
+
var wrap = el('div', 'md-body');
|
|
1052
|
+
wrap.innerHTML = renderMarkdown(md);
|
|
1053
|
+
container.appendChild(wrap);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
var SKILL_TARGETS = [
|
|
1057
|
+
{ source: 'global', label: 'All agents (~/.agents/skills)' },
|
|
1058
|
+
{ source: 'claude-code', label: 'Claude Code' },
|
|
1059
|
+
{ source: 'qwen-code', label: 'Qwen Code' },
|
|
1060
|
+
{ source: 'codex', label: 'Codex' },
|
|
1061
|
+
{ source: 'opencode', label: 'OpenCode' },
|
|
1062
|
+
{ source: 'openclaw', label: 'OpenClaw' },
|
|
1063
|
+
{ source: 'qoderwork', label: 'QoderWork' },
|
|
1064
|
+
{ source: 'windsurf', label: 'Windsurf' },
|
|
1065
|
+
{ source: 'gemini', label: 'Gemini' }
|
|
1066
|
+
];
|
|
1067
|
+
function setSkillErr(msg) { var e = document.getElementById('skillErr'); if (e) e.textContent = msg || ''; }
|
|
1068
|
+
function openSkillInstall() {
|
|
1069
|
+
var title = document.getElementById('infoTitle');
|
|
1070
|
+
title.textContent = ''; title.appendChild(el('span', '', 'Add skill'));
|
|
1071
|
+
var body = document.getElementById('infoBody'); body.innerHTML = '';
|
|
1072
|
+
var sel = el('select', 'select'); sel.id = 'skillNewSource';
|
|
1073
|
+
SKILL_TARGETS.forEach(function (s) { var o = el('option', '', s.label); o.value = s.source; sel.appendChild(o); });
|
|
1074
|
+
body.appendChild(detailSection('Install to', sel));
|
|
1075
|
+
var nameInp = el('input'); nameInp.id = 'skillNewName'; nameInp.type = 'text';
|
|
1076
|
+
nameInp.placeholder = 'Optional — folder name (defaults to the archive folder)'; nameInp.autocomplete = 'off';
|
|
1077
|
+
body.appendChild(detailSection('Skill name (optional)', nameInp));
|
|
1078
|
+
var fileInp = el('input'); fileInp.id = 'skillFile'; fileInp.type = 'file'; fileInp.accept = '.zip,application/zip';
|
|
1079
|
+
fileInp.style.display = 'none';
|
|
1080
|
+
var picker = el('div', 'file-picker');
|
|
1081
|
+
var pickBtn = el('button', 'file-pick-btn', 'Choose .zip file'); pickBtn.type = 'button';
|
|
1082
|
+
var fileName = el('span', 'file-name', 'No file selected');
|
|
1083
|
+
pickBtn.onclick = function () { fileInp.click(); };
|
|
1084
|
+
fileInp.onchange = function () {
|
|
1085
|
+
var f = fileInp.files && fileInp.files[0];
|
|
1086
|
+
fileName.textContent = f ? f.name : 'No file selected';
|
|
1087
|
+
fileName.classList.toggle('has-file', !!f);
|
|
1088
|
+
};
|
|
1089
|
+
picker.appendChild(pickBtn); picker.appendChild(fileName); picker.appendChild(fileInp);
|
|
1090
|
+
body.appendChild(detailSection('Skill package (.zip)', picker));
|
|
1091
|
+
body.appendChild(el('p', 'mcp-note', 'The .zip must contain a SKILL.md at its root or inside a single top-level folder.'));
|
|
1092
|
+
var err = el('div', 'modal-err'); err.id = 'skillErr'; body.appendChild(err);
|
|
1093
|
+
openInfoDrawer();
|
|
1094
|
+
var foot = document.getElementById('infoFoot'); foot.innerHTML = ''; foot.hidden = false;
|
|
1095
|
+
var install = el('button', 'btn-primary', 'Install'); install.type = 'button';
|
|
1096
|
+
install.onclick = function () { doInstallSkill(install); };
|
|
1097
|
+
foot.appendChild(install);
|
|
1098
|
+
}
|
|
1099
|
+
function doInstallSkill(btn) {
|
|
1100
|
+
setSkillErr('');
|
|
1101
|
+
var source = document.getElementById('skillNewSource').value;
|
|
1102
|
+
var name = (document.getElementById('skillNewName').value || '').trim();
|
|
1103
|
+
var fileInput = document.getElementById('skillFile');
|
|
1104
|
+
var file = fileInput.files && fileInput.files[0];
|
|
1105
|
+
if (!file) { setSkillErr('Please choose a .zip file.'); return; }
|
|
1106
|
+
btn.disabled = true;
|
|
1107
|
+
file.arrayBuffer().then(function (buf) {
|
|
1108
|
+
return api('/api/skill/install?source=' + encodeURIComponent(source) + '&name=' + encodeURIComponent(name),
|
|
1109
|
+
{ method: 'POST', headers: { 'Content-Type': 'application/zip' }, body: buf });
|
|
1110
|
+
}).then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
1111
|
+
.then(function (res) {
|
|
1112
|
+
btn.disabled = false;
|
|
1113
|
+
if (!res.ok) { setSkillErr((res.j && res.j.error) || 'Install failed'); return; }
|
|
1114
|
+
closeInfoDrawer(); loaded.skills = false; loadSkills();
|
|
1115
|
+
notify('Installed', 'Skill "' + res.j.installed + '" installed (' + res.j.files + ' files) to ' + source + '.');
|
|
1116
|
+
})
|
|
1117
|
+
.catch(function (e) { btn.disabled = false; setSkillErr('Install failed: ' + e); });
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function openSkillDetail(s) {
|
|
1121
|
+
var title = document.getElementById('infoTitle');
|
|
1122
|
+
title.textContent = '';
|
|
1123
|
+
title.appendChild(el('span', '', s.name));
|
|
1124
|
+
if (s.version) title.appendChild(el('span', 'ver', 'v' + s.version));
|
|
1125
|
+
title.appendChild(originBadge(s.origin));
|
|
1126
|
+
var body = document.getElementById('infoBody');
|
|
1127
|
+
body.innerHTML = '';
|
|
1128
|
+
if (s.description) body.appendChild(detailSection('Description', el('div', 'detail-desc', s.description)));
|
|
1129
|
+
var chips = el('div', 'detail-chips');
|
|
1130
|
+
(s.sources || []).forEach(function (src) { chips.appendChild(el('span', 'chip blue', src)); });
|
|
1131
|
+
chips.appendChild(el('span', 'chip', s.fileCount + ' files'));
|
|
1132
|
+
body.appendChild(detailSection('Installed in', chips));
|
|
1133
|
+
body.appendChild(detailSection('Path', el('div', 'detail-path', s.path)));
|
|
1134
|
+
var codeSec = detailSection('SKILL.md', el('div', 'loading', 'Loading…'));
|
|
1135
|
+
body.appendChild(codeSec);
|
|
1136
|
+
openInfoDrawer();
|
|
1137
|
+
api('/api/skill?id=' + encodeURIComponent(s.id)).then(function (r) { return r.json(); }).then(function (j) {
|
|
1138
|
+
codeSec.removeChild(codeSec.lastChild);
|
|
1139
|
+
renderMarkdownInto(codeSec, (j && j.content) || '');
|
|
1140
|
+
}).catch(function (e) {
|
|
1141
|
+
codeSec.removeChild(codeSec.lastChild);
|
|
1142
|
+
codeSec.appendChild(el('div', 'err', 'Failed to load: ' + e));
|
|
128
1143
|
});
|
|
129
1144
|
}
|
|
130
1145
|
|
|
1146
|
+
function makeSelect(key, options, current) {
|
|
1147
|
+
var sel = document.createElement('select');
|
|
1148
|
+
sel.id = 'f_' + key; sel.name = key; sel.className = 'select';
|
|
1149
|
+
var blank = document.createElement('option'); blank.value = ''; blank.textContent = '(unset)';
|
|
1150
|
+
sel.appendChild(blank);
|
|
1151
|
+
options.forEach(function (opt) {
|
|
1152
|
+
var o = document.createElement('option'); o.value = opt; o.textContent = opt;
|
|
1153
|
+
sel.appendChild(o);
|
|
1154
|
+
});
|
|
1155
|
+
sel.value = current;
|
|
1156
|
+
return sel;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
131
1159
|
function renderForm() {
|
|
132
1160
|
var form = document.getElementById('form');
|
|
133
1161
|
form.innerHTML = '';
|
|
@@ -139,237 +1167,1551 @@ Omni output voices:
|
|
|
139
1167
|
useBtn.textContent = selectedName === ACTIVE ? 'Active' : 'Save & Activate';
|
|
140
1168
|
var data = profileData(CURRENT);
|
|
141
1169
|
KEYS.forEach(function (key) {
|
|
142
|
-
var row =
|
|
143
|
-
|
|
144
|
-
var label = document.createElement('label');
|
|
145
|
-
label.textContent = key;
|
|
146
|
-
label.htmlFor = 'f_' + key;
|
|
147
|
-
var input = document.createElement('input');
|
|
148
|
-
input.id = 'f_' + key;
|
|
149
|
-
input.name = key;
|
|
1170
|
+
var row = el('div', 'row');
|
|
1171
|
+
var label = el('label', '', key); label.htmlFor = 'f_' + key;
|
|
150
1172
|
var val = data[key];
|
|
151
|
-
|
|
1173
|
+
var strVal = (val === undefined || val === null) ? '' : String(val);
|
|
152
1174
|
if (SECRETS.indexOf(key) >= 0) {
|
|
1175
|
+
var input = el('input'); input.id = 'f_' + key; input.name = key; input.value = strVal;
|
|
153
1176
|
input.type = 'password';
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
1177
|
+
// Prevent the browser password manager from autofilling a previously
|
|
1178
|
+
// saved value over the server's current value (e.g. after logout clears
|
|
1179
|
+
// the key). 'new-password' reliably suppresses saved-credential autofill.
|
|
1180
|
+
input.autocomplete = 'new-password';
|
|
1181
|
+
input.setAttribute('autocorrect', 'off'); input.spellcheck = false;
|
|
1182
|
+
var toggle = el('button', 'toggle', 'show'); toggle.type = 'button';
|
|
158
1183
|
toggle.onclick = function () {
|
|
159
1184
|
if (input.type === 'password') { input.type = 'text'; toggle.textContent = 'hide'; }
|
|
160
1185
|
else { input.type = 'password'; toggle.textContent = 'show'; }
|
|
161
1186
|
};
|
|
162
|
-
var wrap =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
row.appendChild(
|
|
1187
|
+
var wrap = el('div', 'inputwrap'); wrap.appendChild(input); wrap.appendChild(toggle);
|
|
1188
|
+
row.appendChild(label); row.appendChild(wrap);
|
|
1189
|
+
} else if (ENUMS[key]) {
|
|
1190
|
+
row.appendChild(label); row.appendChild(makeSelect(key, ENUMS[key], strVal));
|
|
1191
|
+
} else if (BOOLEANS.indexOf(key) >= 0) {
|
|
1192
|
+
row.appendChild(label); row.appendChild(makeSelect(key, ['true', 'false'], strVal));
|
|
168
1193
|
} else {
|
|
169
|
-
input.
|
|
170
|
-
|
|
171
|
-
|
|
1194
|
+
var textInput = el('input'); textInput.id = 'f_' + key; textInput.name = key;
|
|
1195
|
+
textInput.type = 'text';
|
|
1196
|
+
textInput.value = strVal || (FIELD_DEFAULTS[key] || '');
|
|
1197
|
+
row.appendChild(label); row.appendChild(textInput);
|
|
1198
|
+
if (MODEL_CATALOG[key]) row.appendChild(modelCatalogBlock(key, textInput));
|
|
172
1199
|
}
|
|
173
1200
|
form.appendChild(row);
|
|
174
1201
|
});
|
|
175
1202
|
}
|
|
176
1203
|
|
|
1204
|
+
function modelCatLabel(key) {
|
|
1205
|
+
return key.replace(/^default_/, '').replace(/_model$/, '');
|
|
1206
|
+
}
|
|
1207
|
+
function modelCatNote(key) {
|
|
1208
|
+
if (key === 'default_video_model') {
|
|
1209
|
+
return 'Applies to <code>bl video generate</code> only (text/image-to-video). '
|
|
1210
|
+
+ '<code>bl video ref</code> (multi-image) and <code>bl video edit</code> keep their own '
|
|
1211
|
+
+ 'fixed models — pass <code>--model</code> to override those per run.';
|
|
1212
|
+
}
|
|
1213
|
+
return '';
|
|
1214
|
+
}
|
|
1215
|
+
function modelCatalogBlock(key, input) {
|
|
1216
|
+
var opts = MODEL_CATALOG[key] || [];
|
|
1217
|
+
var box = el('div', 'model-cat');
|
|
1218
|
+
box.appendChild(el('div', 'model-cat-hint', 'Available ' + modelCatLabel(key) + ' models · click to use'));
|
|
1219
|
+
var chips = el('div', 'model-chips');
|
|
1220
|
+
function mark() {
|
|
1221
|
+
var cur = input.value.trim();
|
|
1222
|
+
Array.prototype.forEach.call(chips.children, function (c) {
|
|
1223
|
+
c.className = c.getAttribute('data-id') === cur ? 'mchip active' : 'mchip';
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
opts.forEach(function (o) {
|
|
1227
|
+
var chip = el('button', 'mchip', o.id);
|
|
1228
|
+
chip.type = 'button';
|
|
1229
|
+
chip.title = o.role;
|
|
1230
|
+
chip.setAttribute('data-id', o.id);
|
|
1231
|
+
chip.onclick = function () { input.value = o.id; mark(); };
|
|
1232
|
+
chips.appendChild(chip);
|
|
1233
|
+
});
|
|
1234
|
+
input.addEventListener('input', mark);
|
|
1235
|
+
box.appendChild(chips);
|
|
1236
|
+
var note = modelCatNote(key);
|
|
1237
|
+
if (note) {
|
|
1238
|
+
var noteEl = el('div', 'model-cat-note');
|
|
1239
|
+
noteEl.innerHTML = note;
|
|
1240
|
+
box.appendChild(noteEl);
|
|
1241
|
+
}
|
|
1242
|
+
setTimeout(mark, 0);
|
|
1243
|
+
return box;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
177
1246
|
function collect() {
|
|
178
1247
|
var data = {};
|
|
179
|
-
KEYS.forEach(function (key) {
|
|
180
|
-
var el = document.getElementById('f_' + key);
|
|
181
|
-
data[key] = el ? el.value : '';
|
|
182
|
-
});
|
|
1248
|
+
KEYS.forEach(function (key) { var e = document.getElementById('f_' + key); data[key] = e ? e.value : ''; });
|
|
183
1249
|
return data;
|
|
184
1250
|
}
|
|
185
1251
|
|
|
186
1252
|
function saveProfile(name, data) {
|
|
187
|
-
var
|
|
188
|
-
var body = JSON.stringify({ name: name, data: profileData });
|
|
1253
|
+
var payload = data === undefined ? collect() : data;
|
|
189
1254
|
return api('/api/profile', {
|
|
190
|
-
method: 'POST',
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
var saved = result.json.saved || {};
|
|
202
|
-
if (name === '') DATA.default = saved; else DATA.named[name] = saved;
|
|
203
|
-
return saved;
|
|
204
|
-
});
|
|
1255
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
1256
|
+
body: JSON.stringify({ name: name, data: payload })
|
|
1257
|
+
}).then(function (resp) {
|
|
1258
|
+
return resp.json().then(function (json) { return { ok: resp.ok, json: json }; });
|
|
1259
|
+
}).then(function (result) {
|
|
1260
|
+
if (!result.ok) throw new Error((result.json && result.json.error) || 'error');
|
|
1261
|
+
var saved = result.json.saved || {};
|
|
1262
|
+
if (name === '') DATA.default = saved; else DATA.named[name] = saved;
|
|
1263
|
+
return saved;
|
|
1264
|
+
});
|
|
205
1265
|
}
|
|
206
1266
|
|
|
207
1267
|
function save() {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
.then(function () {
|
|
211
|
-
renderForm();
|
|
212
|
-
setStatus('Saved.');
|
|
213
|
-
})
|
|
214
|
-
.catch(function (error) { setStatus('Save failed: ' + error.message, true); });
|
|
1268
|
+
saveProfile(CURRENT).then(function () { renderForm(); setStatus('Saved.'); })
|
|
1269
|
+
.catch(function (err) { setStatus('Save failed: ' + err.message, true); });
|
|
215
1270
|
}
|
|
216
1271
|
|
|
217
1272
|
function newProfile() {
|
|
218
|
-
var
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
1273
|
+
var input = document.getElementById('modalInput');
|
|
1274
|
+
input.value = '';
|
|
1275
|
+
setModalErr('');
|
|
1276
|
+
document.getElementById('modal').hidden = false;
|
|
1277
|
+
document.body.style.overflow = 'hidden';
|
|
1278
|
+
setTimeout(function () { input.focus(); }, 30);
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
function closeModal() {
|
|
1282
|
+
document.getElementById('modal').hidden = true;
|
|
1283
|
+
document.body.style.overflow = '';
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
function setModalErr(msg) {
|
|
1287
|
+
document.getElementById('modalErr').textContent = msg || '';
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
var _confirmOnOk = null;
|
|
1291
|
+
function openConfirm(opts) {
|
|
1292
|
+
opts = opts || {};
|
|
1293
|
+
document.getElementById('confirmTitle').textContent = opts.title || 'Are you sure?';
|
|
1294
|
+
document.getElementById('confirmMsg').textContent = opts.message || '';
|
|
1295
|
+
var ok = document.getElementById('confirmOk');
|
|
1296
|
+
var cancel = document.getElementById('confirmCancel');
|
|
1297
|
+
ok.textContent = opts.okLabel || 'Delete';
|
|
1298
|
+
ok.className = opts.danger === false ? 'btn-primary' : 'btn-danger-solid';
|
|
1299
|
+
cancel.hidden = !!opts.hideCancel;
|
|
1300
|
+
_confirmOnOk = opts.onConfirm || null;
|
|
1301
|
+
document.getElementById('confirm').hidden = false;
|
|
1302
|
+
document.body.style.overflow = 'hidden';
|
|
1303
|
+
setTimeout(function () { (opts.hideCancel ? ok : cancel).focus(); }, 30);
|
|
1304
|
+
}
|
|
1305
|
+
function closeConfirm() {
|
|
1306
|
+
document.getElementById('confirm').hidden = true;
|
|
1307
|
+
document.body.style.overflow = '';
|
|
1308
|
+
_confirmOnOk = null;
|
|
1309
|
+
}
|
|
1310
|
+
function confirmOk() {
|
|
1311
|
+
var cb = _confirmOnOk;
|
|
1312
|
+
closeConfirm();
|
|
1313
|
+
if (cb) cb();
|
|
1314
|
+
}
|
|
1315
|
+
function notify(title, message) {
|
|
1316
|
+
openConfirm({ title: title, message: message, okLabel: 'OK', danger: false, hideCancel: true });
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
function submitNewProfile() {
|
|
1320
|
+
var name = (document.getElementById('modalInput').value || '').trim();
|
|
1321
|
+
if (!name) { setModalErr('Please enter a profile name.'); return; }
|
|
1322
|
+
if (!/^[A-Za-z0-9_-]+$/.test(name)) { setModalErr('Only letters, numbers, - and _ are allowed.'); return; }
|
|
1323
|
+
if (name === 'default') { setModalErr('"default" is reserved for the top-level profile.'); return; }
|
|
1324
|
+
if (DATA.named[name] !== undefined) { setModalErr('A profile named "' + name + '" already exists.'); return; }
|
|
1325
|
+
var btn = document.getElementById('modalCreate');
|
|
1326
|
+
btn.disabled = true; setModalErr('');
|
|
1327
|
+
saveProfile(name, {}).then(function () {
|
|
1328
|
+
btn.disabled = false;
|
|
1329
|
+
CURRENT = name; setCount('profiles', 1 + Object.keys(DATA.named).length);
|
|
1330
|
+
renderProfiles(); renderForm(); closeModal(); openDrawer(); setStatus('Profile created and saved.');
|
|
1331
|
+
}).catch(function (err) {
|
|
1332
|
+
btn.disabled = false;
|
|
1333
|
+
setModalErr('Create failed: ' + err.message);
|
|
1334
|
+
});
|
|
236
1335
|
}
|
|
237
1336
|
|
|
238
1337
|
function saveAndActivateProfile() {
|
|
239
1338
|
var name = CURRENT === '' ? 'default' : CURRENT;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
1339
|
+
setStatus('Saving…');
|
|
1340
|
+
saveProfile(CURRENT).then(function () {
|
|
1341
|
+
return api('/api/active', {
|
|
1342
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
1343
|
+
body: JSON.stringify({ name: name })
|
|
1344
|
+
});
|
|
1345
|
+
}).then(function (resp) {
|
|
1346
|
+
return resp.json().then(function (json) { return { ok: resp.ok, json: json }; });
|
|
1347
|
+
}).then(function (result) {
|
|
1348
|
+
if (!result.ok) throw new Error('Saved, but activation failed: ' + ((result.json && result.json.error) || 'error'));
|
|
1349
|
+
ACTIVE = result.json.activeProfile || 'default';
|
|
1350
|
+
renderProfiles(); renderForm(); setStatus('Saved and activated.');
|
|
1351
|
+
}).catch(function (err) { setStatus(err.message || String(err), true); });
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
function deleteProfile() {
|
|
1355
|
+
if (CURRENT === '') return;
|
|
1356
|
+
openConfirm({
|
|
1357
|
+
title: 'Delete profile',
|
|
1358
|
+
message: 'Delete profile "' + CURRENT + '"? This permanently removes its credentials and default models.',
|
|
1359
|
+
okLabel: 'Delete profile',
|
|
1360
|
+
onConfirm: function () {
|
|
1361
|
+
api('/api/profile?name=' + encodeURIComponent(CURRENT), { method: 'DELETE' }).then(function (r) {
|
|
1362
|
+
if (!r.ok) return r.json().then(function (j) { throw new Error(j.error || 'error'); });
|
|
1363
|
+
return r.json();
|
|
1364
|
+
}).then(function (result) {
|
|
1365
|
+
delete DATA.named[CURRENT];
|
|
1366
|
+
ACTIVE = result.activeProfile || 'default'; CURRENT = '';
|
|
1367
|
+
setCount('profiles', 1 + Object.keys(DATA.named).length);
|
|
1368
|
+
renderProfiles(); renderForm(); closeDrawer();
|
|
1369
|
+
}).catch(function (e) { setStatus('Delete failed: ' + e, true); });
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/* ---------- inventory views ---------- */
|
|
1375
|
+
function renderEmpty(container, msg, hint) {
|
|
1376
|
+
container.innerHTML = '';
|
|
1377
|
+
var box = el('div', 'empty');
|
|
1378
|
+
box.appendChild(el('div', '', msg));
|
|
1379
|
+
if (hint) { var p = el('p', 'muted'); p.style.marginTop = '10px'; p.innerHTML = hint; box.appendChild(p); }
|
|
1380
|
+
container.appendChild(box);
|
|
1381
|
+
}
|
|
1382
|
+
function renderError(container, e) { renderEmpty(container, 'Failed to load: ' + e); }
|
|
1383
|
+
|
|
1384
|
+
/* ---------- search + pagination helpers ---------- */
|
|
1385
|
+
function matchQ(hay, q) {
|
|
1386
|
+
if (!q) return true;
|
|
1387
|
+
return String(hay || '').toLowerCase().indexOf(q.toLowerCase()) >= 0;
|
|
1388
|
+
}
|
|
1389
|
+
function pageSlice(list, page, size) {
|
|
1390
|
+
var pages = Math.max(1, Math.ceil(list.length / size));
|
|
1391
|
+
var p = Math.min(Math.max(1, page), pages);
|
|
1392
|
+
return { items: list.slice((p - 1) * size, p * size), page: p, pages: pages, total: list.length };
|
|
1393
|
+
}
|
|
1394
|
+
function pageList(cur, total) {
|
|
1395
|
+
var pages = [];
|
|
1396
|
+
if (total <= 7) { for (var i = 1; i <= total; i++) pages.push(i); return pages; }
|
|
1397
|
+
var left = Math.max(2, cur - 2), right = Math.min(total - 1, cur + 2);
|
|
1398
|
+
if (cur - 1 <= 3) { left = 2; right = 5; }
|
|
1399
|
+
if (total - cur <= 3) { left = total - 4; right = total - 1; }
|
|
1400
|
+
pages.push(1);
|
|
1401
|
+
if (left > 2) pages.push('jp');
|
|
1402
|
+
for (var j = left; j <= right; j++) pages.push(j);
|
|
1403
|
+
if (right < total - 1) pages.push('jn');
|
|
1404
|
+
pages.push(total);
|
|
1405
|
+
return pages;
|
|
1406
|
+
}
|
|
1407
|
+
function renderPager(id, info, view, onGo) {
|
|
1408
|
+
var bar = document.getElementById(id);
|
|
1409
|
+
if (!bar) return;
|
|
1410
|
+
bar.innerHTML = '';
|
|
1411
|
+
if (info.total <= PAGE_SIZES[0]) return;
|
|
1412
|
+
function navBtn(label, target, disabled) {
|
|
1413
|
+
var b = el('button', 'pg pg-nav', label); b.type = 'button'; b.disabled = !!disabled;
|
|
1414
|
+
if (!disabled) b.onclick = function () { onGo(target); };
|
|
1415
|
+
return b;
|
|
1416
|
+
}
|
|
1417
|
+
bar.appendChild(navBtn('‹', info.page - 1, info.page <= 1));
|
|
1418
|
+
pageList(info.page, info.pages).forEach(function (it) {
|
|
1419
|
+
if (it === 'jp' || it === 'jn') {
|
|
1420
|
+
var jump = el('button', 'pg pg-jump', '···'); jump.type = 'button';
|
|
1421
|
+
jump.title = it === 'jp' ? 'Jump backward 5 pages' : 'Jump forward 5 pages';
|
|
1422
|
+
jump.onclick = function () {
|
|
1423
|
+
var t = it === 'jp' ? info.page - 5 : info.page + 5;
|
|
1424
|
+
onGo(Math.min(Math.max(1, t), info.pages));
|
|
1425
|
+
};
|
|
1426
|
+
bar.appendChild(jump);
|
|
1427
|
+
} else {
|
|
1428
|
+
var pg = el('button', 'pg' + (it === info.page ? ' is-active' : ''), String(it)); pg.type = 'button';
|
|
1429
|
+
if (it !== info.page) pg.onclick = function () { onGo(it); };
|
|
1430
|
+
bar.appendChild(pg);
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
bar.appendChild(navBtn('›', info.page + 1, info.page >= info.pages));
|
|
1434
|
+
var sel = el('select', 'pg-size'); sel.title = 'Items per page';
|
|
1435
|
+
PAGE_SIZES.forEach(function (s) {
|
|
1436
|
+
var o = el('option', '', s + ' / page'); o.value = String(s);
|
|
1437
|
+
if (s === getPageSize(view)) o.selected = true;
|
|
1438
|
+
sel.appendChild(o);
|
|
1439
|
+
});
|
|
1440
|
+
sel.onchange = function () { setPageSize(view, parseInt(sel.value, 10) || 20); onGo(1); };
|
|
1441
|
+
bar.appendChild(sel);
|
|
1442
|
+
}
|
|
1443
|
+
function bindSearch(id, fn) {
|
|
1444
|
+
var inp = document.getElementById(id);
|
|
1445
|
+
if (inp) inp.addEventListener('input', function () { fn(inp.value.trim()); });
|
|
1446
|
+
}
|
|
1447
|
+
function initSearches() {
|
|
1448
|
+
bindSearch('scenarioSearch', function (v) { SCN_Q = v; SCN_PAGE = 1; renderScenarios(); });
|
|
1449
|
+
bindSearch('skillSearch', function (v) { SKILL_Q = v; SKILL_PAGE = 1; renderSkills(); });
|
|
1450
|
+
bindSearch('mcpSearch', function (v) { MCP_Q = v; MCP_PAGE = 1; renderMcp(); });
|
|
1451
|
+
bindSearch('agentSearch', function (v) { AGENT_Q = v; AGENT_PAGE = 1; renderAgents(); });
|
|
1452
|
+
bindSearch('assetSearch', function (v) { ASSET_Q = v; ASSET_PAGE = 1; renderAssets(); });
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
function loadSkills() {
|
|
1456
|
+
loaded.skills = true;
|
|
1457
|
+
var body = document.getElementById('skillsBody');
|
|
1458
|
+
api('/api/skills').then(function (r) { return r.json(); }).then(function (j) {
|
|
1459
|
+
SKILLS = j.skills || [];
|
|
1460
|
+
setCount('skills', SKILLS.length);
|
|
1461
|
+
renderSkills();
|
|
1462
|
+
}).catch(function (e) { renderError(body, e); });
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
function skillMatches(s, q) {
|
|
1466
|
+
return matchQ(s.name, q) || matchQ(s.description, q) || matchQ((s.sources || []).join(' '), q) || matchQ(s.path, q);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
function renderSkills() {
|
|
1470
|
+
var body = document.getElementById('skillsBody');
|
|
1471
|
+
var pager = document.getElementById('skillsPager');
|
|
1472
|
+
if (!SKILLS.length) { pager.innerHTML = ''; renderEmpty(body, 'No skills installed.', 'Install with <code>npx skills add modelstudioai/cli --all -g</code>'); return; }
|
|
1473
|
+
var list = SKILLS.filter(function (s) { return skillMatches(s, SKILL_Q); });
|
|
1474
|
+
if (!list.length) { pager.innerHTML = ''; renderEmpty(body, 'No skills match "' + SKILL_Q + '".', ''); return; }
|
|
1475
|
+
var info = pageSlice(list, SKILL_PAGE, getPageSize('skills')); SKILL_PAGE = info.page;
|
|
1476
|
+
body.innerHTML = '';
|
|
1477
|
+
var grid = el('div', 'grid');
|
|
1478
|
+
info.items.forEach(function (s) {
|
|
1479
|
+
var t = el('div', 'tile clickable');
|
|
1480
|
+
t.onclick = function () { openSkillDetail(s); };
|
|
1481
|
+
var top = el('div', 'tile-top');
|
|
1482
|
+
top.appendChild(el('span', 'tile-name', s.name));
|
|
1483
|
+
top.appendChild(originBadge(s.origin));
|
|
1484
|
+
if (s.version) top.appendChild(el('span', 'ver', 'v' + s.version));
|
|
1485
|
+
t.appendChild(top);
|
|
1486
|
+
if (s.description) t.appendChild(el('p', 'tile-desc', s.description));
|
|
1487
|
+
var srcRow = el('div', 'tile-foot');
|
|
1488
|
+
(s.sources || []).forEach(function (src) { srcRow.appendChild(el('span', 'chip blue', src)); });
|
|
1489
|
+
srcRow.appendChild(el('span', 'chip', s.fileCount + ' files'));
|
|
1490
|
+
t.appendChild(srcRow);
|
|
1491
|
+
grid.appendChild(t);
|
|
1492
|
+
});
|
|
1493
|
+
body.appendChild(grid);
|
|
1494
|
+
renderPager('skillsPager', info, 'skills', function (p) { SKILL_PAGE = p; renderSkills(); });
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
function loadMcp() {
|
|
1498
|
+
loaded.mcp = true;
|
|
1499
|
+
var body = document.getElementById('mcpBody');
|
|
1500
|
+
api('/api/mcp').then(function (r) { return r.json(); }).then(function (j) {
|
|
1501
|
+
MCPS = j.servers || [];
|
|
1502
|
+
setCount('mcp', MCPS.length);
|
|
1503
|
+
renderMcp();
|
|
1504
|
+
}).catch(function (e) { renderError(body, e); });
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
function mcpMatches(m, q) {
|
|
1508
|
+
return matchQ(m.name, q) || matchQ(m.detail, q) || matchQ(m.source, q) || matchQ(m.transport, q) || matchQ(m.scope, q);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
function renderMcp() {
|
|
1512
|
+
var body = document.getElementById('mcpBody');
|
|
1513
|
+
var pager = document.getElementById('mcpPager');
|
|
1514
|
+
if (!MCPS.length) { pager.innerHTML = ''; renderEmpty(body, 'No local MCP servers found.', 'MCP servers configured in Claude Code, Codex, Qwen Code or OpenCode will appear here.'); return; }
|
|
1515
|
+
var list = MCPS.filter(function (m) { return mcpMatches(m, MCP_Q); });
|
|
1516
|
+
if (!list.length) { pager.innerHTML = ''; renderEmpty(body, 'No MCP servers match "' + MCP_Q + '".', ''); return; }
|
|
1517
|
+
var info = pageSlice(list, MCP_PAGE, getPageSize('mcp')); MCP_PAGE = info.page;
|
|
1518
|
+
body.innerHTML = '';
|
|
1519
|
+
var grid = el('div', 'grid');
|
|
1520
|
+
info.items.forEach(function (m) {
|
|
1521
|
+
var t = el('div', 'tile clickable');
|
|
1522
|
+
t.onclick = function () { openMcpDetail(m); };
|
|
1523
|
+
var top = el('div', 'tile-top');
|
|
1524
|
+
top.appendChild(el('span', 'tile-name', m.name));
|
|
1525
|
+
top.appendChild(originBadge(m.origin));
|
|
1526
|
+
top.appendChild(el('span', 'pill neutral', m.source));
|
|
1527
|
+
t.appendChild(top);
|
|
1528
|
+
if (m.detail) { var d = el('p', 'tile-desc', m.detail); d.style.fontFamily = 'var(--mono)'; d.style.fontSize = '12px'; t.appendChild(d); }
|
|
1529
|
+
var foot = el('div', 'tile-foot');
|
|
1530
|
+
foot.appendChild(el('span', 'chip blue', m.transport));
|
|
1531
|
+
if (m.scope && m.scope !== 'global') { var sc = el('span', '', m.scope); sc.title = m.scope; foot.appendChild(sc); }
|
|
1532
|
+
else foot.appendChild(el('span', '', 'global'));
|
|
1533
|
+
t.appendChild(foot);
|
|
1534
|
+
grid.appendChild(t);
|
|
1535
|
+
});
|
|
1536
|
+
body.appendChild(grid);
|
|
1537
|
+
renderPager('mcpPager', info, 'mcp', function (p) { MCP_PAGE = p; renderMcp(); });
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
function openMcpDetail(m) {
|
|
1541
|
+
var title = document.getElementById('infoTitle');
|
|
1542
|
+
title.textContent = '';
|
|
1543
|
+
title.appendChild(el('span', '', m.name));
|
|
1544
|
+
title.appendChild(originBadge(m.origin));
|
|
1545
|
+
var body = document.getElementById('infoBody');
|
|
1546
|
+
body.innerHTML = '';
|
|
1547
|
+
var meta = el('div', 'detail-chips');
|
|
1548
|
+
meta.appendChild(el('span', 'chip blue', m.transport));
|
|
1549
|
+
meta.appendChild(el('span', 'chip', m.source));
|
|
1550
|
+
body.appendChild(detailSection('Transport / Source', meta));
|
|
1551
|
+
body.appendChild(detailSection('Scope', el('div', 'detail-path', m.scope || 'global')));
|
|
1552
|
+
var cfg = (m.config && typeof m.config === 'object') ? m.config : {};
|
|
1553
|
+
var json = JSON.stringify(cfg, null, 2);
|
|
1554
|
+
var editable = !!m.editable;
|
|
1555
|
+
var block;
|
|
1556
|
+
if (editable) {
|
|
1557
|
+
block = el('textarea', 'detail-code code-edit'); block.id = 'mcpEdit';
|
|
1558
|
+
block.spellcheck = false; block.setAttribute('autocomplete', 'off'); block.value = json;
|
|
1559
|
+
} else {
|
|
1560
|
+
block = el('pre', 'detail-code', json);
|
|
1561
|
+
}
|
|
1562
|
+
body.appendChild(detailSection('Configuration' + (editable ? ' (editable)' : ''), block, copyButton(function () {
|
|
1563
|
+
return editable ? document.getElementById('mcpEdit').value : json;
|
|
1564
|
+
})));
|
|
1565
|
+
if (!editable) body.appendChild(el('p', 'mcp-note', 'This source is read-only here (its config is TOML). Edit it directly in ' + (m.source || 'its config file') + '.'));
|
|
1566
|
+
var err = el('div', 'modal-err'); err.id = 'mcpErr'; body.appendChild(err);
|
|
1567
|
+
openInfoDrawer();
|
|
1568
|
+
if (editable) {
|
|
1569
|
+
var foot = document.getElementById('infoFoot'); foot.innerHTML = ''; foot.hidden = false;
|
|
1570
|
+
var del = el('button', 'btn-danger', 'Delete'); del.type = 'button';
|
|
1571
|
+
del.onclick = function () {
|
|
1572
|
+
openConfirm({ title: 'Delete MCP server?', message: 'Remove "' + m.name + '" from ' + m.source + '? This rewrites the source config file.', onConfirm: function () { doDeleteMcp(m); } });
|
|
1573
|
+
};
|
|
1574
|
+
var save = el('button', 'btn-primary', 'Save'); save.type = 'button';
|
|
1575
|
+
save.onclick = function () { doSaveMcp(m, save); };
|
|
1576
|
+
foot.appendChild(del); foot.appendChild(save);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
var MCP_SOURCES = [
|
|
1581
|
+
{ id: 'claude-code', label: 'Claude Code' },
|
|
1582
|
+
{ id: 'claude-desktop', label: 'Claude Desktop' },
|
|
1583
|
+
{ id: 'qwen-code', label: 'Qwen Code' },
|
|
1584
|
+
{ id: 'cursor', label: 'Cursor' },
|
|
1585
|
+
{ id: 'windsurf', label: 'Windsurf' },
|
|
1586
|
+
{ id: 'gemini', label: 'Gemini' },
|
|
1587
|
+
{ id: 'opencode', label: 'OpenCode' },
|
|
1588
|
+
{ id: 'openclaw', label: 'OpenClaw' },
|
|
1589
|
+
{ id: 'qoderwork', label: 'QoderWork' }
|
|
1590
|
+
];
|
|
1591
|
+
function copyButton(getText) {
|
|
1592
|
+
var b = el('button', 'copy-btn', 'Copy'); b.type = 'button';
|
|
1593
|
+
b.onclick = function () {
|
|
1594
|
+
var text = getText();
|
|
1595
|
+
var done = function () { b.classList.add('copied'); b.textContent = 'Copied'; setTimeout(function () { b.classList.remove('copied'); b.textContent = 'Copy'; }, 1500); };
|
|
1596
|
+
if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(done).catch(function () { fallbackCopy(text); done(); }); }
|
|
1597
|
+
else { fallbackCopy(text); done(); }
|
|
1598
|
+
};
|
|
1599
|
+
return b;
|
|
1600
|
+
}
|
|
1601
|
+
function setMcpErr(msg) { var e = document.getElementById('mcpErr'); if (e) e.textContent = msg || ''; }
|
|
1602
|
+
function parseMcpEditor() {
|
|
1603
|
+
var parsed = JSON.parse(document.getElementById('mcpEdit').value);
|
|
1604
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('Config must be a JSON object.');
|
|
1605
|
+
return parsed;
|
|
1606
|
+
}
|
|
1607
|
+
function doSaveMcp(m, btn) {
|
|
1608
|
+
setMcpErr('');
|
|
1609
|
+
var parsed;
|
|
1610
|
+
try { parsed = parseMcpEditor(); } catch (e) { setMcpErr('Invalid JSON: ' + (e.message || e)); return; }
|
|
1611
|
+
btn.disabled = true;
|
|
1612
|
+
api('/api/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ source: m.source, scope: m.scope, name: m.name, config: parsed }) })
|
|
1613
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
1614
|
+
.then(function (res) {
|
|
1615
|
+
btn.disabled = false;
|
|
1616
|
+
if (!res.ok) { setMcpErr((res.j && res.j.error) || 'Save failed'); return; }
|
|
1617
|
+
closeInfoDrawer(); loaded.mcp = false; loadMcp();
|
|
1618
|
+
notify('Saved', 'MCP server "' + m.name + '" was updated.');
|
|
249
1619
|
})
|
|
250
|
-
.
|
|
251
|
-
|
|
1620
|
+
.catch(function (e) { btn.disabled = false; setMcpErr('Save failed: ' + e); });
|
|
1621
|
+
}
|
|
1622
|
+
function doDeleteMcp(m) {
|
|
1623
|
+
api('/api/mcp?source=' + encodeURIComponent(m.source) + '&scope=' + encodeURIComponent(m.scope) + '&name=' + encodeURIComponent(m.name), { method: 'DELETE' })
|
|
1624
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
1625
|
+
.then(function (res) {
|
|
1626
|
+
if (!res.ok) { notify('Delete failed', (res.j && res.j.error) || 'Could not delete this server.'); return; }
|
|
1627
|
+
closeInfoDrawer(); loaded.mcp = false; loadMcp();
|
|
252
1628
|
})
|
|
253
|
-
.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
1629
|
+
.catch(function (e) { notify('Delete failed', String(e)); });
|
|
1630
|
+
}
|
|
1631
|
+
function openMcpCreate() {
|
|
1632
|
+
var title = document.getElementById('infoTitle');
|
|
1633
|
+
title.textContent = ''; title.appendChild(el('span', '', 'New MCP server'));
|
|
1634
|
+
var body = document.getElementById('infoBody'); body.innerHTML = '';
|
|
1635
|
+
var sel = el('select', 'select'); sel.id = 'mcpNewSource';
|
|
1636
|
+
MCP_SOURCES.forEach(function (s) { var o = el('option', '', s.label); o.value = s.id; sel.appendChild(o); });
|
|
1637
|
+
body.appendChild(detailSection('Target agent config', sel));
|
|
1638
|
+
var nameInp = el('input'); nameInp.id = 'mcpNewName'; nameInp.type = 'text'; nameInp.placeholder = 'e.g. amap-maps'; nameInp.autocomplete = 'off';
|
|
1639
|
+
body.appendChild(detailSection('Server name', nameInp));
|
|
1640
|
+
var ta = el('textarea', 'detail-code code-edit'); ta.id = 'mcpEdit'; ta.spellcheck = false;
|
|
1641
|
+
ta.value = JSON.stringify({ command: 'npx', args: ['-y', '@scope/package'], env: { API_KEY: '' } }, null, 2);
|
|
1642
|
+
body.appendChild(detailSection('Configuration', ta));
|
|
1643
|
+
var err = el('div', 'modal-err'); err.id = 'mcpErr'; body.appendChild(err);
|
|
1644
|
+
openInfoDrawer();
|
|
1645
|
+
var foot = document.getElementById('infoFoot'); foot.innerHTML = ''; foot.hidden = false;
|
|
1646
|
+
var create = el('button', 'btn-primary', 'Create'); create.type = 'button';
|
|
1647
|
+
create.onclick = function () { doCreateMcp(create); };
|
|
1648
|
+
foot.appendChild(create);
|
|
1649
|
+
}
|
|
1650
|
+
function doCreateMcp(btn) {
|
|
1651
|
+
setMcpErr('');
|
|
1652
|
+
var source = document.getElementById('mcpNewSource').value;
|
|
1653
|
+
var name = (document.getElementById('mcpNewName').value || '').trim();
|
|
1654
|
+
if (!name) { setMcpErr('Please enter a server name.'); return; }
|
|
1655
|
+
var parsed;
|
|
1656
|
+
try { parsed = parseMcpEditor(); } catch (e) { setMcpErr('Invalid JSON: ' + (e.message || e)); return; }
|
|
1657
|
+
btn.disabled = true;
|
|
1658
|
+
api('/api/mcp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ source: source, scope: 'global', name: name, config: parsed }) })
|
|
1659
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
1660
|
+
.then(function (res) {
|
|
1661
|
+
btn.disabled = false;
|
|
1662
|
+
if (!res.ok) { setMcpErr((res.j && res.j.error) || 'Create failed'); return; }
|
|
1663
|
+
closeInfoDrawer(); loaded.mcp = false; loadMcp();
|
|
1664
|
+
notify('Created', 'MCP server "' + name + '" was added to ' + source + '.');
|
|
261
1665
|
})
|
|
262
|
-
.catch(function (
|
|
1666
|
+
.catch(function (e) { btn.disabled = false; setMcpErr('Create failed: ' + e); });
|
|
263
1667
|
}
|
|
264
1668
|
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
api('/api/
|
|
269
|
-
.
|
|
270
|
-
|
|
271
|
-
|
|
1669
|
+
function loadAgents() {
|
|
1670
|
+
loaded.agents = true;
|
|
1671
|
+
var body = document.getElementById('agentsBody');
|
|
1672
|
+
api('/api/agents').then(function (r) { return r.json(); }).then(function (j) {
|
|
1673
|
+
AGENTS = j.agents || [];
|
|
1674
|
+
var installed = AGENTS.filter(function (a) { return a.installed; }).length;
|
|
1675
|
+
setCount('agents', installed);
|
|
1676
|
+
renderAgentFilters();
|
|
1677
|
+
renderAgents();
|
|
1678
|
+
}).catch(function (e) { renderError(body, e); });
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
function renderAgentFilters() {
|
|
1682
|
+
var bar = document.getElementById('agentFilters');
|
|
1683
|
+
bar.innerHTML = '';
|
|
1684
|
+
var counts = {
|
|
1685
|
+
all: AGENTS.length,
|
|
1686
|
+
local: AGENTS.filter(function (a) { return a.origin !== 'remote'; }).length,
|
|
1687
|
+
remote: AGENTS.filter(function (a) { return a.origin === 'remote'; }).length
|
|
1688
|
+
};
|
|
1689
|
+
var labels = { all: 'All', local: 'Local', remote: 'Remote' };
|
|
1690
|
+
['all', 'local', 'remote'].forEach(function (cat) {
|
|
1691
|
+
var b = el('button', 'filter' + (cat === AGENT_FILTER ? ' is-active' : ''));
|
|
1692
|
+
b.appendChild(el('span', '', labels[cat]));
|
|
1693
|
+
b.appendChild(el('span', 'n', String(counts[cat] || 0)));
|
|
1694
|
+
b.onclick = function () { AGENT_FILTER = cat; AGENT_PAGE = 1; renderAgentFilters(); renderAgents(); };
|
|
1695
|
+
bar.appendChild(b);
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
function agentMatches(a, q) {
|
|
1700
|
+
return matchQ(a.label, q) || matchQ(a.id, q) || matchQ(a.model, q) || matchQ((a.paths || []).join(' '), q);
|
|
1701
|
+
}
|
|
1702
|
+
function renderAgents() {
|
|
1703
|
+
var body = document.getElementById('agentsBody');
|
|
1704
|
+
var pager = document.getElementById('agentsPager');
|
|
1705
|
+
var base = AGENT_FILTER === 'all'
|
|
1706
|
+
? AGENTS
|
|
1707
|
+
: AGENTS.filter(function (a) { return (a.origin === 'remote' ? 'remote' : 'local') === AGENT_FILTER; });
|
|
1708
|
+
var list = base.filter(function (a) { return agentMatches(a, AGENT_Q); });
|
|
1709
|
+
if (!list.length) {
|
|
1710
|
+
pager.innerHTML = '';
|
|
1711
|
+
if (AGENT_Q) renderEmpty(body, 'No agents match "' + AGENT_Q + '".', '');
|
|
1712
|
+
else if (AGENT_FILTER === 'remote') renderEmpty(body, 'No remote agents yet.', 'Remote agents loaded from a URL will appear here.');
|
|
1713
|
+
else renderEmpty(body, 'No agents in this category.', '');
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
var info = pageSlice(list, AGENT_PAGE, getPageSize('agents')); AGENT_PAGE = info.page;
|
|
1717
|
+
body.innerHTML = '';
|
|
1718
|
+
var grid = el('div', 'grid');
|
|
1719
|
+
info.items.forEach(function (a) {
|
|
1720
|
+
var t = el('div', 'tile clickable');
|
|
1721
|
+
t.onclick = function () { openAgentDetail(a); };
|
|
1722
|
+
var top = el('div', 'tile-top');
|
|
1723
|
+
var nm = el('span', 'tile-name', a.label); nm.title = a.label;
|
|
1724
|
+
top.appendChild(nm);
|
|
1725
|
+
t.appendChild(top);
|
|
1726
|
+
var meta = el('div', 'tile-meta');
|
|
1727
|
+
meta.appendChild(originBadge(a.origin));
|
|
1728
|
+
var pill;
|
|
1729
|
+
if (a.installed && a.configured) pill = el('span', 'pill ok', 'Connected');
|
|
1730
|
+
else if (a.installed) pill = el('span', 'pill neutral', 'Installed');
|
|
1731
|
+
else pill = el('span', 'pill off', 'Not installed');
|
|
1732
|
+
meta.appendChild(pill);
|
|
1733
|
+
t.appendChild(meta);
|
|
1734
|
+
var foot = el('div', 'tile-foot');
|
|
1735
|
+
foot.appendChild(el('span', 'chip', a.id));
|
|
1736
|
+
if (a.model) foot.appendChild(el('span', 'chip blue', a.model));
|
|
1737
|
+
t.appendChild(foot);
|
|
1738
|
+
if (a.paths && a.paths.length) {
|
|
1739
|
+
var path = el('div', 'tile-path', a.paths.join('\\n'));
|
|
1740
|
+
path.title = a.paths.join('\\n');
|
|
1741
|
+
t.appendChild(path);
|
|
1742
|
+
}
|
|
1743
|
+
var actions = el('div', 'tile-actions');
|
|
1744
|
+
var launch = el('button', 'icon-run');
|
|
1745
|
+
launch.innerHTML = PLAY_SVG;
|
|
1746
|
+
launch.setAttribute('aria-label', 'Quick launch');
|
|
1747
|
+
var connected = a.installed && a.configured;
|
|
1748
|
+
var st = el('span', 'launch-status');
|
|
1749
|
+
if (connected && a.launchable) {
|
|
1750
|
+
launch.title = 'Open a new terminal and start this agent';
|
|
1751
|
+
launch.onclick = function (e) { e.stopPropagation(); launchAgentCli(a, launch, st); };
|
|
1752
|
+
} else {
|
|
1753
|
+
launch.disabled = true;
|
|
1754
|
+
if (!a.installed) launch.title = 'Install this agent before launching';
|
|
1755
|
+
else if (!connected) launch.title = 'Connect this agent to bailian-cli before launching';
|
|
1756
|
+
else launch.title = 'The CLI for this agent was not found on your PATH — install it before launching';
|
|
1757
|
+
}
|
|
1758
|
+
actions.appendChild(st);
|
|
1759
|
+
actions.appendChild(launch);
|
|
1760
|
+
t.appendChild(actions);
|
|
1761
|
+
grid.appendChild(t);
|
|
1762
|
+
});
|
|
1763
|
+
body.appendChild(grid);
|
|
1764
|
+
renderPager('agentsPager', info, 'agents', function (p) { AGENT_PAGE = p; renderAgents(); });
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
function launchAgentCli(a, btn, st) {
|
|
1768
|
+
btn.disabled = true;
|
|
1769
|
+
st.textContent = 'Launching…'; st.className = 'launch-status';
|
|
1770
|
+
api('/api/agent/launch?id=' + encodeURIComponent(a.id), { method: 'POST' })
|
|
1771
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
1772
|
+
.then(function (res) {
|
|
1773
|
+
btn.disabled = false;
|
|
1774
|
+
if (!res.ok) { st.textContent = (res.j && res.j.error) || 'Launch failed'; st.className = 'launch-status err'; return; }
|
|
1775
|
+
st.textContent = 'Launched → ' + (res.j.command || a.id); st.className = 'launch-status ok';
|
|
272
1776
|
})
|
|
273
|
-
.
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
1777
|
+
.catch(function (e) { btn.disabled = false; st.textContent = 'Launch failed: ' + e; st.className = 'launch-status err'; });
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
function openAgentDetail(a) {
|
|
1781
|
+
var title = document.getElementById('infoTitle');
|
|
1782
|
+
title.textContent = '';
|
|
1783
|
+
title.appendChild(el('span', '', a.label));
|
|
1784
|
+
title.appendChild(originBadge(a.origin));
|
|
1785
|
+
var body = document.getElementById('infoBody');
|
|
1786
|
+
body.innerHTML = '<div class="loading">Loading…</div>';
|
|
1787
|
+
openInfoDrawer();
|
|
1788
|
+
api('/api/agent?id=' + encodeURIComponent(a.id)).then(function (r) { return r.json(); })
|
|
1789
|
+
.then(function (d) { renderAgentDetail(d); })
|
|
1790
|
+
.catch(function (e) { renderError(body, e); });
|
|
1791
|
+
}
|
|
1792
|
+
function renderAgentDetail(d) {
|
|
1793
|
+
var body = document.getElementById('infoBody');
|
|
1794
|
+
body.innerHTML = '';
|
|
1795
|
+
var chips = el('div', 'detail-chips');
|
|
1796
|
+
chips.appendChild(el('span', 'chip', d.id));
|
|
1797
|
+
var pill;
|
|
1798
|
+
if (d.installed && d.configured) pill = el('span', 'pill ok', 'Connected');
|
|
1799
|
+
else if (d.installed) pill = el('span', 'pill neutral', 'Installed');
|
|
1800
|
+
else pill = el('span', 'pill off', 'Not installed');
|
|
1801
|
+
chips.appendChild(pill);
|
|
1802
|
+
body.appendChild(detailSection('Status', chips));
|
|
1803
|
+
if (d.fields && d.fields.length) {
|
|
1804
|
+
var kv = el('div', 'detail-kv');
|
|
1805
|
+
d.fields.forEach(function (f) {
|
|
1806
|
+
var row = el('div', 'kv-row');
|
|
1807
|
+
row.appendChild(el('span', 'kv-key', f.label));
|
|
1808
|
+
var val = el('span', 'kv-val' + (f.secret ? ' secret' : ''), f.value);
|
|
1809
|
+
row.appendChild(val);
|
|
1810
|
+
if (f.secret && f.raw) {
|
|
1811
|
+
var shown = false;
|
|
1812
|
+
var btn = el('button', 'kv-reveal', 'Show');
|
|
1813
|
+
btn.type = 'button';
|
|
1814
|
+
btn.onclick = function () {
|
|
1815
|
+
shown = !shown;
|
|
1816
|
+
val.textContent = shown ? f.raw : f.value;
|
|
1817
|
+
if (shown) { val.classList.remove('secret'); } else { val.classList.add('secret'); }
|
|
1818
|
+
btn.textContent = shown ? 'Hide' : 'Show';
|
|
1819
|
+
};
|
|
1820
|
+
row.appendChild(btn);
|
|
1821
|
+
}
|
|
1822
|
+
kv.appendChild(row);
|
|
1823
|
+
});
|
|
1824
|
+
body.appendChild(detailSection('Configuration', kv));
|
|
1825
|
+
} else if (d.installed) {
|
|
1826
|
+
body.appendChild(detailSection('Configuration', el('div', 'detail-path', 'bailian-cli is not wired into this agent yet.')));
|
|
1827
|
+
} else {
|
|
1828
|
+
body.appendChild(detailSection('Configuration', el('div', 'detail-path', 'This agent is not installed yet.')));
|
|
1829
|
+
}
|
|
1830
|
+
if (d.files && d.files.length) {
|
|
1831
|
+
var wrap = el('div', '');
|
|
1832
|
+
d.files.forEach(function (fl) {
|
|
1833
|
+
var p = el('div', 'detail-path', fl.path + (fl.exists ? '' : ' (missing)'));
|
|
1834
|
+
p.title = fl.path;
|
|
1835
|
+
wrap.appendChild(p);
|
|
1836
|
+
});
|
|
1837
|
+
body.appendChild(detailSection('Config files', wrap));
|
|
1838
|
+
}
|
|
1839
|
+
if (d.settings && d.settings.length) {
|
|
1840
|
+
var sw = el('div', '');
|
|
1841
|
+
d.settings.forEach(function (fl) {
|
|
1842
|
+
var item = el('div', 'settings-item');
|
|
1843
|
+
var lbl = el('div', 'detail-path', fl.path);
|
|
1844
|
+
lbl.title = fl.path;
|
|
1845
|
+
item.appendChild(lbl);
|
|
1846
|
+
item.appendChild(el('pre', 'detail-code', fl.text));
|
|
1847
|
+
sw.appendChild(item);
|
|
1848
|
+
});
|
|
1849
|
+
var openBtn = el('button', 'kv-reveal', 'Open');
|
|
1850
|
+
openBtn.type = 'button';
|
|
1851
|
+
openBtn.title = 'Open the config file with the system default app';
|
|
1852
|
+
openBtn.onclick = function () { openAgentSettings(d); };
|
|
1853
|
+
body.appendChild(detailSection('Settings', sw, openBtn));
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
function openAgentSettings(d) {
|
|
1857
|
+
(d.settings || []).forEach(function (fl) {
|
|
1858
|
+
api('/api/agent/open?id=' + encodeURIComponent(d.id) + '&path=' + encodeURIComponent(fl.path), { method: 'POST' })
|
|
1859
|
+
.then(function (r) { if (!r.ok) return r.json().then(function (j) { throw new Error(j.error || 'error'); }); })
|
|
1860
|
+
.catch(function (e) { notify('Open failed', String(e)); });
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/* ---------- playground ---------- */
|
|
1865
|
+
function loadPlayground() {
|
|
1866
|
+
loaded.playground = true;
|
|
1867
|
+
var body = document.getElementById('playgroundBody');
|
|
1868
|
+
api('/api/scenarios').then(function (r) { return r.json(); }).then(function (j) {
|
|
1869
|
+
BUILTIN_SCENARIOS = j.scenarios || [];
|
|
1870
|
+
SCENARIOS = composeScenarios();
|
|
1871
|
+
DISPATCH_AGENTS = j.agents || [];
|
|
1872
|
+
renderScenarioFilters();
|
|
1873
|
+
renderScenarios();
|
|
1874
|
+
}).catch(function (e) { renderError(body, e); });
|
|
1875
|
+
}
|
|
1876
|
+
var SCN_ORDER = ['图像', '音频', '视频', '多模态', '代码', '文档'];
|
|
1877
|
+
function scenarioCategories() {
|
|
1878
|
+
var present = {};
|
|
1879
|
+
SCENARIOS.forEach(function (s) { if (s.category) present[s.category] = true; });
|
|
1880
|
+
var cats = SCN_ORDER.filter(function (c) { return present[c]; });
|
|
1881
|
+
Object.keys(present).forEach(function (c) { if (SCN_ORDER.indexOf(c) < 0) cats.push(c); });
|
|
1882
|
+
return cats;
|
|
1883
|
+
}
|
|
1884
|
+
function renderScenarioFilters() {
|
|
1885
|
+
var bar = document.getElementById('scenarioFilters');
|
|
1886
|
+
bar.innerHTML = '';
|
|
1887
|
+
var defs = [{ key: 'all', label: 'All', n: SCENARIOS.length }];
|
|
1888
|
+
scenarioCategories().forEach(function (c) {
|
|
1889
|
+
defs.push({ key: c, label: c, n: SCENARIOS.filter(function (s) { return s.category === c; }).length });
|
|
1890
|
+
});
|
|
1891
|
+
defs.forEach(function (d) {
|
|
1892
|
+
var b = el('button', 'filter' + (d.key === SCN_FILTER ? ' is-active' : ''));
|
|
1893
|
+
b.appendChild(el('span', '', d.label));
|
|
1894
|
+
b.appendChild(el('span', 'n', String(d.n)));
|
|
1895
|
+
b.onclick = function () { SCN_FILTER = d.key; SCN_PAGE = 1; renderScenarioFilters(); renderScenarios(); };
|
|
1896
|
+
bar.appendChild(b);
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
function scenarioMatches(s, q) {
|
|
1900
|
+
return matchQ(s.title, q) || matchQ(s.description, q) || matchQ(s.category, q);
|
|
1901
|
+
}
|
|
1902
|
+
function pgWarnNode() {
|
|
1903
|
+
return el('div', 'pg-warn', 'No connected agent can accept tasks yet. Install and connect qwen-code (or another supported agent) first, and make sure its CLI is on your PATH.');
|
|
1904
|
+
}
|
|
1905
|
+
function renderScenarios() {
|
|
1906
|
+
var body = document.getElementById('playgroundBody');
|
|
1907
|
+
var pager = document.getElementById('playgroundPager');
|
|
1908
|
+
var base = SCN_FILTER === 'all' ? SCENARIOS : SCENARIOS.filter(function (s) { return s.category === SCN_FILTER; });
|
|
1909
|
+
var list = base.filter(function (s) { return scenarioMatches(s, SCN_Q); });
|
|
1910
|
+
if (!list.length) {
|
|
1911
|
+
pager.innerHTML = '';
|
|
1912
|
+
renderEmpty(body, SCN_Q ? 'No scenarios match "' + SCN_Q + '".' : 'No scenarios in this category.', '');
|
|
1913
|
+
if (!DISPATCH_AGENTS.length) body.insertBefore(pgWarnNode(), body.firstChild);
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
var info = pageSlice(list, SCN_PAGE, getPageSize('playground')); SCN_PAGE = info.page;
|
|
1917
|
+
body.innerHTML = '';
|
|
1918
|
+
if (!DISPATCH_AGENTS.length) {
|
|
1919
|
+
body.appendChild(pgWarnNode());
|
|
1920
|
+
}
|
|
1921
|
+
var grid = el('div', 'grid');
|
|
1922
|
+
info.items.forEach(function (s) {
|
|
1923
|
+
var t = el('div', 'tile clickable');
|
|
1924
|
+
t.title = 'Click to edit this scenario';
|
|
1925
|
+
t.onclick = function () { openScnDrawer(s); };
|
|
1926
|
+
var top = el('div', 'tile-top');
|
|
1927
|
+
top.appendChild(el('span', 'tile-name', s.title));
|
|
1928
|
+
if (s.category) top.appendChild(el('span', 'chip', s.category));
|
|
1929
|
+
if (s.custom) top.appendChild(el('span', 'chip blue', 'custom'));
|
|
1930
|
+
else if (s.edited) top.appendChild(el('span', 'chip blue', 'edited'));
|
|
1931
|
+
t.appendChild(top);
|
|
1932
|
+
t.appendChild(el('p', 'scn-desc', s.description));
|
|
1933
|
+
var actions = el('div', 'tile-actions');
|
|
1934
|
+
var run = el('button', 'icon-run');
|
|
1935
|
+
run.innerHTML = PLAY_SVG;
|
|
1936
|
+
run.setAttribute('aria-label', 'Run it');
|
|
1937
|
+
if (DISPATCH_AGENTS.length) {
|
|
1938
|
+
run.title = 'Dispatch this task to a local agent';
|
|
1939
|
+
run.onclick = function (e) { e.stopPropagation(); openDispatch(s); };
|
|
1940
|
+
} else {
|
|
1941
|
+
run.disabled = true; run.title = 'No connected agent available';
|
|
1942
|
+
}
|
|
1943
|
+
actions.appendChild(run);
|
|
1944
|
+
t.appendChild(actions);
|
|
1945
|
+
grid.appendChild(t);
|
|
1946
|
+
});
|
|
1947
|
+
body.appendChild(grid);
|
|
1948
|
+
renderPager('playgroundPager', info, 'playground', function (p) { SCN_PAGE = p; renderScenarios(); });
|
|
1949
|
+
}
|
|
1950
|
+
function fillPrompt(s, values) {
|
|
1951
|
+
var out = s.prompt;
|
|
1952
|
+
(s.inputs || []).forEach(function (inp) {
|
|
1953
|
+
var v = values[inp.key];
|
|
1954
|
+
v = (v && String(v).trim()) ? String(v).trim() : ('{{' + inp.key + '}}');
|
|
1955
|
+
out = out.split('{{' + inp.key + '}}').join(v);
|
|
1956
|
+
});
|
|
1957
|
+
return out;
|
|
1958
|
+
}
|
|
1959
|
+
function dispatchValues() {
|
|
1960
|
+
var v = {};
|
|
1961
|
+
((DISPATCH_SCN && DISPATCH_SCN.inputs) || []).forEach(function (inp) {
|
|
1962
|
+
var e = document.getElementById('dsp_' + inp.key);
|
|
1963
|
+
v[inp.key] = e ? e.value : '';
|
|
1964
|
+
});
|
|
1965
|
+
return v;
|
|
1966
|
+
}
|
|
1967
|
+
function updateDispatchPreview() {
|
|
1968
|
+
if (!DISPATCH_SCN) return;
|
|
1969
|
+
document.getElementById('dispatchPreview').textContent = fillPrompt(DISPATCH_SCN, dispatchValues());
|
|
1970
|
+
}
|
|
1971
|
+
function setDispatchErr(m) { document.getElementById('dispatchErr').textContent = m || ''; }
|
|
1972
|
+
var LAST_AGENT_KEY = 'bl.lastDispatchAgent';
|
|
1973
|
+
function openDispatch(s) {
|
|
1974
|
+
DISPATCH_SCN = s;
|
|
1975
|
+
document.getElementById('dispatchTitle').textContent = s.title;
|
|
1976
|
+
document.getElementById('dispatchDesc').textContent = s.description;
|
|
1977
|
+
var sel = document.getElementById('dispatchAgent');
|
|
1978
|
+
sel.innerHTML = '';
|
|
1979
|
+
var last = '';
|
|
1980
|
+
try { last = localStorage.getItem(LAST_AGENT_KEY) || ''; } catch (e) { /* ignore */ }
|
|
1981
|
+
var preferred = DISPATCH_AGENTS.some(function (a) { return a.id === last; }) ? last : 'qwen-code';
|
|
1982
|
+
DISPATCH_AGENTS.forEach(function (a) {
|
|
1983
|
+
var o = el('option', '', a.label + ' (' + a.id + ')'); o.value = a.id;
|
|
1984
|
+
if (a.id === preferred) o.selected = true;
|
|
1985
|
+
sel.appendChild(o);
|
|
1986
|
+
});
|
|
1987
|
+
var wrap = document.getElementById('dispatchInputs');
|
|
1988
|
+
wrap.innerHTML = '';
|
|
1989
|
+
(s.inputs || []).forEach(function (inp) {
|
|
1990
|
+
var lab = el('label', 'modal-label', inp.label); lab.htmlFor = 'dsp_' + inp.key;
|
|
1991
|
+
var input = el('input'); input.id = 'dsp_' + inp.key; input.type = 'text';
|
|
1992
|
+
input.placeholder = inp.placeholder || ''; input.autocomplete = 'off'; input.spellcheck = false;
|
|
1993
|
+
input.addEventListener('input', updateDispatchPreview);
|
|
1994
|
+
wrap.appendChild(lab); wrap.appendChild(input);
|
|
1995
|
+
});
|
|
1996
|
+
setDispatchErr('');
|
|
1997
|
+
updateDispatchPreview();
|
|
1998
|
+
document.getElementById('dispatch').hidden = false;
|
|
1999
|
+
document.body.style.overflow = 'hidden';
|
|
2000
|
+
var first = wrap.querySelector('input');
|
|
2001
|
+
setTimeout(function () { if (first) first.focus(); }, 30);
|
|
2002
|
+
}
|
|
2003
|
+
function closeDispatch() {
|
|
2004
|
+
document.getElementById('dispatch').hidden = true;
|
|
2005
|
+
document.body.style.overflow = '';
|
|
2006
|
+
DISPATCH_SCN = null;
|
|
2007
|
+
}
|
|
2008
|
+
function doDispatch() {
|
|
2009
|
+
var s = DISPATCH_SCN; if (!s) return;
|
|
2010
|
+
var agent = document.getElementById('dispatchAgent').value;
|
|
2011
|
+
var values = dispatchValues();
|
|
2012
|
+
var missing = (s.inputs || []).filter(function (inp) { return !values[inp.key] || !values[inp.key].trim(); });
|
|
2013
|
+
if (missing.length) { setDispatchErr('Please fill in: ' + missing.map(function (m) { return m.label; }).join(', ')); return; }
|
|
2014
|
+
var btn = document.getElementById('dispatchGo');
|
|
2015
|
+
btn.disabled = true; setDispatchErr('');
|
|
2016
|
+
var payload = (s.custom || s.edited)
|
|
2017
|
+
? { agent: agent, values: values, custom: { title: s.title, prompt: s.prompt, inputs: s.inputs || [] } }
|
|
2018
|
+
: { scenario: s.id, agent: agent, values: values };
|
|
2019
|
+
api('/api/agent/dispatch', {
|
|
2020
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
2021
|
+
body: JSON.stringify(payload)
|
|
2022
|
+
}).then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
|
|
2023
|
+
.then(function (res) {
|
|
2024
|
+
btn.disabled = false;
|
|
2025
|
+
if (!res.ok) { setDispatchErr((res.j && res.j.error) || 'Dispatch failed'); return; }
|
|
2026
|
+
try { localStorage.setItem(LAST_AGENT_KEY, agent); } catch (err) { /* ignore */ }
|
|
2027
|
+
closeDispatch();
|
|
2028
|
+
notify('Dispatched', 'Task sent to ' + agent + '. Check the newly opened terminal window.');
|
|
2029
|
+
markFirstRun();
|
|
2030
|
+
if (loaded.start) loadQuickStart();
|
|
280
2031
|
})
|
|
281
|
-
.catch(function (e) {
|
|
2032
|
+
.catch(function (e) { btn.disabled = false; setDispatchErr('Dispatch failed: ' + e); });
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
/* ---------- custom scenarios ---------- */
|
|
2036
|
+
var CUSTOM_KEY = 'bl.customScenarios';
|
|
2037
|
+
var OVERRIDE_KEY = 'bl.scenarioOverrides';
|
|
2038
|
+
var HIDDEN_KEY = 'bl.scenarioHidden';
|
|
2039
|
+
var SCN_EDIT_ID = null;
|
|
2040
|
+
var SCN_EDIT_KIND = null;
|
|
2041
|
+
function loadOverrides() {
|
|
2042
|
+
try { var o = JSON.parse(localStorage.getItem(OVERRIDE_KEY) || '{}'); return (o && typeof o === 'object') ? o : {}; } catch (e) { return {}; }
|
|
2043
|
+
}
|
|
2044
|
+
function saveOverrides(o) { try { localStorage.setItem(OVERRIDE_KEY, JSON.stringify(o)); } catch (e) {} }
|
|
2045
|
+
function loadHidden() {
|
|
2046
|
+
try { var a = JSON.parse(localStorage.getItem(HIDDEN_KEY) || '[]'); return Array.isArray(a) ? a : []; } catch (e) { return []; }
|
|
2047
|
+
}
|
|
2048
|
+
function saveHidden(a) { try { localStorage.setItem(HIDDEN_KEY, JSON.stringify(a)); } catch (e) {} }
|
|
2049
|
+
function isBuiltin(id) {
|
|
2050
|
+
for (var i = 0; i < BUILTIN_SCENARIOS.length; i++) { if (BUILTIN_SCENARIOS[i].id === id) return true; }
|
|
2051
|
+
return false;
|
|
2052
|
+
}
|
|
2053
|
+
function composeScenarios() {
|
|
2054
|
+
var ov = loadOverrides(), hidden = loadHidden();
|
|
2055
|
+
var builtins = BUILTIN_SCENARIOS
|
|
2056
|
+
.filter(function (s) { return hidden.indexOf(s.id) < 0; })
|
|
2057
|
+
.map(function (s) {
|
|
2058
|
+
var o = ov[s.id];
|
|
2059
|
+
if (!o) return s;
|
|
2060
|
+
return {
|
|
2061
|
+
id: s.id,
|
|
2062
|
+
title: o.title != null ? o.title : s.title,
|
|
2063
|
+
description: o.description != null ? o.description : s.description,
|
|
2064
|
+
category: o.category != null ? o.category : s.category,
|
|
2065
|
+
prompt: o.prompt != null ? o.prompt : s.prompt,
|
|
2066
|
+
inputs: Array.isArray(o.inputs) ? o.inputs : (s.inputs || []),
|
|
2067
|
+
edited: true
|
|
2068
|
+
};
|
|
2069
|
+
});
|
|
2070
|
+
return builtins.concat(loadCustomScenarios());
|
|
2071
|
+
}
|
|
2072
|
+
function loadCustomScenarios() {
|
|
2073
|
+
try {
|
|
2074
|
+
var raw = localStorage.getItem(CUSTOM_KEY);
|
|
2075
|
+
var arr = raw ? JSON.parse(raw) : [];
|
|
2076
|
+
if (!Array.isArray(arr)) return [];
|
|
2077
|
+
return arr.filter(function (s) { return s && s.id && s.title && s.prompt; }).map(function (s) {
|
|
2078
|
+
return {
|
|
2079
|
+
id: s.id, title: s.title, description: s.description || '',
|
|
2080
|
+
category: s.category || 'Custom', prompt: s.prompt,
|
|
2081
|
+
inputs: Array.isArray(s.inputs) ? s.inputs : [], custom: true
|
|
2082
|
+
};
|
|
2083
|
+
});
|
|
2084
|
+
} catch (e) { return []; }
|
|
2085
|
+
}
|
|
2086
|
+
function saveCustomScenarios(arr) {
|
|
2087
|
+
try { localStorage.setItem(CUSTOM_KEY, JSON.stringify(arr)); } catch (e) {}
|
|
2088
|
+
}
|
|
2089
|
+
function refreshScenarioViews() {
|
|
2090
|
+
SCENARIOS = composeScenarios();
|
|
2091
|
+
renderScenarioFilters();
|
|
2092
|
+
renderScenarios();
|
|
2093
|
+
}
|
|
2094
|
+
function scnInputRow(inp) {
|
|
2095
|
+
var row = el('div', 'scn-input-row');
|
|
2096
|
+
var k = el('input'); k.className = 'scn-k'; k.placeholder = 'key'; k.autocomplete = 'off'; k.spellcheck = false;
|
|
2097
|
+
var l = el('input'); l.className = 'scn-l'; l.placeholder = 'label'; l.autocomplete = 'off'; l.spellcheck = false;
|
|
2098
|
+
var p = el('input'); p.className = 'scn-p'; p.placeholder = 'placeholder (optional)'; p.autocomplete = 'off'; p.spellcheck = false;
|
|
2099
|
+
if (inp) { k.value = inp.key || ''; l.value = inp.label || ''; p.value = inp.placeholder || ''; }
|
|
2100
|
+
var del = el('button', 'btn-mini', '×'); del.type = 'button'; del.title = 'Remove'; del.onclick = function () { row.remove(); };
|
|
2101
|
+
row.appendChild(k); row.appendChild(l); row.appendChild(p); row.appendChild(del);
|
|
2102
|
+
return row;
|
|
2103
|
+
}
|
|
2104
|
+
function addScnInputRow(inp) { document.getElementById('scnInputRows').appendChild(scnInputRow(inp)); }
|
|
2105
|
+
function setScnErr(m) { document.getElementById('scnDrawerErr').textContent = m || ''; }
|
|
2106
|
+
function fillScnCatList() {
|
|
2107
|
+
var dl = document.getElementById('scnCatList'); dl.innerHTML = '';
|
|
2108
|
+
scenarioCategories().forEach(function (c) { var o = document.createElement('option'); o.value = c; dl.appendChild(o); });
|
|
2109
|
+
}
|
|
2110
|
+
function openScnDrawer(existing) {
|
|
2111
|
+
SCN_EDIT_ID = existing ? existing.id : null;
|
|
2112
|
+
SCN_EDIT_KIND = existing ? (existing.custom ? 'custom' : 'builtin') : 'new';
|
|
2113
|
+
var isEdit = !!existing;
|
|
2114
|
+
document.getElementById('scnDrawerTitle').textContent = isEdit ? (existing.custom ? 'Edit scenario' : 'Edit preset scenario') : 'Custom scenario';
|
|
2115
|
+
document.getElementById('scnTitle').value = existing ? existing.title : '';
|
|
2116
|
+
document.getElementById('scnCategory').value = existing ? (existing.category || '') : 'Custom';
|
|
2117
|
+
document.getElementById('scnDesc').value = existing ? (existing.description || '') : '';
|
|
2118
|
+
document.getElementById('scnPrompt').value = existing ? existing.prompt : '';
|
|
2119
|
+
var rows = document.getElementById('scnInputRows'); rows.innerHTML = '';
|
|
2120
|
+
((existing && existing.inputs) || []).forEach(function (inp) { addScnInputRow(inp); });
|
|
2121
|
+
fillScnCatList();
|
|
2122
|
+
var del = document.getElementById('scnDelete');
|
|
2123
|
+
del.hidden = !isEdit;
|
|
2124
|
+
del.textContent = 'Delete';
|
|
2125
|
+
setScnErr('');
|
|
2126
|
+
document.getElementById('scnDrawer').hidden = false;
|
|
2127
|
+
document.body.style.overflow = 'hidden';
|
|
2128
|
+
setTimeout(function () { document.getElementById('scnTitle').focus(); }, 30);
|
|
2129
|
+
}
|
|
2130
|
+
function closeScnDrawer() {
|
|
2131
|
+
document.getElementById('scnDrawer').hidden = true;
|
|
2132
|
+
document.body.style.overflow = '';
|
|
2133
|
+
SCN_EDIT_ID = null;
|
|
2134
|
+
SCN_EDIT_KIND = null;
|
|
2135
|
+
}
|
|
2136
|
+
function collectScnInputs() {
|
|
2137
|
+
var out = [], seen = {};
|
|
2138
|
+
var rows = document.getElementById('scnInputRows').querySelectorAll('.scn-input-row');
|
|
2139
|
+
for (var i = 0; i < rows.length; i++) {
|
|
2140
|
+
var key = rows[i].querySelector('.scn-k').value.trim();
|
|
2141
|
+
if (!key) continue;
|
|
2142
|
+
if (!/^[a-zA-Z0-9_]+$/.test(key)) return { error: 'Input key "' + key + '" may only use letters, digits, underscore.' };
|
|
2143
|
+
if (seen[key]) return { error: 'Duplicate input key: ' + key };
|
|
2144
|
+
seen[key] = 1;
|
|
2145
|
+
var label = rows[i].querySelector('.scn-l').value.trim() || key;
|
|
2146
|
+
var ph = rows[i].querySelector('.scn-p').value.trim();
|
|
2147
|
+
var o = { key: key, label: label }; if (ph) o.placeholder = ph;
|
|
2148
|
+
out.push(o);
|
|
2149
|
+
}
|
|
2150
|
+
return { inputs: out };
|
|
2151
|
+
}
|
|
2152
|
+
function saveScnDrawer() {
|
|
2153
|
+
var title = document.getElementById('scnTitle').value.trim();
|
|
2154
|
+
var prompt = document.getElementById('scnPrompt').value.trim();
|
|
2155
|
+
if (!title) { setScnErr('Title is required.'); return; }
|
|
2156
|
+
if (!prompt) { setScnErr('Prompt template is required.'); return; }
|
|
2157
|
+
var res = collectScnInputs();
|
|
2158
|
+
if (res.error) { setScnErr(res.error); return; }
|
|
2159
|
+
var cat = document.getElementById('scnCategory').value.trim() || 'Custom';
|
|
2160
|
+
var desc = document.getElementById('scnDesc').value.trim();
|
|
2161
|
+
if (SCN_EDIT_KIND === 'builtin' && SCN_EDIT_ID && isBuiltin(SCN_EDIT_ID)) {
|
|
2162
|
+
var ov = loadOverrides();
|
|
2163
|
+
ov[SCN_EDIT_ID] = { title: title, description: desc, category: cat, prompt: prompt, inputs: res.inputs };
|
|
2164
|
+
saveOverrides(ov);
|
|
2165
|
+
} else {
|
|
2166
|
+
var scn = {
|
|
2167
|
+
id: SCN_EDIT_ID || ('custom-' + Date.now().toString(36)),
|
|
2168
|
+
title: title, description: desc, category: cat, prompt: prompt, inputs: res.inputs, custom: true
|
|
2169
|
+
};
|
|
2170
|
+
var arr = loadCustomScenarios(), idx = -1;
|
|
2171
|
+
for (var i = 0; i < arr.length; i++) { if (arr[i].id === scn.id) { idx = i; break; } }
|
|
2172
|
+
if (idx >= 0) arr[idx] = scn; else arr.push(scn);
|
|
2173
|
+
saveCustomScenarios(arr);
|
|
2174
|
+
}
|
|
2175
|
+
closeScnDrawer();
|
|
2176
|
+
refreshScenarioViews();
|
|
2177
|
+
}
|
|
2178
|
+
function deleteScnDrawer() {
|
|
2179
|
+
if (!SCN_EDIT_ID) return;
|
|
2180
|
+
var id = SCN_EDIT_ID;
|
|
2181
|
+
if (SCN_EDIT_KIND === 'builtin' && isBuiltin(id)) {
|
|
2182
|
+
var hidden = loadHidden();
|
|
2183
|
+
if (hidden.indexOf(id) < 0) hidden.push(id);
|
|
2184
|
+
saveHidden(hidden);
|
|
2185
|
+
var ov = loadOverrides();
|
|
2186
|
+
if (ov[id]) { delete ov[id]; saveOverrides(ov); }
|
|
2187
|
+
} else {
|
|
2188
|
+
saveCustomScenarios(loadCustomScenarios().filter(function (s) { return s.id !== id; }));
|
|
2189
|
+
}
|
|
2190
|
+
closeScnDrawer();
|
|
2191
|
+
refreshScenarioViews();
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
/* ---------- assets ---------- */
|
|
2195
|
+
function fmtBytes(n) {
|
|
2196
|
+
if (!n && n !== 0) return '';
|
|
2197
|
+
if (n < 1024) return n + ' B';
|
|
2198
|
+
if (n < 1048576) return (n / 1024).toFixed(1) + ' KB';
|
|
2199
|
+
if (n < 1073741824) return (n / 1048576).toFixed(1) + ' MB';
|
|
2200
|
+
return (n / 1073741824).toFixed(2) + ' GB';
|
|
2201
|
+
}
|
|
2202
|
+
function fmtTime(ms) {
|
|
2203
|
+
var d = new Date(ms);
|
|
2204
|
+
if (isNaN(d.getTime())) return '';
|
|
2205
|
+
function p(x) { return (x < 10 ? '0' : '') + x; }
|
|
2206
|
+
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes());
|
|
2207
|
+
}
|
|
2208
|
+
function assetIcon(kind) {
|
|
2209
|
+
if (kind === 'audio') return '🎵';
|
|
2210
|
+
if (kind === 'video') return '🎬';
|
|
2211
|
+
if (kind === 'image') return '🖼';
|
|
2212
|
+
return '📄';
|
|
2213
|
+
}
|
|
2214
|
+
function assetKindLabel(kind) {
|
|
2215
|
+
if (kind === 'image') return 'Image';
|
|
2216
|
+
if (kind === 'video') return 'Video';
|
|
2217
|
+
if (kind === 'audio') return 'Audio';
|
|
2218
|
+
return 'File';
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
function fmtDim(w, h) { return w && h ? w + ' × ' + h : ''; }
|
|
2222
|
+
function assetFolder(rel) {
|
|
2223
|
+
if (!rel) return '';
|
|
2224
|
+
var norm = String(rel).replace(/\\\\/g, '/');
|
|
2225
|
+
var i = norm.lastIndexOf('/');
|
|
2226
|
+
return i > 0 ? norm.slice(0, i) : '';
|
|
2227
|
+
}
|
|
2228
|
+
function setDim(span, a, w, h) {
|
|
2229
|
+
var t = fmtDim(w, h);
|
|
2230
|
+
if (!t) return;
|
|
2231
|
+
a.dim = t;
|
|
2232
|
+
span.textContent = t;
|
|
2233
|
+
span.hidden = false;
|
|
2234
|
+
}
|
|
2235
|
+
function wireDim(mediaEl, a, span) {
|
|
2236
|
+
if (a.dim) { span.textContent = a.dim; span.hidden = false; return; }
|
|
2237
|
+
if (a.kind === 'image') {
|
|
2238
|
+
if (mediaEl.complete && mediaEl.naturalWidth) setDim(span, a, mediaEl.naturalWidth, mediaEl.naturalHeight);
|
|
2239
|
+
else mediaEl.addEventListener('load', function () { setDim(span, a, mediaEl.naturalWidth, mediaEl.naturalHeight); });
|
|
2240
|
+
} else if (a.kind === 'video') {
|
|
2241
|
+
if (mediaEl.videoWidth) setDim(span, a, mediaEl.videoWidth, mediaEl.videoHeight);
|
|
2242
|
+
else mediaEl.addEventListener('loadedmetadata', function () { setDim(span, a, mediaEl.videoWidth, mediaEl.videoHeight); });
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
function loadAssets() {
|
|
2247
|
+
loaded.assets = true;
|
|
2248
|
+
var body = document.getElementById('assetsBody');
|
|
2249
|
+
api('/api/assets').then(function (r) { return r.json(); }).then(function (j) {
|
|
2250
|
+
ASSETS = j.assets || [];
|
|
2251
|
+
setCount('assets', ASSETS.length);
|
|
2252
|
+
var baseEl = document.getElementById('assetsBase');
|
|
2253
|
+
if (baseEl) baseEl.textContent = j.base ? '— ' + j.base : '';
|
|
2254
|
+
renderAssetFilters();
|
|
2255
|
+
renderAssets();
|
|
2256
|
+
}).catch(function (e) { renderError(body, e); });
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
function renderAssetFilters() {
|
|
2260
|
+
var bar = document.getElementById('assetFilters');
|
|
2261
|
+
bar.innerHTML = '';
|
|
2262
|
+
var counts = { all: ASSETS.length };
|
|
2263
|
+
ASSETS.forEach(function (a) { counts[a.kind] = (counts[a.kind] || 0) + 1; });
|
|
2264
|
+
var tabs = [['all', 'All']].concat(
|
|
2265
|
+
[['image', 'Images'], ['video', 'Videos'], ['audio', 'Audio'], ['other', 'Files']]
|
|
2266
|
+
.filter(function (t) { return counts[t[0]]; })
|
|
2267
|
+
);
|
|
2268
|
+
tabs.forEach(function (t) {
|
|
2269
|
+
var cat = t[0];
|
|
2270
|
+
var b = el('button', 'filter' + (cat === ASSET_FILTER ? ' is-active' : ''));
|
|
2271
|
+
b.appendChild(el('span', '', t[1]));
|
|
2272
|
+
b.appendChild(el('span', 'n', String(counts[cat] || 0)));
|
|
2273
|
+
b.onclick = function () { ASSET_FILTER = cat; ASSET_PAGE = 1; renderAssetFilters(); renderAssets(); };
|
|
2274
|
+
bar.appendChild(b);
|
|
2275
|
+
});
|
|
2276
|
+
var sort = el('button', 'filter sort-toggle');
|
|
2277
|
+
sort.title = 'Toggle sort by generation time';
|
|
2278
|
+
sort.textContent = ASSET_SORT === 'new' ? '↓ Newest first' : '↑ Oldest first';
|
|
2279
|
+
sort.onclick = function () { ASSET_SORT = ASSET_SORT === 'new' ? 'old' : 'new'; ASSET_PAGE = 1; renderAssetFilters(); renderAssets(); };
|
|
2280
|
+
bar.appendChild(sort);
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
function assetMatches(a, q) {
|
|
2284
|
+
return matchQ(a.name, q) || matchQ(a.relPath, q) || matchQ(a.ext, q) || matchQ(assetKindLabel(a.kind), q);
|
|
2285
|
+
}
|
|
2286
|
+
function renderAssets() {
|
|
2287
|
+
var body = document.getElementById('assetsBody');
|
|
2288
|
+
var pager = document.getElementById('assetsPager');
|
|
2289
|
+
if (!ASSETS.length) {
|
|
2290
|
+
pager.innerHTML = '';
|
|
2291
|
+
renderEmpty(body, 'No generated assets yet.', 'Assets from <code>bl image</code>, <code>bl video</code>, <code>bl speech</code> and <code>bl omni</code> will appear here.');
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
var list = ASSET_FILTER === 'all' ? ASSETS : ASSETS.filter(function (a) { return a.kind === ASSET_FILTER; });
|
|
2295
|
+
list = list.filter(function (a) { return assetMatches(a, ASSET_Q); });
|
|
2296
|
+
list = list.slice().sort(function (a, b) { return ASSET_SORT === 'new' ? b.mtime - a.mtime : a.mtime - b.mtime; });
|
|
2297
|
+
if (!list.length) {
|
|
2298
|
+
pager.innerHTML = '';
|
|
2299
|
+
renderEmpty(body, ASSET_Q ? 'No assets match "' + ASSET_Q + '".' : 'No assets in this category.', '');
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
var info = pageSlice(list, ASSET_PAGE, getPageSize('assets')); ASSET_PAGE = info.page;
|
|
2303
|
+
body.innerHTML = '';
|
|
2304
|
+
var grid = el('div', 'asset-grid');
|
|
2305
|
+
info.items.forEach(function (a) {
|
|
2306
|
+
var card = el('div', 'asset');
|
|
2307
|
+
card.onclick = function () { openAssetDetail(a); };
|
|
2308
|
+
var media = el('div', 'asset-media');
|
|
2309
|
+
var src = '/api/asset/file?path=' + encodeURIComponent(a.relPath) + '&token=' + encodeURIComponent(token);
|
|
2310
|
+
var mediaEl = null;
|
|
2311
|
+
if (a.kind === 'image') {
|
|
2312
|
+
var img = el('img'); img.src = src; img.loading = 'lazy'; img.alt = a.name;
|
|
2313
|
+
img.title = 'View details';
|
|
2314
|
+
media.appendChild(img); mediaEl = img;
|
|
2315
|
+
} else if (a.kind === 'video') {
|
|
2316
|
+
var vid = el('video'); vid.src = src; vid.controls = true; vid.preload = 'metadata';
|
|
2317
|
+
vid.onclick = function (e) { e.stopPropagation(); };
|
|
2318
|
+
media.appendChild(vid); mediaEl = vid;
|
|
2319
|
+
} else if (a.kind === 'audio') {
|
|
2320
|
+
var au = el('audio'); au.src = src; au.controls = true; au.preload = 'none';
|
|
2321
|
+
au.onclick = function (e) { e.stopPropagation(); };
|
|
2322
|
+
media.appendChild(au);
|
|
2323
|
+
} else {
|
|
2324
|
+
var icon = el('span', 'asset-icon', assetIcon(a.kind));
|
|
2325
|
+
icon.title = 'View details';
|
|
2326
|
+
media.appendChild(icon);
|
|
2327
|
+
}
|
|
2328
|
+
card.appendChild(media);
|
|
2329
|
+
card.appendChild(el('span', 'asset-cat', assetKindLabel(a.kind)));
|
|
2330
|
+
var del = el('button', 'asset-del', '×'); del.title = 'Delete';
|
|
2331
|
+
del.onclick = function (e) { e.stopPropagation(); deleteAsset(a); };
|
|
2332
|
+
card.appendChild(del);
|
|
2333
|
+
var b = el('div', 'asset-body');
|
|
2334
|
+
var nm = el('div', 'asset-name link', a.name); nm.title = 'View details — ' + a.relPath;
|
|
2335
|
+
b.appendChild(nm);
|
|
2336
|
+
var folder = assetFolder(a.relPath);
|
|
2337
|
+
if (folder) {
|
|
2338
|
+
var fol = el('div', 'asset-folder', folder); fol.title = folder;
|
|
2339
|
+
b.appendChild(fol);
|
|
2340
|
+
}
|
|
2341
|
+
var meta = el('div', 'asset-meta');
|
|
2342
|
+
meta.appendChild(el('span', '', fmtTime(a.mtime)));
|
|
2343
|
+
if (a.ext) meta.appendChild(el('span', 'chip', a.ext));
|
|
2344
|
+
if (a.kind === 'image' || a.kind === 'video') {
|
|
2345
|
+
var dimSpan = el('span', 'chip', ''); dimSpan.hidden = true;
|
|
2346
|
+
if (mediaEl) wireDim(mediaEl, a, dimSpan);
|
|
2347
|
+
meta.appendChild(dimSpan);
|
|
2348
|
+
}
|
|
2349
|
+
meta.appendChild(el('span', '', fmtBytes(a.size)));
|
|
2350
|
+
b.appendChild(meta);
|
|
2351
|
+
card.appendChild(b);
|
|
2352
|
+
grid.appendChild(card);
|
|
2353
|
+
});
|
|
2354
|
+
body.appendChild(grid);
|
|
2355
|
+
renderPager('assetsPager', info, 'assets', function (p) { ASSET_PAGE = p; renderAssets(); });
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
function openAsset(a) {
|
|
2359
|
+
api('/api/asset/open?path=' + encodeURIComponent(a.relPath), { method: 'POST' }).then(function (r) {
|
|
2360
|
+
if (!r.ok) return r.json().then(function (j) { throw new Error(j.error || 'error'); });
|
|
2361
|
+
}).catch(function (e) { notify('Open failed', String(e)); });
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
function openAssetDetail(a) {
|
|
2365
|
+
var title = document.getElementById('infoTitle');
|
|
2366
|
+
title.textContent = '';
|
|
2367
|
+
title.appendChild(el('span', '', a.name));
|
|
2368
|
+
var body = document.getElementById('infoBody');
|
|
2369
|
+
body.innerHTML = '';
|
|
2370
|
+
var src = '/api/asset/file?path=' + encodeURIComponent(a.relPath) + '&token=' + encodeURIComponent(token);
|
|
2371
|
+
var prev = el('div', 'detail-preview');
|
|
2372
|
+
var mediaEl = null;
|
|
2373
|
+
if (a.kind === 'image') { var img = el('img'); img.src = src; img.alt = a.name; prev.appendChild(img); mediaEl = img; }
|
|
2374
|
+
else if (a.kind === 'video') { var vid = el('video'); vid.src = src; vid.controls = true; vid.preload = 'metadata'; prev.appendChild(vid); mediaEl = vid; }
|
|
2375
|
+
else if (a.kind === 'audio') { var au = el('audio'); au.src = src; au.controls = true; prev.appendChild(au); }
|
|
2376
|
+
else { prev.appendChild(el('span', 'asset-icon-lg', assetIcon(a.kind))); }
|
|
2377
|
+
body.appendChild(prev);
|
|
2378
|
+
body.appendChild(detailSection('Type', el('div', 'detail-desc', assetKindLabel(a.kind))));
|
|
2379
|
+
var chips = el('div', 'detail-chips');
|
|
2380
|
+
if (a.ext) chips.appendChild(el('span', 'chip', a.ext));
|
|
2381
|
+
if (a.kind === 'image' || a.kind === 'video') {
|
|
2382
|
+
var dimChip = el('span', 'chip', ''); dimChip.hidden = true;
|
|
2383
|
+
if (mediaEl) wireDim(mediaEl, a, dimChip);
|
|
2384
|
+
chips.appendChild(dimChip);
|
|
2385
|
+
}
|
|
2386
|
+
chips.appendChild(el('span', 'chip', fmtBytes(a.size)));
|
|
2387
|
+
chips.appendChild(el('span', 'chip', fmtTime(a.mtime)));
|
|
2388
|
+
body.appendChild(detailSection('Details', chips));
|
|
2389
|
+
body.appendChild(detailSection('Path', el('div', 'detail-path', a.relPath)));
|
|
2390
|
+
openInfoDrawer();
|
|
2391
|
+
var openBtn = el('button', 'btn-primary', 'Open locally');
|
|
2392
|
+
openBtn.onclick = function () { openAsset(a); };
|
|
2393
|
+
var delBtn = el('button', 'btn-danger', 'Delete');
|
|
2394
|
+
delBtn.onclick = function () { deleteAsset(a, true); };
|
|
2395
|
+
var foot = document.getElementById('infoFoot');
|
|
2396
|
+
foot.appendChild(openBtn); foot.appendChild(delBtn);
|
|
2397
|
+
foot.hidden = false;
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
function deleteAsset(a, fromDrawer) {
|
|
2401
|
+
openConfirm({
|
|
2402
|
+
title: 'Delete asset',
|
|
2403
|
+
message: 'Delete asset "' + a.name + '"? This removes the file from disk.',
|
|
2404
|
+
okLabel: 'Delete asset',
|
|
2405
|
+
onConfirm: function () {
|
|
2406
|
+
api('/api/asset?path=' + encodeURIComponent(a.relPath), { method: 'DELETE' }).then(function (r) {
|
|
2407
|
+
if (!r.ok) return r.json().then(function (j) { throw new Error(j.error || 'error'); });
|
|
2408
|
+
return r.json();
|
|
2409
|
+
}).then(function () {
|
|
2410
|
+
ASSETS = ASSETS.filter(function (x) { return x.relPath !== a.relPath; });
|
|
2411
|
+
setCount('assets', ASSETS.length);
|
|
2412
|
+
if (fromDrawer) closeInfoDrawer();
|
|
2413
|
+
renderAssetFilters();
|
|
2414
|
+
renderAssets();
|
|
2415
|
+
}).catch(function (e) { notify('Delete failed', String(e)); });
|
|
2416
|
+
}
|
|
2417
|
+
});
|
|
282
2418
|
}
|
|
283
2419
|
|
|
2420
|
+
/* ---------- wiring ---------- */
|
|
2421
|
+
var navItems = document.querySelectorAll('.nav-item');
|
|
2422
|
+
for (var n = 0; n < navItems.length; n++) {
|
|
2423
|
+
navItems[n].onclick = function () { showView(this.getAttribute('data-view')); };
|
|
2424
|
+
}
|
|
2425
|
+
(function () {
|
|
2426
|
+
var sidebar = document.getElementById('sidebar');
|
|
2427
|
+
var toggle = document.getElementById('sidebarToggle');
|
|
2428
|
+
if (!sidebar || !toggle) return;
|
|
2429
|
+
function apply(collapsed) {
|
|
2430
|
+
sidebar.classList.toggle('is-collapsed', collapsed);
|
|
2431
|
+
var label = collapsed ? 'Expand sidebar' : 'Collapse sidebar';
|
|
2432
|
+
toggle.setAttribute('aria-label', label);
|
|
2433
|
+
toggle.title = label;
|
|
2434
|
+
}
|
|
2435
|
+
var collapsed = false;
|
|
2436
|
+
try { collapsed = localStorage.getItem(SIDEBAR_KEY) === '1'; } catch (e) { /* ignore */ }
|
|
2437
|
+
apply(collapsed);
|
|
2438
|
+
toggle.onclick = function () {
|
|
2439
|
+
collapsed = !collapsed;
|
|
2440
|
+
apply(collapsed);
|
|
2441
|
+
try { localStorage.setItem(SIDEBAR_KEY, collapsed ? '1' : '0'); } catch (e) { /* ignore */ }
|
|
2442
|
+
};
|
|
2443
|
+
})();
|
|
284
2444
|
document.getElementById('saveBtn').onclick = save;
|
|
285
|
-
document.getElementById('newBtn').onclick = newProfile;
|
|
286
2445
|
document.getElementById('useBtn').onclick = saveAndActivateProfile;
|
|
287
2446
|
document.getElementById('deleteBtn').onclick = deleteProfile;
|
|
288
|
-
|
|
2447
|
+
document.getElementById('closeBtn').onclick = closeDrawer;
|
|
2448
|
+
document.getElementById('drawer').onclick = function (e) { if (e.target === this) closeDrawer(); };
|
|
2449
|
+
document.getElementById('infoClose').onclick = closeInfoDrawer;
|
|
2450
|
+
document.getElementById('infoDrawer').onclick = function (e) { if (e.target === this) closeInfoDrawer(); };
|
|
2451
|
+
document.getElementById('modalCancel').onclick = closeModal;
|
|
2452
|
+
document.getElementById('modalCreate').onclick = submitNewProfile;
|
|
2453
|
+
document.getElementById('modal').onclick = function (e) { if (e.target === this) closeModal(); };
|
|
2454
|
+
document.getElementById('modalInput').addEventListener('keydown', function (e) {
|
|
2455
|
+
if (e.key === 'Enter') { e.preventDefault(); submitNewProfile(); }
|
|
2456
|
+
});
|
|
2457
|
+
document.getElementById('confirmCancel').onclick = closeConfirm;
|
|
2458
|
+
document.getElementById('confirmOk').onclick = confirmOk;
|
|
2459
|
+
document.getElementById('confirm').onclick = function (e) { if (e.target === this) closeConfirm(); };
|
|
2460
|
+
document.getElementById('dispatchCancel').onclick = closeDispatch;
|
|
2461
|
+
document.getElementById('dispatchGo').onclick = doDispatch;
|
|
2462
|
+
document.getElementById('dispatch').onclick = function (e) { if (e.target === this) closeDispatch(); };
|
|
2463
|
+
document.getElementById('customScnBtn').onclick = function () { openScnDrawer(null); };
|
|
2464
|
+
document.getElementById('addMcpBtn').onclick = function () { openMcpCreate(); };
|
|
2465
|
+
document.getElementById('addSkillBtn').onclick = function () { openSkillInstall(); };
|
|
2466
|
+
document.getElementById('scnDrawerClose').onclick = closeScnDrawer;
|
|
2467
|
+
document.getElementById('scnDrawerSave').onclick = saveScnDrawer;
|
|
2468
|
+
document.getElementById('scnAddInput').onclick = function () { addScnInputRow(); };
|
|
2469
|
+
document.getElementById('scnDelete').onclick = deleteScnDrawer;
|
|
2470
|
+
document.getElementById('scnDrawer').onclick = function (e) { if (e.target === this) closeScnDrawer(); };
|
|
2471
|
+
document.addEventListener('keydown', function (e) {
|
|
2472
|
+
if (e.key !== 'Escape') return;
|
|
2473
|
+
if (!document.getElementById('confirm').hidden) closeConfirm();
|
|
2474
|
+
else if (!document.getElementById('dispatch').hidden) closeDispatch();
|
|
2475
|
+
else if (!document.getElementById('scnDrawer').hidden) closeScnDrawer();
|
|
2476
|
+
else if (!document.getElementById('acctMenu').hidden) closeAcctMenu();
|
|
2477
|
+
else if (!document.getElementById('modal').hidden) closeModal();
|
|
2478
|
+
else if (!document.getElementById('infoDrawer').hidden) closeInfoDrawer();
|
|
2479
|
+
else if (!document.getElementById('drawer').hidden) closeDrawer();
|
|
2480
|
+
});
|
|
2481
|
+
initSessionFooter();
|
|
2482
|
+
initAccount();
|
|
2483
|
+
initSearches();
|
|
2484
|
+
loadConfig();
|
|
2485
|
+
loadPlayground();
|
|
2486
|
+
|
|
2487
|
+
function initSessionFooter() {
|
|
2488
|
+
var url = location.href;
|
|
2489
|
+
var img = document.getElementById('qrImg');
|
|
2490
|
+
img.src = '/api/qr?token=' + encodeURIComponent(token) + '&data=' + encodeURIComponent(url);
|
|
2491
|
+
var link = document.getElementById('urlLink');
|
|
2492
|
+
link.href = url; link.textContent = url; link.title = url;
|
|
2493
|
+
var btn = document.getElementById('copyUrl');
|
|
2494
|
+
btn.onclick = function () {
|
|
2495
|
+
var done = function () {
|
|
2496
|
+
btn.textContent = 'Copied'; btn.classList.add('copied');
|
|
2497
|
+
setTimeout(function () { btn.textContent = 'Copy'; btn.classList.remove('copied'); }, 1400);
|
|
2498
|
+
};
|
|
2499
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
2500
|
+
navigator.clipboard.writeText(url).then(done).catch(function () { fallbackCopy(url); done(); });
|
|
2501
|
+
} else { fallbackCopy(url); done(); }
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
function fallbackCopy(text) {
|
|
2505
|
+
var ta = document.createElement('textarea');
|
|
2506
|
+
ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0';
|
|
2507
|
+
document.body.appendChild(ta); ta.select();
|
|
2508
|
+
try { document.execCommand('copy'); } catch (e) { /* ignore */ }
|
|
2509
|
+
document.body.removeChild(ta);
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
function authMethodLabel(p) {
|
|
2513
|
+
if (p === 'console') return 'Console gateway';
|
|
2514
|
+
if (p === 'apiKey') return 'API key';
|
|
2515
|
+
if (p === 'openapi') return 'OpenAPI (AK/SK)';
|
|
2516
|
+
return 'Account';
|
|
2517
|
+
}
|
|
2518
|
+
function acctHue(seed) {
|
|
2519
|
+
var h = 0, s = seed || 'bl';
|
|
2520
|
+
for (var i = 0; i < s.length; i++) { h = (h * 31 + s.charCodeAt(i)) % 360; }
|
|
2521
|
+
return h;
|
|
2522
|
+
}
|
|
2523
|
+
function avatarStyle(seed) {
|
|
2524
|
+
var h = acctHue(seed);
|
|
2525
|
+
return 'linear-gradient(135deg, hsl(' + h + ' 68% 56%), hsl(' + ((h + 40) % 360) + ' 68% 46%))';
|
|
2526
|
+
}
|
|
2527
|
+
function initAccount() {
|
|
2528
|
+
document.getElementById('loginBtn').onclick = startLogin;
|
|
2529
|
+
document.getElementById('logoutBtn').onclick = doLogout;
|
|
2530
|
+
document.getElementById('avatarBtn').onclick = function (e) { e.stopPropagation(); toggleAcctMenu(); };
|
|
2531
|
+
document.getElementById('acctMenu').onclick = function (e) { e.stopPropagation(); };
|
|
2532
|
+
document.addEventListener('click', function () { closeAcctMenu(); });
|
|
2533
|
+
loadAuthStatus().then(function (st) {
|
|
2534
|
+
if (AUTO_START_CHECKED) return;
|
|
2535
|
+
AUTO_START_CHECKED = true;
|
|
2536
|
+
if (st && !st.authenticated) showView('start');
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
function loadAuthStatus() {
|
|
2540
|
+
return api('/api/auth/status').then(function (r) { return r.json(); }).then(function (st) {
|
|
2541
|
+
AUTH = st; renderAccount(st); return st;
|
|
2542
|
+
}).catch(function () { return null; });
|
|
2543
|
+
}
|
|
2544
|
+
function renderAccount(st) {
|
|
2545
|
+
var wrap = document.getElementById('account');
|
|
2546
|
+
var loginBtn = document.getElementById('loginBtn');
|
|
2547
|
+
var avatar = document.getElementById('avatarBtn');
|
|
2548
|
+
wrap.hidden = false;
|
|
2549
|
+
if (st && st.authenticated) {
|
|
2550
|
+
loginBtn.hidden = true;
|
|
2551
|
+
var seed = st.masked || st.primary || st.site || 'bl';
|
|
2552
|
+
avatar.hidden = false;
|
|
2553
|
+
setAvatar(avatar, seed);
|
|
2554
|
+
avatar.title = authMethodLabel(st.primary);
|
|
2555
|
+
var lg = document.getElementById('acctAvatarLg');
|
|
2556
|
+
setAvatar(lg, seed);
|
|
2557
|
+
document.getElementById('acctMethod').textContent = authMethodLabel(st.primary);
|
|
2558
|
+
var meta = [];
|
|
2559
|
+
if (st.region) meta.push(st.region);
|
|
2560
|
+
if (st.site) meta.push(st.site);
|
|
2561
|
+
document.getElementById('acctMeta').textContent = meta.join(' · ') || 'Authenticated';
|
|
2562
|
+
var tok = document.getElementById('acctToken');
|
|
2563
|
+
tok.textContent = st.masked || '';
|
|
2564
|
+
tok.hidden = !st.masked;
|
|
2565
|
+
} else {
|
|
2566
|
+
avatar.hidden = true;
|
|
2567
|
+
closeAcctMenu();
|
|
2568
|
+
loginBtn.hidden = false;
|
|
2569
|
+
loginBtn.disabled = false;
|
|
2570
|
+
loginBtn.querySelector('span').textContent = 'Log in';
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
function toggleAcctMenu() {
|
|
2574
|
+
var m = document.getElementById('acctMenu');
|
|
2575
|
+
var willOpen = m.hidden;
|
|
2576
|
+
m.hidden = !willOpen;
|
|
2577
|
+
document.getElementById('avatarBtn').setAttribute('aria-expanded', willOpen ? 'true' : 'false');
|
|
2578
|
+
}
|
|
2579
|
+
function closeAcctMenu() {
|
|
2580
|
+
var m = document.getElementById('acctMenu');
|
|
2581
|
+
if (m && !m.hidden) {
|
|
2582
|
+
m.hidden = true;
|
|
2583
|
+
document.getElementById('avatarBtn').setAttribute('aria-expanded', 'false');
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
function setLoginUi(busy, label) {
|
|
2587
|
+
var b = document.getElementById('loginBtn');
|
|
2588
|
+
if (b) { b.disabled = busy; b.querySelector('span').textContent = label; }
|
|
2589
|
+
if (QS_LOGIN_BTN && document.body.contains(QS_LOGIN_BTN)) { QS_LOGIN_BTN.disabled = busy; QS_LOGIN_BTN.textContent = label; }
|
|
2590
|
+
}
|
|
2591
|
+
function startLogin() {
|
|
2592
|
+
setLoginUi(true, 'Opening browser…');
|
|
2593
|
+
api('/api/auth/login', { method: 'POST' }).then(function (r) { return r.json(); }).then(function (j) {
|
|
2594
|
+
if (j && j.started) {
|
|
2595
|
+
setLoginUi(true, 'Waiting for login…');
|
|
2596
|
+
pollAuth();
|
|
2597
|
+
} else {
|
|
2598
|
+
setLoginUi(false, 'Log in');
|
|
2599
|
+
}
|
|
2600
|
+
}).catch(function () {
|
|
2601
|
+
setLoginUi(false, 'Log in');
|
|
2602
|
+
});
|
|
2603
|
+
}
|
|
2604
|
+
function pollAuth() {
|
|
2605
|
+
if (authPoll) clearInterval(authPoll);
|
|
2606
|
+
var tries = 0;
|
|
2607
|
+
authPoll = setInterval(function () {
|
|
2608
|
+
tries++;
|
|
2609
|
+
loadAuthStatus().then(function (st) {
|
|
2610
|
+
if (st && st.authenticated) {
|
|
2611
|
+
clearInterval(authPoll); authPoll = null;
|
|
2612
|
+
// Reload so every view reflects the freshly stored credentials
|
|
2613
|
+
// (Profiles, base_url, console fields). Same effect as a restart, but
|
|
2614
|
+
// keeps the session token in the URL and the server process alive.
|
|
2615
|
+
setLoginUi(true, 'Signed in…');
|
|
2616
|
+
location.reload();
|
|
2617
|
+
} else if (tries >= 150) {
|
|
2618
|
+
clearInterval(authPoll); authPoll = null;
|
|
2619
|
+
setLoginUi(false, 'Log in');
|
|
2620
|
+
notify('Login timed out', 'The login was not completed in time. Click "Log in" to try again.');
|
|
2621
|
+
}
|
|
2622
|
+
});
|
|
2623
|
+
}, 2500);
|
|
2624
|
+
}
|
|
2625
|
+
function doLogout() {
|
|
2626
|
+
closeAcctMenu();
|
|
2627
|
+
// Reload after logout so every view reflects the cleared credentials
|
|
2628
|
+
// (Profiles, base_url, console fields), keeping the session token in the URL.
|
|
2629
|
+
api('/api/auth/logout', { method: 'POST' }).then(function () { location.reload(); }).catch(function () { loadAuthStatus(); });
|
|
2630
|
+
}
|
|
289
2631
|
<\/script>
|
|
290
2632
|
</body>
|
|
291
2633
|
</html>
|
|
292
|
-
`);return}if(s===`/api/config`&&
|
|
293
|
-
`)}catch{
|
|
294
|
-
`;)n+=1;continue}if(i===`/`&&a===`*`){for(n+=2;n<e.length&&!(e[n]===`*`&&e[n+1]===`/`);)n+=1;n+=2;continue}t+=i,n+=1}let i=``;for(n=0,r=!1;n<t.length;){let e=t[n];if(r){if(i+=e,e===`\\`){i+=t[n+1]??``,n+=2;continue}e===`"`&&(r=!1),n+=1;continue}if(e===`"`&&(r=!0),e===`,`){let e=n+1;for(;e<t.length&&/\s/.test(t[e]);)e+=1;if(t[e]===`}`||t[e]===`]`){n+=1;continue}}i+=e,n+=1}return i}function
|
|
295
|
-
`,{mode:384}),
|
|
296
|
-
`);let l=B(
|
|
297
|
-
`),t.dryRun){
|
|
2634
|
+
`);return}if(u===`/api/qr`&&c===`GET`){let e=(s.searchParams.get(`data`)??``).slice(0,512);if(!e){q(a,400,{error:`missing data`});return}try{let t=Ca(e);a.writeHead(200,{"Content-Type":`image/svg+xml; charset=utf-8`,"Cache-Control":`no-store`}),a.end(t)}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/config`&&c===`GET`){let e=t.profiles();q(a,200,{configFile:t.path,keys:ci,secretKeys:[...oi],enums:li,booleanKeys:[...ui],fieldDefaults:{...di,base_url:l.cn,output_dir:Da(),timeout:`300`},modelCatalog:fi,activeProfile:e.active,default:e.default,named:e.named});return}if(u===`/api/skills`&&c===`GET`){q(a,200,{skills:wi()});return}if(u===`/api/skill`&&c===`GET`){let e=Ti(s.searchParams.get(`id`)??``);if(!e){q(a,404,{error:`not found`});return}q(a,200,e);return}if(u===`/api/skill/install`&&c===`POST`){let e=s.searchParams.get(`source`)??``,t=s.searchParams.get(`name`)??``;try{q(a,200,ki(e,await Fa(i,25165824),t))}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/mcp`&&c===`GET`){q(a,200,{servers:ji()});return}if(u===`/api/mcp`&&c===`POST`){let e=await Pa(i),t;try{t=JSON.parse(e)}catch{q(a,400,{error:`invalid JSON body`});return}let n=t,r=typeof n.source==`string`?n.source:``,o=typeof n.scope==`string`&&n.scope?n.scope:`global`,s=typeof n.name==`string`?n.name:``;try{Fi(r,o,s,n.config),q(a,200,{saved:s.trim()})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/mcp`&&c===`DELETE`){let e=s.searchParams.get(`source`)??``,t=s.searchParams.get(`scope`)||`global`,n=s.searchParams.get(`name`)??``;try{Ii(e,t,n),q(a,200,{deleted:n})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/health`&&c===`GET`){let e=Number(process.versions.node.split(`.`)[0]);q(a,200,{node:process.version,nodeOk:Number.isFinite(e)&&e>=18,platform:process.platform,cwd:process.cwd()});return}if(u===`/api/agents`&&c===`GET`){let e=Ri(),t=await Promise.all(e.map(e=>Xi(e.id)));q(a,200,{agents:e.map((e,n)=>({...e,launchable:t[n],dispatchable:t[n]&&Ji(e.id)}))});return}if(u===`/api/agent`&&c===`GET`){let e=Wi(s.searchParams.get(`id`)??``);if(!e){q(a,404,{error:`not found`});return}q(a,200,e);return}if(u===`/api/agent/open`&&c===`POST`){let e=Wi(s.searchParams.get(`id`)??``),t=s.searchParams.get(`path`)??``,n=e?.settings.some(e=>e.path===t)??!1;if(!e||!n||!I(t)){q(a,404,{error:`not found`});return}try{await sr(t),q(a,200,{opened:t})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/scenarios`&&c===`GET`){let e=Ri(),t=await Promise.all(e.map(e=>Xi(e.id)));q(a,200,{scenarios:ea,agents:e.map((e,n)=>({id:e.id,label:e.label,dispatchable:t[n]&&Ji(e.id)})).filter(e=>e.dispatchable)});return}if(u===`/api/auth/status`&&c===`GET`){q(a,200,r?r.status():{authenticated:!1,methods:{apiKey:!1,console:!1,openapi:!1},primary:null});return}if(u===`/api/auth/login`&&c===`POST`){if(!r){q(a,400,{error:`login unavailable`});return}r.startConsoleLogin(),q(a,200,{started:!0});return}if(u===`/api/auth/logout`&&c===`POST`){if(!r){q(a,400,{error:`logout unavailable`});return}try{q(a,200,{loggedOut:await r.logout()})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/assets`&&c===`GET`){q(a,200,ja(n));return}if(u===`/api/asset/file`&&c===`GET`){let e=Ma(n,s.searchParams.get(`path`)??``),t=e&&I(e)?fn(e):null;if(!e||!t||!t.isFile()){q(a,404,{error:`not found`});return}a.writeHead(200,{"Content-Type":ka(_n(e)),"Content-Length":t.size,"Cache-Control":`no-store`});let r=cn(e);r.on(`error`,()=>{a.headersSent||a.writeHead(500),a.end()}),r.pipe(a);return}if(u===`/api/asset`&&c===`DELETE`){let e=s.searchParams.get(`path`)??``,t=Ma(n,e);if(!t||!I(t)||!fn(t).isFile()){q(a,404,{error:`not found`});return}try{pn(t),q(a,200,{deleted:e})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/asset/open`&&c===`POST`){let e=s.searchParams.get(`path`)??``,t=Ma(n,e);if(!t||!I(t)||!fn(t).isFile()){q(a,404,{error:`not found`});return}try{await sr(t),q(a,200,{opened:e})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/agent/launch`&&c===`POST`){try{q(a,200,await $i(s.searchParams.get(`id`)??``))}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/agent/dispatch`&&c===`POST`){let e=await Pa(i),t;try{t=JSON.parse(e)}catch{q(a,400,{error:`invalid JSON body`});return}let n=t,r=typeof n.agent==`string`?n.agent:``;if(!Ji(r)){q(a,400,{error:`agent cannot be dispatched a prompt`});return}let o,s=n.custom;if(s&&typeof s==`object`&&!Array.isArray(s)){let e=s,t=typeof e.prompt==`string`?e.prompt.trim():``;if(!t){q(a,400,{error:`custom scenario needs a prompt`});return}let n=[];if(Array.isArray(e.inputs)){for(let t of e.inputs)if(t&&typeof t==`object`){let e=t,r=typeof e.key==`string`?e.key.trim():``;if(r){let t=typeof e.label==`string`&&e.label.trim()?e.label.trim():r;n.push({key:r,label:t})}}}o={id:`custom`,title:typeof e.title==`string`&&e.title.trim()?e.title.trim():`Custom`,description:``,category:`自定义`,prompt:t,inputs:n}}else o=typeof n.scenario==`string`?ta(n.scenario):void 0;if(!o){q(a,400,{error:`unknown scenario`});return}let c={};if(n.values&&typeof n.values==`object`&&!Array.isArray(n.values))for(let[e,t]of Object.entries(n.values))typeof t==`string`&&(c[e]=t);for(let e of o.inputs??[])if(!c[e.key]||!c[e.key].trim()){q(a,400,{error:`Missing input: ${e.label}`});return}let l=na(o,c);try{let e=await $i(r,process.cwd(),l);q(a,200,{launched:!0,agent:r,scenario:o.id,command:e.command})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/active`&&c===`POST`){let e=await Pa(i),n;try{n=JSON.parse(e)}catch{q(a,400,{error:`invalid JSON body`});return}let r=n;try{q(a,200,{activeProfile:await t.activate(r.name)})}catch(e){q(a,400,{error:K(e)})}return}if(u===`/api/profile`&&c===`POST`){let e=await Pa(i),t;try{t=JSON.parse(e)}catch{q(a,400,{error:`invalid JSON body`});return}let n=t;if(!n.data||typeof n.data!=`object`||Array.isArray(n.data)){q(a,400,{error:`missing or invalid 'data'`});return}let r,o;try{r=Ke(n.name),o=La(n.data)}catch(e){q(a,400,{error:K(e)});return}let s=Ra(et(r),o);await St(s,r),q(a,200,{saved:s});return}if(u===`/api/profile`&&c===`DELETE`){try{q(a,200,{deleted:await re(s.searchParams.get(`name`)??void 0),activeProfile:t.profiles().active})}catch(e){q(a,400,{error:K(e)})}return}a.writeHead(404,{"Content-Type":`text/plain; charset=utf-8`}),a.end(`not found
|
|
2635
|
+
`)}catch(e){if(console.error(`[config ui] request failed:`,e),a.headersSent){a.end();return}q(a,500,{error:K(e)})}})}var Ba=w({description:`Open a local web UI to manage config profiles`,auth:`none`,usageArgs:`[--port <port>] [--no-open]`,flags:Na,exampleArgs:[``,`--port 8787`,`--no-open`],async run(e){let{settings:n,flags:r}=e,i=T(n.output);if(n.dryRun){M({host:`127.0.0.1`,port:r.port??`random free port`,config_file:e.configStore.path,routes:[`GET / -> web UI`,`GET /api/config -> read all profiles`,`GET /api/skills -> list installed agent skills`,`GET /api/skill -> read one skill's SKILL.md detail`,`POST /api/skill/install -> install a skill from an uploaded .zip into a skills root`,`GET /api/mcp -> list local MCP servers`,`POST /api/mcp -> create or update one MCP server (writes its source config)`,`DELETE /api/mcp -> remove one MCP server from its source config`,`GET /api/health -> runtime environment info (node, platform, cwd)`,`GET /api/agents -> list coding agent frameworks`,`GET /api/agent -> one agent's config detail (secrets masked)`,`POST /api/agent/open -> open one agent's config file with the OS default app`,`GET /api/auth/status -> current auth state`,`POST /api/auth/login -> start console login (opens browser)`,`POST /api/auth/logout -> clear all stored credentials`,`GET /api/assets -> list generated assets`,`GET /api/asset/file -> stream one asset file`,`POST /api/asset/open -> open one asset with the OS default app`,`POST /api/agent/launch -> launch a coding agent CLI in a new terminal`,`GET /api/scenarios -> list Playground scenarios and dispatchable agents`,`POST /api/agent/dispatch -> dispatch a scenario prompt to a connected agent`,`POST /api/profile -> save a profile`,`POST /api/active -> activate a profile`,`DELETE /api/profile -> delete a named profile`,`DELETE /api/asset -> delete one asset file`]},i);return}let o=Kt(16).toString(`hex`),s=n.outputDir||Da(),c=za(o,e.configStore,s,wa(e)),l;try{l=await or(c,r.port??0)}catch(e){throw new t(`Could not bind to 127.0.0.1 (no free port or permission denied): ${K(e)}`,a.USAGE)}let u=`http://127.0.0.1:${l}/?token=${o}`;if(!r.noOpen)try{await cr(u),j(`Opened the config UI in your default browser.`)}catch{j(`Could not open the browser automatically. Open the URL below manually.`)}j(`Config UI running at ${u}`),j(`Note: credentials are shown in cleartext in the browser (localhost only).`),j(`Press Ctrl+C to stop.`),await new Promise(e=>{let t=()=>c.close(()=>e());process.once(`SIGINT`,t),process.once(`SIGTERM`,t),c.once(`close`,()=>e())})}});function Va(e){let t=``,n=0,r=!1;for(;n<e.length;){let i=e[n],a=e[n+1];if(r){if(t+=i,i===`\\`){t+=a??``,n+=2;continue}i===`"`&&(r=!1),n+=1;continue}if(i===`"`){r=!0,t+=i,n+=1;continue}if(i===`/`&&a===`/`){for(;n<e.length&&e[n]!==`
|
|
2636
|
+
`;)n+=1;continue}if(i===`/`&&a===`*`){for(n+=2;n<e.length&&!(e[n]===`*`&&e[n+1]===`/`);)n+=1;n+=2;continue}t+=i,n+=1}let i=``;for(n=0,r=!1;n<t.length;){let e=t[n];if(r){if(i+=e,e===`\\`){i+=t[n+1]??``,n+=2;continue}e===`"`&&(r=!1),n+=1;continue}if(e===`"`&&(r=!0),e===`,`){let e=n+1;for(;e<t.length&&/\s/.test(t[e]);)e+=1;if(t[e]===`}`||t[e]===`]`){n+=1;continue}}i+=e,n+=1}return i}function Ha(e){if(!Qt(e))return{};try{return JSON.parse(en(e,`utf-8`))}catch{return{}}}function Ua(e){if(!Qt(e))return{};try{return JSON.parse(Va(en(e,`utf-8`)))}catch{return{}}}function Wa(e,t){$t(on(e),{recursive:!0});let n=e+`.tmp`;rn(n,JSON.stringify(t,null,2)+`
|
|
2637
|
+
`,{mode:384}),tn(n,e)}function Ga(e,t){$t(on(e),{recursive:!0});let n=e+`.tmp`;rn(n,t,{mode:384}),tn(n,e)}function Ka(e){Qt(e)&&Xt(e,`${e}.bak.${Math.floor(Date.now()/1e3)}`)}function qa(e){return e.includes(`/apps/anthropic`)}function Ja(e){let n=e.trim().replace(/\/+$/,``);if(qa(n))return{url:n};if(n.includes(`/compatible-mode`))return{url:n.replace(/\/compatible-mode(?:\/v\d+)?/,`/apps/anthropic`),rewrittenFrom:e.trim()};try{let t=new URL(n),r=t.hostname;if((r.includes(`dashscope`)||r.includes(`maas.aliyuncs.com`)||r.includes(`token-plan`))&&(t.pathname===`/`||t.pathname===``))return{url:`${t.origin}/apps/anthropic`,rewrittenFrom:e.trim()}}catch{}throw new t(`Claude Code requires an Anthropic-compatible base URL, got "${e}".`,a.USAGE,`Use a URL ending in /apps/anthropic (not /compatible-mode/v1). Example: https://dashscope.aliyuncs.com/apps/anthropic`)}function Ya(e){let n=e.trim();if(!/^[a-z0-9-]+$/.test(n))throw new t(`Invalid --region "${e}".`,a.USAGE,`Use a Model Studio region id, e.g. cn-beijing or ap-southeast-1.`);return`https://token-plan.${n}.maas.aliyuncs.com/compatible-mode/v1`}function Xa(e,t,n){let r=e[t];(r===void 0||r.trim()===``)&&(e[t]=n)}var Za={label:`Claude Code`,write({baseUrl:e,apiKey:t,model:n}){let r=F(process.env.CLAUDE_CONFIG_DIR||F(B(),`.claude`),`settings.json`),i=F(B(),`.claude.json`),a=[],o=Ja(e);o.rewrittenFrom&&a.push(`Rewrote base URL for Claude Code: "${o.rewrittenFrom}" → "${o.url}" (Claude Code needs /apps/anthropic, not OpenAI compatible-mode).`),Ka(r);let s=Ha(r),c=s.env??{};c.ANTHROPIC_BASE_URL=o.url,c.ANTHROPIC_AUTH_TOKEN=t,delete c.ANTHROPIC_API_KEY,c.ANTHROPIC_MODEL=n,Xa(c,`ANTHROPIC_DEFAULT_HAIKU_MODEL`,n),Xa(c,`ANTHROPIC_DEFAULT_SONNET_MODEL`,n),Xa(c,`ANTHROPIC_DEFAULT_OPUS_MODEL`,n),Xa(c,`CLAUDE_CODE_SUBAGENT_MODEL`,n),s.env=c,Wa(r,s),Ka(i);let l=Ha(i);return l.hasCompletedOnboarding=!0,Wa(i,l),{paths:[r,i],nextStep:"Run `claude` to start using Claude Code with DashScope.",warnings:a.length>0?a:void 0}}};const Qa=`DASHSCOPE_API_KEY`;function $a(e){return`[Bailian] ${e}`}function eo(e){if(e.envKey===Qa)return!0;let t=typeof e.name==`string`?e.name:``;return t===`bailian-cli`||t.startsWith(`[Bailian]`)}var to={label:`Qwen Code`,write({baseUrl:e,apiKey:t,model:n}){let r=F(B(),`.qwen`,`settings.json`),i=qa(e)?`anthropic`:`openai`,a=[];Ka(r);let o=Ha(r);o.$version=3;let s=o.env??{};s[Qa]=t,o.env=s;let c=process.env[Qa];c!==void 0&&c!==t&&a.push(`Shell/environment ${Qa} is set and overrides settings.json. Unset it (e.g. \`unset ${Qa}\`) so the key written here takes effect.`);let l=o.modelProviders??{},u=l[i]??[],d=u.find(e=>eo(e)&&e.id===n),f=u.find(e=>!eo(e)&&e.id===n);if(d){d.baseUrl=e,d.envKey=Qa;let t=typeof d.name==`string`?d.name.trim():``;(!t||t===`bailian-cli`)&&(d.name=$a(n))}else if(f){let e=typeof f.name==`string`&&f.name.length>0?f.name:String(f.id);a.push(`Model id "${n}" already exists as "${e}"; left unchanged (Qwen Code loads only the first entry per id). Remove or rename that entry if you want bailian-cli to own this model.`)}else u.push({id:n,name:$a(n),baseUrl:e,envKey:Qa});l[i]=u,o.modelProviders=l;let p=o.security??{};return p.auth={selectedType:i,apiKey:t,baseUrl:e},o.security=p,o.model={name:n,baseUrl:e},Wa(r,o),{paths:[r],nextStep:"Run `qwen` to start using Qwen Code with DashScope.",warnings:a.length>0?a:void 0}}},no={label:`OpenCode`,write({baseUrl:e,apiKey:t,model:n}){let r=F(B(),`.config`,`opencode`,`opencode.json`);Ka(r);let i=Ua(r);i.$schema||=`https://opencode.ai/config.json`;let a=i.provider??{};return a[`bailian-cli`]={npm:qa(e)?`@ai-sdk/anthropic`:`@ai-sdk/openai-compatible`,name:`Alibaba Cloud Model Studio`,options:{baseURL:e,apiKey:t,setCacheKey:!0},models:{[n]:{name:n}}},i.provider=a,Wa(r,i),{paths:[r],nextStep:"Run `opencode` then type `/models` to select your model."}}};const ro=`bailian-cli`;function io(e){let t=e.model;if(!t||typeof t!=`object`)return;let n=t.primary;return typeof n==`string`&&n.trim()!==``?n.trim():void 0}var ao={label:`OpenClaw`,write({baseUrl:e,apiKey:t,model:n,contextWindow:r}){let i=F(B(),`.openclaw`,`openclaw.json`),a=[],o=`${ro}/${n}`;Ka(i);let s=Ha(i),c=s.models??{};c.mode=`merge`;let l=c.providers??{};l[ro]={baseUrl:e,apiKey:t,api:qa(e)?`anthropic-messages`:`openai-completions`,models:[{id:n,name:n,contextWindow:r??256e3,cost:{input:0,output:0,cacheRead:0,cacheWrite:0}}]},c.providers=l,s.models=c;let u=s.agents??{},d=u.defaults??{},f=d.models??{};f[o]=f[o]??{},d.models=f;let p=io(d);return p?p.startsWith(`${ro}/`)?d.model={primary:o}:a.push(`Left existing primary model unchanged ("${p}"). Added provider "${ro}" — switch to "${o}" in OpenClaw if you want to use it.`):d.model={primary:o},u.defaults=d,s.agents=u,Wa(i,s),{paths:[i],nextStep:"Run `openclaw gateway restart`, then `openclaw` to start using OpenClaw with DashScope.",warnings:a.length>0?a:void 0}}},oo={label:`Hermes Agent`,write({baseUrl:e,apiKey:t,model:n}){let r=F(B(),`.hermes`,`config.yaml`);Ka(r);let i={};if(Qt(r))try{i=xn.parse(en(r,`utf-8`))??{}}catch{i={}}let a={default:n,provider:`custom`,base_url:e,api_key:t};return qa(e)&&(a.api_mode=`anthropic_messages`),i.model=a,Ga(r,xn.stringify(i)),{paths:[r],nextStep:'Run `hermes chat -q "hello"` to verify.'}}};const so=`bailian-cli`,co={"claude-code":Za,"qwen-code":to,opencode:no,openclaw:ao,hermes:oo,codex:{label:`Codex`,write({baseUrl:e,apiKey:t,model:n,wireApi:r}){let i=F(B(),`.codex`,`config.toml`),a=[];Ka(i);let o={};if(Qt(i))try{o=Sn(en(i,`utf-8`))}catch{o={}}o.model_provider=so,o.model=n;let s=r===`chat`?`chat`:`responses`;s===`chat`&&a.push('Current Codex releases refuse to load `wire_api = "chat"`; only use --wire-api chat with legacy Codex <= 0.80.0 (e.g. `npm install -g @openai/codex@0.80.0`).');let c=o.model_providers??{};c[so]={...c[so]??{},name:so,base_url:e,env_key:`OPENAI_API_KEY`,wire_api:s,requires_openai_auth:!0},o.model_providers=c,Ga(i,Cn(o)+`
|
|
2638
|
+
`);let l=F(B(),`.codex`,`auth.json`);Ka(l);let u=Ha(l);return u.OPENAI_API_KEY=t,Wa(l,u),{paths:[i,l],nextStep:"Run `codex` to start using Codex with DashScope.",warnings:a.length>0?a:void 0}}}},lo=Object.keys(co),uo=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.`,fo=new Map(uo.split(``).map((e,t)=>[e,t])),po=/^[A-Za-z0-9._-]+$/;function mo(){return new t(`Invalid obfuscated API key.`,a.USAGE,`--key expects the obfuscated key copied from the web console (starts with "o1_").`)}function ho(e){let t=[];for(let n of e){let e=fo.get(n);if(e===void 0)throw mo();t.push(e)}return t}function go(e){return e.map(e=>uo[e]).join(``)}function _o(e,t){return Math.imul((e^t)>>>0,16777619)>>>0}function vo(e){let t=e>>>0;return t^=t<<13,t^=t>>>17,t^=t<<5,t>>>0}function yo(e,t,n,r){let i=(2166136261^Math.imul(n+1,2654435761))>>>0;i=_o(i,e.length),i=_o(i,r);for(let e of t)i=_o(i,(fo.get(e)??-1)+1);for(let t of e)i=_o(i,t+1);i^=i>>>16,i=Math.imul(i,2246822507)>>>0,i^=i>>>13,i=Math.imul(i,3266489909)>>>0,i^=i>>>16,i=i>>>0||1831565813;let a=[];for(let e=0;e<r;e+=1)i=i+Math.imul(e+1,2654435761)>>>0,i=vo(i),a.push(i%65);return a}function bo(e,t){let n=ho(e),r=Math.floor(n.length/2),i=n.slice(0,r),a=n.slice(r);for(let e=7;e>=0;--e){let n=i,r=yo(n,t,e,a.length);i=a.map((e,t)=>(e-r[t]+65)%65),a=n}return go([...i,...a])}function xo(e){let t=4294967295;for(let n=0;n<e.length;n+=1){t^=e.charCodeAt(n);for(let e=0;e<8;e+=1){let e=-(t&1);t=t>>>1^3988292384&e}}return(t^4294967295)>>>0}function So(e,t){let n=e>>>0,r=Array(t).fill(uo[0]);for(let e=t-1;e>=0;--e)r[e]=uo[n%65],n=Math.floor(n/65);if(n!==0)throw mo();return r.join(``)}function Co(e){if(e.length!==6||!po.test(e))throw mo()}function wo(e){if(e.length<16||!e.startsWith(`o1_`))throw mo();let t=e.slice(3);if(!po.test(t))throw mo();let n=t.slice(0,6),r=t.slice(6,-6),i=t.slice(-6);if(Co(n),!r)throw mo();let a=bo(r,n);if(!po.test(a)||i!==So(xo(a),6))throw mo();return a}var To=w({description:`Configure a coding agent to use DashScope API`,auth:`none`,usageArgs:`--agent <name> (--base-url <url> | --region <region>) (--api-key <key> | --key <encoded>) --model <model>`,flags:{agent:{type:`string`,valueHint:`<name>`,description:`Target agent: ${lo.join(`, `)}`,required:!0,choices:lo},baseUrl:{type:`string`,valueHint:`<url>`,description:`API base URL`},region:{type:`string`,valueHint:`<region>`,description:`Model Studio region (e.g. cn-beijing, ap-southeast-1); converted into --base-url. Token Plan only`},apiKey:{type:`string`,valueHint:`<key>`,description:`API key`},key:{type:`string`,valueHint:`<encoded>`,description:`Obfuscated API key from the web console (starts with "o1_"); decoded into --api-key`},model:{type:`string`,valueHint:`<model>`,description:`Default model name`,required:!0},contextWindow:{type:`number`,valueHint:`<tokens>`,description:`OpenClaw only: model context window in tokens (default: 256000)`},wireApi:{type:`string`,valueHint:`<api>`,description:`Codex only: wire protocol (default: responses). "chat" only works with legacy Codex <= 0.80.0`,choices:[`chat`,`responses`]}},exampleArgs:[`--agent claude-code --base-url https://dashscope.aliyuncs.com/apps/anthropic --api-key sk-xxxxx --model qwen3-max`,`--agent qwen-code --base-url https://dashscope.aliyuncs.com/compatible-mode/v1 --api-key sk-xxxxx --model qwen3-coder-plus`,`--agent codex --base-url https://dashscope.aliyuncs.com/compatible-mode/v1 --api-key sk-xxxxx --model qwen3-coder-plus`],validate(e){if(!e.baseUrl&&!e.region)return`one of --base-url or --region is required`;if(e.baseUrl&&e.region)return`--base-url and --region are mutually exclusive`;if(!e.apiKey&&!e.key)return`one of --api-key or --key is required`;if(e.apiKey&&e.key)return`--api-key and --key are mutually exclusive`},async run(e){let{settings:t,flags:n}=e,r=n.agent,{model:i,contextWindow:a,wireApi:o}=n,s=n.region?Ya(n.region):n.baseUrl,c=n.key?wo(n.key):n.apiKey,l=co[r],u=T(t.output);if(r===`hermes`&&wn()===`win32`&&process.stderr.write(`Warning: Hermes Agent does not support native Windows. Please use WSL2.
|
|
2639
|
+
`),t.dryRun){M({agent:r,label:l.label,base_url:s,api_key:E(c),model:i},u);return}let d={baseUrl:s,apiKey:c,model:i,contextWindow:a,wireApi:o},f=l.write(d);if(!t.quiet){j(`${l.label} configured successfully.`);for(let e of f.paths)j(` Written: ${e}`);j(` ${f.nextStep}`);for(let e of f.warnings??[])process.stderr.write(`Warning: ${e}\n`)}}});const Eo=`npx skills add modelstudioai/cli --all -g -y`;function Do(e){return{cmd:`npm install -g ${e}@latest`,label:`npm`}}function Oo(e){process.stderr.write(`
|
|
298
2640
|
Updating agent skill...
|
|
299
|
-
`);try{
|
|
300
|
-
`);let o=await
|
|
2641
|
+
`);try{Tn(Eo,{stdio:`inherit`}),process.stderr.write(`${e.green(`✓ Agent skill updated.`)}\n`)}catch{process.stderr.write(`${e.yellow(`Agent skill update skipped. Run manually: ${Eo}`)}\n`)}}var ko=w({description:`Update the CLI to the latest version`,auth:`none`,exampleArgs:[``],async run(e){let{identity:t}=e,n=t.npmPackage,r=t.binName,i=t.version,a=k(process.stderr);process.stderr.write(`Current version: ${a.yellow(i)}\n`),process.stderr.write(`Checking for updates...
|
|
2642
|
+
`);let o=await Ft(5e3,n);if(o&&o===i){process.stderr.write(`${a.green(`\u2713 Already up to date (${i}).`)}\n`),Oo(a);return}o&&process.stderr.write(`Latest version: ${a.green(o)}\n\n`);let{cmd:s,label:c}=Do(n);process.stderr.write(`Updating ${n} via ${c}...\n\n`);try{Tn(s,{stdio:`inherit`});try{let e=Tn(`${r} --version 2>/dev/null`,{encoding:`utf-8`}).trim().replace(RegExp(`^${r}\\s+`),``);process.stderr.write(`\n${a.green(`\u2713 Update complete: ${i} \u2192 ${e}`)}\n`);try{rn(F(ve(),`update-state.json`),JSON.stringify({lastChecked:Date.now(),latestVersion:e}))}catch{}}catch{process.stderr.write(`\n${a.green(`✓ Update complete.`)}\n`)}Oo(a)}catch{process.stderr.write(`
|
|
301
2643
|
Automatic update failed. Please run manually:
|
|
302
|
-
`),process.stderr.write(` ${s}\n\n`)}}}),
|
|
303
|
-
`)}else{let n=await e.client.requestJson({path:h(r),method:`POST`,body:s}),i=n.output?.text??``;t.quiet||o===`text`?P(i):F(n,o)}}});const Gi=`zeldaEasy.broadscope-bailian.app-control.list`;var Ki=T({description:`List Bailian applications`,auth:`console`,usageArgs:`[flags]`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Filter by app name (keyword search)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 30)`}},exampleArgs:[``,`--name customer service`,`--page 2 --page-size 10`,`--output json`],async run(e){let{settings:t,flags:n}=e,r=n.name||``,i=n.page||1,a=n.pageSize||30,o=E(t.output),s={reqDTO:{name:r,notInTypes:[10],type:5,statuses:[1,4],page_no:i,page_size:a}};if(t.dryRun){F({api:Gi,data:s},o);return}let c=await e.client.console(Gi,s),l=c?.data?.DataV2?.data?.data?.list??[];F({total:c?.data?.DataV2?.data?.data?.total??0,apps:l.map(e=>({code:e.code,name:e.name,user_prompt_params:e.config?.user_prompt_params??[]}))},o)}}),qi=T({description:`Add memory from messages or custom content`,auth:`apiKey`,usageArgs:`--user-id <id> [--messages <json>] [--content <text>] [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},messages:{type:`string`,valueHint:`<json>`,description:`Messages JSON array: [{"role":"user","content":"..."},...]`},content:{type:`string`,valueHint:`<text>`,description:`Custom content text to memorize`},profileSchema:{type:`string`,valueHint:`<id>`,description:`Profile schema ID for user profiling`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (isolate memory space)`}},exampleArgs:[`--user-id user1 --content "The user likes Python programming"`,`--user-id user1 --messages '[{"role":"user","content":"I like traveling"}]'`,`--user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx`],validate:e=>!e.messages&&!e.content?`Provide --messages or --content.`:void 0,async run(e){let{settings:t,flags:n}=e,r={user_id:n.userId};if(n.messages)try{r.messages=JSON.parse(n.messages)}catch{throw new p(`--messages must be valid JSON array`)}n.content&&(r.custom_content=n.content),n.profileSchema&&(r.profile_schema=n.profileSchema),n.memoryLibraryId&&(r.memory_library_id=n.memoryLibraryId);let i=E(t.output);if(t.dryRun){F({endpoint:e.client.url(Be()),request:r},i);return}let a=await e.client.requestJson({path:Be(),method:`POST`,body:r});t.quiet||i===`text`?P(`Memory added. IDs: ${a.memory_ids?.join(`, `)||`none`}`):F(a,i)}}),Ji=T({description:`Search memory nodes by query or messages`,auth:`apiKey`,usageArgs:`--user-id <id> [--query <text>] [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},query:{type:`string`,valueHint:`<text>`,description:`Search query text`},messages:{type:`string`,valueHint:`<json>`,description:`Messages JSON array for context-based search`},topK:{type:`number`,valueHint:`<n>`,description:`Number of results to return (default: 10)`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID`}},exampleArgs:[`--user-id user1 --query "programming preferences"`,`--user-id user1 --messages '[{"role":"user","content":"recommend a book"}]' --top-k 5`],validate:e=>!e.query&&!e.messages?`Provide --query or --messages.`:void 0,async run(e){let{settings:t,flags:n}=e,r={user_id:n.userId};if(n.query&&(r.query=n.query),n.messages)try{r.messages=JSON.parse(n.messages)}catch{throw new p(`--messages must be valid JSON array`)}!r.messages&&r.query&&(r.messages=[{role:`user`,content:r.query}]),n.topK!==void 0&&(r.top_k=n.topK),n.memoryLibraryId&&(r.memory_library_id=n.memoryLibraryId);let i=E(t.output);if(t.dryRun){F({endpoint:e.client.url(Ue()),request:r},i);return}let a=await e.client.requestJson({path:Ue(),method:`POST`,body:r});if(t.quiet||i===`text`)if(!a.memory_nodes||a.memory_nodes.length===0)P(`No memory nodes found.`);else for(let e of a.memory_nodes)P(`[${e.memory_node_id}] ${e.content}`);else F(a,i)}}),Yi=T({description:`List memory nodes for a user`,auth:`apiKey`,usageArgs:`--user-id <id> [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID`}},exampleArgs:[`--user-id user1`,`--user-id user1 --page-size 20 --page 2`],async run(e){let{settings:t,flags:n}=e,r=n.userId,i=E(t.output),a=new URLSearchParams;a.set(`user_id`,r),n.pageSize!==void 0&&a.set(`page_size`,String(n.pageSize)),n.page!==void 0&&a.set(`page_num`,String(n.page)),n.memoryLibraryId&&a.set(`memory_library_id`,n.memoryLibraryId);let o=`${Ve()}?${a.toString()}`;if(t.dryRun){F({endpoint:e.client.url(o),method:`GET`},i);return}let s=await e.client.requestJson({path:o,method:`GET`});if(t.quiet||i===`text`)if(!s.memory_nodes||s.memory_nodes.length===0)P(`No memory nodes found.`);else{for(let e of s.memory_nodes)P(`[${e.memory_node_id}] ${e.content}`);s.total!==void 0&&P(`\nTotal: ${s.total}`)}else F(s,i)}}),Xi=T({description:`Update a memory node content`,auth:`apiKey`,usageArgs:`--node-id <id> --user-id <id> --content <text>`,flags:{nodeId:{type:`string`,valueHint:`<id>`,description:`Memory node ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},content:{type:`string`,valueHint:`<text>`,description:`New content for the memory node (required)`,required:!0},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (non-default library)`}},exampleArgs:[`--node-id node_xxx --user-id user1 --content "updated memory content"`],async run(e){let{settings:t,flags:n}=e,r=n.nodeId,i={user_id:n.userId,custom_content:n.content};n.memoryLibraryId&&(i.memory_library_id=n.memoryLibraryId);let a=E(t.output);if(t.dryRun){F({endpoint:e.client.url(He(r)),method:`PATCH`,request:i},a);return}let o=await e.client.requestJson({path:He(r),method:`PATCH`,body:i});t.quiet||a===`text`?P(`Memory node ${r} updated.`):F(o,a)}}),Zi=T({description:`Delete a memory node`,auth:`apiKey`,usageArgs:`--node-id <id> --user-id <id>`,flags:{nodeId:{type:`string`,valueHint:`<id>`,description:`Memory node ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (non-default library)`}},exampleArgs:[`--node-id node_xxx --user-id user1`],async run(e){let{settings:t,flags:n}=e,r=n.nodeId,i=n.userId,a=E(t.output),o=new URLSearchParams({user_id:i});n.memoryLibraryId&&o.set(`memory_library_id`,n.memoryLibraryId);let s=`${He(r)}?${o.toString()}`;if(t.dryRun){F({endpoint:e.client.url(s),method:`DELETE`},a);return}let c=await e.client.requestJson({path:s,method:`DELETE`});t.quiet||a===`text`?P(`Memory node ${r} deleted.`):F(c,a)}}),Qi=T({description:`Create a user profile schema for memory profiling`,auth:`apiKey`,usageArgs:`--name <name> --attributes <json> [flags]`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Schema name (required)`,required:!0},description:{type:`string`,valueHint:`<text>`,description:`Schema description`},attributes:{type:`string`,valueHint:`<json>`,description:`Attributes JSON array: [{"name":"age","description":"age"}]`,required:!0}},exampleArgs:[`--name "user_basic" --attributes '[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]'`],async run(e){let{settings:t,flags:n}=e,r=n.name,i=n.attributes,a;try{a=JSON.parse(i)}catch{throw new p(`--attributes must be valid JSON array`)}let o={name:r,attributes:a};n.description&&(o.description=n.description);let s=E(t.output);if(t.dryRun){F({endpoint:e.client.url(Ze()),request:o},s);return}let c=await e.client.requestJson({path:Ze(),method:`POST`,body:o});t.quiet||s===`text`?P(`Profile schema created: ${c.profile_schema_id}`):F(c,s)}}),$i=T({description:`Get user profile by schema ID and user ID`,auth:`apiKey`,usageArgs:`--schema-id <id> --user-id <id>`,flags:{schemaId:{type:`string`,valueHint:`<id>`,description:`Profile schema ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0}},exampleArgs:[`--schema-id schema_xxx --user-id user1`],async run(e){let{settings:t,flags:n}=e,r=n.schemaId,i=n.userId,a=E(t.output),o=new URLSearchParams({user_id:i}),s=`${_t(r)}?${o.toString()}`;if(t.dryRun){F({endpoint:e.client.url(s),method:`GET`},a);return}let c=await e.client.requestJson({path:s,method:`GET`});if(t.quiet||a===`text`)if(c.profile?.attributes)for(let e of c.profile.attributes)P(`${e.name}: ${e.value??`(empty)`}`);else P(`No profile data found.`);else F(c,a)}}),ea=T({description:"Retrieve from a Bailian knowledge base (deprecated, use `search` instead)",auth:`apiKey`,usageArgs:`--index-id <id> --query <text> [flags]`,flags:{indexId:{type:`string`,valueHint:`<id>`,description:`Knowledge base index ID (required)`,required:!0},query:{type:`string`,valueHint:`<text>`,description:`Search query (required)`,required:!0},denseSimilarityTopK:{type:`number`,valueHint:`<n>`,description:`Dense retrieval top K`},sparseSimilarityTopK:{type:`number`,valueHint:`<n>`,description:`Sparse retrieval top K`},rerank:{type:`switch`,description:`Enable reranking`},rerankTopN:{type:`number`,valueHint:`<n>`,description:`Rerank top N results`},rerankModel:{type:`string`,valueHint:`<name>`,description:`Rerank model, e.g. qwen3-rerank-hybrid`},rerankMode:{type:`string`,valueHint:`<mode>`,description:`Rerank mode: qa, similar, or custom`},rerankInstruct:{type:`string`,valueHint:`<text>`,description:`Custom rerank instruction, when mode=custom`},topK:{type:`number`,valueHint:`<n>`,description:`Number of results (deprecated, use --rerank-top-n)`}},exampleArgs:[`--index-id idx_xxx --query "How to use Alibaba Cloud Bailian"`,`--index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid`],async run(e){let{settings:t,flags:n}=e,r=E(t.output);n.topK!==void 0&&n.rerankTopN===void 0&&(process.stderr.write(`Warning: --top-k is deprecated. Use --rerank-top-n instead.
|
|
304
|
-
`),n.rerankTopN=n.topK);let i={index_id:n.indexId,query:n.query,search_filters:[]};if(n.denseSimilarityTopK!==void 0&&(i.dense_similarity_top_k=n.denseSimilarityTopK),n.sparseSimilarityTopK!==void 0&&(i.sparse_similarity_top_k=n.sparseSimilarityTopK),n.rerank&&(i.enable_reranking=!0),n.rerankTopN!==void 0&&(i.rerank_top_n=n.rerankTopN),n.rerankModel){let e={model_name:n.rerankModel};n.rerankMode&&(e.rerank_mode=n.rerankMode),n.rerankInstruct&&(e.rerank_instruct=n.rerankInstruct),i.rerank=[e]}if(t.dryRun){
|
|
2644
|
+
`),process.stderr.write(` ${s}\n\n`)}}}),Ao=w({description:`Call a Bailian application (agent or workflow)`,auth:`apiKey`,usageArgs:`--app-id <id> --prompt <text> [flags]`,flags:{appId:{type:`string`,valueHint:`<id>`,description:`Application ID (required)`,required:!0},prompt:{type:`string`,valueHint:`<text>`,description:`Input prompt text`,required:!0},image:{type:`array`,valueHint:`<url>`,description:`Image URL(s) to pass to the app (repeatable)`},fileId:{type:`array`,valueHint:`<id>`,description:`Pre-uploaded file ID(s) (repeatable)`},sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID for multi-turn conversation`},stream:{type:`switch`,description:`Stream response (default: on in TTY)`},pipelineIds:{type:`string`,valueHint:`<ids>`,description:`Knowledge base pipeline IDs (comma-separated)`},memoryId:{type:`string`,valueHint:`<id>`,description:`Memory ID for long-term memory`},bizParams:{type:`string`,valueHint:`<json>`,description:`Business parameters JSON (workflow variables)`},hasThoughts:{type:`switch`,description:`Show agent thinking process`}},exampleArgs:[`--app-id abc123 --prompt "Hello"`,`--app-id abc123 --prompt "Describe this image" --image https://example.com/photo.jpg`,`--app-id abc123 --prompt "Analyze the image" --image img1.jpg --image img2.jpg`,`--app-id abc123 --prompt "Continue" --session-id sess_xxx --stream`,`--app-id abc123 --prompt "Search for materials" --pipeline-ids pipe1,pipe2`,`--app-id abc123 --prompt "Start" --biz-params '{"key":"value"}'`],async run(e){let{settings:t,flags:n}=e,r=n.appId,i=n.prompt,a=n.stream||process.stdout.isTTY,o=T(t.output),s={input:{prompt:i},parameters:{incremental_output:a}};n.sessionId&&(s.input.session_id=n.sessionId);let c=n.image;c&&c.length>0&&(s.input.image_list=c);let l=n.fileId;if(l&&l.length>0&&(s.input.file_ids=l),n.hasThoughts&&(s.parameters.has_thoughts=!0),n.pipelineIds){let e=n.pipelineIds.split(`,`).map(e=>e.trim()).filter(Boolean);s.parameters.rag_options={pipeline_ids:e}}if(n.memoryId&&(s.parameters.memory_id=n.memoryId),n.bizParams)try{s.input.biz_params=JSON.parse(n.bizParams)}catch{throw new p(`--biz-params must be valid JSON`)}if(t.dryRun){M({endpoint:e.client.url(h(r)),request:s},o);return}if(a){let i=await e.client.request({path:h(r),method:`POST`,body:s,headers:{"X-DashScope-SSE":`enable`},stream:!0}),a=``,c=``,l=o===`text`,u=k(process.stderr);for await(let e of Ye(i)){if(e.data===`[DONE]`)break;try{let t=JSON.parse(e.data),r=t.output?.text;if(r&&(l&&process.stdout.write(r),a+=r),t.output?.session_id&&(c=t.output.session_id),t.output?.thoughts&&n.hasThoughts)for(let e of t.output.thoughts)e.thought&&process.stderr.write(`${u.dim(`[Thinking] ${e.thought}`)}\n`),e.action_name&&process.stderr.write(`${u.dim(`[Action] ${e.action_name}: ${e.action_input||``}`)}\n`),e.observation&&process.stderr.write(`${u.dim(`[Observation] ${e.observation}`)}\n`)}catch{}}c&&!t.quiet&&process.stderr.write(`${u.dim(`Session ID: ${c}`)}\n`),o===`json`?M({text:a,session_id:c},o):process.stdout.write(`
|
|
2645
|
+
`)}else{let n=await e.client.requestJson({path:h(r),method:`POST`,body:s}),i=n.output?.text??``;t.quiet||o===`text`?j(i):M(n,o)}}});const jo=`zeldaEasy.broadscope-bailian.app-control.list`;var Mo=w({description:`List Bailian applications`,auth:`console`,usageArgs:`[flags]`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Filter by app name (keyword search)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 30)`}},exampleArgs:[``,`--name customer service`,`--page 2 --page-size 10`,`--output json`],async run(e){let{settings:t,flags:n}=e,r=n.name||``,i=n.page||1,a=n.pageSize||30,o=T(t.output),s={reqDTO:{name:r,notInTypes:[10],type:5,statuses:[1,4],page_no:i,page_size:a}};if(t.dryRun){M({api:jo,data:s},o);return}let c=await e.client.console(jo,s),l=c?.data?.DataV2?.data?.data?.list??[];M({total:c?.data?.DataV2?.data?.data?.total??0,apps:l.map(e=>({code:e.code,name:e.name,user_prompt_params:e.config?.user_prompt_params??[]}))},o)}}),No=w({description:`Add memory from messages or custom content`,auth:`apiKey`,usageArgs:`--user-id <id> [--messages <json>] [--content <text>] [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},messages:{type:`string`,valueHint:`<json>`,description:`Messages JSON array: [{"role":"user","content":"..."},...]`},content:{type:`string`,valueHint:`<text>`,description:`Custom content text to memorize`},profileSchema:{type:`string`,valueHint:`<id>`,description:`Profile schema ID for user profiling`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (isolate memory space)`}},exampleArgs:[`--user-id user1 --content "The user likes Python programming"`,`--user-id user1 --messages '[{"role":"user","content":"I like traveling"}]'`,`--user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx`],validate:e=>!e.messages&&!e.content?`Provide --messages or --content.`:void 0,async run(e){let{settings:t,flags:n}=e,r={user_id:n.userId};if(n.messages)try{r.messages=JSON.parse(n.messages)}catch{throw new p(`--messages must be valid JSON array`)}n.content&&(r.custom_content=n.content),n.profileSchema&&(r.profile_schema=n.profileSchema),n.memoryLibraryId&&(r.memory_library_id=n.memoryLibraryId);let i=T(t.output);if(t.dryRun){M({endpoint:e.client.url(Ve()),request:r},i);return}let a=await e.client.requestJson({path:Ve(),method:`POST`,body:r});t.quiet||i===`text`?j(`Memory added. IDs: ${a.memory_ids?.join(`, `)||`none`}`):M(a,i)}}),Po=w({description:`Search memory nodes by query or messages`,auth:`apiKey`,usageArgs:`--user-id <id> [--query <text>] [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},query:{type:`string`,valueHint:`<text>`,description:`Search query text`},messages:{type:`string`,valueHint:`<json>`,description:`Messages JSON array for context-based search`},topK:{type:`number`,valueHint:`<n>`,description:`Number of results to return (default: 10)`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID`}},exampleArgs:[`--user-id user1 --query "programming preferences"`,`--user-id user1 --messages '[{"role":"user","content":"recommend a book"}]' --top-k 5`],validate:e=>!e.query&&!e.messages?`Provide --query or --messages.`:void 0,async run(e){let{settings:t,flags:n}=e,r={user_id:n.userId};if(n.query&&(r.query=n.query),n.messages)try{r.messages=JSON.parse(n.messages)}catch{throw new p(`--messages must be valid JSON array`)}!r.messages&&r.query&&(r.messages=[{role:`user`,content:r.query}]),n.topK!==void 0&&(r.top_k=n.topK),n.memoryLibraryId&&(r.memory_library_id=n.memoryLibraryId);let i=T(t.output);if(t.dryRun){M({endpoint:e.client.url(We()),request:r},i);return}let a=await e.client.requestJson({path:We(),method:`POST`,body:r});if(t.quiet||i===`text`)if(!a.memory_nodes||a.memory_nodes.length===0)j(`No memory nodes found.`);else for(let e of a.memory_nodes)j(`[${e.memory_node_id}] ${e.content}`);else M(a,i)}}),Fo=w({description:`List memory nodes for a user`,auth:`apiKey`,usageArgs:`--user-id <id> [flags]`,flags:{userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID`}},exampleArgs:[`--user-id user1`,`--user-id user1 --page-size 20 --page 2`],async run(e){let{settings:t,flags:n}=e,r=n.userId,i=T(t.output),a=new URLSearchParams;a.set(`user_id`,r),n.pageSize!==void 0&&a.set(`page_size`,String(n.pageSize)),n.page!==void 0&&a.set(`page_num`,String(n.page)),n.memoryLibraryId&&a.set(`memory_library_id`,n.memoryLibraryId);let o=`${He()}?${a.toString()}`;if(t.dryRun){M({endpoint:e.client.url(o),method:`GET`},i);return}let s=await e.client.requestJson({path:o,method:`GET`});if(t.quiet||i===`text`)if(!s.memory_nodes||s.memory_nodes.length===0)j(`No memory nodes found.`);else{for(let e of s.memory_nodes)j(`[${e.memory_node_id}] ${e.content}`);s.total!==void 0&&j(`\nTotal: ${s.total}`)}else M(s,i)}}),Io=w({description:`Update a memory node content`,auth:`apiKey`,usageArgs:`--node-id <id> --user-id <id> --content <text>`,flags:{nodeId:{type:`string`,valueHint:`<id>`,description:`Memory node ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},content:{type:`string`,valueHint:`<text>`,description:`New content for the memory node (required)`,required:!0},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (non-default library)`}},exampleArgs:[`--node-id node_xxx --user-id user1 --content "updated memory content"`],async run(e){let{settings:t,flags:n}=e,r=n.nodeId,i={user_id:n.userId,custom_content:n.content};n.memoryLibraryId&&(i.memory_library_id=n.memoryLibraryId);let a=T(t.output);if(t.dryRun){M({endpoint:e.client.url(Ue(r)),method:`PATCH`,request:i},a);return}let o=await e.client.requestJson({path:Ue(r),method:`PATCH`,body:i});t.quiet||a===`text`?j(`Memory node ${r} updated.`):M(o,a)}}),Lo=w({description:`Delete a memory node`,auth:`apiKey`,usageArgs:`--node-id <id> --user-id <id>`,flags:{nodeId:{type:`string`,valueHint:`<id>`,description:`Memory node ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0},memoryLibraryId:{type:`string`,valueHint:`<id>`,description:`Memory library ID (non-default library)`}},exampleArgs:[`--node-id node_xxx --user-id user1`],async run(e){let{settings:t,flags:n}=e,r=n.nodeId,i=n.userId,a=T(t.output),o=new URLSearchParams({user_id:i});n.memoryLibraryId&&o.set(`memory_library_id`,n.memoryLibraryId);let s=`${Ue(r)}?${o.toString()}`;if(t.dryRun){M({endpoint:e.client.url(s),method:`DELETE`},a);return}let c=await e.client.requestJson({path:s,method:`DELETE`});t.quiet||a===`text`?j(`Memory node ${r} deleted.`):M(c,a)}}),Ro=w({description:`Create a user profile schema for memory profiling`,auth:`apiKey`,usageArgs:`--name <name> --attributes <json> [flags]`,flags:{name:{type:`string`,valueHint:`<name>`,description:`Schema name (required)`,required:!0},description:{type:`string`,valueHint:`<text>`,description:`Schema description`},attributes:{type:`string`,valueHint:`<json>`,description:`Attributes JSON array: [{"name":"age","description":"age"}]`,required:!0}},exampleArgs:[`--name "user_basic" --attributes '[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]'`],async run(e){let{settings:t,flags:n}=e,r=n.name,i=n.attributes,a;try{a=JSON.parse(i)}catch{throw new p(`--attributes must be valid JSON array`)}let o={name:r,attributes:a};n.description&&(o.description=n.description);let s=T(t.output);if(t.dryRun){M({endpoint:e.client.url(Qe()),request:o},s);return}let c=await e.client.requestJson({path:Qe(),method:`POST`,body:o});t.quiet||s===`text`?j(`Profile schema created: ${c.profile_schema_id}`):M(c,s)}}),zo=w({description:`Get user profile by schema ID and user ID`,auth:`apiKey`,usageArgs:`--schema-id <id> --user-id <id>`,flags:{schemaId:{type:`string`,valueHint:`<id>`,description:`Profile schema ID (required)`,required:!0},userId:{type:`string`,valueHint:`<id>`,description:`User ID (required)`,required:!0}},exampleArgs:[`--schema-id schema_xxx --user-id user1`],async run(e){let{settings:t,flags:n}=e,r=n.schemaId,i=n.userId,a=T(t.output),o=new URLSearchParams({user_id:i}),s=`${yt(r)}?${o.toString()}`;if(t.dryRun){M({endpoint:e.client.url(s),method:`GET`},a);return}let c=await e.client.requestJson({path:s,method:`GET`});if(t.quiet||a===`text`)if(c.profile?.attributes)for(let e of c.profile.attributes)j(`${e.name}: ${e.value??`(empty)`}`);else j(`No profile data found.`);else M(c,a)}}),Bo=w({description:"Retrieve from a Bailian knowledge base (deprecated, use `search` instead)",auth:`apiKey`,usageArgs:`--index-id <id> --query <text> [flags]`,flags:{indexId:{type:`string`,valueHint:`<id>`,description:`Knowledge base index ID (required)`,required:!0},query:{type:`string`,valueHint:`<text>`,description:`Search query (required)`,required:!0},denseSimilarityTopK:{type:`number`,valueHint:`<n>`,description:`Dense retrieval top K`},sparseSimilarityTopK:{type:`number`,valueHint:`<n>`,description:`Sparse retrieval top K`},rerank:{type:`switch`,description:`Enable reranking`},rerankTopN:{type:`number`,valueHint:`<n>`,description:`Rerank top N results`},rerankModel:{type:`string`,valueHint:`<name>`,description:`Rerank model, e.g. qwen3-rerank-hybrid`},rerankMode:{type:`string`,valueHint:`<mode>`,description:`Rerank mode: qa, similar, or custom`},rerankInstruct:{type:`string`,valueHint:`<text>`,description:`Custom rerank instruction, when mode=custom`},topK:{type:`number`,valueHint:`<n>`,description:`Number of results (deprecated, use --rerank-top-n)`}},exampleArgs:[`--index-id idx_xxx --query "How to use Alibaba Cloud Bailian"`,`--index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid`],async run(e){let{settings:t,flags:n}=e,r=T(t.output);n.topK!==void 0&&n.rerankTopN===void 0&&(process.stderr.write(`Warning: --top-k is deprecated. Use --rerank-top-n instead.
|
|
2646
|
+
`),n.rerankTopN=n.topK);let i={index_id:n.indexId,query:n.query,search_filters:[]};if(n.denseSimilarityTopK!==void 0&&(i.dense_similarity_top_k=n.denseSimilarityTopK),n.sparseSimilarityTopK!==void 0&&(i.sparse_similarity_top_k=n.sparseSimilarityTopK),n.rerank&&(i.enable_reranking=!0),n.rerankTopN!==void 0&&(i.rerank_top_n=n.rerankTopN),n.rerankModel){let e={model_name:n.rerankModel};n.rerankMode&&(e.rerank_mode=n.rerankMode),n.rerankInstruct&&(e.rerank_instruct=n.rerankInstruct),i.rerank=[e]}if(t.dryRun){M({endpoint:e.client.url(Ae()),request:i},r);return}let a=await e.client.requestJson({path:Ae(),method:`POST`,body:i}),o=a.data?.nodes||[];t.quiet||r===`text`?Vo(o.map(e=>({text:e.text,score:e.score}))):M(a,r)}});function Vo(e){if(e.length===0)j(`No results found.`);else for(let t=0;t<e.length;t++){let n=e[t];j(`[${t+1}] (score: ${n.score.toFixed(4)})`),j(n.text),j(``)}}var Ho=w({description:`Search a Bailian knowledge base (RAG semantic retrieval)`,auth:`apiKey`,usageArgs:`--query <text> --agent-id <id> [flags]`,flags:{query:{type:`string`,valueHint:`<text>`,description:`Search query text (required, cannot be empty)`,required:!0},agentId:{type:`string`,valueHint:`<id>`,description:`Retrieval service ID (find in console knowledge retrieval page)`,required:!0},workspaceId:{type:`string`,valueHint:`<id>`,description:`Workspace ID for API endpoint URL (or set BAILIAN_WORKSPACE_ID)`},image:{type:`array`,valueHint:`<url>`,description:`Image URL for multimodal retrieval (repeatable)`},queryHistory:{type:`string`,valueHint:`<json>`,description:`User conversation history JSON for context understanding and query rewriting. Format: '[{"role":"user","content":"What is RAG"},{"role":"assistant","content":"RAG is..."}]'`}},notes:[`Retrieval scope and strategy (multi-index weighting, routing, reranking, etc.) are driven by the agent_id service config. Only query and agent_id are required.`,`Auth: uses DashScope API Key (Bearer token). Get yours from the console API Key page.`,"`--workspace-id` can be set via BAILIAN_WORKSPACE_ID env or `kscli config set workspace_id <id>`.","`--query-history` passes prior conversation turns; the server rewrites the query based on context to improve retrieval relevance."],exampleArgs:[`--query "What is RAG?" --agent-id aid-xxx --workspace-id ws-xxx`,`--api-key $DASHSCOPE_API_KEY --query "test search" --agent-id aid-xxx --workspace-id ws-xxx --image https://example.com/img.jpg`,`--query "How does it work" --agent-id aid-xxx --workspace-id ws-xxx --query-history '[{"role":"user","content":"What is RAG"},{"role":"assistant","content":"RAG is retrieval-augmented generation"}]'`],async run(e){let{settings:n,flags:r}=e,i=r.workspaceId||n.workspaceId;if(!i)throw new t(`Workspace ID is required.`,a.USAGE,`Pass --workspace-id, set BAILIAN_WORKSPACE_ID env, or configure: ${e.identity.binName} config set workspace_id <id>`);let o=T(n.output),s={query:r.query,agent_id:r.agentId};if(r.image&&r.image.length>0&&(s.images=r.image),r.queryHistory)try{s.query_history=JSON.parse(r.queryHistory)}catch{throw new t(`--query-history must be valid JSON. Example: --query-history '[{"role":"user","content":"What is RAG"}]'`,a.USAGE)}let c=je(i);if(n.dryRun){M({endpoint:c,request:s},o);return}let l=await e.client.requestJson({path:c,method:`POST`,body:s}),u=l.data?.nodes||[];if(n.quiet||o===`text`)if(u.length===0)j(`No results found.`);else for(let e=0;e<u.length;e++){let t=u[e];j(`[${e+1}] (score: ${t.score.toFixed(4)})`),j(t.text),j(``)}else M(l,o)}});const Uo={message:{type:`array`,valueHint:`<text>`,description:`Message text (repeatable). Supports role:content prefix to set role (e.g. user:hello), defaults to user. Follows OpenAI message format`},agentId:{type:`string`,valueHint:`<id>`,description:`Q&A service ID (find in console knowledge Q&A page)`,required:!0},workspaceId:{type:`string`,valueHint:`<id>`,description:`Workspace ID for API endpoint URL (or set BAILIAN_WORKSPACE_ID)`},image:{type:`array`,valueHint:`<url>`,description:`Image URL (repeatable). Attached to the last user message as multimodal content`}};function Wo(e){let t=[];if(e.message){let n=new Set([`user`,`assistant`]);for(let r of e.message){if(r.startsWith(`{`))try{let e=JSON.parse(r);if(e.role&&n.has(e.role)&&e.content!==void 0){t.push(e);continue}}catch{}let e=r.indexOf(`:`),i=e===-1?``:r.slice(0,e);n.has(i)?t.push({role:i,content:r.slice(e+1)}):t.push({role:`user`,content:r})}}return t}function Go(e){for(let t of e)if(Array.isArray(t.content)&&t.content.some(e=>e.type===`image_url`))return!0;return!1}function Ko(e,t){let n=-1;for(let t=e.length-1;t>=0;t--)if(e[t].role===`user`){n=t;break}n===-1&&(e.push({role:`user`,content:``}),n=e.length-1);let r=e[n],i=[];typeof r.content==`string`?i.push({type:`text`,text:r.content}):i.push(...r.content);for(let e of t)i.push({type:`image_url`,image_url:{url:e}});r.content=i}const qo={tool_calling:`🔍 Retrieving...`,plan_start:`🤔 Planning...`,generation_start:`✍️ Generating...`};var Jo=w({description:`Chat with a Bailian knowledge base (RAG Q&A with streaming)`,auth:`apiKey`,usageArgs:`--message <text> --agent-id <id> [flags]`,flags:Uo,notes:[`Response is returned as SSE stream events. Event lifecycle: tool_calling → tool_return → plan_start → planning → plan_end → generation_start → generating → generation_end. tool_calling → tool_return may loop multiple times.`,`Auth: uses DashScope API Key (Bearer token). Get yours from the console API Key page.`,"`--workspace-id` can be set via BAILIAN_WORKSPACE_ID env or `kscli config set workspace_id <id>`.",`Multi-turn: use --message "user:..." and --message "assistant:..." to pass conversation history.`],exampleArgs:[`--message "What is RAG?" --agent-id aid-xxx --workspace-id ws-xxx`,`--message "user:What is RAG?" --message "assistant:RAG is..." --message "How does it work?" --agent-id aid-xxx --workspace-id ws-xxx`,`--message "Describe these images" --image https://example.com/a.png --image https://example.com/b.png --agent-id aid-xxx --workspace-id ws-xxx`],validate:e=>e.message&&e.message.length>0||e.image&&e.image.length>0?void 0:`Provide --message (or --image for a pure image query).`,async run(e){let{settings:n,flags:r}=e,i=Wo(r),o=r.image,s=!!o&&o.length>0;i.length===0&&s&&(i=[{role:`user`,content:``}]);let c=r.workspaceId||n.workspaceId;if(!c)throw new t(`Workspace ID is required.`,a.USAGE,`Pass --workspace-id, set BAILIAN_WORKSPACE_ID env, or configure: ${e.identity.binName} config set workspace_id <id>`);let l=T(n.output),u=l===`text`&&!!process.stdout.isTTY;if(s){if(Go(i))throw new t(`Cannot use --image when messages already contain embedded image_url content parts. Use one approach or the other.`,a.USAGE);Ko(i,o)}let d={input:{messages:i},parameters:{agent_options:{agent_id:r.agentId}},stream:!0},f=ke(c);if(n.dryRun){M({endpoint:f,request:d},l);return}let p=await e.client.request({path:f,method:`POST`,body:d,stream:!0});if(u){let e=k(process.stdout),r=n.verbose;for await(let n of Ye(p)){if(n.data===`[DONE]`)break;if(n.event===`error`){let e=`Chat API error`,r;try{let t=JSON.parse(n.data);e=t.message||e,r=t.code}catch{}throw new t(e,a.GENERAL,r?`API error: ${r}`:void 0)}try{let t=JSON.parse(n.data);for(let n of t.output?.choices??[]){let t=n.message;if(t.extra?.step_change){let n=qo[t.extra.step_change];n&&process.stdout.write(`${e.dim(n)}\n`)}if(r&&t.extra?.step_change&&process.stderr.write(k(process.stderr).dim(`[event] step_change=${t.extra.step_change} step=${t.extra?.step??``} group=${t.extra?.group??``}`)+`
|
|
305
2647
|
`),t.content&&process.stdout.write(t.content),n.finish_reason===`stop`)break}}catch{}}process.stdout.write(`
|
|
306
|
-
`)}else{let e=``,r=``;for await(let n of
|
|
307
|
-
`)}function
|
|
308
|
-
`)}`);
|
|
309
|
-
`)}`);if(n.quiet||s.stop(`Done.`),i===`json`)
|
|
310
|
-
`),process.stdout.write(`See: ${
|
|
311
|
-
`));else if(d.length===1){let e=s[0].output?.audio?.expires_at;
|
|
312
|
-
Hint: Add --diarization flag to enable speaker separation.`,a.USAGE);let c=r.model||`fun-asr`,l=
|
|
2648
|
+
`)}else{let e=``,r=``;for await(let n of Ye(p)){if(n.data===`[DONE]`)break;if(n.event===`error`){let e=`Chat API error`,r;try{let t=JSON.parse(n.data);e=t.message||e,r=t.code}catch{}throw new t(e,a.GENERAL,r?`API error: ${r}`:void 0)}try{let t=JSON.parse(n.data);t.request_id&&(r=t.request_id);for(let n of t.output?.choices??[])if(n.message?.content&&(e+=n.message.content),n.finish_reason===`stop`)break}catch{}}n.quiet||l===`text`?j(e):M({answer:e,request_id:r},l)}}});function Yo(e){if(!(e instanceof t))return!1;let n=e.message;return/MCP request failed:\s*404\b/i.test(n)?/未开通|MCP不存在|MCP_IS_INVALID/i.test(n):!1}function Xo(e){let t=[`Activate (or re-activate) the ${e} MCP in the Bailian MCP marketplace, then retry.`];return e===`WebSearch`&&t.push(`If it was previously on SSE, cancel and activate again to upgrade to Streamable HTTP.`),t.push(`Open: ${zt(e)}`),t.join(`
|
|
2649
|
+
`)}function Zo(e,n){throw Yo(e)&&e instanceof t&&!e.hint?new t(e.message,e.exitCode,Xo(n),{cause:e,api:e.api,rawResponse:e.rawResponse}):e}const Qo={target:{type:`string`,valueHint:`<server.tool>`,description:`Server code and tool name joined by a dot, e.g. market-cmapi00073529.SmartStockSelection`,required:!0},arg:{type:`array`,valueHint:`<kv>`,description:`Tool argument (repeatable). Values parsed as JSON if possible, else string.`},json:{type:`string`,valueHint:`<obj>`,description:`Full arguments object as JSON; merged with --arg (arg wins).`},query:{type:`string`,valueHint:`<text>`,description:`Shortcut for --arg query=<text> (mirrors many DashScope MCP tools).`},url:{type:`string`,valueHint:`<url>`,description:`Override the MCP endpoint URL (for non-Bailian servers)`}};function $o(e){let t=e.indexOf(`.`);if(t<=0||t===e.length-1)throw new p(`target must be <server-code>.<tool>, got "${e}".`);return{serverCode:e.slice(0,t),toolName:e.slice(t+1)}}function es(e){let t={};for(let n of e){let e=n.indexOf(`=`);if(e<=0)throw new p(`--arg must be in K=V form, got: ${n}`);let r=n.slice(0,e).trim(),i=n.slice(e+1);try{t[r]=JSON.parse(i)}catch{t[r]=i}}return t}function ts(e){let t;try{t=JSON.parse(e)}catch(e){throw new p(`--json is not valid JSON — ${e.message}`)}if(!t||typeof t!=`object`||Array.isArray(t))throw new p(`--json must decode to an object.`);return t}function ns(e){let t=e.json?ts(e.json):{};return Object.assign(t,es(e.arg??[])),e.query!==void 0&&(t.query=e.query),t}function rs(e){try{$o(e.target),ns(e)}catch(e){if(e instanceof p)return e.message;throw e}}var is=w({description:`Call a tool on an MCP server (tools/call)`,auth:`apiKey`,usageArgs:`--target <server.tool> [--arg k=v ...] [--json '{...}'] [--url <url>]`,flags:Qo,exampleArgs:[`--target market-cmapi00073529.SmartStockSelection --query "Screen consumer stocks with ROE > 15%"`,`--target market-cmapi00073529.FinQuery --json '{"q":"Guizhou Maotai","limit":5}'`,`--target market-cmapi00073529.SmartFundSelection --arg riskLevel=R3 --arg minScale=10`],validate:rs,async run(e){let{settings:n,flags:r}=e,{serverCode:i,toolName:a}=$o(r.target),o=ns(r),s=r.url||e.client.url(g(i)),c=T(n.output);if(n.dryRun){M({server:i,url:s,tool:a,arguments:o},c);return}let l=e.client.mcp(s);try{await l.initialize();let e=await l.callTool(a,o);if(e.isError)throw new t(`Tool error: ${e.content.map(e=>e.text||``).join(`
|
|
2650
|
+
`)}`);M(e,c)}catch(e){throw r.url||Zo(e,i),e}}});const as=`zeldaEasy.broadscope-bailian.mcp-server.PageList`;var os=w({description:`List MCP servers activated under your Bailian account`,auth:`console`,usageArgs:`[flags]`,flags:{name:{type:`string`,valueHint:`<text>`,description:`Filter by server name (substring match)`},type:{type:`string`,valueHint:`<type>`,description:`Server type: OFFICIAL | PRIVATE (default: OFFICIAL)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 30)`}},exampleArgs:[``,`--name finance`,`--output json`],async run(e){let{settings:n,identity:r,flags:i}=e,o=i.name||``,s=i.type||`OFFICIAL`,c=i.page||1,l=i.pageSize||30,u=T(n.output),d={reqDTO:{type:s,displayTools:!1,activated:1,pageNo:c,pageSize:l,serverName:o}};if(n.dryRun){M({api:as,data:d,...ce(n)},u);return}let f=(await e.client.console(as,d))?.data??{};if(f.success===!1){let e=f.errorCode??`UnknownError`,n=f.errorMsg??e,i=e===`BailianGateway.Login.NotLogined`?`Run \`${r.binName} auth login --console\` to refresh your console session.`:void 0;throw new t(`Console gateway: ${n}`,a.AUTH,i)}let p=(f.DataV2??{}).data?.data??{},m=p.mcpServerDetailList??[];M({total:p.total??0,servers:m.map(e=>({code:e.serverCode??``,name:e.serverName??``,description:e.description,type:e.type??``,source:e.source,bizType:e.bizType,installType:e.installType,streamable:e.streamable===!0}))},u)}}),ss=w({description:`List tools exposed by an MCP server (tools/list)`,auth:`apiKey`,usageArgs:`--server <code> [--url <url>]`,flags:{server:{type:`string`,valueHint:`<code>`,description:"Server code from `mcp list` (e.g. market-cmapi00073529)",required:!0},url:{type:`string`,valueHint:`<url>`,description:`Override the MCP endpoint URL (for non-Bailian servers)`}},exampleArgs:[`--server market-cmapi00073529`,`--server market-cmapi00073529 --output json`,`--server my-server --url https://example.com/mcp`],async run(e){let{settings:t,flags:n}=e,r=n.server,i=n.url||e.client.url(g(r)),a=T(t.output);if(t.dryRun){M({server:r,url:i,action:`tools/list`},a);return}let o=e.client.mcp(i);try{await o.initialize(),M({server:r,url:i,tools:await o.listTools()},a)}catch(e){throw n.url||Zo(e,r),e}}});function cs(e){Zo(e,`WebSearch`)}var ls=w({description:`Search the web using DashScope MCP WebSearch service`,auth:`apiKey`,usageArgs:`--query <text> [flags]`,flags:{query:{type:`string`,valueHint:`<text>`,description:`Search query text`},count:{type:`number`,valueHint:`<n>`,description:`Number of search results (default: 10)`},listTools:{type:`switch`,description:`List available MCP tools and exit`}},exampleArgs:[`--query "Alibaba Cloud Bailian latest features"`,`--query "TypeScript 5.9 new features" --count 5`,`--query "Today's news"`,`--list-tools`],validate:e=>!e.listTools&&!e.query?`Missing required flag: --query`:void 0,async run(e){let{settings:n,flags:r}=e,i=T(n.output);if(r.listTools){if(n.dryRun){M({endpoint:e.client.url(Be()),action:`tools/list`},i);return}try{let t=e.client.mcp(Be());await t.initialize(),M({tools:await t.listTools()},i)}catch(e){cs(e)}return}let a=r.query;if(n.dryRun){M({endpoint:e.client.url(Be()),action:`tools/call`,tool:`bailian_web_search`,arguments:{query:a,count:r.count||void 0}},i);return}let o=e.client.mcp(Be()),s=jt(`Initializing search...`);n.quiet||s.start();try{await o.initialize(),n.quiet||s.update(`Searching...`);let e={query:a};r.count&&(e.count=r.count);let c=await o.callTool(`bailian_web_search`,e);if(c.isError)throw new t(`Search error: ${c.content.map(e=>e.text||``).join(`
|
|
2651
|
+
`)}`);if(n.quiet||s.stop(`Done.`),i===`json`)M(c,i);else for(let e of c.content)if(e.type===`text`&&e.text)try{let t=JSON.parse(e.text);t.pages&&Array.isArray(t.pages)?M({pages:t.pages,total:t.pages.length},i):M(t,i)}catch{M({text:e.text},i)}}catch(e){s.stop(`Failed.`),cs(e)}}});const us=`${i.cn}/cosyvoice-clone-design-api`,ds=[{voice:`longanyang`,name:`龙安洋`,desc:`阳光大男孩`,lang:`中文/英文`},{voice:`longanhuan_v3`,name:`龙安欢`,desc:`欢脱元气女`,lang:`中文/英文`},{voice:`longantai_v3`,name:`龙安台`,desc:`嗲甜台湾女`,lang:`中文/英文`},{voice:`longhua_v3`,name:`龙华`,desc:`元气甜美女`,lang:`中文/英文`},{voice:`longcheng_v3`,name:`龙橙`,desc:`智慧青年男`,lang:`中文/英文`},{voice:`longze_v3`,name:`龙泽`,desc:`温暖元气男`,lang:`中文/英文`},{voice:`longzhe_v3`,name:`龙哲`,desc:`呆板大暖男`,lang:`中文/英文`},{voice:`longyan_v3`,name:`龙颜`,desc:`温暖春风女`,lang:`中文/英文`},{voice:`longxing_v3`,name:`龙星`,desc:`温婉邻家女`,lang:`中文/英文`},{voice:`longtian_v3`,name:`龙天`,desc:`磁性理智男`,lang:`中文/英文`},{voice:`longwan_v3`,name:`龙婉`,desc:`细腻柔声女`,lang:`中文/英文`},{voice:`longqiang_v3`,name:`龙嫱`,desc:`浪漫风情女`,lang:`中文/英文`},{voice:`longfeifei_v3`,name:`龙菲菲`,desc:`甜美娇气女`,lang:`中文/英文`},{voice:`longhao_v3`,name:`龙浩`,desc:`多情忧郁男`,lang:`中文/英文`},{voice:`longanrou_v3`,name:`龙安柔`,desc:`温柔娴静女`,lang:`中文/英文`},{voice:`longxiaochun_v3`,name:`龙小淳`,desc:`知性积极女`,lang:`中文/英文`},{voice:`longxiaoxia_v3`,name:`龙小夏`,desc:`沉稳权威女`,lang:`中文/英文`},{voice:`longyumi_v3`,name:`YUMI`,desc:`正经青年女`,lang:`中文/英文`},{voice:`longanyun_v3`,name:`龙安昀`,desc:`居家暖男`,lang:`中文/英文`},{voice:`longanwen_v3`,name:`龙安温`,desc:`优雅知性女`,lang:`中文/英文`},{voice:`longanli_v3`,name:`龙安莉`,desc:`利落从容女`,lang:`中文/英文`},{voice:`longanlang_v3`,name:`龙安朗`,desc:`清爽利落男`,lang:`中文/英文`},{voice:`longyingmu_v3`,name:`龙应沐`,desc:`优雅知性女`,lang:`中文/英文`},{voice:`longyingxun_v3`,name:`龙应询`,desc:`年轻青涩男`,lang:`中文/英文`},{voice:`longyingjing_v3`,name:`龙应静`,desc:`低调冷静女`,lang:`中文/英文`},{voice:`longyingling_v3`,name:`龙应聆`,desc:`温和共情女`,lang:`中文/英文`},{voice:`longyingtao_v3`,name:`龙应桃`,desc:`温柔淡定女`,lang:`中文/英文`},{voice:`longyingxiao_v3`,name:`龙应笑`,desc:`清甜推销女`,lang:`中文/英文`},{voice:`longfei_v3`,name:`龙飞`,desc:`热血磁性男`,lang:`中文/英文`},{voice:`longhuhu_v3`,name:`龙呼呼`,desc:`天真烂漫女童`,lang:`中文/英文`},{voice:`longpaopao_v3`,name:`龙泡泡`,desc:`飞天泡泡音`,lang:`中文/英文`},{voice:`longjielidou_v3`,name:`龙杰力豆`,desc:`阳光顽皮男`,lang:`中文/英文`},{voice:`longxian_v3`,name:`龙仙`,desc:`豪放可爱女`,lang:`中文/英文`},{voice:`longling_v3`,name:`龙铃`,desc:`稚气呆板女`,lang:`中文/英文`},{voice:`longshanshan_v3`,name:`龙闪闪`,desc:`戏剧化童声`,lang:`中文/英文`},{voice:`longniuniu_v3`,name:`龙牛牛`,desc:`阳光男童声`,lang:`中文/英文`},{voice:`longjiaxin_v3`,name:`龙嘉欣`,desc:`优雅粤语女`,lang:`粤语/英文`},{voice:`longjiayi_v3`,name:`龙嘉怡`,desc:`知性粤语女`,lang:`粤语/英文`},{voice:`longanyue_v3`,name:`龙安粤`,desc:`欢脱粤语男`,lang:`粤语/英文`},{voice:`longlaotie_v3`,name:`龙老铁`,desc:`东北直率男`,lang:`东北话/英文`},{voice:`longshange_v3`,name:`龙陕哥`,desc:`原味陕北男`,lang:`陕西话/英文`},{voice:`longanmin_v3`,name:`龙安闽`,desc:`清纯萝莉女`,lang:`闽南话/英文`},{voice:`loongabby_v3`,name:`loongabby`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongandy_v3`,name:`loongandy`,desc:`美式英文男`,lang:`美式英语`},{voice:`loongannie_v3`,name:`loongannie`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongava_v3`,name:`loongava`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongbeth_v3`,name:`loongbeth`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongbetty_v3`,name:`loongbetty`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongcally_v3`,name:`loongcally`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongcindy_v3`,name:`loongcindy`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongdavid_v3`,name:`loongdavid`,desc:`美式英文男`,lang:`美式英语`},{voice:`loongdonna_v3`,name:`loongdonna`,desc:`美式英文女`,lang:`美式英语`},{voice:`loongemily_v3`,name:`loongemily`,desc:`英式英文女`,lang:`英式英语`},{voice:`loongeric_v3`,name:`loongeric`,desc:`英式英文男`,lang:`英式英语`},{voice:`loongluna_v3`,name:`loongluna`,desc:`英式英文女`,lang:`英式英语`},{voice:`loongluca_v3`,name:`loongluca`,desc:`英式英文男`,lang:`英式英语`},{voice:`loongriko_v3`,name:`Riko`,desc:`二次元霓虹女`,lang:`日语`},{voice:`loongtomoka_v3`,name:`loongtomoka`,desc:`日语女`,lang:`日语`},{voice:`loongtomoya_v3`,name:`loongtomoya`,desc:`日语男`,lang:`日语`},{voice:`loongyuuna_v3`,name:`Yuuna`,desc:`日语女`,lang:`日语`},{voice:`loongyuuma_v3`,name:`Yuuma`,desc:`日语男`,lang:`日语`},{voice:`loongkyong_v3`,name:`loongkyong`,desc:`韩语女`,lang:`韩语`},{voice:`loongjihun_v3`,name:`Jihun`,desc:`韩语男`,lang:`韩语`},{voice:`loongindah_v3`,name:`loongindah`,desc:`印尼女`,lang:`印尼语`}],fs={"cosyvoice-v3-flash":ds,"cosyvoice-v3-plus":ds,"cosyvoice-v3.5-flash":[],"cosyvoice-v3.5-plus":[],"cosyvoice-v2":[]};function ps(e){let t=fs[e];if(!t){process.stdout.write(`No built-in voice list available for model: ${e}\n`),process.stdout.write(`Browse voices in the console: ${Ot}\n`);return}if(t.length===0){process.stdout.write(`Model ${e} has no system voices.\n`),process.stdout.write(`Use clone or design voices created via the CosyVoice API.
|
|
2652
|
+
`),process.stdout.write(`See: ${us}\n`),process.stdout.write(`Browse voices in the console: ${Ot}\n`);return}let n=(e,t)=>e.padEnd(t);process.stdout.write(`\nSystem voices for ${e}:\n`),process.stdout.write(`${n(`VOICE ID`,26)} ${n(`NAME`,10)} ${n(`DESCRIPTION`,16)} LANGUAGE\n`),process.stdout.write(`${`-`.repeat(26)} ${`-`.repeat(10)} ${`-`.repeat(16)} ${`-`.repeat(12)}\n`);for(let e of t)process.stdout.write(`${n(e.voice,26)} ${n(e.name,10)} ${n(e.desc,16)} ${e.lang}\n`);process.stdout.write(`\nTotal: ${t.length} voices\n`),process.stdout.write(`Preview and browse more voices in the console: \n${Ot}\n`)}var ms=w({description:`Synthesize speech from text (CosyVoice TTS)`,auth:`apiKey`,usageArgs:`--text <text> [flags]`,flags:{text:{type:`string`,valueHint:`<text>`,description:`Text to synthesize into speech (or use --text-file)`},textFile:{type:`string`,valueHint:`<path>`,description:`Read text from a file instead of --text`},model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: cosyvoice-v3-flash). System voices available for cosyvoice-v3-flash`},voice:{type:`string`,valueHint:`<voice>`,description:`Voice ID. Use --list-voices to see built-in voices for cosyvoice-v3-flash; for v3.5-flash provide a clone/design voice ID`},listVoices:{type:`switch`,description:`List built-in system voices for the selected model and exit (console link shown in output)`},format:{type:`string`,valueHint:`<format>`,description:`Audio format: mp3, pcm, wav, opus (default: mp3)`,choices:[`mp3`,`pcm`,`wav`,`opus`]},sampleRate:{type:`string`,valueHint:`<rate>`,description:`Audio sample rate in Hz (e.g. 24000)`},volume:{type:`string`,valueHint:`<volume>`,description:`Volume 0-100 (default: 50)`},rate:{type:`string`,valueHint:`<rate>`,description:`Speech rate 0.5-2.0 (default: 1.0)`},pitch:{type:`string`,valueHint:`<pitch>`,description:`Pitch multiplier 0.5-2.0 (default: 1.0)`},seed:{type:`string`,valueHint:`<seed>`,description:`Random seed 0-65535 for reproducible synthesis`},language:{type:`string`,valueHint:`<lang>`,description:`Language hint (e.g. zh, en, ja, ko, fr, de)`},instruction:{type:`string`,valueHint:`<text>`,description:`Natural language instruction to control speech style (e.g. "Use a gentle tone")`},enableSsml:{type:`switch`,description:`Enable SSML markup parsing in input text`},out:{type:`string`,valueHint:`<path>`,description:`Save audio to file (default: auto-generate in temp dir)`},stream:{type:`switch`,description:`Stream raw PCM audio to stdout (pipe to player)`},...n},exampleArgs:[`--list-voices --model cosyvoice-v3-flash`,`--text "Hello, I am Qwen" --voice <voice_id>`,`--text "Hello world" --voice <voice_id> --language en`,`--text-file script.txt --out speech.wav --voice <voice_id>`,`--text "Today is a good day" --voice <voice_id> --instruction "Use a gentle tone"`,`--text "Hello" --voice <voice_id> --format wav --sample-rate 24000`,`# Stream to audio player (macOS)`,`--text "Hello" --voice <voice_id> --stream | afplay -`,`# Pipe to ffplay`,`--text "Hello" --voice <voice_id> --stream | ffplay -nodisp -autoexit -f s16le -ar 24000 -ac 1 -`],validate:e=>{if(!e.listVoices){if(!e.text&&!e.textFile)return`Provide --text or --text-file.`;if(!e.voice)return`Missing required flag: --voice (use --list-voices; browse more voices: ${Ot})`}},async run(e){let{settings:n,flags:r}=e,i=r.model||n.defaultSpeechModel||`cosyvoice-v3-flash`;if(r.listVoices){ps(i);return}let o=r.text||``;if(!o&&r.textFile){let e=r.textFile;try{o=en(e,`utf-8`).trim()}catch{throw new t(`Cannot read text file: ${e}`,a.USAGE)}}let s=r.voice,c=r.language||void 0,l=r.instruction||void 0,u=r.format||void 0,d=r.sampleRate===void 0?void 0:Number(r.sampleRate),f=r.volume===void 0?void 0:Number(r.volume),p=r.rate===void 0?void 0:Number(r.rate),m=r.pitch===void 0?void 0:Number(r.pitch),h=r.seed===void 0?void 0:Number(r.seed),g=r.enableSsml===!0?!0:void 0,_=r.stream===!0,v=T(n.output),y={model:i,input:{text:o,voice:s,format:u,sample_rate:d,volume:f,rate:p,pitch:m,seed:h,language_hints:c?[c]:void 0,instruction:l,enable_ssml:g}};if(pt(y.input),n.dryRun){M({request:y},v);return}n.quiet||process.stderr.write(`[Model: ${i}] [Voice: ${s}]\n`),_?await gs(e.client,n,y,r,v):await hs(e.client,n,y,r,v)}});async function hs(e,n,r,i,o){let s=await Ut(Lt(i),n,()=>e.requestJson({path:ft(),method:`POST`,body:r})),c=s.map(e=>e.output?.audio?.url).filter(Boolean);if(c.length===0)throw new t(`API returned no audio URL.`,a.GENERAL);let l=await import(`path`),u=ct(n,{subDir:`speech`}),d=await Nt(c.map((e,t)=>{let n=i.out;if(!(n&&c.length===1)){let e=Date.now(),i=c.length>1?`_${String(t+1).padStart(3,`0`)}`:``,a=r.input.format??`mp3`;n=l.join(u,`tts_${e}${i}.${a}`)}return{url:e,destPath:n}}),A,{quiet:n.quiet});if(n.quiet)j(d.join(`
|
|
2653
|
+
`));else if(d.length===1){let e=s[0].output?.audio?.expires_at;M({saved:d[0],audio_url:c[0],model:r.model,voice:r.input.voice,...e?{url_expires_at:e}:{}},o)}else M({saved:d,audio_urls:c,total:d.length,model:r.model,voice:r.input.voice},o)}async function gs(e,t,n,r,i){let a=await e.request({path:ft(),method:`POST`,body:n,stream:!0,headers:{Accept:`text/event-stream`,"X-DashScope-SSE":`enable`}}),o=r.out,s=o?Zt(o):null,c;try{for await(let e of Ye(a)){if(!e.data||e.data===`[DONE]`)continue;let n;try{n=JSON.parse(e.data)}catch{continue}let r=n.output?.audio?.data;if(r){let e=Buffer.from(r,`base64`);s?s.write(e)||await new Promise(e=>s.once(`drain`,()=>e())):process.stdout.write(e)}if(n.output?.finish_reason===`stop`){c=n.output?.audio?.url,c&&!t.quiet&&process.stderr.write(`\nFull audio URL: ${c}\n`);break}}}finally{s&&(await new Promise((e,t)=>{s.on(`finish`,e),s.on(`error`,t),s.end()}),!t.quiet&&o&&process.stderr.write(`Saved: ${o}\n`))}o&&M({saved:o,...c?{audio_url:c}:{},model:n.model,voice:n.input.voice},i)}var _s=w({description:`Recognize speech from audio files (FunAudio-ASR)`,auth:`apiKey`,usageArgs:`--url <audio-url> [flags]`,flags:{url:{type:`array`,valueHint:`<url>`,description:`Audio file URL or local file path (repeatable, max 100)`,required:!0},model:{type:`string`,valueHint:`<model>`,description:`Model ID (default: fun-asr)`},language:{type:`string`,valueHint:`<lang>`,description:`Language hint (e.g. zh, en, ja)`},diarization:{type:`switch`,description:`Enable automatic speaker diarization`},speakerCount:{type:`number`,valueHint:`<n>`,description:`Expected number of speakers (requires --diarization)`},vocabularyId:{type:`string`,valueHint:`<id>`,description:`Hot-word vocabulary ID for improved accuracy`},channelId:{type:`number`,valueHint:`<n>`,description:`Audio channel ID (default: 0)`},out:{type:`string`,valueHint:`<path>`,description:`Save full transcription result to JSON file`},...e,pollInterval:{type:`number`,valueHint:`<seconds>`,description:`Polling interval in seconds (default: 2)`}},exampleArgs:[`--url https://example.com/audio.mp3`,`--url https://example.com/a.mp3 --url https://example.com/b.mp3`,`--url https://example.com/meeting.wav --diarization --speaker-count 3`,`--url https://example.com/audio.mp3 --language zh`,`--url https://example.com/audio.mp3 --vocabulary-id vocab-abc123`,`--url https://example.com/audio.mp3 --out result.json`,`--url https://example.com/audio.mp3 --async --quiet`],async run(e){let{settings:n,flags:r}=e,i=[];Array.isArray(r.url)?i=r.url:typeof r.url==`string`&&(i=[r.url]);let o=r.speakerCount,s=r.diarization===!0;if(o!==void 0&&!s)throw new t(`--speaker-count requires --diarization to be enabled.
|
|
2654
|
+
Hint: Add --diarization flag to enable speaker separation.`,a.USAGE);let c=r.model||`fun-asr`,l=T(n.output),u=await Promise.all(i.map(t=>e.client.uploadFile(t,c))),d=r.channelId,f=r.language,p=r.vocabularyId,m={model:c,input:{file_urls:u},parameters:{channel_id:d===void 0?[0]:[d],language_hints:f?[f]:void 0,diarization_enabled:s?!0:void 0,speaker_count:o,vocabulary_id:p}};if(pt(m.parameters),n.dryRun){M({request:m,mode:`async`},l);return}n.quiet||process.stderr.write(`[Model: ${c}] [Mode: async] [Files: ${u.length}]\n`),await vs(e.client,n,m,r,l,u.length)}});async function vs(e,n,r,i,o,s){let c=(await e.requestJson({path:dt(),method:`POST`,body:r,async:!0})).output.task_id;if(i.async){M({task_id:c},o);return}let l=i.pollInterval??2,u=await Bt(e,n,{url:e.url(O(c)),intervalSec:l,timeoutSec:n.timeout,isComplete:e=>e.output.task_status===`SUCCEEDED`,isFailed:e=>e.output.task_status===`FAILED`,getStatus:e=>e.output.task_status,getErrorMessage:e=>e.output.message}),d=u.output.results??[];if(d.length===0){M({task_id:c,status:u.output.task_status},o);return}let f=[];for(let e=0;e<d.length;e++){let n=d[e],r=s>1;if(r&&process.stdout.write(`=== [${e+1}/${d.length}] ${n.file_url??``} ===\n`),n.subtask_status===`FAILED`){let e=n.message??n.code??`unknown error`;process.stdout.write(`[FAILED] ${n.file_url??``} — ${e}\n`),r&&process.stdout.write(`
|
|
313
2655
|
`);continue}if(!n.transcription_url){r&&process.stdout.write(`
|
|
314
|
-
`);continue}let i=await fetch(n.transcription_url,{headers:
|
|
315
|
-
`);else
|
|
316
|
-
`)}if(i.out){let e=i.out,t=f.length===1?f[0]:f;
|
|
317
|
-
`),n.quiet||process.stderr.write(`Full result saved to: ${e}\n`)}}var
|
|
318
|
-
`);let a=[`Model`,`Type`,`Remaining`,`Total`,`Quota Left`,`Auto-Stop`],o=[],s=[],c=a.length-1,l=
|
|
2656
|
+
`);continue}let i=await fetch(n.transcription_url,{headers:mt()});if(!i.ok)throw new t(`Failed to download transcription: HTTP ${i.status}`,a.GENERAL);let o=await i.json();f.push(o);let c=o.transcripts;if(c&&c.length>0)for(let e of c)if(e.sentences&&e.sentences.length>0)for(let t of e.sentences){let e=t.speaker_id===void 0?``:` [Speaker ${t.speaker_id}]`;process.stdout.write(`${t.text}${e}\n`)}else e.text&&process.stdout.write(e.text+`
|
|
2657
|
+
`);else j(JSON.stringify(o));r&&process.stdout.write(`
|
|
2658
|
+
`)}if(i.out){let e=i.out,t=f.length===1?f[0]:f;rn(e,JSON.stringify(t,null,2)+`
|
|
2659
|
+
`),n.quiet||process.stderr.write(`Full result saved to: ${e}\n`)}}var ys=w({description:`Upload a local file to DashScope temporary storage (48h)`,auth:`apiKey`,usageArgs:`--file <path> --model <model>`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Local file to upload (image, video, audio)`,required:!0},model:{type:`string`,valueHint:`<model>`,description:`Target model name (file is bound to this model)`,required:!0}},exampleArgs:[`--file photo.jpg --model qwen3-vl-plus`,`--file video.mp4 --model wan2.1-t2v-plus`,`--file audio.wav --model qwen3-asr-flash`,`--file cat.png --model qwen-image-2.0`],async run(e){let{settings:t,flags:n}=e,r=n.file,i=n.model,a=T(t.output);if(t.dryRun){M({action:`upload`,file:r,model:i},a);return}let o=await e.client.uploadFile(r,i);t.quiet?j(o):M({url:o,model:i,expires_in:`48 hours`,note:`When using this URL in API calls, add header: X-DashScope-OssResourceResolve: enable`},a)}}),bs=w({description:`Call a Bailian console API via the CLI gateway`,auth:`console`,usageArgs:`--api <api> --data <json> [flags]`,flags:{api:{type:`string`,valueHint:`<api>`,description:`API name (e.g. zeldaEasy.broadscope-bailian.memory-library.getLibraries)`,required:!0},data:{type:`string`,valueHint:`<json>`,description:`Request data as JSON string`,required:!0}},exampleArgs:[`--api zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierQuota --data '{"queryFreeTierQuotaRequest":{"models":["qwen3-max"]}}'`,`--api some.api.name --data '{"key":"value"}' --console-region cn-beijing`],async run(e){let{settings:t,flags:n}=e,r=n.api,i=n.data,a;try{a=JSON.parse(i)}catch{throw new p(`--data must be valid JSON`)}let o=T(t.output);if(t.dryRun){M({api:r,data:a,...ce(t)},o);return}M(await e.client.console(r,a),o)}});function xs(e){return e.toLocaleString(`en-US`)}function Ss(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}function Cs(e){return gt(e)}const ws={Reasoning:`Text`,TG:`Text`,VU:`Text`,IG:`Vision`,VG:`Vision`,"Realtime-Omni":`Multimodal`,"Multimodal-Omni":`Multimodal`,ASR:`Audio`,TTS:`Audio`,"Voice-Replication":`Audio`,"Realtime-Text-to-Speech":`Audio`,"Realtime-Voice-Replication":`Audio`,"Realtime-ASR":`Audio`,"Realtime-Audio-Translate":`Audio`,ME:`Embedding`,TR:`Embedding`};function Ts(e){for(let t of e){let e=ws[t];if(e)return e}return`-`}async function Es(e){let t=[],n=1;for(;;){let r=await pe((t,n)=>e.console(t,n),{pageNo:n,pageSize:50});if(t.push(...r.models),t.length>=r.total)break;n++}return t.filter(e=>typeof e.model==`string`&&e.model).map(e=>({name:e.model,type:Ts(e.capabilities||[])}))}const Ds=`zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierQuota`,Os=`zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierOnlyStatus`;function ks(e,t){let n=e.data;if(!n)return[];let r=n.DataV2;return r?r.data?.data?.[t]||[]:n.data?.[t]||[]}function As(e){return ks(e,`freeTierQuotas`)}function js(e){return ks(e,`freeTierOnlyStatuses`)}function Ms(e){return Ns(e)||e.quotaInitTotal==null||e.quotaInitTotal<=0?null:Math.round(e.quotaTotal/e.quotaInitTotal*1e3)/10}function Ns(e){return e.quotaValidityPeriod>0&&e.quotaValidityPeriod<Date.now()}function Ps(e){let{quotas:t,stopMap:n,typeMap:r}=e,i=k(process.stdout);e.title&&process.stdout.write(i.purple(e.title)+`
|
|
2660
|
+
`);let a=[`Model`,`Type`,`Remaining`,`Total`,`Quota Left`,`Auto-Stop`],o=[],s=[],c=a.length-1,l=Vt({headers:a,rows:t.map(e=>{let t=e.quotaInitTotal!=null&&e.quotaTotal!=null,i=Ns(e),a=t?`${xs(e.quotaTotal)}${i?` (expired)`:``}`:`-`,c=t?xs(e.quotaInitTotal):`-`,l=Ms(e);o.push(l),s.push(i?`expired`:l==null?`-`:null);let u=n.get(e.model),d=e.quotaStatus===`UNKNOWN`?`Unsupported`:u===!0?`ON`:u===!1?`OFF`:`-`;return[e.model,r.get(e.model)||`-`,a,c,``,d]}),align:[`left`,`left`,`right`,`right`,`left`,`left`],barColumns:[{index:4,percents:o,labels:s}],cellColor:(e,t,n)=>{if(t===c){if(n===`ON`)return i.green(n);if(n===`OFF`)return i.yellow(n)}}});for(let e of l)process.stdout.write(e+`
|
|
319
2661
|
`);e.moreHint&&process.stdout.write(i.dim(e.moreHint)+`
|
|
320
|
-
`)}const
|
|
321
|
-
`);return}let y=!i&&!s?h.slice(0,15):h,b=h.length-y.length,x=g===`remaining`?` · sorted by urgency`:``;
|
|
322
|
-
`);return}let a=new Set,o=e.map(e=>{let t=
|
|
2662
|
+
`)}const Fs=`zeldaEasy.bailian-telemetry.model.getModelUsageStatistic`;async function Is(e,t,n){let r;for(let i=0;i<30;i++){let i=r?{reqDTO:{...n,asyncTaskId:r}}:{reqDTO:n},a=await e.console(t,i),o=Cs(a);if(o.taskId&&Object.keys(o).length===1){r=o.taskId,await new Promise(e=>setTimeout(e,500));continue}return a}return null}function Ls(e){let t=Cs(e);if(t.callSuccessCount!==void 0||t.usages!==void 0)return t}const Rs={total_token:{en:`Total Tokens`,unit:`tokens`},input_token:{en:`Input Tokens`,unit:`tokens`},output_token:{en:`Output Tokens`,unit:`tokens`},input_token_cache:{en:`Cached Tokens`,unit:`tokens`},input_token_cache_read:{en:`Cache Read`,unit:`tokens`},input_token_cache_creation:{en:`Cache Creation`,unit:`tokens`},thinking_input_token:{en:`Thinking Input`,unit:`tokens`},thinking_output_token:{en:`Thinking Output`,unit:`tokens`},text_input_token:{en:`Text Input`,unit:`tokens`},purein_text_output_token:{en:`Text Output`,unit:`tokens`},embedding_token:{en:`Embedding`,unit:`tokens`},image_number:{en:`Images`,unit:`images`},video_duration:{en:`Video Duration`,unit:`sec`},content_duration:{en:`Audio Duration`,unit:`sec`},tts_text_number:{en:`TTS Chars`,unit:`chars`},total_token_avg:{en:`Avg Tokens/Req`}};function zs(e){let t=Rs[e];if(!t)return e;let n=t.unit?` [${t.unit}]`:``;return`${t.en}${n}`}function Bs(e,t,n,r,i=`Usage Overview`){let a=k(process.stdout);process.stdout.write(`${a.purple(i)} ${a.dim(`·`)} ${Ss(t)} ~ ${Ss(n)} ${a.dim(`(${r} days)`)}\n`);let o=[[`Models Called`,xs(e.modelCount??0)],[`Successful Calls`,xs(e.callSuccessCount??0)]];for(let t of e.usages??[])o.push([zs(t.key),xs(t.value)]);let s=Math.max(...o.map(([e])=>Mt(e)));for(let[e,t]of o)process.stdout.write(`${a.bold(P(e,s+2))}${t}\n`)}var Vs=w({description:`Query free-tier quota for models (all models if --model is omitted)`,auth:`console`,usageArgs:`[--model <model>[,model2,...]] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name(s) to query, comma-separated for multiple; omit for all models`},expiring:{type:`string`,valueHint:`<days>`,description:`Only show quotas expiring within N days`},sort:{type:`string`,valueHint:`<field>`,description:`Sort by: remaining (ascending), expires (ascending)`,choices:[`remaining`,`expires`]},all:{type:`switch`,description:`Show all models instead of the top rows`}},exampleArgs:[``,`--model qwen3-max`,`--model qwen3-max,qwen-turbo`,`--expiring 30`,`--sort remaining`,`--all`,`--model qwen-turbo --output json`,`--model qwen3-max --console-region cn-beijing`],async run(e){let{identity:t,settings:n,flags:r}=e,i=r.model||void 0,a=Number(r.expiring)||0,o=r.sort||void 0,s=!!r.all,c=T(n.output),l,u=new Map;l=i?[...new Set(i.split(`,`).map(e=>e.trim()).filter(Boolean))]:[];let d={queryFreeTierQuotaRequest:{models:l}};if(n.dryRun){M({api:Ds,data:d},c);return}if(i){let t=await Promise.all(l.map(t=>pe((t,n)=>e.client.console(t,n),{name:t,pageSize:50})));for(let e=0;e<l.length;e++){let n=t[e].models.find(t=>t.model===l[e]);n&&u.set(l[e],Ts(n.capabilities||[]))}}else{let t=await Es(e.client);l=t.map(e=>e.name);for(let e of t)u.set(e.name,e.type);d.queryFreeTierQuotaRequest.models=l}let[f,p]=await Promise.all([e.client.console(Ds,d),e.client.console(Os,{queryFreeTierOnlyStatusRequest:{models:l}})]),m=As(f),h=i?m:m.filter(e=>e.quotaStatus===`VALID`&&e.quotaInitTotal>0);if(a>0){let e=Date.now()+a*24*60*60*1e3;h=h.filter(t=>t.quotaValidityPeriod>0&&t.quotaValidityPeriod<=e)}let g=o??(i?void 0:`remaining`);g===`remaining`?h.sort((e,t)=>(e.quotaInitTotal?e.quotaTotal/e.quotaInitTotal:0)-(t.quotaInitTotal?t.quotaTotal/t.quotaInitTotal:0)):g===`expires`&&h.sort((e,t)=>(e.quotaValidityPeriod??0)-(t.quotaValidityPeriod??0));let _=js(p),v=new Map(_.map(e=>[e.model,e.freeTierOnly]));if(c===`json`){M(h.map(e=>{let t=e.quotaInitTotal!=null&&e.quotaTotal!=null,n=t?e.quotaInitTotal-e.quotaTotal:0,r=v.get(e.model),i=e.quotaStatus===`UNKNOWN`?`unsupported`:r===!0?!0:r===!1?!1:null;return{model:e.model,type:u.get(e.model)||null,remaining:t?e.quotaTotal:null,total:t?e.quotaInitTotal:null,usagePercent:t&&e.quotaInitTotal>0?Math.round(n/e.quotaInitTotal*1e3)/10:null,remainingPercent:Ms(e),expires:e.quotaValidityPeriod?Ss(e.quotaValidityPeriod):null,autoStop:i}}),c);return}if(h.length===0){process.stdout.write(`No free-tier quota found.
|
|
2663
|
+
`);return}let y=!i&&!s?h.slice(0,15):h,b=h.length-y.length,x=g===`remaining`?` · sorted by urgency`:``;Ps({quotas:y,stopMap:v,typeMap:u,title:`Free Tier Quota · ${h.length} models${x}`,moreHint:b>0?`+ ${b} more · ${t.binName} usage free --all to browse all`:void 0})}});function Hs(e,t){let n=e[t];if(n&&typeof n==`object`&&!Array.isArray(n))return n}function Us(e){let t=Hs(e,`data`);if(!t)return e;let n=Hs(t,`DataV2`);if(n){let e=Hs(n,`data`);return(e?Hs(e,`data`):void 0)??e??n}return Hs(t,`data`)??t}async function Ws(e,t,n,r){let i;for(let a=0;a<20;a++){let a={[n]:i?{taskId:i}:{models:r}},o=await e.console(t,a),s=Us(o);if(s.taskId&&Object.keys(s).length===1){i=s.taskId,await new Promise(e=>setTimeout(e,500));continue}return o}return null}async function Gs(e){let t=[],n=1;for(;;){let r=await pe((t,n)=>e.console(t,n),{pageNo:n,pageSize:50});if(t.push(...r.models),t.length>=r.total)break;n++}return t.map(e=>e.model).filter(Boolean)}var Ks=w({description:`Enable or disable auto-stop for free-tier models. Enables by default; use --off to disable`,auth:`console`,usageArgs:`<--model <model>[,model2,...] | --all> [--off] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name(s), comma-separated for multiple`},all:{type:`switch`,description:`Apply to all free-tier models`},on:{type:`switch`,description:`Enable auto-stop (default behavior)`},off:{type:`switch`,description:`Disable auto-stop`}},exampleArgs:[`--model qwen3-max`,`--model qwen3-max,qwen-turbo`,`--all`,`--on --model qwen3-max`,`--off --model qwen3-max`,`--off --all`],validate:e=>!e.model&&!e.all?`Provide --model <model>[,model2,...] or --all.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.model||void 0,i=!!n.off,a=T(t.output),o;o=r?[...new Set(r.split(`,`).map(e=>e.trim()).filter(Boolean))]:[];let s=i?`zeldaEasy.broadscope-bailian.freeTrial.batchDeactivateFreeTierOnly`:`zeldaEasy.broadscope-bailian.freeTrial.batchActivateFreeTierOnly`,c=i?`BatchDeactivateFreeTierOnlyRequest`:`BatchActivateFreeTierOnlyRequest`;if(t.dryRun){M({api:s,data:{[c]:{models:o}}},a);return}if(r||(o=await Gs(e.client)),i){let[t,n]=await Promise.all([e.client.console(`zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierQuota`,{queryFreeTierQuotaRequest:{models:o}}),e.client.console(`zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierOnlyStatus`,{queryFreeTierOnlyStatusRequest:{models:o}})]),r=Us(t).freeTierQuotas??[],i=new Map(r.map(e=>[e.model,e])),a=Us(n).freeTierOnlyStatuses??[],l=new Map(a.map(e=>[e.model,e.freeTierOnly]));for(let t of o){if(l.get(t)===!1){process.stderr.write(`Auto-stop is already disabled for "${t}".\n`);continue}let n=i.get(t);if(n&&n.quotaTotal>0&&l.get(t)===!0){process.stderr.write(`Cannot disable auto-stop for "${t}": free-tier quota has not been fully consumed. Please disable auto-stop after the quota is exhausted.\n`);continue}await Ws(e.client,s,c,[t]),process.stdout.write(`Disabled auto-stop for "${t}".\n`)}return}let l=[];for(let t of o){let n=await Ws(e.client,s,c,[t]);if(a===`json`){l.push(n);continue}if(n){let e=Us(n).failureModels??[];e.length>0?process.stderr.write(`Failed to enable auto-stop for "${t}" (${e[0].errorCode}).\n`):process.stdout.write(`Enabled auto-stop for "${t}".\n`)}else process.stderr.write(`Warning: operation timed out for "${t}".\n`)}a===`json`&&M(l,a)}});const qs=`zeldaEasy.bailian-telemetry.model.getModelUsageStatistic`,Js=`zeldaEasy.bailian-telemetry.model.listModelUsageStatisticData`;function Ys(e,t){let n=e[t];if(n&&typeof n==`object`&&!Array.isArray(n))return n}function Xs(e){let t=Ys(e,`data`);if(!t)return e;let n=Ys(t,`DataV2`);if(n){let e=Ys(n,`data`);return(e?Ys(e,`data`):void 0)??e??n}return Ys(t,`data`)??t}async function Zs(e,t,n){let r;for(let i=0;i<30;i++){let i=r?{reqDTO:{...n,asyncTaskId:r}}:{reqDTO:n},a=await e.console(t,i),o=Xs(a);if(o.taskId&&Object.keys(o).length===1){r=o.taskId,await new Promise(e=>setTimeout(e,500));continue}return a}return null}function Qs(e,n){if(e.workspaceId)return e.workspaceId;throw new t(`workspace-id is required. Set via --workspace-id, BAILIAN_WORKSPACE_ID, or \`${n} config set workspace_id <id>\`.`,a.GENERAL,`Run \`${n} workspace list\` to view available workspaces.`)}function $s(e){return e.toLocaleString(`en-US`)}function J(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}function ec(e){let t=Xs(e);if(t.callSuccessCount!==void 0||t.usages!==void 0)return t}function tc(e){let t=Xs(e);return{list:t.list??[],totalCount:t.totalCount??0,maxResults:t.maxResults??0}}function nc(e){let t={};if(e.usages&&Array.isArray(e.usages))for(let n of e.usages)n.key&&n.value!=null&&(t[n.key]=n.value);if(e.usage&&typeof e.usage==`object`)for(let[n,r]of Object.entries(e.usage))r!=null&&(t[n]=r);return t}const rc={total_token:{en:`Total Tokens`,unit:`tokens`},input_token:{en:`Input Tokens`,unit:`tokens`},output_token:{en:`Output Tokens`,unit:`tokens`},input_token_cache:{en:`Cached Tokens`,unit:`tokens`},input_token_cache_read:{en:`Cache Read`,unit:`tokens`},input_token_cache_creation:{en:`Cache Creation`,unit:`tokens`},thinking_input_token:{en:`Thinking Input`,unit:`tokens`},thinking_output_token:{en:`Thinking Output`,unit:`tokens`},text_input_token:{en:`Text Input`,unit:`tokens`},purein_text_output_token:{en:`Text Output`,unit:`tokens`},embedding_token:{en:`Embedding`,unit:`tokens`},image_number:{en:`Images`,unit:`images`},video_duration:{en:`Video Duration`,unit:`sec`},content_duration:{en:`Audio Duration`,unit:`sec`},tts_text_number:{en:`TTS Chars`,unit:`chars`},total_token_avg:{en:`Avg Tokens/Req`}};function ic(e){let t=e.unit?` [${e.unit}]`:``;return`${e.en}${t}`}function ac(e,t,n,r){let i=k(process.stdout);process.stdout.write(`${i.dim(`Time Range Period:`)} ${J(t)} ~ ${J(n)} ${i.dim(`(${r} days)`)}\n\n`);let a=[[`Models Called`,$s(e.modelCount??0)],[`Successful Calls`,$s(e.callSuccessCount??0)]];for(let t of e.usages??[]){let e=rc[t.key],n=e?ic(e):t.key;a.push([n,$s(t.value)])}let o=Math.max(...a.map(([e])=>Mt(e)));for(let[e,t]of a)process.stdout.write(`${i.bold(P(e,o+2))}${t}\n`)}function oc(e,t,n,r){let i=k(process.stdout);if(process.stdout.write(`${i.dim(`Time Range Period:`)} ${J(t)} ~ ${J(n)} ${i.dim(`(${r} days)`)}\n\n`),e.length===0){process.stdout.write(`No usage data found.
|
|
2664
|
+
`);return}let a=new Set,o=e.map(e=>{let t=nc(e);for(let e of Object.keys(t))a.add(e);return t}),s=[...a].sort((e,t)=>{let n=[`total_token`,`input_token`,`output_token`,`input_token_cache`,`image_number`,`video_duration`,`content_duration`,`tts_text_number`],r=n.indexOf(e),i=n.indexOf(t);return(r===-1?999:r)-(i===-1?999:i)}),c=[`Model`,`Calls`,...s.map(e=>rc[e]?.en??e)],l=e.map((e,t)=>[e.model,$s(e.callSuccessCount??0),...s.map(e=>{let n=o[t][e];return n==null?`-`:$s(n)})]),u=c.map((e,t)=>Math.max(Mt(e),...l.map(e=>Mt(e[t])))),d=c.map((e,t)=>i.bold(P(e,u[t]))).join(` `),f=u.map(e=>i.dim(`─`.repeat(e))).join(`──`);process.stdout.write(d+`
|
|
323
2665
|
`),process.stdout.write(f+`
|
|
324
|
-
`);for(let e of l){let t=e.map((e,t)=>
|
|
2666
|
+
`);for(let e of l){let t=e.map((e,t)=>P(e,u[t]));process.stdout.write(t.join(` `)+`
|
|
325
2667
|
`)}process.stdout.write(i.dim(`\nTotal: ${e.length} models`)+`
|
|
326
|
-
`)}var
|
|
327
|
-
`);return}
|
|
328
|
-
`);else{let e=g.slice(0,10),t=g.length-e.length;
|
|
329
|
-
`),c?y
|
|
2668
|
+
`)}var sc=w({description:`Query model usage statistics`,auth:`console`,usageArgs:`[--model <model>] [--days <days>] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name(s), comma-separated; omit for overview`},days:{type:`string`,valueHint:`<days>`,description:`Number of days (default: 7)`},type:{type:`string`,valueHint:`<type>`,description:`Model type: Text, Vision, Multimodal, Audio, Embedding`}},exampleArgs:[``,`--days 30`,`--model qwen-turbo`,`--model qwen-turbo --days 7`,`--model qwen3.6-plus,deepseek-v4-pro`,`--type Text --days 14`,`--output json`],async run(e){let{identity:n,settings:r,flags:i}=e,o=i.model||void 0,s=Number(i.days)||7,c=i.type||void 0,l=T(r.output),u=Qs(r,n.binName),d=Date.now(),f=d-s*24*60*60*1e3;if(o){let t=[...new Set(o.split(`,`).map(e=>e.trim()).filter(Boolean))],n={startTime:f,endTime:d,modelCallSource:`Online`,filterWorkspaceId:u,maxResults:50,skip:0,sortField:`success_count`,sortOrder:`DESC`};if(c&&(n.obsModelType=c),r.dryRun){M({api:Js,data:{reqDTO:{...n,model:t.join(`,`)}}},l);return}let i=await Promise.all(t.map(t=>Zs(e.client,Js,{...n,model:t}))),a=[];for(let e of i){if(!e)continue;let t=tc(e);a.push(...t.list)}if(l===`json`){let e=a.map(e=>{let t=nc(e),n={model:e.model,successfulCalls:e.callSuccessCount??0};for(let[e,r]of Object.entries(t))n[e]=r;return n});M({period:{start:J(f),end:J(d),days:s},items:e},l);return}oc(a,f,d,s)}else{let n={startTime:f,endTime:d,modelCallSource:`Online`,filterWorkspaceId:u};if(c&&(n.obsModelType=c),r.dryRun){M({api:qs,data:{reqDTO:n}},l);return}let i=await Zs(e.client,qs,n);if(!i)throw new t(`Request timed out.`,a.TIMEOUT);let o=ec(i);if(l===`json`){if(!o){M({period:{start:J(f),end:J(d),days:s},modelsCalled:0,successfulCalls:0},l);return}M({period:{start:J(f),end:J(d),days:s},modelsCalled:o.modelCount??0,successfulCalls:o.callSuccessCount??0,usages:(o.usages??[]).map(e=>({key:e.key,value:e.value,unit:e.unit,label:rc[e.key]?.en??e.key}))},l);return}if(!o){process.stdout.write(`No usage data found.
|
|
2669
|
+
`);return}ac(o,f,d,s)}}}),cc=w({description:`Show a unified usage summary: free-tier quota and recent usage overview`,auth:`console`,usageArgs:`[--days <days>] [flags]`,flags:{days:{type:`string`,valueHint:`<days>`,description:`Number of days for the usage overview (default: 7)`}},exampleArgs:[``,`--days 30`,`--output json`],async run(e){let{identity:n,settings:r,flags:i}=e,o=Number(i.days)||7,s=T(r.output),c=r.workspaceId,l=Date.now(),u=l-o*24*60*60*1e3;if(r.dryRun){M({freeTier:{api:Ds},usage:c?{api:Fs,data:{reqDTO:{startTime:u,endTime:l,modelCallSource:`Online`,filterWorkspaceId:c}}}:null},s);return}let d=await Es(e.client),f=d.map(e=>e.name),p=new Map(d.map(e=>[e.name,e.type])),[m,h]=await Promise.all([e.client.console(Ds,{queryFreeTierQuotaRequest:{models:f}}),e.client.console(Os,{queryFreeTierOnlyStatusRequest:{models:f}})]),g=As(m).filter(e=>e.quotaStatus===`VALID`&&e.quotaInitTotal>0).sort((e,t)=>(e.quotaInitTotal?e.quotaTotal/e.quotaInitTotal:0)-(t.quotaInitTotal?t.quotaTotal/t.quotaInitTotal:0)),_=js(h),v=new Map(_.map(e=>[e.model,e.freeTierOnly])),y;if(c){let n=await Is(e.client,Fs,{startTime:u,endTime:l,modelCallSource:`Online`,filterWorkspaceId:c});if(!n)throw new t(`Request timed out.`,a.TIMEOUT);y=Ls(n)}if(s===`json`){let e=g.map(e=>({model:e.model,type:p.get(e.model)||null,remaining:e.quotaTotal,total:e.quotaInitTotal,remainingPercent:Ms(e),expires:e.quotaValidityPeriod?Ss(e.quotaValidityPeriod):null}));M({period:{start:Ss(u),end:Ss(l),days:o},freeTier:e,usage:y?{modelsCalled:y.modelCount??0,successfulCalls:y.callSuccessCount??0,usages:(y.usages??[]).map(e=>({key:e.key,value:e.value,unit:e.unit,label:Rs[e.key]?.en??e.key}))}:null},s);return}let b=k(process.stdout);if(process.stdout.write(`${b.bold(`Usage Summary`)} ${b.dim(`·`)} ${Ss(l)}\n\n`),g.length===0)process.stdout.write(b.dim(`No active free-tier quota.`)+`
|
|
2670
|
+
`);else{let e=g.slice(0,10),t=g.length-e.length;Ps({quotas:e,stopMap:v,typeMap:p,title:`Free Tier Quota · ${g.length} models · sorted by urgency`,moreHint:t>0?`+ ${t} more · ${n.binName} usage free to browse all`:void 0})}process.stdout.write(`
|
|
2671
|
+
`),c?y?Bs(y,u,l,o):process.stdout.write(b.dim(`No usage data in this period.`)+`
|
|
330
2672
|
`):process.stdout.write(b.dim(`Usage overview skipped · set --workspace-id or \`${n.binName} config set workspace_id <id>\` to include it.`)+`
|
|
331
|
-
`)}});async function
|
|
332
|
-
`);return}let l=await
|
|
2673
|
+
`)}});async function lc(e){let t=await En(e,`utf-8`).catch(e=>{throw new p(`cannot read pipeline file: ${e.message}`)}),n=_n(e).toLowerCase(),r;if(n===`.yaml`||n===`.yml`){let{parse:e}=await import(`yaml`);r=e(t)}else try{r=JSON.parse(t)}catch{let{parse:e}=await import(`yaml`);r=e(t)}return r}var uc=w({description:`Run a pipeline workflow definition`,auth:`none`,usageArgs:`--file <path> [flags]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Pipeline definition file (YAML/JSON)`,required:!0},input:{type:`string`,valueHint:`<json>`,description:`Runtime input as inline JSON`},inputFile:{type:`string`,valueHint:`<path>`,description:`Runtime input from a JSON file`},concurrency:{type:`number`,valueHint:`<n>`,description:`Max parallel steps (default: 1)`},events:{type:`string`,valueHint:`<format>`,description:`Emit lifecycle events: jsonl`,choices:[`jsonl`]},stepTimeout:{type:`number`,valueHint:`<seconds>`,description:`Default step timeout in seconds`}},exampleArgs:[`--file workflow.yaml --input '{"brief":"hello"}'`,`--file workflow.json --input-file inputs.json --concurrency 3`,`--file workflow.yaml --dry-run`,`--file workflow.json --events jsonl`,`--file workflow.yaml --output json`],validate:e=>e.input&&e.inputFile?`use --input or --input-file, not both`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.file;Rt();let i=n.events,a=R(r),o=await lc(a),s=await dc(n),c=gn(a);if(i===`jsonl`){for await(let e of Wt(o,s,{concurrency:n.concurrency,basePath:c,dryRun:t.dryRun,timeoutSeconds:n.stepTimeout}))process.stdout.write(JSON.stringify(e)+`
|
|
2674
|
+
`);return}let l=await Pt(o,s,{concurrency:n.concurrency,basePath:c,dryRun:t.dryRun,timeoutSeconds:n.stepTimeout,onEvent:t.verbose?fc:void 0});t.output===`json`?M(l,`json`):mc(l),l.status===`failed`&&(process.exitCode=1)}});async function dc(e){let t=e.input,n=e.inputFile;if(t)return JSON.parse(t);if(n){let e=await En(R(n),`utf-8`);return JSON.parse(e)}return{}}function fc(e){let t=`[${e.type}]`;if(`stepCount`in e){process.stderr.write(`${t} ${e.stepCount} step${e.stepCount===1?``:`s`}\n`);return}`step`in e&&e.step?process.stderr.write(`${t} ${pc(e.step)}\n`):process.stderr.write(`${t}\n`)}function pc(e){return`${e.index!==void 0&&e.total!==void 0?`${e.index}/${e.total} `:``}${e.id} (${e.type})`}function mc(e){let t=e.status===`succeeded`?`+`:e.status===`failed`?`x`:`~`;process.stdout.write(`\nPipeline ${e.status} [${t}]\n\n`);for(let t of e.steps){let e=` [${t.status===`succeeded`?`+`:t.status===`failed`?`x`:t.status===`skipped`?`-`:`~`}] ${t.id} (${t.type}) — ${t.status}`;t.skipReason&&(e+=` (${t.skipReason})`),t.error&&(e+=`: ${t.error.message}`),process.stdout.write(e+`
|
|
333
2675
|
`)}process.stdout.write(`
|
|
334
|
-
`)}var
|
|
2676
|
+
`)}var hc=w({description:`Validate a pipeline definition without executing`,auth:`none`,usageArgs:`--file <path>`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Pipeline definition file (YAML/JSON)`,required:!0}},exampleArgs:[`--file workflow.yaml`,`--file workflow.json --output json`],async run(e){let{settings:t,flags:n}=e,r=n.file;Rt();let i=await lc(R(r)),a=At(i),o=a.length===0?kt(i):[];if(t.output===`json`)M({valid:a.length===0,issues:a,...o.length>0?{hints:o}:{}},`json`),a.length>0&&(process.exitCode=1);else if(a.length===0){process.stdout.write(`Pipeline definition is valid.
|
|
335
2677
|
`);for(let e of o)process.stderr.write(` hint: ${e}\n`)}else{process.stderr.write(`Pipeline validation failed:
|
|
336
|
-
`);for(let e of a)process.stderr.write(` - ${e}\n`);process.exitCode=1}}});function
|
|
337
|
-
`),{padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:1,right:0},borderColor:n?`cyan`:void 0,borderStyle:`round`,dimBorder:n})}const
|
|
338
|
-
`),{padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:1,right:0},borderColor:r?`gray`:void 0,borderStyle:`round`,dimBorder:r})}function
|
|
339
|
-
`)}function
|
|
2678
|
+
`);for(let e of a)process.stderr.write(` - ${e}\n`);process.exitCode=1}}});function gc(e){return e>=1e6?`${(e/1e6).toFixed(e%1e6==0?0:1)}M`:e>=1e3?`${(e/1e3).toFixed(e%1e3==0?0:1)}K`:String(e)}const _c={Text:`Text`,Image:`Image`,Video:`Video`,Audio:`Audio`},vc={TG:`Text Gen`,VU:`Vision`,IG:`Image Gen`,VG:`Video Gen`,TTS:`Text-to-Speech`,ASR:`Speech-to-Text`,Reasoning:`Reasoning`},yc={low:`Cost-Effective`,medium:`Balanced`,high:`High Investment`},bc={flagship:`Flagship`,balanced:`Balanced`,"cost-optimized":`Value`},xc={scoped:`Scoped`,comparison:`Comparison`,alternative:`Alternative`};function Sc(e){return Gt(e)?kn:new An({level:0})}function Cc(e){let t=Sc(process.stdout),n=Gt(process.stdout),r=[];r.push(t.cyan.bold(`Intent Analysis`)),e.taskSummary&&(r.push(``),r.push(e.taskSummary)),e.scenarioHints.length&&(r.push(``),r.push(`${t.dim(`Scenario`)} ${e.scenarioHints.join(` · `)}`));let i=e.inputModality.map(e=>_c[e]??e),a=e.outputModality.map(e=>_c[e]??e);if(i.length||a.length){r.push(``);let e=[];i.length&&e.push(`${t.dim(`Input`)} ${i.join(`, `)}`),a.length&&e.push(`${t.dim(`Output`)} ${a.join(`, `)}`),r.push(e.join(` `))}let o=e.requiredCapabilities.map(e=>vc[e]??e);o.length&&r.push(`${t.dim(`Capabilities`)} ${o.join(`, `)}`);let s=yc[e.budget]??e.budget,c=bc[e.qualityPreference]??e.qualityPreference;r.push(``),r.push(`${t.dim(`Budget`)} ${s} ${t.dim(`Quality`)} ${c}`);let l=e.modelPreference;if(l&&l.mode!==`unconstrained`){r.push(``);let e=xc[l.mode]??l.mode,n=[t.dim(`Mode`)+` ${t.yellow(e)}`];l.targets?.length&&n.push(t.dim(`Targets`)+` ${l.targets.join(`, `)}`),l.excludes?.length&&n.push(t.dim(`Excludes`)+` ${l.excludes.join(`, `)}`),r.push(n.join(` `))}if(e.segments?.length){r.push(``),r.push(t.dim(`Pipeline`));for(let[n,i]of e.segments.entries()){let e=i.outputModality.map(e=>_c[e]??e).join(`, `);r.push(` ${t.dim(`${n+1}.`)} ${i.step}${e?t.dim(` → ${e}`):``}`)}}return On(r.join(`
|
|
2679
|
+
`),{padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:1,right:0},borderColor:n?`cyan`:void 0,borderStyle:`round`,dimBorder:n})}const wc=[`Best Pick`,`Runner-Up`,`Alternative`];function Tc(e,t,n,r){let i=[n.green.bold,n.blue.bold,n.magenta.bold][t]??n.white.bold,a=wc[t]??`#${t+1}`,o=[];o.push(i(`⬢ #${t+1} — ${a}`)),o.push(``),o.push(`${n.bold(e.name)} ${n.dim(`(${e.model})`)}`),o.push(``),o.push(`${n.cyan(`Why`)} ${e.reason}`),e.highlights.length&&(o.push(``),o.push(e.highlights.map(e=>n.bgGray.white(` ${e} `)).join(` `)));let s=[];e.contextWindow&&s.push(`Context ${gc(e.contextWindow)}`),e.maxOutputTokens&&s.push(`Max Output ${gc(e.maxOutputTokens)}`),s.length&&(o.push(``),o.push(n.dim(s.join(` · `))));let c=v(e.docUrl);return c&&(o.push(``),o.push(n.dim(`Docs ${c}`))),On(o.join(`
|
|
2680
|
+
`),{padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:1,right:0},borderColor:r?`gray`:void 0,borderStyle:`round`,dimBorder:r})}function Ec(e){let t=Sc(process.stdout),n=Gt(process.stdout);return e.map((e,r)=>Tc(e,r,t,n)).join(`
|
|
2681
|
+
`)}function Dc(e,t){let n=Sc(process.stdout),r=Gt(process.stdout),i=[];i.push(` ${n.yellow.bold(`⚡ Pipeline`)} ${e}`);for(let[e,{step:a,recommendations:o,warnings:s}]of t.entries()){if(i.push(``),i.push(n.bold(` ━━━ Step ${e+1}: ${a} ━━━`)),s?.length)for(let e of s)i.push(` ${n.yellow(`⚠`)} ${n.yellow(e)}`);i.push(``),i.push(o.map((e,t)=>Tc(e,t,n,r)).join(`
|
|
340
2682
|
`))}return i.join(`
|
|
341
|
-
`)}function
|
|
342
|
-
`),a.update(`Agent: Recalling candidates...`),a.start();let h=await
|
|
2683
|
+
`)}function Oc(e){return e.type===`pipeline`?Dc(e.summary,e.steps):Ec(e.recommendations)}function kc(e){return e.type===`pipeline`?e.steps.length===0:e.recommendations.length===0}var Ac=w({description:`Recommend the best models for your use case (intent analysis → candidate recall → LLM ranking)`,auth:`apiKey`,usageArgs:`--message <text> [flags]`,flags:{message:{type:`string`,valueHint:`<text>`,description:`Describe your requirements`,required:!0}},exampleArgs:[`--message "I need a visual-understanding chatbot"`,`--message "Build an Agent that auto-generates animations"`,`--message "Legal contract review, high precision required"`,`--message "Low-cost high-concurrency online customer service" --output text`,`--message "Long document summarization" --dry-run`],async run(e){let{settings:t,flags:n}=e,r=n.message,i=t.outputExplicit?T(t.output):`json`,a=jt(`Agent: Loading model data & analyzing intent...`);a.start();let o={onPrepareStart:()=>{}},s=!1,c=!1,l=we(t,o).then(e=>(s=!0,c||a.update(`Agent: Model data loaded, analyzing intent...`),e)),d=m(e.client,r).then(e=>(c=!0,s||a.update(`Agent: Intent analyzed, loading model data...`),e)),[f,p]=await Promise.all([l,d]);a.stop(),p.confidence===0&&process.stderr.write(`Intent analysis timed out, using defaults...
|
|
2684
|
+
`),a.update(`Agent: Recalling candidates...`),a.start();let h=await nt(e.client,f,r,u,p);if(a.stop(),t.dryRun){M({userInput:r,intent:{taskSummary:p.taskSummary,scenarioHints:p.scenarioHints,complexity:p.complexity,inputModality:p.inputModality,outputModality:p.outputModality,requiredCapabilities:p.requiredCapabilities,budget:p.budget,qualityPreference:p.qualityPreference,modelPreference:p.modelPreference?.mode===`unconstrained`?void 0:p.modelPreference,segments:p.segments,semanticQuery:p.semanticQuery},candidateCount:h.length,candidates:h.map(({model:e,score:t,hardScore:n,softScore:r})=>({model:e.model,score:t,hardScore:n,softScore:r})),top:3},i);return}a.update(`Agent: Ranking models...`),a.start();let g=await $e(e.client,h,p,r,3);if(a.stop(),kc(g)){j(`No suitable models found for this request.`);return}if(i!==`text`){M({intent:{taskSummary:p.taskSummary,scenarioHints:p.scenarioHints,complexity:p.complexity,inputModality:p.inputModality,outputModality:p.outputModality,requiredCapabilities:p.requiredCapabilities,budget:p.budget,qualityPreference:p.qualityPreference,modelPreference:p.modelPreference?.mode===`unconstrained`?void 0:p.modelPreference,segments:p.segments,semanticQuery:p.semanticQuery},result:g,candidates:h.length},i);return}j(Cc(p)),j(``),j(Oc(g))}});const jc=/-\d{4}-\d{2}-\d{2}$/,Mc={model:{type:`string`,valueHint:`<model>`,description:`Show full details of a specific model family (switches to detail mode)`},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10)`},provider:{type:`array`,valueHint:`<p>`,description:`Filter by provider (repeatable, e.g. --provider alibaba --provider deepseek)`},capability:{type:`array`,valueHint:`<c>`,description:`Filter by capability code (TG, Reasoning, VU, IG, VG, TTS, ASR, …)`},feature:{type:`array`,valueHint:`<f>`,description:`Filter by feature (function-calling, web-search, structured-outputs, …)`},contextWindow:{type:`array`,valueHint:`<w>`,description:`Filter by context window range bucket`},enrich:{type:`switch`,description:`Also fetch input parameter schema (predictConfig) for trunk models (detail mode only)`}};function Nc(e){return(e.model??``).replace(/^group-/,``)||e.name||`unknown`}function Pc(e){if(!e?.length)return`-`;let t=e.find(e=>typeof e.type==`string`&&e.type.includes(`input`))??e[0];return`${t.type??``}:${String(t.price??`?`)}/${t.priceUnit??``}`}function Fc(e){let t=new Set,n=new Set,r=0,i=0,a,o=[];for(let s of e.items??[]){s.provider&&t.add(s.provider);for(let e of s.capabilities??[])n.add(e);r++,typeof s.contextWindow==`number`&&s.contextWindow>i&&(i=s.contextWindow),s.prices?.length&&(o.push(...s.prices),a||=s.prices.find(e=>typeof e.type==`string`&&e.type.includes(`input`))??s.prices[0])}return{providers:[...t].join(`,`),capabilities:[...n].join(`,`),modelCount:r,maxContext:i>0?i:void 0,price:a?Pc([a]):void 0,prices:o}}function Ic(e){if(e.length===0)return[];let t=e.filter(e=>!jc.test(e.model??``));return t.length>0?t:[...e].sort((e,t)=>String(t.model).localeCompare(String(e.model))).slice(0,1)}function Lc(e,t){if(e.length===0){j(`No model families found.`);return}let n=[`NAME`,`PROVIDER`,`CAPABILITIES`,`MODELS`,`MAX_CONTEXT`,`PRICE`],r=e.map(e=>{let t=Fc(e);return[e.name||Nc(e),t.providers||`-`,t.capabilities||`-`,String(t.modelCount),t.maxContext?String(t.maxContext):`-`,t.price??`-`]});for(let e of N(n,r))j(e);j(`\nTotal: ${t}`)}function Rc(e,t){return{items:e.map(e=>{let t=Fc(e),n=e.items?.[0];return{model:Nc(e),name:e.name,description:e.description,provider:t.providers,capabilities:[...new Set((e.items??[]).flatMap(e=>e.capabilities??[]))],modelCount:t.modelCount,maxContextWindow:t.maxContext,prices:t.prices.length>0?t.prices:void 0,qpmInfo:n?.qpmInfo}}),total:t}}function zc(e,t){let n=e.items??[],r=Ic(n),i=n.length-r.length;j(e.name??e.model),e.description&&j(` ${e.description}`),e.updateAt&&j(` Updated: ${e.updateAt}`),j(``);let a=[`MODEL`,`PROVIDER`,`CAPABILITIES`,`CONTEXT`,`OUTPUT`,`CATEGORY`,`PRICE`],o=n.map(e=>[e.model??`-`,e.provider??`-`,(e.capabilities??[]).join(`,`)||`-`,e.contextWindow?String(e.contextWindow):`-`,e.maxOutputTokens?String(e.maxOutputTokens):`-`,e.category??`-`,Pc(e.prices)]);for(let e of N(a,o))j(e);j(`\nTotal: ${n.length} models (${r.length} trunk, ${i} snapshots)`);for(let e of r){if(!e.prices?.length)continue;j(`\n── Pricing: ${e.model} ──`);let t=[`TYPE`,`PRICE`,`UNIT`],n=e.prices.map(e=>[e.type??`-`,String(e.price??`-`),e.priceUnit??`-`]);for(let e of N(t,n))j(e)}for(let e of r){if(!e.qpmInfo||Object.keys(e.qpmInfo).length===0)continue;j(`\n── Rate Limits: ${e.model} ──`);let t=[`TIER`,`RPM`,`TPM`,`TPM_FIELD`],n=Object.entries(e.qpmInfo).map(([e,t])=>{let n=t.count_limit_period||60,r=n?Math.floor((t.count_limit||0)*60/n):0,i=t.usage_limit_period||60,a=i?Math.floor((t.usage_limit||0)*60/i):0;return[e,r>0?String(r):`-`,a>0?String(a):`-`,t.usage_limit_field??`-`]});for(let e of N(t,n))j(e)}if(t)for(let e of r)!e.predictConfig||e.predictConfig.length===0||(j(`\n── predictConfig: ${e.model} ──`),Vc(e.predictConfig))}function Bc(e,t){let n=e.items??[];return{model:e.model,name:e.name,description:e.description,updateAt:e.updateAt,items:n.map(e=>{let n={model:e.model,name:e.name,provider:e.provider,capabilities:e.capabilities,features:e.features,contextWindow:e.contextWindow,maxOutputTokens:e.maxOutputTokens,maxInputTokens:e.maxInputTokens,category:e.category,openSource:e.openSource,docUrl:e.docUrl,versionTag:e.versionTag};return e.prices&&(n.prices=e.prices),e.qpmInfo&&(n.qpmInfo=e.qpmInfo),t&&e.predictConfig&&(n.predictConfig=e.predictConfig),n})}}function Vc(e){let t=[`PARAM`,`KEY`,`DEFAULT`,`RANGE`],n=e.map(e=>[e.name??`-`,e.key??`-`,e.default===void 0?`-`:JSON.stringify(e.default),e.range===void 0?`-`:JSON.stringify(e.range)]);for(let e of N(t,n))j(e)}var Hc=w({description:`Browse model families or show detailed model info in the Bailian model marketplace`,auth:`console`,usageArgs:`[--model <model>] [--page <n>] [--page-size <n>] [--provider <p>] [--capability <c>] [--feature <f>] [--enrich]`,flags:Mc,exampleArgs:[``,`--provider alibaba`,`--capability TG --capability Reasoning`,`--model qwen-max`,`--model qwen-max --enrich --output json`,`--feature function-calling --output json`],async run(e){let{settings:t,flags:n}=e,r=t.outputExplicit?T(t.output):`json`,i=n.model;if(i){let a=!!n.enrich;if(t.dryRun){M({action:`model.detail`,model:i,enrich:a},r);return}let o=await de(e.client.console.bind(e.client),i);if(!o){j(`Model "${i}" not found.`);return}if(a){let t=Ic(o.items??[]);await Promise.all(t.map(async t=>{if(!t.model)return;let n=await me(e.client.console.bind(e.client),t.model);n&&(t.predictConfig=n)}))}if(r===`json`){M(Bc(o,a),r);return}zc(o,a);return}let a={pageNo:n.page,pageSize:n.pageSize??10,providers:n.provider?.length?n.provider:void 0,capabilities:n.capability?.length?n.capability:void 0,features:n.feature?.length?n.feature:void 0,contextWindows:n.contextWindow?.length?n.contextWindow:void 0};if(t.dryRun){M({action:`model.list`,...a},r);return}let{total:o,groups:s}=await fe(e.client.console.bind(e.client),a);if(r===`json`){M(Rc(s,o),r);return}Lc(s,o)}});const Uc=`zeldaEasy.bailian-dash-workspace.space.listWorkspaces`;function Wc(e,t){let n=e[t];if(n&&typeof n==`object`&&!Array.isArray(n))return n}function Gc(e){let t=Wc(e,`data`);if(!t)return e;let n=Wc(t,`DataV2`);if(n){let e=Wc(n,`data`);return(e?Wc(e,`data`):void 0)??e??n}return Wc(t,`data`)??t}function Kc(e){let t=k(process.stdout),n=[`Name`,`Workspace ID`,`Default`],r=e.map(e=>[e.agentName,e.workspaceId,e.defaultAgent?`Yes`:`-`]),i=n.map((e,t)=>Math.max(Mt(e),...r.map(e=>Mt(e[t])))),a=n.map((e,n)=>t.bold(P(e,i[n]))).join(` `),o=i.map(e=>t.dim(`─`.repeat(e))).join(`──`);process.stdout.write(a+`
|
|
343
2685
|
`),process.stdout.write(o+`
|
|
344
|
-
`);for(let e of r){let n=e.map((e,n)=>n===2&&e===`Yes`?t.green(
|
|
2686
|
+
`);for(let e of r){let n=e.map((e,n)=>n===2&&e===`Yes`?t.green(P(e,i[n])):P(e,i[n]));process.stdout.write(n.join(` `)+`
|
|
345
2687
|
`)}process.stdout.write(t.dim(`\nTotal: ${e.length}`)+`
|
|
346
|
-
`)}var
|
|
347
|
-
`);return}let o=a;if(r>0&&(o=o.slice(0,r)),i===`json`){
|
|
348
|
-
`)}var
|
|
349
|
-
`);return}
|
|
2688
|
+
`)}var qc=w({description:`List all workspaces`,auth:`console`,usageArgs:`[flags]`,flags:{list:{type:`string`,valueHint:`<n>`,description:`Limit number of results`}},exampleArgs:[``,`--list 5`,`--output json`],async run(e){let{settings:t,flags:n}=e,r=Number(n.list)||0,i=T(t.output);if(t.dryRun){M({api:Uc,data:{}},i);return}let a=Gc(await e.client.console(Uc,{})).data;if(!Array.isArray(a)||a.length===0){i===`json`?M([],i):process.stdout.write(`No workspace found.
|
|
2689
|
+
`);return}let o=a;if(r>0&&(o=o.slice(0,r)),i===`json`){M(o.map(e=>({workspaceId:e.workspaceId,name:e.agentName,default:e.defaultAgent})),i);return}Kc(o)}});const Jc=`zeldaEasy.bailian-telemetry.monitor.getMonitorData`;function Yc(e,t){if(!e)return 0;let n=e.count_limit_period||t;return n?Math.floor(e.count_limit*60/n):0}function Xc(e,t){if(!e)return 0;let n=e.usage_limit_period||t;return n?Math.floor(e.usage_limit*60/n):0}function Zc(e){return e.toLocaleString(`en-US`)}async function Qc(e,n,r){let i=Date.now(),o=i-r*60*1e3;try{let t=gt(await e.console(Jc,{reqDTO:{monitorType:`Advanced`,metricFilters:[{aggMethod:`sum_pm`,metricName:`model_total_amount`},{aggMethod:`sum_pm`,metricName:`model_call_count`}],labelFilters:{resourceId:n,resourceType:`model`},startTime:o,endTime:i}})),r=t.data??t;if(!Array.isArray(r))return{rpm:0,tpm:0};let a=0,s=0;for(let e of r){if(e.aggMethod!==`sum_pm`||!e.points?.length)continue;let t=e.points[e.points.length-1].value??0;e.metricName===`model_call_count`&&(a=Math.round(t)),e.metricName===`model_total_amount`&&(s=Math.round(t))}return{rpm:a,tpm:s}}catch(e){if(e instanceof t&&e.exitCode===a.AUTH)throw e;return{rpm:-1,tpm:-1}}}async function $c(e){let t=[],n=1;for(;;){let r={pageNo:n,pageSize:50,group:!1,queryQpmInfo:!0,ignoreWorkspaceServiceSite:!0,supports:{selfServiceLimitIncrease:!0}},i=gt(await e.console(c,{input:r})),a=i.list??[],o=i.total??0;if(t.push(...a),t.length>=o||a.length===0)break;n++}return t}function el(e){let t=[`Model`,`Req/min`,`Token/min`,`RPM Left`,`TPM Left`],n=e.map(e=>e.rpmQuotaLeft),r=e.map(e=>e.rpmQuotaLabel),i=e.map(e=>e.tpmQuotaLeft),a=e.map(e=>e.tpmQuotaLabel),o=Vt({headers:t,rows:e.map(e=>[e.model,e.rpm,e.tpm,``,``]),align:[`left`,`right`,`right`,`left`,`left`],barColumns:[{index:3,percents:n,labels:r,width:15},{index:4,percents:i,labels:a,width:15}]});for(let e of o)process.stdout.write(e+`
|
|
2690
|
+
`)}var tl=w({description:`View model RPM/TPM rate limits`,auth:`console`,usageArgs:`[--model <model>] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name(s), comma-separated`}},exampleArgs:[``,`--model qwen3.6-plus`,`--model qwen3.6-plus,qwen-turbo`,`--output json`],async run(e){let{settings:n,flags:r}=e,i=r.model||void 0,a=T(n.output);if(n.dryRun){M({apis:[c,{api:Jc,note:`called per-model for text output with gauges`}],modelListInput:{input:{pageNo:1,pageSize:50,group:!1,queryQpmInfo:!0,ignoreWorkspaceServiceSite:!0,supports:{selfServiceLimitIncrease:!0}}}},a);return}let o=await $c(e.client);if(i){let e=new Set(i.split(`,`).map(e=>e.trim()).filter(Boolean));if(o=o.filter(t=>e.has(t.model)),o.length===0)throw new t(`no matching models found for "${i}".`)}if(a===`json`){M(o.map(e=>{let t=e.qpmInfo,n=t?.[`model-default`],r=t?.[`user-spec`],i=Yc(n),a=Xc(n),o=Yc(r,n?.count_limit_period)||i,s=Xc(r,n?.usage_limit_period)||a;return{model:e.model,rpm:o>0?o:null,tpm:s>0?s:null}}),a);return}let s=await Promise.all(o.map(t=>Qc(e.client,t.model,2))),l=o.map((e,t)=>{let n=e.qpmInfo,r=n?.[`model-default`],i=n?.[`user-spec`],a=Yc(r),o=Xc(r),c=Yc(i,r?.count_limit_period)||a,l=Xc(i,r?.usage_limit_period)||o,u=s[t].rpm,d=s[t].tpm,f=null,p=null;u>=0&&c>0&&(f=Math.max(0,100-u/c*100),p=f.toFixed(1)+`%`);let m=null,h=null;return d>=0&&l>0&&(m=Math.max(0,100-d/l*100),h=m.toFixed(1)+`%`),{model:e.model,rpm:c>0?Zc(c):`-`,tpm:l>0?Zc(l):`-`,rpmQuotaLeft:f,tpmQuotaLeft:m,rpmQuotaLabel:p,tpmQuotaLabel:h}});if(l.length===0){process.stdout.write(`No models found.
|
|
2691
|
+
`);return}el(l)}});const nl=`zeldaEasy.broadscope-platform.modelInstance.updateFoundationModelLimits`;function rl(e,t){if(!e)return 0;let n=e.usage_limit_period||t;return n?Math.floor(e.usage_limit*60/n):0}function il(e,t){let n=e[t];if(n&&typeof n==`object`&&!Array.isArray(n))return n}function al(e){let t=il(e,`data`);if(!t)return e;let n=il(t,`DataV2`);if(n){let e=il(n,`data`);return(e?il(e,`data`):void 0)??e??n}return il(t,`data`)??t}async function ol(e,t){return(al(await e.console(`zeldaHttp.dashscopeModel./zelda/api/v1/modelCenter/listFoundationModels`,{input:{pageNo:1,pageSize:50,name:t,group:!1,queryQpmInfo:!0,ignoreWorkspaceServiceSite:!0,supports:{selfServiceLimitIncrease:!0}}})).list??[]).find(e=>e.model===t&&e.qpmInfo)}var sl=w({description:`Request a temporary quota increase`,auth:`console`,usageArgs:`--model <model> --tpm <value> [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name (required)`,required:!0},tpm:{type:`string`,valueHint:`<value>`,description:`Target TPM value (required)`,required:!0}},exampleArgs:[`--model qwen-turbo --tpm 100000`,`--model qwen3.6-plus --tpm 8000000`,`--model qwen-turbo --tpm 100000 --output json`],validate:e=>Number(e.tpm)>0?void 0:`--tpm must be a positive number.`,async run(e){let{identity:n,settings:r,flags:i}=e,o=i.model,s=Number(i.tpm),c=T(r.output);if(r.dryRun){M({api:nl,data:{input:{model:o,limit:{usage_limit:s}}}},c);return}let l=await ol(e.client,o);if(!l)throw new t(`model "${o}" not found or does not support self-service quota increase.`,a.GENERAL,`Run \`${n.binName} quota list\` to view available models.`);let u=l.qpmInfo[`model-default`],d=l.qpmInfo[`user-spec`],f=rl(u),m=rl(d,u?.usage_limit_period)||f,h=f*2;if(s<f||s>h)throw new p(`TPM value ${s.toLocaleString()} is out of range. Current: ${m.toLocaleString()}, Range: ${f.toLocaleString()} ~ ${h.toLocaleString()}.`);let g={input:{model:o,limit:{usage_limit:s},originalQpmInfo:l.qpmInfo}},_=async r=>{r&&(g.input.confirmedDowngrade=!0);try{return await e.client.console(nl,g)}catch(e){throw e instanceof t&&e.message.includes(`NotLogined`)?new t(`session expired.`,a.AUTH,`Run \`${n.binName} auth login --console\` to re-authenticate.`):e}},v=await _(),y=al(v);if(y.needConfirm){let e=y.confirmCode;if(e===`Refresh_Required`)throw new t(`rate limit has been updated externally. Please retry.`);e===`Downgrade`&&(v=await _(!0))}if(c===`json`){M(v,c);return}process.stdout.write(`Quota updated for "${o}": TPM ${m.toLocaleString()} → ${s.toLocaleString()}\n`)}});const cl=`zeldaEasy.broadscope-platform.modelInstance.listModelLimitApplications`;function ll(e,t){let n=e[t];if(n&&typeof n==`object`&&!Array.isArray(n))return n}function ul(e){let t=ll(e,`data`);if(!t)return e;let n=ll(t,`DataV2`);if(n){let e=ll(n,`data`);return(e?ll(e,`data`):void 0)??e??n}return ll(t,`data`)??t}function dl(e){if(!e)return`-`;try{let t=new Date(e);return isNaN(t.getTime())?e:`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)} ${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`}catch{return e}}function fl(e){return e.toLocaleString(`en-US`)}function pl(e,t){let n=k(process.stdout),r=[`Model`,`Token Limit`,`Applied At`],i=e.map(e=>[e.deployedModel,fl(e.usageLimit),dl(e.gmtCreate)]),a=r.map((e,t)=>Math.max(Mt(e),...i.map(e=>Mt(e[t])))),o=r.map((e,t)=>n.bold(P(e,a[t]))).join(` `),s=a.map(e=>n.dim(`─`.repeat(e))).join(`──`);process.stdout.write(o+`
|
|
350
2692
|
`),process.stdout.write(s+`
|
|
351
|
-
`);for(let e of i)process.stdout.write(e.map((e,t)=>
|
|
2693
|
+
`);for(let e of i)process.stdout.write(e.map((e,t)=>P(e,a[t])).join(` `)+`
|
|
352
2694
|
`);process.stdout.write(n.dim(`\nTotal: ${t} records`)+`
|
|
353
|
-
`)}var
|
|
354
|
-
`);return}
|
|
355
|
-
`)}var
|
|
356
|
-
`);return}let s=await Promise.all(o.map(t=>
|
|
357
|
-
`),a.GENERAL)}if(l.warnings.length>0&&!r.quiet){process.stderr.write(`Dataset validation passed with ${l.warnings.length} warning(s):\n`);for(let e of l.warnings.slice(0,5))process.stderr.write(`${
|
|
358
|
-
`),a.GENERAL)}if(u.warnings.length>0&&!e.quiet){process.stderr.write(`Dataset validation passed with ${u.warnings.length} warning(s) for ${r}:\n`);for(let e of u.warnings.slice(0,5))process.stderr.write(`${
|
|
359
|
-
`)}if(e&&!Le(e).includes(u)){let n=Le(e);throw new t(`Model "${c}" does not support training type "${u}".`,a.USAGE,n.length?`This model supports: ${n.join(`, `)}.`:`This model reports no supported training types.`)}}o.dryRun||(await Ws(n.client,o,h,`fine-tune`,`datasets`),_&&await Ws(n.client,o,_,`fine-tune`,`validations`));let S={model:c,training_file_ids:g,training_type:d.serverTrainingType,hyper_parameters:x};v&&v.length>0&&(S.validation_file_ids=v),y&&(S.model_name=y),b&&(S.finetuned_output_suffix=b);let C=E(o.output);if(o.dryRun){let e=[...h.localPaths.map(e=>({field:`datasets`,path:e})),...(_?.localPaths??[]).map(e=>({field:`validations`,path:e}))];F(e.length>0?{action:`finetune.create`,body:S,pending_uploads:e}:{action:`finetune.create`,body:S},C);return}let te=await ee(n.client,S),w=te.output??te.data;o.quiet?w?.job_id&&P(w.job_id):C===`text`&&w?.job_id?(P(`Created fine-tune job: ${w.job_id}`),w.status&&P(`Status: ${w.status}`)):F(te,C)}const ec=T({description:`Create a text model fine-tune job (sft | sft-lora | dpo | dpo-lora | cpt)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path,...> [--validations <id|path,...>] [--model-name <name>] [--suffix <text>] [--n-epochs <n>] [--batch-size <n>] [--learning-rate <str>] [--max-length <n>] [--training-type <sft|sft-lora|dpo|dpo-lora|cpt>]`,flags:Ks,exampleArgs:[`--model qwen3-8b --datasets file-xxx`,`--model qwen3-8b --datasets ./train.jsonl`,`--model qwen3-8b --datasets ./train.jsonl --validations ./eval.jsonl`,`--model qwen3-8b --datasets file-aaa,./extra.jsonl`,`--model qwen3-8b --datasets ./train.jsonl --training-type sft`,`--model qwen3-8b --datasets file-xxx --learning-rate "1.6e-5" --n-epochs 4`,`--model qwen3-8b --datasets file-xxx --output json`,`--model qwen3-8b --datasets file-xxx --dry-run`],notes:Xs,run:e=>$s(`text`,e)}),tc=T({description:`Create an audio TTS model fine-tune job (sft-lora)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path> [--validations <id|path>] [--model-name <name>] [--suffix <text>]`,flags:qs,exampleArgs:[`--model cosyvoice-v3-flash --datasets ./audio.zip`,`--model cosyvoice-v3-flash --datasets file-xxx`,`--model cosyvoice-v3-flash --datasets ./audio.zip --model-name my-tts`,`--model cosyvoice-v3-flash --datasets file-xxx --output json`,`--model cosyvoice-v3-flash --datasets ./audio.zip --dry-run`],notes:Zs,run:e=>$s(`audio`,e)}),nc=T({description:`Create an image generation model fine-tune job (sft-lora)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path> [--validations <id|path>] [--model-name <name>] [--suffix <text>] [--generation-type <t2i|i2i>] [--learning-rate <str>]`,flags:Js,exampleArgs:[`--model wan2.7-image-pro --datasets ./images.zip`,`--model wan2.7-image-pro --datasets file-xxx`,`--model wan2.7-image-pro --datasets file-xxx --generation-type i2i`,`--model wan2.7-image-pro --datasets ./images.zip --model-name my-wan`,`--model wan2.7-image-pro --datasets file-xxx --output json`,`--model wan2.7-image-pro --datasets ./images.zip --dry-run`],notes:Qs,run:e=>$s(`image`,e)});var rc=T({description:`List fine-tune jobs`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--status <s>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10, max 100)`},status:{type:`string`,valueHint:`<s>`,description:`Filter by status (PENDING / RUNNING / SUCCEEDED / FAILED / CANCELED)`}},exampleArgs:[``,`--status RUNNING`,`--page-size 20 --output json`],async run(e){let{identity:t,settings:n,flags:r}=e,i=E(n.output),a=r.page,o=r.pageSize,s=r.status||void 0;if(n.dryRun){F({action:`finetune.list`,page:a,page_size:o,status:s},i);return}let c=await Ie(e.client,{pageNo:a,pageSize:o,status:s}),l=c.output??c.data,u=l?.jobs??[],d=l?.total,f=u.map(e=>({job_id:e.job_id??``,base_model:e.model??``,status:e.status??``,training_type:e.training_type??``,output_model:e.finetuned_output??``,created_at:e.create_time??e.gmt_create??``}));if(i===`json`){F({items:f,total:d},i);return}if(f.length===0){P(`No fine-tune jobs found.`);return}let p=[`JOB_ID`,`BASE_MODEL`,`STATUS`,`TRAINING_TYPE`,`OUTPUT_MODEL`,`CREATED_AT`],m=f.map(e=>[e.job_id,e.base_model,e.status,e.training_type,e.output_model,e.created_at]);for(let e of I(p,m))P(e);d!==void 0&&P(`\nTotal: ${d}`),P(`Tip: OUTPUT_MODEL is the input for \`${t.binName} deploy text create --model\``)}}),ic=T({description:`Get details of a single fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --output json`],async run(e){let{identity:t,settings:n,flags:r}=e,i=r.jobId,a=E(n.output);if(n.dryRun){F({action:`finetune.get`,job_id:i},a);return}let o=await be(e.client,i),s=o.output??o.data;if(!s){P(`No data returned for ${i}`);return}let c=s.hyper_parameters,l=[];c?.n_epochs!==void 0&&l.push(`n_epochs=${c.n_epochs}`),c?.batch_size!==void 0&&l.push(`batch_size=${c.batch_size}`),c?.learning_rate!==void 0&&l.push(`learning_rate=${c.learning_rate}`),c?.max_length!==void 0&&l.push(`max_length=${c.max_length}`);let u={job_id:s.job_id??i,base_model:s.model??``,status:s.status??``,training_type:s.training_type??``,training_files:s.training_file_ids??[],validation_files:s.validation_file_ids??[],hyper_params:l.length?l.join(` · `):``,output_model:s.finetuned_output??``,model_name:s.model_name??``,created_at:s.create_time??s.gmt_create??``,updated_at:s.end_time??s.gmt_modified??``};if(a===`json`){F(u,a);return}P(`job_id: ${u.job_id}`),u.base_model&&P(`base_model: ${u.base_model}`),u.status&&P(`status: ${u.status}`),u.training_type&&P(`training_type: ${u.training_type}`),u.training_files.length&&P(`training_files: ${u.training_files.join(`, `)}`),u.validation_files.length&&P(`validation_files: ${u.validation_files.join(`, `)}`),u.hyper_params&&P(`hyper_params: ${u.hyper_params}`),u.output_model&&P(`output_model: ${u.output_model} (→ ${t.binName} deploy text create --model)`),u.model_name&&P(`model_name: ${u.model_name}`),u.created_at&&P(`created_at: ${u.created_at}`),u.updated_at&&P(`updated_at: ${u.updated_at}`)}}),ac=T({description:`Cancel a running fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --dry-run`],notes:[`Only PENDING / RUNNING jobs can be cancelled. Completed / failed / already-`,`cancelled jobs return a server-side error (passed through verbatim).`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=E(t.output);if(t.dryRun){F({action:`finetune.cancel`,job_id:r},i);return}let a=await b(e.client,r),o=a.output??a.data;t.quiet?P(r):i===`text`?P(`Cancelled ${r}${o?.status?` (status=${o.status})`:``}.`):F(a,i)}}),oc=T({description:`Delete a fine-tune job record`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --dry-run`],notes:["Cancel a RUNNING job first via `finetune cancel` — the platform refuses",`to delete jobs that are still in flight.`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=E(t.output);if(t.dryRun){F({action:`finetune.delete`,job_id:r},i);return}let a=await ae(e.client,r);t.quiet?P(r):i===`text`?P(`Deleted ${r}.`):F(a,i)}});function sc(e){if(typeof e==`string`)return e;let t=e,n=t.timestamp??t.time??t.create_time??``,r=t.level??``,i=t.message??t.msg??t.log??``;return i||n||r?[n,r,i].filter(Boolean).join(` `):JSON.stringify(e)}function cc(e,t){return sc(e).toLowerCase().includes(t)}async function lc(e,t,n){let r=[],i=1,a=0;for(let o=0;o<200;o++){let o=await xe(e,t,{pageNo:i,pageSize:n}),s=o.output??o.data,c=s?.logs??[];if(a=s?.total??a,c.length===0||(r.push(...c),a&&r.length>=a)||c.length<n)break;i++}return{entries:r,total:a}}var uc=T({description:`Fetch training logs for a fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id> [--page <n>] [--page-size <n>] [--search <keyword>] [--tail <n>]`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Lines per page (default: server-defined)`},search:{type:`string`,valueHint:`<keyword>`,description:`Case-insensitive substring filter. When set, all log pages are fetched and filtered client-side (--page is ignored).`},tail:{type:`number`,valueHint:`<n>`,description:`Keep only the last N entries. When set, all log pages are fetched and the trailing N are kept (--page is ignored).`}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --page-size 100 --output json`,`--job-id ft-xxx --search checkpoint`,`--job-id ft-xxx --search error --output json`,`--job-id ft-xxx --tail 20`,`--job-id ft-xxx --search checkpoint --tail 5`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=n.page,a=n.pageSize,o=n.search||void 0,s=n.tail,c=E(t.output);if(t.dryRun){F({action:`finetune.logs`,job_id:r,page:i,page_size:a,search:o,tail:s},c);return}if(o||s!==void 0){let{entries:n,total:i}=await lc(e.client,r,a??100),l=n,u;if(o){let e=o.toLowerCase();l=n.filter(t=>cc(t,e)),u=l.length}let d=s!==void 0&&s>=0?Math.min(s,l.length):void 0,f=d===void 0?l:l.slice(l.length-d);if(t.quiet||c===`text`){if(f.length===0){P(o?`No logs matched "${o}".`:`No logs returned.`);return}for(let e of f)P(sc(e));let e=[`${f.length} shown`];u!==void 0&&e.push(`matched ${u}`),e.push(`of ${n.length}`+(i?` (total ${i})`:``)),P(`\n${e.join(`, `)}`);return}F({...u===void 0?{}:{matched:u},scanned:n.length,total:i||n.length,...o?{search:o}:{},...d===void 0?{}:{tail:d},logs:f},c);return}let l=await xe(e.client,r,{pageNo:i,pageSize:a}),u=l.output??l.data,d=u?.logs??[];if(t.quiet||c===`text`){if(d.length===0){P(`No logs returned.`);return}for(let e of d)P(sc(e));u?.total!==void 0&&P(`\nTotal: ${u.total}`)}else F(l,c)}}),dc=T({description:`List checkpoints produced by a fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --output json`],notes:["Use the returned `checkpoint` value with `finetune export` to publish",`a deployable model.`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=E(t.output);if(t.dryRun){F({action:`finetune.checkpoints`,job_id:r},i);return}let a=await Me(e.client,r),o=a.output??a.data,s=Array.isArray(o)?o:o?.checkpoints??[],c=Array.isArray(o)?o.length:o?.total??s.length,l=s.map(e=>({checkpoint:e.checkpoint??e.checkpoint_id??``,step:e.step===void 0?``:String(e.step),status:e.status??``}));if(i===`json`){F({items:l,total:c},i);return}if(l.length===0){P(`No checkpoints found.`);return}let u=[`CHECKPOINT`,`STEP`,`STATUS`],d=l.map(e=>[e.checkpoint,e.step,e.status]);for(let e of I(u,d))P(e);P(`\nTotal: ${c}`)}}),fc=T({description:`Publish a checkpoint as a deployable model`,auth:`apiKey`,usageArgs:`--job-id <id> --checkpoint <name> --model-name <name>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},checkpoint:{type:`string`,valueHint:`<name>`,description:"Checkpoint identifier from `finetune checkpoints` (required)",required:!0},modelName:{type:`string`,valueHint:`<name>`,description:`Deployable model name (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx --checkpoint ckpt-3 --model-name my-qwen-sft`],notes:["Required before `deploy <modality> create` can target a checkpoint. The",`platform may auto-export the best checkpoint when a job reaches SUCCEEDED —`,`explicit export is the canonical path for non-best checkpoints.`],async run(e){let{identity:t,settings:n,flags:r}=e,i=r.jobId,a=r.checkpoint,o=r.modelName,s=E(n.output);if(n.dryRun){F({action:`finetune.export`,job_id:i,checkpoint:a,model_name:o},s);return}let c=await ce(e.client,i,a,o),l=(c.output??c.data)?.model_name??o;n.quiet?P(l):s===`text`?(P(`Exported ${i} / ${a} → model_name=${l}`),P(`Next: ${t.binName} deploy text create --model ${l} --name <display-name>`)):F(c,s)}});const pc=new Set([`SUCCEEDED`,`FAILED`,`CANCELED`]);function mc(){let e=new Date,t=e=>String(e).padStart(2,`0`);return`${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function hc(e){let t=Math.floor(e/1e3),n=Math.floor(t/60),r=t%60;return n===0?`${r}s`:`${n}m ${r}s`}function gc(e,t){return new Promise((n,r)=>{if(t.aborted){r(Error(`aborted`));return}let i=()=>{clearTimeout(a),r(Error(`aborted`))},a=setTimeout(()=>{t.removeEventListener(`abort`,i),n()},e);t.addEventListener(`abort`,i,{once:!0})})}var _c=T({description:`Probe a fine-tune job's status (default: single non-blocking fetch). Pass --follow to poll until terminal.`,auth:`apiKey`,usageArgs:`--job-id <id> [--follow] [--interval <sec>] [--poll-timeout <sec>]`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},follow:{type:`switch`,description:`Block and poll until a terminal state (the legacy behavior). Without it, a single status probe is performed and the command returns immediately.`},interval:{type:`number`,valueHint:`<sec>`,description:`Seconds between polls with --follow (default: 10, min: 1). Ignored without --follow.`},pollTimeout:{type:`number`,valueHint:`<sec>`,description:`With --follow, stop polling after this many seconds (default: no limit). Ignored without --follow.`}},exampleArgs:[`--job-id ft-xxx # single probe, returns immediately`,`--job-id ft-xxx --output json # status probe for agents`,`--job-id ft-xxx --follow # block until terminal`,`--job-id ft-xxx --follow --interval 5`,`--job-id ft-xxx --follow --poll-timeout 3600`],notes:[`Default (no --follow) is a NON-BLOCKING single status probe: one fetch, then`,`return immediately. This is the mode meant for agents / scripts — the caller`,`owns the polling cadence, so the CLI never holds the terminal.`,`A terminal FAILED/CANCELED status raises a normal CLI error (non-zero exit);`,`a SUCCEEDED or still-running status returns 0. With --follow, exceeding`,`--poll-timeout raises a timeout error.`,`Use --follow for the blocking, human-terminal-follow experience; use the`,`default mode when driving the loop yourself (e.g. from an agent).`,"For per-step training output (not status), use `finetune logs`."],async run(e){let{settings:n,flags:r}=e,i=r.jobId,o=r.follow,s=Math.max(1,r.interval??10),c=r.pollTimeout,l=E(n.output);if(n.dryRun){F({action:`finetune.watch`,job_id:i,follow:o,interval:s,timeout:c},l);return}if(!o){let r=await be(e.client,i),o=r.output??r.data,s=String(o?.status??``).toUpperCase(),c=pc.has(s);if(n.quiet?P(s||`UNKNOWN`):l===`text`?(P(`${mc()} ${i} ${s||`UNKNOWN`}`),s===`SUCCEEDED`&&P(`✓ ${i} ${s}`)):F({job_id:i,status:s||`UNKNOWN`,terminal:c},l),c&&s!==`SUCCEEDED`)throw new t(`Fine-tune job ${i} ended in status ${s}.`,a.GENERAL);return}let u=new AbortController,d=()=>u.abort();process.on(`SIGINT`,d);try{let r=``,o=Date.now();for(;;){let d=await be(e.client,i,u.signal),f=d.output??d.data,p=String(f?.status??``).toUpperCase();if(l===`text`&&!n.quiet&&p!==r&&(P(`${mc()} ${i} ${p||`UNKNOWN`}`),r=p),pc.has(p)){let e=Date.now()-o;if(l!==`text`||n.quiet?F(d,l):p===`SUCCEEDED`&&P(`\n✓ ${i} ${p} (elapsed ${hc(e)})`),p!==`SUCCEEDED`)throw new t(`Fine-tune job ${i} ended in status ${p} (elapsed ${hc(e)}).`,a.GENERAL);return}if(c!==void 0&&(Date.now()-o)/1e3>=c)throw new t(`Watching fine-tune job ${i} timed out after ${hc(Date.now()-o)} (last status: ${p||`UNKNOWN`}).`,a.TIMEOUT);await gc(s*1e3,u.signal)}}catch(e){if(u.signal.aborted){P(`
|
|
360
|
-
Interrupted.`);return}throw e}finally{process.off(`SIGINT`,d)}}});async function vc(e){let t=se(e),n=(n,r)=>y({region:t.consoleRegion,site:t.consoleSite,switchAgent:t.consoleSwitchAgent},e.timeout,{api:n,data:r}),r=await fe(n,{pageNo:1,pageSize:50}),i=[...r.models],a=Math.ceil(r.total/50);for(let e=2;e<=a;e++){let t=await fe(n,{pageNo:e,pageSize:50});i.push(...t.models)}return i}const yc={full:`full-parameter`,lora:`LoRA`};function bc(e){if(!De(e))return e;let{method:t,variant:n}=pt(e);return`${yc[n]??n} ${t.toUpperCase()}`}var xc=T({description:`Query fine-tune training capability — by model (which training types it supports) or by training type (which models support it)`,auth:`none`,usageArgs:`--model <m> | --training-type <t>`,flags:{model:{type:`string`,valueHint:`<m>`,description:`List training types supported by this base model.`},trainingType:{type:`string`,valueHint:`<t>`,description:`List models supporting this training type: ${f.join(` | `)}.`}},exampleArgs:[`--model qwen3-8b`,`--training-type sft-lora`,`--training-type cpt --output json`,`--training-type sft --quiet`],notes:[`Exactly one of --model / --training-type is required.`,"Training-type values use the `<method>` / `<method>-lora` convention:",`sft | sft-lora | dpo | dpo-lora | cpt. (cpt has no -lora variant server-side.)`,`Queries listFoundationModels, a public API — no console login needed.`],validate:e=>{if(e.model&&e.trainingType)return`--model and --training-type are mutually exclusive; pass one.`;if(!e.model&&!e.trainingType)return`one of --model / --training-type is required.`},async run(e){let{settings:t,flags:n}=e,r=n.model||void 0,i=n.trainingType||void 0,a=E(t.output);if(t.dryRun){F({action:`finetune.capability`,model:r,training_type:i},a);return}if(r){let e=await le(t,r);if(!e){P(`No foundation model found matching "${r}".`);return}let n=Le(e);if(t.quiet){for(let e of n)P(e);return}if(a!==`text`){F({model:e.model??r,supported:n,supports:e.supports,trainingTypes:e.trainingTypes},a);return}P(`${e.model??r}`),P(n.length?`Supported training types:`:`No supported training types.`);for(let e of n)P(` ${e.padEnd(10)} ${bc(e)}`);return}if(!i||!De(i))throw new p(`--training-type "${i}" is not supported. Valid: ${f.join(`, `)}.`);let{method:o,variant:s}=pt(i),c=(await vc(t)).filter(e=>We(e,i)).map(e=>({model:e.model,name:e.name??e.model})).filter(e=>!!e.model).sort((e,t)=>e.model.localeCompare(t.model));if(t.quiet){for(let e of c)P(e.model);return}if(a!==`text`){F({training_type:i,method:o,variant:s,count:c.length,models:c},a);return}P(`Models supporting ${i} (${o} / ${s}): ${c.length}`);for(let e of c)P(` ${e.model}`)}});const Sc={model:{type:`string`,valueHint:`<name>`,description:`Model name (catalog model or fine-tuned output) (required)`,required:!0},name:{type:`string`,valueHint:`<display_name>`,description:`Console display name for the deployment (required)`,required:!0},plan:{type:`string`,valueHint:`<plan>`,description:`Billing plan: lora (default, Token-billed) | ptu (Token-billed) | mu`},deploySpec:{type:`string`,valueHint:`<id>`,description:`Deploy spec (only used by plan=mu; auto-picked if omitted)`},capacity:{type:`number`,valueHint:`<n>`,description:`Resource units (plan=mu only; required by API; defaults to the template's unit)`},billingMethod:{type:`string`,valueHint:`<m>`,description:`Billing method (plan=mu only; default "POST_PAY", the only supported value)`},inputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max input tokens/min (required for plan=ptu)`},outputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max output tokens/min (required for plan=ptu)`},thinkingOutputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max thinking-output tokens/min (optional, some models)`}},Cc=`--model <model_name> --name <display_name> [--plan <plan>] [--deploy-spec <id>] [--capacity <n>] [--billing-method <m>] [--input-tpm <n>] [--output-tpm <n>] [--thinking-output-tpm <n>]`,wc=["Plan defaults to `lora` (Token-billed) for text/image and `mu` (model-unit-",`billed) for audio (CosyVoice TTS). Pass --plan to override.`,`For plan=ptu (Token-billed, provisioned throughput), --input-tpm and`,`--output-tpm are required (the platform rejects creation without an`,`explicit ptu_capacity despite the doc listing defaults).`,"For plan=mu, `capacity`, `billing_method` and `deploy_spec` are required.",`billing_method defaults to POST_PAY (only supported value); deploy_spec`,`and capacity are auto-picked from GET /deployments/models when omitted.`,"Use `bl deploy models --source base` to inspect available templates.",`After creation, status starts at PENDING and transitions to RUNNING.`,`Invoke the deployed model with: bl text chat --model <deployed_model>`,`WARNING: --model is overloaded across commands and refers to DIFFERENT`,"values. `bl deploy <modality> create --model` takes the exported model_name","(e.g. `qwen3-8b-ft-...`), but the create response also returns a","`deployed_model` field (the deployment instance id, e.g.","`qwen3-8b-5ecb5f068d79`). The inference call `bl text chat --model` must use","the `deployed_model` from the create response — NOT the `model_name` you","passed to `deploy <modality> create`. Do not reuse the value across the two",`commands.`];function Tc(e,t){let n=t.plan||w(e),r=d[n];return r?r.validateFlags(t):`Unsupported plan "${n}". Supported plans: ${Object.keys(d).join(`, `)}.`}async function Ec(e,t){let{identity:n,settings:r,flags:i}=t,a=i.model,o=i.name,s=i.plan||w(e),c=E(r.output),l={model_name:a,name:o,plan:s,...(await Ye(s).resolve({client:t.client,dryRun:r.dryRun,binName:n.binName,flags:i,model:a,name:o})).body};if(r.dryRun){F({action:`deploy.create`,body:l},c);return}let u=await C(t.client,l),d=u.output??u.data;r.quiet?P(d?.deployed_model??``):c===`text`?(P(`Created deployment.`),d?.deployed_model&&P(` deployed_model: ${d.deployed_model}`),d?.status&&P(` status: ${d.status}`),d?.plan&&P(` plan: ${d.plan}`),P(`\nNext: track readiness with: ${n.binName} deploy get --deployed-model ${d?.deployed_model??`<id>`}`)):F(u,c)}const Dc=T({description:`Create a text model deployment`,auth:`apiKey`,usageArgs:Cc,flags:Sc,exampleArgs:[`--model my-qwen-sft --name my-sft-test`,`--model qwen3.6-flash-2026-04-16 --name my-flash --plan ptu --input-tpm 10000 --output-tpm 1000`,`--model qwen3-8b --name my-qwen3-mu --plan mu`,`--model qwen3-8b --name my-qwen3 --plan mu --deploy-spec MU1 --capacity 2`],notes:wc,validate:e=>Tc(`text`,e),run:e=>Ec(`text`,e)}),Oc=T({description:`Create an audio (TTS) model deployment`,auth:`apiKey`,usageArgs:Cc,flags:Sc,exampleArgs:[`--model my-cosyvoice-ft --name my-tts`,`--model my-cosyvoice-ft --name my-tts --deploy-spec dps-xxxx --capacity 1`,`--model my-cosyvoice-ft --name my-tts --dry-run`],notes:wc,validate:e=>Tc(`audio`,e),run:e=>Ec(`audio`,e)}),kc=T({description:`Create an image generation model deployment`,auth:`apiKey`,usageArgs:Cc,flags:Sc,exampleArgs:[`--model my-wan-ft --name my-wan`,`--model my-wan-ft --name my-wan-mu --plan mu`,`--model my-wan-ft --name my-wan --dry-run`],notes:wc,validate:e=>Tc(`image`,e),run:e=>Ec(`image`,e)});var Ac=T({description:`List model deployments`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--status <s>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10, max 100)`},status:{type:`string`,valueHint:`<s>`,description:`Filter by status (PENDING / RUNNING / STOPPED / FAILED)`}},exampleArgs:[``,`--status RUNNING`,`--page-size 20 --output json`],async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.status||void 0;if(t.dryRun){F({action:`deploy.list`,page:n.page,page_size:n.pageSize,status:i},r);return}let a=await Fe(e.client,{pageNo:n.page,pageSize:n.pageSize,status:i}),o=a.output??a.data,s=o?.deployments??[],c=o?.total,l=s.map(e=>({deployed_model:e.deployed_model??``,model_name:e.model_name??``,status:e.status??``,plan:e.plan??``,capacity:e.capacity===void 0?``:String(e.capacity),created_at:e.gmt_create??``}));if(r===`json`){F({items:l,total:c},r);return}if(l.length===0){P(`No deployments found.`);return}let u=[`DEPLOYED_MODEL`,`MODEL_NAME`,`STATUS`,`PLAN`,`CAPACITY`,`CREATED_AT`],d=l.map(e=>[e.deployed_model,e.model_name,e.status,e.plan,e.capacity,e.created_at]);for(let e of I(u,d))P(e);c!==void 0&&P(`\nTotal: ${c}`)}}),jc=T({description:`Get details of a single model deployment`,auth:`apiKey`,usageArgs:`--deployed-model <id>`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0}},exampleArgs:[`--deployed-model qwen-plus-2025-12-01-b6d61c71`,`--deployed-model qwen-plus-2025-12-01-b6d61c71 --output json`],async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=E(t.output);if(t.dryRun){F({action:`deploy.get`,deployed_model:r},i);return}let a=await ye(e.client,r),o=a.output??a.data;if(!o){P(`No data returned for ${r}`);return}let s={deployed_model:o.deployed_model??r,deployed_name:o.name??``,model_name:o.model_name??``,base_model:o.base_model??``,status:o.status??``,plan:o.plan??``};if(o.model_unit_spec&&(s.model_unit_spec=o.model_unit_spec),o.charge_type&&(s.charge_type=o.charge_type),o.capacity!==void 0&&(s.capacity=o.capacity),o.base_capacity!==void 0&&(s.base_capacity=o.base_capacity),o.ready_capacity!==void 0&&(s.ready_capacity=o.ready_capacity),o.rpm_limit!==void 0&&(s.rpm_limit=o.rpm_limit),o.tpm_limit!==void 0&&(s.tpm_limit=o.tpm_limit),o.input_tpm!==void 0&&(s.input_tpm=o.input_tpm),o.output_tpm!==void 0&&(s.output_tpm=o.output_tpm),o.gmt_create&&(s.created_at=o.gmt_create),o.gmt_modified&&(s.updated_at=o.gmt_modified),i===`json`){F(s,i);return}let c=e=>`${e}:`.padEnd(18);for(let[e,t]of Object.entries(s)){if(t===``||t===void 0)continue;let n=typeof t==`string`?t:JSON.stringify(t);P(`${c(e)}${n}`)}}}),Mc=T({description:`List models available for deployment`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--catalog-version <v>] [--source <custom|public>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 100)`},catalogVersion:{type:`string`,valueHint:`<v>`,description:`Catalog version filter (default: v1.0; required for new catalog models)`},source:{type:`string`,valueHint:`<s>`,description:`Model source filter: custom (fine-tuned) | base (catalog) | public`}},exampleArgs:[``,`--source base`,`--source custom --page-size 50`,`--catalog-version v1.0 --output json`],async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.catalogVersion===``?void 0:n.catalogVersion??`v1.0`,a=n.source||void 0;if(t.dryRun){F({action:`deploy.models`,page:n.page,page_size:n.pageSize,version:i,model_source:a},r);return}let o=await Pe(e.client,{pageNo:n.page,pageSize:n.pageSize,version:i,modelSource:a}),s=o.output??o.data,c=s?.models??[],l=s?.total;if(r===`json`){F({items:c.map(e=>{let t={model_name:e.model_name??``};return e.base_model&&(t.base_model=e.base_model),e.model_source&&(t.model_source=e.model_source),e.supported_plans&&e.supported_plans.length>0&&(t.supported_plans=e.supported_plans),e.plans&&e.plans.length>0&&(t.plans=e.plans.map(e=>{let t={plan:e.plan??``};return e.cu_specs&&e.cu_specs.length>0&&(t.cu_specs=e.cu_specs),e.templates&&e.templates.length>0&&(t.templates=e.templates.map(e=>{let t={};e.template_id&&(t.template_id=e.template_id),e.template_name&&(t.template_name=e.template_name),e.charge_type&&(t.charge_type=e.charge_type);let n=e.roles?.unified;return n?.model_unit_spec&&(t.model_unit_spec=n.model_unit_spec),n?.capacity_unit_per_instance!==void 0&&(t.capacity_unit_per_instance=n.capacity_unit_per_instance),(e.roles?.prefill||e.roles?.decode)&&(t.roles={prefill:e.roles?.prefill,decode:e.roles?.decode}),e.template_desc&&(t.template_desc=e.template_desc),t})),t})),t}),total:l},r);return}let u=c.map(e=>{let t=``;return t=e.supported_plans&&e.supported_plans.length>0?e.supported_plans.join(`,`):e.plans&&e.plans.length>0?e.plans.map(e=>{let t=e.plan??`?`;return e.templates&&e.templates.length>0?`${t}(${e.templates.length}t)`:e.cu_specs&&e.cu_specs.length>0?`${t}(${e.cu_specs.join(`/`)})`:t}).join(`,`):`-`,{model_name:e.model_name??``,base_model:e.base_model??``,source:e.model_source??``,plans:t}});if(u.length===0){P(`No deployable models found.`);return}let d=[`MODEL_NAME`,`BASE_MODEL`,`SOURCE`,`PLANS`],f=u.map(e=>[e.model_name,e.base_model,e.source,e.plans]);for(let e of I(d,f))P(e);l!==void 0&&P(`\nTotal: ${l}`)}}),Nc=T({description:`Scale a deployment's capacity`,auth:`apiKey`,usageArgs:`--deployed-model <id> --capacity <n> [--input-tpm <n>] [--output-tpm <n>]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},capacity:{type:`number`,valueHint:`<n>`,description:`New capacity in plan units (must be a multiple of base_capacity)`},inputTpm:{type:`number`,valueHint:`<n>`,description:`PTU only — input tokens per minute`},outputTpm:{type:`number`,valueHint:`<n>`,description:`PTU only — output tokens per minute`}},exampleArgs:[`--deployed-model qwen-plus-...-b6d61c71 --capacity 8`,`--deployed-model dep-... --capacity 2`],validate:e=>e.capacity===void 0&&e.inputTpm===void 0&&e.outputTpm===void 0?`Provide at least one of --capacity / --input-tpm / --output-tpm.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=E(t.output),a={};if(n.capacity!==void 0&&(a.capacity=n.capacity),n.inputTpm!==void 0&&(a.input_tpm=n.inputTpm),n.outputTpm!==void 0&&(a.output_tpm=n.outputTpm),t.dryRun){F({action:`deploy.scale`,deployed_model:r,body:a},i);return}let o=await ct(e.client,r,a),s=o.output??o.data;t.quiet?P(r):i===`text`?P(`Scaled ${r}${s?.capacity===void 0?``:` (capacity=${s.capacity})`}.`):F(o,i)}}),Pc=T({description:`Update a deployment's rate limits (rpm_limit / tpm_limit)`,auth:`apiKey`,usageArgs:`--deployed-model <id> [--rpm-limit <n>] [--tpm-limit <n>]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},rpmLimit:{type:`number`,valueHint:`<n>`,description:`Requests per minute`},tpmLimit:{type:`number`,valueHint:`<n>`,description:`Tokens per minute`}},exampleArgs:[`--deployed-model dep-... --rpm-limit 1000`,`--deployed-model dep-... --rpm-limit 1000 --tpm-limit 200000`],notes:[`At least one of --rpm-limit / --tpm-limit must be provided.`],validate:e=>e.rpmLimit===void 0&&e.tpmLimit===void 0?`Provide at least one of --rpm-limit / --tpm-limit.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=E(t.output),a={};if(n.rpmLimit!==void 0&&(a.rpm_limit=n.rpmLimit),n.tpmLimit!==void 0&&(a.tpm_limit=n.tpmLimit),t.dryRun){F({action:`deploy.update`,deployed_model:r,body:a},i);return}let o=await ht(e.client,r,a),s=o.output??o.data;if(t.quiet)P(r);else if(i===`text`){let e=[];s?.rpm_limit!==void 0&&e.push(`rpm_limit=${s.rpm_limit}`),s?.tpm_limit!==void 0&&e.push(`tpm_limit=${s.tpm_limit}`),P(`Updated ${r}${e.length?` (${e.join(`, `)})`:``}.`)}else F(o,i)}}),Fc=T({description:`Delete a model deployment (must be STOPPED or FAILED)`,auth:`apiKey`,usageArgs:`--deployed-model <id> [--skip-precheck]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},skipPrecheck:{type:`switch`,description:`Skip the local STOPPED/FAILED status precheck`}},exampleArgs:[`--deployed-model dep-...`,`--deployed-model dep-... --dry-run`],async run(e){let{settings:n,flags:r}=e,i=r.deployedModel,o=E(n.output);if(n.dryRun){F({action:`deploy.delete`,deployed_model:i},o);return}if(!r.skipPrecheck)try{let n=await ye(e.client,i),r=((n.output??n.data)?.status??``).toUpperCase();if(r&&r!==`STOPPED`&&r!==`FAILED`)throw new t(`Deployment ${i} is ${r}. Only STOPPED / FAILED deployments can be deleted. Stop it first via the platform console, or pass --skip-precheck to attempt deletion anyway.`,a.USAGE)}catch(e){if(e instanceof t)throw e}let s=await ie(e.client,i);n.quiet?P(i):o===`text`?P(`Deleted ${i}.`):F(s,o)}});const Ic={callerUacAccountId:{type:`string`,valueHint:`<id>`,description:`Caller UAC account ID`},namespaceId:{type:`string`,valueHint:`<id>`,description:`Product namespace ID (Token Plan default: namespace-1)`}},Lc={workspaceId:{type:`string`,valueHint:`<id>`,description:`Workspace ID (env: BAILIAN_WORKSPACE_ID, config: workspace_id)`}},Rc={cn:`modelstudio.cn-beijing.aliyuncs.com`,intl:`modelstudio.ap-southeast-1.aliyuncs.com`};function zc(e){for(let[t,n]of Object.entries(l))if(e===n||e.startsWith(`${n}/`))return t;return`cn`}function Bc(e){return Rc[zc(e)]??Rc.cn}function Vc(e,n,r){let i=n.workspaceId||e.workspaceId;if(!i)throw new t(`Missing workspace ID.
|
|
361
|
-
Set via: --workspace-id flag, env: BAILIAN_WORKSPACE_ID, or config: ${r} config set workspace_id <id>`,a.USAGE);return i}function
|
|
2695
|
+
`)}var ml=w({description:`View quota change history`,auth:`console`,usageArgs:`[flags]`,flags:{page:{type:`string`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`string`,valueHint:`<n>`,description:`Page size (default: 10)`},model:{type:`string`,valueHint:`<model>`,description:`Filter by model name`}},exampleArgs:[``,`--page 2`,`--page-size 20`,`--model qwen-turbo`,`--output json`],async run(e){let{identity:n,settings:r,flags:i}=e,o=Number(i.page)||1,s=Number(i.pageSize)||10,c=i.model||void 0,l=T(r.output),u={input:{pageNo:o,pageSize:s}};if(r.dryRun){M({api:cl,data:u},l);return}let d;try{d=await e.client.console(cl,u)}catch(e){throw e instanceof t&&e.message.includes(`NotLogined`)?new t(`session expired.`,a.AUTH,`Run \`${n.binName} auth login --console\` to re-authenticate.`):e}let f=ul(d),p=f.records??[],m=f.items??p.length;if(c&&(p=p.filter(e=>e.deployedModel===c)),l===`json`){M({records:p.map(e=>({model:e.deployedModel,tokenLimit:e.usageLimit,appliedAt:dl(e.gmtCreate)})),total:c?p.length:m},l);return}if(p.length===0){process.stdout.write(`No quota change history found.
|
|
2696
|
+
`);return}pl(p,c?p.length:m)}});const hl=`zeldaEasy.bailian-telemetry.monitor.getMonitorData`;function gl(e,t){if(!e)return 0;let n=e.count_limit_period||t;return n?Math.floor(e.count_limit*60/n):0}function _l(e,t){if(!e)return 0;let n=e.usage_limit_period||t;return n?Math.floor(e.usage_limit*60/n):0}async function vl(e){let t=[],n=1;for(;;){let r=gt(await e.console(c,{input:{pageNo:n,pageSize:50,group:!1,queryQpmInfo:!0,ignoreWorkspaceServiceSite:!0,supports:{selfServiceLimitIncrease:!0}}})),i=r.list??[],a=r.total??0;if(t.push(...i),t.length>=a||i.length===0)break;n++}return t}async function yl(e,n,r){let i=Date.now(),o=i-r*60*1e3;try{let t=gt(await e.console(hl,{reqDTO:{monitorType:`Advanced`,metricFilters:[{aggMethod:`sum_pm`,metricName:`model_total_amount`},{aggMethod:`sum_pm`,metricName:`model_call_count`}],labelFilters:{resourceId:n,resourceType:`model`},startTime:o,endTime:i}})),r=t.data??t;if(!Array.isArray(r))return{rpm:0,tpm:0};let a=0,s=0;for(let e of r){if(e.aggMethod!==`sum_pm`||!e.points?.length)continue;let t=e.points[e.points.length-1].value??0;e.metricName===`model_call_count`&&(a=Math.round(t)),e.metricName===`model_total_amount`&&(s=Math.round(t))}return{rpm:a,tpm:s}}catch(e){if(e instanceof t&&e.exitCode===a.AUTH)throw e;return{rpm:-1,tpm:-1}}}function bl(e){let t=k(process.stdout),n=[`Model`,`RPM Used/Limit`,`TPM Used/Limit`,`Status`,`RPM Left`,`TPM Left`],r=e.map(e=>e.rpmQuotaLeft),i=e.map(e=>e.rpmQuotaLabel),a=e.map(e=>e.tpmQuotaLeft),o=e.map(e=>e.tpmQuotaLabel),s=Vt({headers:n,rows:e.map(e=>{let t=e.rpmUsage<0?`-`:`${e.rpmUsage}/${e.rpmLimit}`,n=e.tpmUsage<0?`-`:`${e.tpmUsage}/${e.tpmLimit}`,r=Math.max(e.rpmLimit>0?e.rpmUsage/e.rpmLimit*100:0,e.tpmLimit>0?e.tpmUsage/e.tpmLimit*100:0),i=e.rpmUsage<0?`-`:r>=100?`Rate Limited`:r>=80?`Near limit`:`Normal`;return[e.model,t,n,i,``,``]}),align:[`left`,`right`,`right`,`left`,`left`,`left`],barColumns:[{index:4,percents:r,labels:i,width:15},{index:5,percents:a,labels:o,width:15}],cellColor:(e,n,r)=>{if(n===3){if(r===`Rate Limited`)return t.red(r);if(r===`Near limit`)return t.yellow(r);if(r===`Normal`)return t.green(r)}}});for(let e of s)process.stdout.write(e+`
|
|
2697
|
+
`)}var xl=w({description:`Check current usage against rate limits`,auth:`console`,usageArgs:`[--model <model>] [flags]`,flags:{model:{type:`string`,valueHint:`<model>`,description:`Model name(s), comma-separated`},period:{type:`string`,valueHint:`<minutes>`,description:`Query usage for the last N minutes (default: 2)`}},exampleArgs:[``,`--model qwen3.6-plus`,`--period 5`,`--model qwen3.6-plus,qwen-turbo`,`--output json`],validate:e=>(Number(e.period)||2)<1?`--period must be at least 1 minute.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.model||void 0,i=Number(n.period)||2,a=T(t.output);if(t.dryRun){M({apis:[c,hl],...ce(t)},a);return}let o=await vl(e.client);if(r){let e=new Set(r.split(`,`).map(e=>e.trim()).filter(Boolean));o=o.filter(t=>e.has(t.model))}if(o=o.filter(e=>e.qpmInfo),o.length===0){process.stdout.write(`No models found.
|
|
2698
|
+
`);return}let s=await Promise.all(o.map(t=>yl(e.client,t.model,i))),l=o.map((e,t)=>{let n=e.qpmInfo,r=n[`model-default`],i=n[`user-spec`],a=gl(i,r?.count_limit_period)||gl(r),o=_l(i,r?.usage_limit_period)||_l(r),c=s[t].rpm,l=s[t].tpm,u=null,d=null;c>=0&&a>0&&(u=Math.max(0,100-c/a*100),d=u.toFixed(1)+`%`);let f=null,p=null;return l>=0&&o>0&&(f=Math.max(0,100-l/o*100),p=f.toFixed(1)+`%`),{model:e.model,rpmUsage:c,rpmLimit:a,tpmUsage:l,tpmLimit:o,rpmQuotaLeft:u,tpmQuotaLeft:f,rpmQuotaLabel:d,tpmQuotaLabel:p}});if(a===`json`){M(l,a);return}bl(l)}}),Sl=w({description:`Upload a dataset file (.jsonl or .zip) to Bailian`,auth:`apiKey`,usageArgs:`--file <path> [--purpose <name>] [--schema <chatml|dpo|cpt|tts|image>] [--no-validate] [--full-validate]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Local dataset file (.jsonl or .zip; ≤300MB text, ≤1GB image)`,required:!0},purpose:{type:`string`,valueHint:`<name>`,description:`Dataset purpose tag (default: "fine-tune"; e.g. "evaluation")`},schema:{type:`string`,valueHint:`<s>`,description:`Record schema: "chatml" (SFT), "dpo" (chosen/rejected), "cpt" (raw text), "tts" (audio), or "image" (image generation). Default auto-detects per record.`},noValidate:{type:`switch`,description:`Skip the local JSONL pre-flight check (not recommended)`},fullValidate:{type:`switch`,description:`JSON.parse every line instead of sampling (slower)`}},exampleArgs:[`--file train.jsonl`,`--file dpo.jsonl --schema dpo`,`--file cpt.jsonl --schema cpt`,`--file audio.zip --schema tts`,`--file eval.jsonl --purpose evaluation`,`--file train.jsonl --full-validate`,`--file train.jsonl --no-validate`],notes:[`Supports .jsonl (text) and .zip (audio/image archives with a data.jsonl`,`manifest). Five record schemas are recognized: chatml = {messages:[...]}`,`(SFT); dpo = {messages:[...], chosen, rejected}; cpt = {text:"..."}`,`(continual pre-training, raw text); tts = {wav_fn:"train/xxx.wav",`,`text:"..."} (audio fine-tuning); image = {img_path:"..."} (image`,`generation). With no --schema, a record carrying wav_fn is validated as`,`TTS, img_path as image, chosen/rejected as DPO, text (no messages) as CPT,`,`otherwise ChatML. Upload cap: 300MB text, 1GB image. Upload uses the`,`OpenAI-compatible /compatible-mode/v1/files endpoint so the purpose tag is`,`persisted (the DashScope-native /api/v1/files drops it).`],async run(e){let{identity:n,settings:r,flags:i}=e,c=i.file,l=i.purpose||`fine-tune`,u=Je(i.schema);if(u===`video`)throw new t(`--schema video is not supported.`,a.USAGE,`Supported schemas: chatml, dpo, cpt, tts, image.`);let d=T(r.output),f=u===`image`;if(!i.noValidate){let e=f?s:o,l=await bt(c,{fullValidate:i.fullValidate,schema:u,maxBytes:e});if(!l.valid){let e=[`Dataset validation failed for ${c}`,...l.errors.slice(0,10).map(he)];throw l.errors.length>10&&e.push(` … and ${l.errors.length-10} more error(s).`),e.push(``,`Hint: re-run \`${n.binName} dataset validate --file <path>\` for the full report,`,` or pass --no-validate to skip this check at your own risk.`),new t(e.join(`
|
|
2699
|
+
`),a.GENERAL)}if(l.warnings.length>0&&!r.quiet){process.stderr.write(`Dataset validation passed with ${l.warnings.length} warning(s):\n`);for(let e of l.warnings.slice(0,5))process.stderr.write(`${he(e)}\n`);l.warnings.length>5&&process.stderr.write(` … and ${l.warnings.length-5} more.\n`)}}if(r.dryRun){M({action:`dataset.upload`,file:c,purpose:l,max_bytes:f?s:o,validate:!i.noValidate,schema:u??`auto`},d);return}let p=await vt(e.client,{filePath:c,purpose:l});r.quiet?j(p.file_id):d===`text`?j(`Uploaded ${p.name} → file_id=${p.file_id}`):M(p,d)}}),Cl=w({description:`List uploaded dataset files`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--purpose <name>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10, max 100)`},purpose:{type:`string`,valueHint:`<name>`,description:`Filter by purpose (e.g. "fine-tune", "evaluation"). Omit to list all.`}},exampleArgs:[``,`--purpose fine-tune`,`--purpose evaluation --page-size 20`,`--output json`],async run(e){let{settings:t,flags:n}=e,r=T(t.output);if(t.dryRun){M({action:`dataset.list`,page:n.page,page_size:n.pageSize,purpose:n.purpose},r);return}let i=await Pe(e.client,{pageNo:n.page,pageSize:n.pageSize,purpose:n.purpose||void 0}),a=i.data?.files??[],o=i.data?.total,s=a.map(e=>({file_id:e.file_id??``,name:e.name??``,size:e.size===void 0?`?`:`${(e.size/1024).toFixed(1)} KB`,purpose:e.purpose??``}));if(r===`json`){M({items:s,total:o},r);return}if(s.length===0){j(`No dataset files found.`);return}let c=[`FILE_ID`,`NAME`,`SIZE`,`PURPOSE`],l=s.map(e=>[e.file_id,e.name,e.size,e.purpose]);for(let e of N(c,l))j(e);o!==void 0&&j(`\nTotal: ${o}`)}}),wl=w({description:`Get details of a single dataset file`,auth:`apiKey`,usageArgs:`--file-id <id>`,flags:{fileId:{type:`string`,valueHint:`<id>`,description:`Dataset file ID (required)`,required:!0}},exampleArgs:[`--file-id file-xxx`,`--file-id file-xxx --output json`],async run(e){let{settings:t,flags:n}=e,r=n.fileId,i=T(t.output);if(t.dryRun){M({action:`dataset.get`,file_id:r},i);return}let a=(await ye(e.client,r)).data;if(!a){j(`No data returned for ${r}`);return}let o=a.size===void 0?`?`:`${(a.size/1024).toFixed(1)} KB`,s={file_id:a.file_id??r,name:a.name??``,size:o,md5:a.md5??``,purpose:a.purpose??``,created_at:a.gmt_create??``,description:a.description??``};if(i===`json`){M(s,i);return}j(`file_id: ${s.file_id}`),j(`name: ${s.name}`),j(`size: ${s.size}`),s.md5&&j(`md5: ${s.md5}`),s.purpose&&j(`purpose: ${s.purpose}`),s.created_at&&j(`created_at: ${s.created_at}`),s.description&&j(`description: ${s.description}`)}}),Tl=w({description:`Delete a dataset file by ID`,auth:`apiKey`,usageArgs:`--file-id <id>`,flags:{fileId:{type:`string`,valueHint:`<id>`,description:`Dataset file ID (required)`,required:!0}},exampleArgs:[`--file-id file-id-xxx`,`--file-id file-id-xxx --dry-run`],async run(e){let{settings:t,flags:n}=e,r=n.fileId,i=T(t.output);if(t.dryRun){M({action:`dataset.delete`,file_id:r},i);return}let a=await ie(e.client,r);t.quiet||i===`text`?j(`Deleted ${r}.`):M(a,i)}});function El(e){let t=[];return e.stats.totalRecords!==void 0&&t.push(`records: ${e.stats.totalRecords}`),e.stats.sampledRecords!==void 0&&t.push(`sampled: ${e.stats.sampledRecords}`),e.stats.bytes!==void 0&&t.push(`bytes: ${e.stats.bytes}`),e.stats.durationMs!==void 0&&t.push(`took: ${e.stats.durationMs}ms`),t}var Dl=w({description:`Locally validate a dataset file (.jsonl or .zip) without uploading`,auth:`none`,usageArgs:`--file <path> [--full-validate] [--schema <chatml|dpo|cpt|tts|image>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Local dataset file (.jsonl or .zip)`,required:!0},fullValidate:{type:`switch`,description:`JSON.parse every line instead of sampling (slower)`},schema:{type:`string`,valueHint:`<s>`,description:`Record schema: "chatml" (SFT), "dpo" (chosen/rejected), "cpt" (raw text), "tts" (audio), or "image" (image generation). Default auto-detects per record.`}},exampleArgs:[`--file train.jsonl`,`--file dpo.jsonl --schema dpo`,`--file cpt.jsonl --schema cpt`,`--file audio.zip --schema tts`,`--file eval.jsonl --full-validate`,`--file train.jsonl --output json`],notes:[`Default scan: every line gets a structural check, then ~160 lines (front 50,`,`evenly spaced 100, last 10) are JSON.parsed against the active schema.`,`Schemas: chatml = {messages:[...]} (SFT); dpo = {messages:[...], chosen,`,`rejected}; cpt = {text:"..."} (continual pre-training, raw text);`,`tts = {wav_fn:"train/xxx.wav", text:"..."} (audio fine-tuning);`,`image = {img_path:"..."} (image generation). With no --schema, a record`,`carrying wav_fn is validated as TTS, img_path as image, chosen/rejected`,`as DPO, text (no messages) as CPT, otherwise ChatML. Pass --schema to`,`require a specific shape on every record. ZIP archives (.zip) are`,`validated structurally (data.jsonl present, media references resolve) in`,`addition to per-record content checks. Use --full-validate to JSON.parse`,`every line.`],async run(e){let{settings:n,flags:r}=e,i=r.file,o=Je(r.schema);if(o===`video`)throw new t(`--schema video is not supported.`,a.USAGE,`Supported schemas: chatml, dpo, cpt, tts, image.`);let s=T(n.output);if(n.dryRun){M({action:`dataset.validate`,file:i,full:r.fullValidate,schema:o??`auto`},s);return}let c=await bt(i,{fullValidate:r.fullValidate,schema:o});if(s===`json`)M(c,s);else if(n.quiet)j(c.valid?`ok`:`fail`);else{j(`Dataset validation ${c.valid?`PASSED`:`FAILED`} for ${c.filePath}`);let e=El(c);if(e.length&&j(` ${e.join(` · `)}`),c.errors.length){j(`Errors (${c.errors.length}):`);for(let e of c.errors.slice(0,20))j(he(e));c.errors.length>20&&j(` … and ${c.errors.length-20} more.`)}if(c.warnings.length){j(`Warnings (${c.warnings.length}):`);for(let e of c.warnings.slice(0,10))j(he(e));c.warnings.length>10&&j(` … and ${c.warnings.length-10} more.`)}}if(!c.valid)throw new t(`Dataset validation failed: ${c.errors.length} error(s).`,a.GENERAL)}});function Ol(e){return Qt(e)&&nn(e).isFile()}async function kl(e,n,r,i,o,s,c,l){let u=r.split(`,`).map(e=>e.trim()).filter(Boolean);if(u.length===0)throw new t(`--${i} must contain at least one entry.`,a.USAGE);let d=[],f=[],p,m,h=!0;for(let r of u){if(!Ol(r)){d.push(r),h=!1;continue}if(d.push(r),f.push(r),e.dryRun)continue;let i=l&&l.path===r?l.modality:s,u=await o.validate(r,i,{model:c});if(!u.valid){let e=[`Dataset validation failed for ${r}`,...u.errors.slice(0,10).map(he)];throw u.errors.length>10&&e.push(` … and ${u.errors.length-10} more error(s).`),e.push(``,`Hint: re-run \`${n} dataset validate --file <path>\` for the full report,`,` or upload manually with \`${n} dataset upload --no-validate\` and`,` pass the resulting file-id here.`),new t(e.join(`
|
|
2700
|
+
`),a.GENERAL)}if(u.warnings.length>0&&!e.quiet){process.stderr.write(`Dataset validation passed with ${u.warnings.length} warning(s) for ${r}:\n`);for(let e of u.warnings.slice(0,5))process.stderr.write(`${he(e)}\n`);u.warnings.length>5&&process.stderr.write(` … and ${u.warnings.length-5} more.\n`)}let g=u.stats.totalRecords;typeof g==`number`&&(m=(m??0)+g),p===void 0&&(p=nn(r).size)}return{fileIds:d,localPaths:f,firstSize:p,recordCount:h?m:void 0}}async function Al(e,n,r,i,o){let s=[];for(let[c,l]of r.fileIds.entries()){if(!Ol(l))continue;let u=await vt(e,{filePath:l,purpose:i});if(!u.file_id)throw new t(`Upload of ${l} succeeded but no file_id was returned.`,a.GENERAL);s.push(u),r.fileIds[c]=u.file_id,n.quiet||process.stderr.write(`Uploaded ${an(l)} → ${u.file_id} (auto from --${o})\n`)}return s}const jl={model:{type:`string`,valueHint:`<model>`,description:`Base model to fine-tune`,required:!0},datasets:{type:`string`,valueHint:`<ids|paths>`,description:`Comma-separated dataset file IDs or local paths (.jsonl for text, .zip for audio/image). Local paths are uploaded (validated) first, then their file-ids are used.`,required:!0},validations:{type:`string`,valueHint:`<ids|paths>`,description:`Comma-separated validation dataset file IDs or local paths (auto-uploaded like --datasets).`},modelName:{type:`string`,valueHint:`<name>`,description:`Output model name (after training)`},suffix:{type:`string`,valueHint:`<text>`,description:`Output suffix appended by the platform (finetuned_output_suffix)`}},Ml={...jl,trainingType:{type:`string`,valueHint:`<t>`,description:`Training type: ${f.join(` | `)} (default: ${r}). Mapping to the server happens at the interface boundary (e.g. sft-lora -> efficient_sft, dpo -> dpo_full).`},nEpochs:{type:`number`,valueHint:`<n>`,description:`Number of epochs (default: 3)`},batchSize:{type:`number`,valueHint:`<n>`,description:`Per-device batch size (clamped to [8, 1024]). Auto-set to 8 for small datasets (<100KB)`},learningRate:{type:`string`,valueHint:`<str>`,description:`Learning rate as a string to preserve precision (e.g. "1.6e-5")`},maxLength:{type:`number`,valueHint:`<n>`,description:`Max sequence length`}},Nl={...jl},Pl={...jl,generationType:{type:`string`,choices:[`t2i`,`i2i`],valueHint:`<t2i|i2i>`,description:`Generation type: t2i (default) | i2i. Sets generation_type/max_pixels. Required to train I2I from a file-id or with --dry-run (local data auto-detects input_img).`},learningRate:{type:`string`,valueHint:`<str>`,description:`Learning rate as a string to preserve precision (e.g. "3e-5")`}},Fl=[`Creating a job uploads any local datasets and consumes training quota.`,`Use --dry-run to preview the request body without submitting.`,"--datasets / --validations accept either file-ids (from `dataset upload`)",`or local paths. Local paths are validated and uploaded first, then their`,`file-ids are submitted — a one-step upload-and-train.`],Il=[...Fl,"Training-type values use the `<method>` / `<method>-lora` convention:",`sft (full) | sft-lora (LoRA) | dpo (full) | dpo-lora (LoRA) | cpt. These map`,`to the server's training_type at the interface boundary, so the rest of the`,`CLI never sees the raw server strings.`,`Before submitting (non dry-run) the job, the model's training capability is`,`checked via listFoundationModels (no console login required); an unsupported`,`training type fails fast with the list the model actually supports.`,`n_epochs defaults to 3. Other hyper-parameters are platform defaults unless set.`,`Learning rate is forwarded as a string to avoid JSON-number precision loss.`,`Pre-submit gate: if the training dataset's sample count is not greater`,`than batch_size, the job is rejected before upload or quota consumption`,`(the platform would otherwise fail ~10 min in, after data processing).`],Ll=[...Fl,`Audio TTS training runs sft-lora (efficient_sft) with fixed CosyVoice`,`hyper-parameter defaults; there are no training-type or hyper-parameter`,`knobs to set.`],Rl=[...Fl,`Image generation training runs sft-lora (efficient_sft) with fixed defaults;`,`only --learning-rate is overridable. T2I vs I2I is declared with`,`--generation-type (default t2i), which sets generation_type/max_pixels. For`,`local data the type is auto-detected (records with input_img train I2I);`,`pass --generation-type explicitly to train I2I from a file-id or in --dry-run.`];async function zl(e,n){let{identity:i,settings:o}=n,s=n.flags,c=s.model,l=s.datasets;if(e===`audio`){let e=l.split(`,`).map(e=>e.trim()).filter(Boolean);if(e.length>1)throw new t(`Audio (TTS) fine-tuning accepts exactly one training file, got ${e.length}.`,a.USAGE,`Merge your recordings into a single .zip (or pass one file-id).`)}let u=s.trainingType||r;if(!Oe(u))throw new t(`--training-type "${u}" is not supported.`,a.USAGE,`Supported values: ${f.join(`, `)} (default: ${r}).`);let d=Te(u),p=l.split(`,`).map(e=>e.trim()).find(e=>Ol(e)),m=e;if(e===`image`){let e=s.generationType;(e===`i2i`||!e&&p&&!o.dryRun&&await se(p)===`image-i2i`)&&(m=`image-i2i`)}let h=await kl(o,i.binName,l,`datasets`,d,m,c,p?{path:p,modality:m}:void 0),g=h.fileIds,_=s.validations?await kl(o,i.binName,s.validations,`validations`,d,m,c):void 0,v=_?.fileIds,y=s.modelName,b=s.suffix,x=d.resolveHyperParameters(m,s);if(s.batchSize!==void 0&&x.batch_size!==void 0&&!o.quiet&&!d.shouldSkipGate(`batch_size`,m)){let e=s.batchSize;x.batch_size!==e&&process.stderr.write(`warning: --batch-size ${e} clamped to ${x.batch_size} (server range [8, 1024] for the common training types).\n`)}if(s.batchSize!==void 0&&!o.quiet&&d.shouldSkipGate(`batch_size`,m)){let e=s.batchSize;x.batch_size!==void 0&&x.batch_size!==e&&process.stderr.write(`warning: --batch-size ${e} ignored for ${m} training (model uses a fixed batch_size of ${x.batch_size}).\n`)}if(m===`text`&&x.batch_size===void 0&&!o.dryRun){let e=h.firstSize??0;if(e===0)try{e=(await ye(n.client,g[0])).data?.size??0}catch{}e>0&&e<100*1024&&(x.batch_size=8)}if(!o.dryRun&&h.recordCount!==void 0&&!d.shouldSkipGate(`batch_size`,m)){let e=x.batch_size??16,n=Ze({recordCount:h.recordCount,batchSize:e});if(!n.ok&&n.issue)throw new t(n.issue.message,a.GENERAL,n.hint)}if(!o.dryRun&&!d.shouldSkipCapabilityCheck(m)){let e;try{e=await ue(o,c)}catch(e){o.quiet||process.stderr.write(`warning: model capability lookup failed (${e.message}); proceeding without local pre-flight.
|
|
2701
|
+
`)}if(e&&!Re(e).includes(u)){let n=Re(e);throw new t(`Model "${c}" does not support training type "${u}".`,a.USAGE,n.length?`This model supports: ${n.join(`, `)}.`:`This model reports no supported training types.`)}}o.dryRun||(await Al(n.client,o,h,`fine-tune`,`datasets`),_&&await Al(n.client,o,_,`fine-tune`,`validations`));let S={model:c,training_file_ids:g,training_type:d.serverTrainingType,hyper_parameters:x};v&&v.length>0&&(S.validation_file_ids=v),y&&(S.model_name=y),b&&(S.finetuned_output_suffix=b);let C=T(o.output);if(o.dryRun){let e=[...h.localPaths.map(e=>({field:`datasets`,path:e})),...(_?.localPaths??[]).map(e=>({field:`validations`,path:e}))];M(e.length>0?{action:`finetune.create`,body:S,pending_uploads:e}:{action:`finetune.create`,body:S},C);return}let te=await ee(n.client,S),ne=te.output??te.data;o.quiet?ne?.job_id&&j(ne.job_id):C===`text`&&ne?.job_id?(j(`Created fine-tune job: ${ne.job_id}`),ne.status&&j(`Status: ${ne.status}`)):M(te,C)}const Bl=w({description:`Create a text model fine-tune job (sft | sft-lora | dpo | dpo-lora | cpt)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path,...> [--validations <id|path,...>] [--model-name <name>] [--suffix <text>] [--n-epochs <n>] [--batch-size <n>] [--learning-rate <str>] [--max-length <n>] [--training-type <sft|sft-lora|dpo|dpo-lora|cpt>]`,flags:Ml,exampleArgs:[`--model qwen3-8b --datasets file-xxx`,`--model qwen3-8b --datasets ./train.jsonl`,`--model qwen3-8b --datasets ./train.jsonl --validations ./eval.jsonl`,`--model qwen3-8b --datasets file-aaa,./extra.jsonl`,`--model qwen3-8b --datasets ./train.jsonl --training-type sft`,`--model qwen3-8b --datasets file-xxx --learning-rate "1.6e-5" --n-epochs 4`,`--model qwen3-8b --datasets file-xxx --output json`,`--model qwen3-8b --datasets file-xxx --dry-run`],notes:Il,run:e=>zl(`text`,e)}),Vl=w({description:`Create an audio TTS model fine-tune job (sft-lora)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path> [--validations <id|path>] [--model-name <name>] [--suffix <text>]`,flags:Nl,exampleArgs:[`--model cosyvoice-v3-flash --datasets ./audio.zip`,`--model cosyvoice-v3-flash --datasets file-xxx`,`--model cosyvoice-v3-flash --datasets ./audio.zip --model-name my-tts`,`--model cosyvoice-v3-flash --datasets file-xxx --output json`,`--model cosyvoice-v3-flash --datasets ./audio.zip --dry-run`],notes:Ll,run:e=>zl(`audio`,e)}),Hl=w({description:`Create an image generation model fine-tune job (sft-lora)`,auth:`apiKey`,usageArgs:`--model <model> --datasets <id|path> [--validations <id|path>] [--model-name <name>] [--suffix <text>] [--generation-type <t2i|i2i>] [--learning-rate <str>]`,flags:Pl,exampleArgs:[`--model wan2.7-image-pro --datasets ./images.zip`,`--model wan2.7-image-pro --datasets file-xxx`,`--model wan2.7-image-pro --datasets file-xxx --generation-type i2i`,`--model wan2.7-image-pro --datasets ./images.zip --model-name my-wan`,`--model wan2.7-image-pro --datasets file-xxx --output json`,`--model wan2.7-image-pro --datasets ./images.zip --dry-run`],notes:Rl,run:e=>zl(`image`,e)});var Ul=w({description:`List fine-tune jobs`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--status <s>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10, max 100)`},status:{type:`string`,valueHint:`<s>`,description:`Filter by status (PENDING / RUNNING / SUCCEEDED / FAILED / CANCELED)`}},exampleArgs:[``,`--status RUNNING`,`--page-size 20 --output json`],async run(e){let{identity:t,settings:n,flags:r}=e,i=T(n.output),a=r.page,o=r.pageSize,s=r.status||void 0;if(n.dryRun){M({action:`finetune.list`,page:a,page_size:o,status:s},i);return}let c=await Le(e.client,{pageNo:a,pageSize:o,status:s}),l=c.output??c.data,u=l?.jobs??[],d=l?.total,f=u.map(e=>({job_id:e.job_id??``,base_model:e.model??``,status:e.status??``,training_type:e.training_type??``,output_model:e.finetuned_output??``,created_at:e.create_time??e.gmt_create??``}));if(i===`json`){M({items:f,total:d},i);return}if(f.length===0){j(`No fine-tune jobs found.`);return}let p=[`JOB_ID`,`BASE_MODEL`,`STATUS`,`TRAINING_TYPE`,`OUTPUT_MODEL`,`CREATED_AT`],m=f.map(e=>[e.job_id,e.base_model,e.status,e.training_type,e.output_model,e.created_at]);for(let e of N(p,m))j(e);d!==void 0&&j(`\nTotal: ${d}`),j(`Tip: OUTPUT_MODEL is the input for \`${t.binName} deploy text create --model\``)}}),Wl=w({description:`Get details of a single fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --output json`],async run(e){let{identity:t,settings:n,flags:r}=e,i=r.jobId,a=T(n.output);if(n.dryRun){M({action:`finetune.get`,job_id:i},a);return}let o=await xe(e.client,i),s=o.output??o.data;if(!s){j(`No data returned for ${i}`);return}let c=s.hyper_parameters,l=[];c?.n_epochs!==void 0&&l.push(`n_epochs=${c.n_epochs}`),c?.batch_size!==void 0&&l.push(`batch_size=${c.batch_size}`),c?.learning_rate!==void 0&&l.push(`learning_rate=${c.learning_rate}`),c?.max_length!==void 0&&l.push(`max_length=${c.max_length}`);let u={job_id:s.job_id??i,base_model:s.model??``,status:s.status??``,training_type:s.training_type??``,training_files:s.training_file_ids??[],validation_files:s.validation_file_ids??[],hyper_params:l.length?l.join(` · `):``,output_model:s.finetuned_output??``,model_name:s.model_name??``,created_at:s.create_time??s.gmt_create??``,updated_at:s.end_time??s.gmt_modified??``};if(a===`json`){M(u,a);return}j(`job_id: ${u.job_id}`),u.base_model&&j(`base_model: ${u.base_model}`),u.status&&j(`status: ${u.status}`),u.training_type&&j(`training_type: ${u.training_type}`),u.training_files.length&&j(`training_files: ${u.training_files.join(`, `)}`),u.validation_files.length&&j(`validation_files: ${u.validation_files.join(`, `)}`),u.hyper_params&&j(`hyper_params: ${u.hyper_params}`),u.output_model&&j(`output_model: ${u.output_model} (→ ${t.binName} deploy text create --model)`),u.model_name&&j(`model_name: ${u.model_name}`),u.created_at&&j(`created_at: ${u.created_at}`),u.updated_at&&j(`updated_at: ${u.updated_at}`)}}),Gl=w({description:`Cancel a running fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --dry-run`],notes:[`Only PENDING / RUNNING jobs can be cancelled. Completed / failed / already-`,`cancelled jobs return a server-side error (passed through verbatim).`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=T(t.output);if(t.dryRun){M({action:`finetune.cancel`,job_id:r},i);return}let a=await b(e.client,r),o=a.output??a.data;t.quiet?j(r):i===`text`?j(`Cancelled ${r}${o?.status?` (status=${o.status})`:``}.`):M(a,i)}}),Kl=w({description:`Delete a fine-tune job record`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --dry-run`],notes:["Cancel a RUNNING job first via `finetune cancel` — the platform refuses",`to delete jobs that are still in flight.`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=T(t.output);if(t.dryRun){M({action:`finetune.delete`,job_id:r},i);return}let a=await oe(e.client,r);t.quiet?j(r):i===`text`?j(`Deleted ${r}.`):M(a,i)}});function ql(e){if(typeof e==`string`)return e;let t=e,n=t.timestamp??t.time??t.create_time??``,r=t.level??``,i=t.message??t.msg??t.log??``;return i||n||r?[n,r,i].filter(Boolean).join(` `):JSON.stringify(e)}function Jl(e,t){return ql(e).toLowerCase().includes(t)}async function Yl(e,t,n){let r=[],i=1,a=0;for(let o=0;o<200;o++){let o=await Se(e,t,{pageNo:i,pageSize:n}),s=o.output??o.data,c=s?.logs??[];if(a=s?.total??a,c.length===0||(r.push(...c),a&&r.length>=a)||c.length<n)break;i++}return{entries:r,total:a}}var Xl=w({description:`Fetch training logs for a fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id> [--page <n>] [--page-size <n>] [--search <keyword>] [--tail <n>]`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Lines per page (default: server-defined)`},search:{type:`string`,valueHint:`<keyword>`,description:`Case-insensitive substring filter. When set, all log pages are fetched and filtered client-side (--page is ignored).`},tail:{type:`number`,valueHint:`<n>`,description:`Keep only the last N entries. When set, all log pages are fetched and the trailing N are kept (--page is ignored).`}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --page-size 100 --output json`,`--job-id ft-xxx --search checkpoint`,`--job-id ft-xxx --search error --output json`,`--job-id ft-xxx --tail 20`,`--job-id ft-xxx --search checkpoint --tail 5`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=n.page,a=n.pageSize,o=n.search||void 0,s=n.tail,c=T(t.output);if(t.dryRun){M({action:`finetune.logs`,job_id:r,page:i,page_size:a,search:o,tail:s},c);return}if(o||s!==void 0){let{entries:n,total:i}=await Yl(e.client,r,a??100),l=n,u;if(o){let e=o.toLowerCase();l=n.filter(t=>Jl(t,e)),u=l.length}let d=s!==void 0&&s>=0?Math.min(s,l.length):void 0,f=d===void 0?l:l.slice(l.length-d);if(t.quiet||c===`text`){if(f.length===0){j(o?`No logs matched "${o}".`:`No logs returned.`);return}for(let e of f)j(ql(e));let e=[`${f.length} shown`];u!==void 0&&e.push(`matched ${u}`),e.push(`of ${n.length}`+(i?` (total ${i})`:``)),j(`\n${e.join(`, `)}`);return}M({...u===void 0?{}:{matched:u},scanned:n.length,total:i||n.length,...o?{search:o}:{},...d===void 0?{}:{tail:d},logs:f},c);return}let l=await Se(e.client,r,{pageNo:i,pageSize:a}),u=l.output??l.data,d=u?.logs??[];if(t.quiet||c===`text`){if(d.length===0){j(`No logs returned.`);return}for(let e of d)j(ql(e));u?.total!==void 0&&j(`\nTotal: ${u.total}`)}else M(l,c)}}),Zl=w({description:`List checkpoints produced by a fine-tune job`,auth:`apiKey`,usageArgs:`--job-id <id>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx`,`--job-id ft-xxx --output json`],notes:["Use the returned `checkpoint` value with `finetune export` to publish",`a deployable model.`],async run(e){let{settings:t,flags:n}=e,r=n.jobId,i=T(t.output);if(t.dryRun){M({action:`finetune.checkpoints`,job_id:r},i);return}let a=await Ne(e.client,r),o=a.output??a.data,s=Array.isArray(o)?o:o?.checkpoints??[],c=Array.isArray(o)?o.length:o?.total??s.length,l=s.map(e=>({checkpoint:e.checkpoint??e.checkpoint_id??``,step:e.step===void 0?``:String(e.step),status:e.status??``}));if(i===`json`){M({items:l,total:c},i);return}if(l.length===0){j(`No checkpoints found.`);return}let u=[`CHECKPOINT`,`STEP`,`STATUS`],d=l.map(e=>[e.checkpoint,e.step,e.status]);for(let e of N(u,d))j(e);j(`\nTotal: ${c}`)}}),Ql=w({description:`Publish a checkpoint as a deployable model`,auth:`apiKey`,usageArgs:`--job-id <id> --checkpoint <name> --model-name <name>`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},checkpoint:{type:`string`,valueHint:`<name>`,description:"Checkpoint identifier from `finetune checkpoints` (required)",required:!0},modelName:{type:`string`,valueHint:`<name>`,description:`Deployable model name (required)`,required:!0}},exampleArgs:[`--job-id ft-xxx --checkpoint ckpt-3 --model-name my-qwen-sft`],notes:["Required before `deploy <modality> create` can target a checkpoint. The",`platform may auto-export the best checkpoint when a job reaches SUCCEEDED —`,`explicit export is the canonical path for non-best checkpoints.`],async run(e){let{identity:t,settings:n,flags:r}=e,i=r.jobId,a=r.checkpoint,o=r.modelName,s=T(n.output);if(n.dryRun){M({action:`finetune.export`,job_id:i,checkpoint:a,model_name:o},s);return}let c=await le(e.client,i,a,o),l=(c.output??c.data)?.model_name??o;n.quiet?j(l):s===`text`?(j(`Exported ${i} / ${a} → model_name=${l}`),j(`Next: ${t.binName} deploy text create --model ${l} --name <display-name>`)):M(c,s)}});const $l=new Set([`SUCCEEDED`,`FAILED`,`CANCELED`]);function eu(){let e=new Date,t=e=>String(e).padStart(2,`0`);return`${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`}function tu(e){let t=Math.floor(e/1e3),n=Math.floor(t/60),r=t%60;return n===0?`${r}s`:`${n}m ${r}s`}function nu(e,t){return new Promise((n,r)=>{if(t.aborted){r(Error(`aborted`));return}let i=()=>{clearTimeout(a),r(Error(`aborted`))},a=setTimeout(()=>{t.removeEventListener(`abort`,i),n()},e);t.addEventListener(`abort`,i,{once:!0})})}var ru=w({description:`Probe a fine-tune job's status (default: single non-blocking fetch). Pass --follow to poll until terminal.`,auth:`apiKey`,usageArgs:`--job-id <id> [--follow] [--interval <sec>] [--poll-timeout <sec>]`,flags:{jobId:{type:`string`,valueHint:`<id>`,description:`Fine-tune job ID (required)`,required:!0},follow:{type:`switch`,description:`Block and poll until a terminal state (the legacy behavior). Without it, a single status probe is performed and the command returns immediately.`},interval:{type:`number`,valueHint:`<sec>`,description:`Seconds between polls with --follow (default: 10, min: 1). Ignored without --follow.`},pollTimeout:{type:`number`,valueHint:`<sec>`,description:`With --follow, stop polling after this many seconds (default: no limit). Ignored without --follow.`}},exampleArgs:[`--job-id ft-xxx # single probe, returns immediately`,`--job-id ft-xxx --output json # status probe for agents`,`--job-id ft-xxx --follow # block until terminal`,`--job-id ft-xxx --follow --interval 5`,`--job-id ft-xxx --follow --poll-timeout 3600`],notes:[`Default (no --follow) is a NON-BLOCKING single status probe: one fetch, then`,`return immediately. This is the mode meant for agents / scripts — the caller`,`owns the polling cadence, so the CLI never holds the terminal.`,`A terminal FAILED/CANCELED status raises a normal CLI error (non-zero exit);`,`a SUCCEEDED or still-running status returns 0. With --follow, exceeding`,`--poll-timeout raises a timeout error.`,`Use --follow for the blocking, human-terminal-follow experience; use the`,`default mode when driving the loop yourself (e.g. from an agent).`,"For per-step training output (not status), use `finetune logs`."],async run(e){let{settings:n,flags:r}=e,i=r.jobId,o=r.follow,s=Math.max(1,r.interval??10),c=r.pollTimeout,l=T(n.output);if(n.dryRun){M({action:`finetune.watch`,job_id:i,follow:o,interval:s,timeout:c},l);return}if(!o){let r=await xe(e.client,i),o=r.output??r.data,s=String(o?.status??``).toUpperCase(),c=$l.has(s);if(n.quiet?j(s||`UNKNOWN`):l===`text`?(j(`${eu()} ${i} ${s||`UNKNOWN`}`),s===`SUCCEEDED`&&j(`✓ ${i} ${s}`)):M({job_id:i,status:s||`UNKNOWN`,terminal:c},l),c&&s!==`SUCCEEDED`)throw new t(`Fine-tune job ${i} ended in status ${s}.`,a.GENERAL);return}let u=new AbortController,d=()=>u.abort();process.on(`SIGINT`,d);try{let r=``,o=Date.now();for(;;){let d=await xe(e.client,i,u.signal),f=d.output??d.data,p=String(f?.status??``).toUpperCase();if(l===`text`&&!n.quiet&&p!==r&&(j(`${eu()} ${i} ${p||`UNKNOWN`}`),r=p),$l.has(p)){let e=Date.now()-o;if(l!==`text`||n.quiet?M(d,l):p===`SUCCEEDED`&&j(`\n✓ ${i} ${p} (elapsed ${tu(e)})`),p!==`SUCCEEDED`)throw new t(`Fine-tune job ${i} ended in status ${p} (elapsed ${tu(e)}).`,a.GENERAL);return}if(c!==void 0&&(Date.now()-o)/1e3>=c)throw new t(`Watching fine-tune job ${i} timed out after ${tu(Date.now()-o)} (last status: ${p||`UNKNOWN`}).`,a.TIMEOUT);await nu(s*1e3,u.signal)}}catch(e){if(u.signal.aborted){j(`
|
|
2702
|
+
Interrupted.`);return}throw e}finally{process.off(`SIGINT`,d)}}});async function iu(e){let t=ce(e),n=(n,r)=>y({region:t.consoleRegion,site:t.consoleSite,switchAgent:t.consoleSwitchAgent},e.timeout,{api:n,data:r}),r=await pe(n,{pageNo:1,pageSize:50}),i=[...r.models],a=Math.ceil(r.total/50);for(let e=2;e<=a;e++){let t=await pe(n,{pageNo:e,pageSize:50});i.push(...t.models)}return i}const au={full:`full-parameter`,lora:`LoRA`};function ou(e){if(!Oe(e))return e;let{method:t,variant:n}=ht(e);return`${au[n]??n} ${t.toUpperCase()}`}var su=w({description:`Query fine-tune training capability — by model (which training types it supports) or by training type (which models support it)`,auth:`none`,usageArgs:`--model <m> | --training-type <t>`,flags:{model:{type:`string`,valueHint:`<m>`,description:`List training types supported by this base model.`},trainingType:{type:`string`,valueHint:`<t>`,description:`List models supporting this training type: ${f.join(` | `)}.`}},exampleArgs:[`--model qwen3-8b`,`--training-type sft-lora`,`--training-type cpt --output json`,`--training-type sft --quiet`],notes:[`Exactly one of --model / --training-type is required.`,"Training-type values use the `<method>` / `<method>-lora` convention:",`sft | sft-lora | dpo | dpo-lora | cpt. (cpt has no -lora variant server-side.)`,`Queries listFoundationModels, a public API — no console login needed.`],validate:e=>{if(e.model&&e.trainingType)return`--model and --training-type are mutually exclusive; pass one.`;if(!e.model&&!e.trainingType)return`one of --model / --training-type is required.`},async run(e){let{settings:t,flags:n}=e,r=n.model||void 0,i=n.trainingType||void 0,a=T(t.output);if(t.dryRun){M({action:`finetune.capability`,model:r,training_type:i},a);return}if(r){let e=await ue(t,r);if(!e){j(`No foundation model found matching "${r}".`);return}let n=Re(e);if(t.quiet){for(let e of n)j(e);return}if(a!==`text`){M({model:e.model??r,supported:n,supports:e.supports,trainingTypes:e.trainingTypes},a);return}j(`${e.model??r}`),j(n.length?`Supported training types:`:`No supported training types.`);for(let e of n)j(` ${e.padEnd(10)} ${ou(e)}`);return}if(!i||!Oe(i))throw new p(`--training-type "${i}" is not supported. Valid: ${f.join(`, `)}.`);let{method:o,variant:s}=ht(i),c=(await iu(t)).filter(e=>Ge(e,i)).map(e=>({model:e.model,name:e.name??e.model})).filter(e=>!!e.model).sort((e,t)=>e.model.localeCompare(t.model));if(t.quiet){for(let e of c)j(e.model);return}if(a!==`text`){M({training_type:i,method:o,variant:s,count:c.length,models:c},a);return}j(`Models supporting ${i} (${o} / ${s}): ${c.length}`);for(let e of c)j(` ${e.model}`)}});const cu={model:{type:`string`,valueHint:`<name>`,description:`Model name (catalog model or fine-tuned output) (required)`,required:!0},name:{type:`string`,valueHint:`<display_name>`,description:`Console display name for the deployment (required)`,required:!0},plan:{type:`string`,valueHint:`<plan>`,description:`Billing plan: lora (default, Token-billed) | ptu (Token-billed) | mu`},deploySpec:{type:`string`,valueHint:`<id>`,description:`Deploy spec (only used by plan=mu; auto-picked if omitted)`},capacity:{type:`number`,valueHint:`<n>`,description:`Resource units (plan=mu only; required by API; defaults to the template's unit)`},billingMethod:{type:`string`,valueHint:`<m>`,description:`Billing method (plan=mu only; default "POST_PAY", the only supported value)`},inputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max input tokens/min (required for plan=ptu)`},outputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max output tokens/min (required for plan=ptu)`},thinkingOutputTpm:{type:`number`,valueHint:`<n>`,description:`PTU max thinking-output tokens/min (optional, some models)`}},lu=`--model <model_name> --name <display_name> [--plan <plan>] [--deploy-spec <id>] [--capacity <n>] [--billing-method <m>] [--input-tpm <n>] [--output-tpm <n>] [--thinking-output-tpm <n>]`,uu=["Plan defaults to `lora` (Token-billed) for text/image and `mu` (model-unit-",`billed) for audio (CosyVoice TTS). Pass --plan to override.`,`For plan=ptu (Token-billed, provisioned throughput), --input-tpm and`,`--output-tpm are required (the platform rejects creation without an`,`explicit ptu_capacity despite the doc listing defaults).`,"For plan=mu, `capacity`, `billing_method` and `deploy_spec` are required.",`billing_method defaults to POST_PAY (only supported value); deploy_spec`,`and capacity are auto-picked from GET /deployments/models when omitted.`,"Use `bl deploy models --source base` to inspect available templates.",`After creation, status starts at PENDING and transitions to RUNNING.`,`Invoke the deployed model with: bl text chat --model <deployed_model>`,`WARNING: --model is overloaded across commands and refers to DIFFERENT`,"values. `bl deploy <modality> create --model` takes the exported model_name","(e.g. `qwen3-8b-ft-...`), but the create response also returns a","`deployed_model` field (the deployment instance id, e.g.","`qwen3-8b-5ecb5f068d79`). The inference call `bl text chat --model` must use","the `deployed_model` from the create response — NOT the `model_name` you","passed to `deploy <modality> create`. Do not reuse the value across the two",`commands.`];function du(e,t){let n=t.plan||ne(e),r=d[n];return r?r.validateFlags(t):`Unsupported plan "${n}". Supported plans: ${Object.keys(d).join(`, `)}.`}async function fu(e,t){let{identity:n,settings:r,flags:i}=t,a=i.model,o=i.name,s=i.plan||ne(e),c=T(r.output),l={model_name:a,name:o,plan:s,...(await Xe(s).resolve({client:t.client,dryRun:r.dryRun,binName:n.binName,flags:i,model:a,name:o})).body};if(r.dryRun){M({action:`deploy.create`,body:l},c);return}let u=await C(t.client,l),d=u.output??u.data;r.quiet?j(d?.deployed_model??``):c===`text`?(j(`Created deployment.`),d?.deployed_model&&j(` deployed_model: ${d.deployed_model}`),d?.status&&j(` status: ${d.status}`),d?.plan&&j(` plan: ${d.plan}`),j(`\nNext: track readiness with: ${n.binName} deploy get --deployed-model ${d?.deployed_model??`<id>`}`)):M(u,c)}const pu=w({description:`Create a text model deployment`,auth:`apiKey`,usageArgs:lu,flags:cu,exampleArgs:[`--model my-qwen-sft --name my-sft-test`,`--model qwen3.6-flash-2026-04-16 --name my-flash --plan ptu --input-tpm 10000 --output-tpm 1000`,`--model qwen3-8b --name my-qwen3-mu --plan mu`,`--model qwen3-8b --name my-qwen3 --plan mu --deploy-spec MU1 --capacity 2`],notes:uu,validate:e=>du(`text`,e),run:e=>fu(`text`,e)}),mu=w({description:`Create an audio (TTS) model deployment`,auth:`apiKey`,usageArgs:lu,flags:cu,exampleArgs:[`--model my-cosyvoice-ft --name my-tts`,`--model my-cosyvoice-ft --name my-tts --deploy-spec dps-xxxx --capacity 1`,`--model my-cosyvoice-ft --name my-tts --dry-run`],notes:uu,validate:e=>du(`audio`,e),run:e=>fu(`audio`,e)}),hu=w({description:`Create an image generation model deployment`,auth:`apiKey`,usageArgs:lu,flags:cu,exampleArgs:[`--model my-wan-ft --name my-wan`,`--model my-wan-ft --name my-wan-mu --plan mu`,`--model my-wan-ft --name my-wan --dry-run`],notes:uu,validate:e=>du(`image`,e),run:e=>fu(`image`,e)});var gu=w({description:`List model deployments`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--status <s>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 10, max 100)`},status:{type:`string`,valueHint:`<s>`,description:`Filter by status (PENDING / RUNNING / STOPPED / FAILED)`}},exampleArgs:[``,`--status RUNNING`,`--page-size 20 --output json`],async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.status||void 0;if(t.dryRun){M({action:`deploy.list`,page:n.page,page_size:n.pageSize,status:i},r);return}let a=await Ie(e.client,{pageNo:n.page,pageSize:n.pageSize,status:i}),o=a.output??a.data,s=o?.deployments??[],c=o?.total,l=s.map(e=>({deployed_model:e.deployed_model??``,model_name:e.model_name??``,status:e.status??``,plan:e.plan??``,capacity:e.capacity===void 0?``:String(e.capacity),created_at:e.gmt_create??``}));if(r===`json`){M({items:l,total:c},r);return}if(l.length===0){j(`No deployments found.`);return}let u=[`DEPLOYED_MODEL`,`MODEL_NAME`,`STATUS`,`PLAN`,`CAPACITY`,`CREATED_AT`],d=l.map(e=>[e.deployed_model,e.model_name,e.status,e.plan,e.capacity,e.created_at]);for(let e of N(u,d))j(e);c!==void 0&&j(`\nTotal: ${c}`)}}),_u=w({description:`Get details of a single model deployment`,auth:`apiKey`,usageArgs:`--deployed-model <id>`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0}},exampleArgs:[`--deployed-model qwen-plus-2025-12-01-b6d61c71`,`--deployed-model qwen-plus-2025-12-01-b6d61c71 --output json`],async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=T(t.output);if(t.dryRun){M({action:`deploy.get`,deployed_model:r},i);return}let a=await be(e.client,r),o=a.output??a.data;if(!o){j(`No data returned for ${r}`);return}let s={deployed_model:o.deployed_model??r,deployed_name:o.name??``,model_name:o.model_name??``,base_model:o.base_model??``,status:o.status??``,plan:o.plan??``};if(o.model_unit_spec&&(s.model_unit_spec=o.model_unit_spec),o.charge_type&&(s.charge_type=o.charge_type),o.capacity!==void 0&&(s.capacity=o.capacity),o.base_capacity!==void 0&&(s.base_capacity=o.base_capacity),o.ready_capacity!==void 0&&(s.ready_capacity=o.ready_capacity),o.rpm_limit!==void 0&&(s.rpm_limit=o.rpm_limit),o.tpm_limit!==void 0&&(s.tpm_limit=o.tpm_limit),o.input_tpm!==void 0&&(s.input_tpm=o.input_tpm),o.output_tpm!==void 0&&(s.output_tpm=o.output_tpm),o.gmt_create&&(s.created_at=o.gmt_create),o.gmt_modified&&(s.updated_at=o.gmt_modified),i===`json`){M(s,i);return}let c=e=>`${e}:`.padEnd(18);for(let[e,t]of Object.entries(s)){if(t===``||t===void 0)continue;let n=typeof t==`string`?t:JSON.stringify(t);j(`${c(e)}${n}`)}}}),vu=w({description:`List models available for deployment`,auth:`apiKey`,usageArgs:`[--page <n>] [--page-size <n>] [--catalog-version <v>] [--source <custom|public>]`,flags:{page:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Results per page (default: 100)`},catalogVersion:{type:`string`,valueHint:`<v>`,description:`Catalog version filter (default: v1.0; required for new catalog models)`},source:{type:`string`,valueHint:`<s>`,description:`Model source filter: custom (fine-tuned) | base (catalog) | public`}},exampleArgs:[``,`--source base`,`--source custom --page-size 50`,`--catalog-version v1.0 --output json`],async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.catalogVersion===``?void 0:n.catalogVersion??`v1.0`,a=n.source||void 0;if(t.dryRun){M({action:`deploy.models`,page:n.page,page_size:n.pageSize,version:i,model_source:a},r);return}let o=await Fe(e.client,{pageNo:n.page,pageSize:n.pageSize,version:i,modelSource:a}),s=o.output??o.data,c=s?.models??[],l=s?.total;if(r===`json`){M({items:c.map(e=>{let t={model_name:e.model_name??``};return e.base_model&&(t.base_model=e.base_model),e.model_source&&(t.model_source=e.model_source),e.supported_plans&&e.supported_plans.length>0&&(t.supported_plans=e.supported_plans),e.plans&&e.plans.length>0&&(t.plans=e.plans.map(e=>{let t={plan:e.plan??``};return e.cu_specs&&e.cu_specs.length>0&&(t.cu_specs=e.cu_specs),e.templates&&e.templates.length>0&&(t.templates=e.templates.map(e=>{let t={};e.template_id&&(t.template_id=e.template_id),e.template_name&&(t.template_name=e.template_name),e.charge_type&&(t.charge_type=e.charge_type);let n=e.roles?.unified;return n?.model_unit_spec&&(t.model_unit_spec=n.model_unit_spec),n?.capacity_unit_per_instance!==void 0&&(t.capacity_unit_per_instance=n.capacity_unit_per_instance),(e.roles?.prefill||e.roles?.decode)&&(t.roles={prefill:e.roles?.prefill,decode:e.roles?.decode}),e.template_desc&&(t.template_desc=e.template_desc),t})),t})),t}),total:l},r);return}let u=c.map(e=>{let t=``;return t=e.supported_plans&&e.supported_plans.length>0?e.supported_plans.join(`,`):e.plans&&e.plans.length>0?e.plans.map(e=>{let t=e.plan??`?`;return e.templates&&e.templates.length>0?`${t}(${e.templates.length}t)`:e.cu_specs&&e.cu_specs.length>0?`${t}(${e.cu_specs.join(`/`)})`:t}).join(`,`):`-`,{model_name:e.model_name??``,base_model:e.base_model??``,source:e.model_source??``,plans:t}});if(u.length===0){j(`No deployable models found.`);return}let d=[`MODEL_NAME`,`BASE_MODEL`,`SOURCE`,`PLANS`],f=u.map(e=>[e.model_name,e.base_model,e.source,e.plans]);for(let e of N(d,f))j(e);l!==void 0&&j(`\nTotal: ${l}`)}}),yu=w({description:`Scale a deployment's capacity`,auth:`apiKey`,usageArgs:`--deployed-model <id> --capacity <n> [--input-tpm <n>] [--output-tpm <n>]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},capacity:{type:`number`,valueHint:`<n>`,description:`New capacity in plan units (must be a multiple of base_capacity)`},inputTpm:{type:`number`,valueHint:`<n>`,description:`PTU only — input tokens per minute`},outputTpm:{type:`number`,valueHint:`<n>`,description:`PTU only — output tokens per minute`}},exampleArgs:[`--deployed-model qwen-plus-...-b6d61c71 --capacity 8`,`--deployed-model dep-... --capacity 2`],validate:e=>e.capacity===void 0&&e.inputTpm===void 0&&e.outputTpm===void 0?`Provide at least one of --capacity / --input-tpm / --output-tpm.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=T(t.output),a={};if(n.capacity!==void 0&&(a.capacity=n.capacity),n.inputTpm!==void 0&&(a.input_tpm=n.inputTpm),n.outputTpm!==void 0&&(a.output_tpm=n.outputTpm),t.dryRun){M({action:`deploy.scale`,deployed_model:r,body:a},i);return}let o=await ut(e.client,r,a),s=o.output??o.data;t.quiet?j(r):i===`text`?j(`Scaled ${r}${s?.capacity===void 0?``:` (capacity=${s.capacity})`}.`):M(o,i)}}),bu=w({description:`Update a deployment's rate limits (rpm_limit / tpm_limit)`,auth:`apiKey`,usageArgs:`--deployed-model <id> [--rpm-limit <n>] [--tpm-limit <n>]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},rpmLimit:{type:`number`,valueHint:`<n>`,description:`Requests per minute`},tpmLimit:{type:`number`,valueHint:`<n>`,description:`Tokens per minute`}},exampleArgs:[`--deployed-model dep-... --rpm-limit 1000`,`--deployed-model dep-... --rpm-limit 1000 --tpm-limit 200000`],notes:[`At least one of --rpm-limit / --tpm-limit must be provided.`],validate:e=>e.rpmLimit===void 0&&e.tpmLimit===void 0?`Provide at least one of --rpm-limit / --tpm-limit.`:void 0,async run(e){let{settings:t,flags:n}=e,r=n.deployedModel,i=T(t.output),a={};if(n.rpmLimit!==void 0&&(a.rpm_limit=n.rpmLimit),n.tpmLimit!==void 0&&(a.tpm_limit=n.tpmLimit),t.dryRun){M({action:`deploy.update`,deployed_model:r,body:a},i);return}let o=await _t(e.client,r,a),s=o.output??o.data;if(t.quiet)j(r);else if(i===`text`){let e=[];s?.rpm_limit!==void 0&&e.push(`rpm_limit=${s.rpm_limit}`),s?.tpm_limit!==void 0&&e.push(`tpm_limit=${s.tpm_limit}`),j(`Updated ${r}${e.length?` (${e.join(`, `)})`:``}.`)}else M(o,i)}}),xu=w({description:`Delete a model deployment (must be STOPPED or FAILED)`,auth:`apiKey`,usageArgs:`--deployed-model <id> [--skip-precheck]`,flags:{deployedModel:{type:`string`,valueHint:`<id>`,description:`Deployed model identifier (required)`,required:!0},skipPrecheck:{type:`switch`,description:`Skip the local STOPPED/FAILED status precheck`}},exampleArgs:[`--deployed-model dep-...`,`--deployed-model dep-... --dry-run`],async run(e){let{settings:n,flags:r}=e,i=r.deployedModel,o=T(n.output);if(n.dryRun){M({action:`deploy.delete`,deployed_model:i},o);return}if(!r.skipPrecheck)try{let n=await be(e.client,i),r=((n.output??n.data)?.status??``).toUpperCase();if(r&&r!==`STOPPED`&&r!==`FAILED`)throw new t(`Deployment ${i} is ${r}. Only STOPPED / FAILED deployments can be deleted. Stop it first via the platform console, or pass --skip-precheck to attempt deletion anyway.`,a.USAGE)}catch(e){if(e instanceof t)throw e}let s=await ae(e.client,i);n.quiet?j(i):o===`text`?j(`Deleted ${i}.`):M(s,o)}});const Su={callerUacAccountId:{type:`string`,valueHint:`<id>`,description:`Caller UAC account ID`},namespaceId:{type:`string`,valueHint:`<id>`,description:`Product namespace ID (Token Plan default: namespace-1)`}},Cu={workspaceId:{type:`string`,valueHint:`<id>`,description:`Workspace ID (env: BAILIAN_WORKSPACE_ID, config: workspace_id)`}},wu={cn:`modelstudio.cn-beijing.aliyuncs.com`,intl:`modelstudio.ap-southeast-1.aliyuncs.com`};function Tu(e){for(let[t,n]of Object.entries(l))if(e===n||e.startsWith(`${n}/`))return t;return`cn`}function Eu(e){return wu[Tu(e)]??wu.cn}function Du(e,n,r){let i=n.workspaceId||e.workspaceId;if(!i)throw new t(`Missing workspace ID.
|
|
2703
|
+
Set via: --workspace-id flag, env: BAILIAN_WORKSPACE_ID, or config: ${r} config set workspace_id <id>`,a.USAGE);return i}function Ou(e,t){t.callerUacAccountId&&(e.CallerUacAccountId=t.callerUacAccountId),t.namespaceId&&(e.NamespaceId=t.namespaceId)}function ku(e,t,n){let r=_(n),i=Eu(e);return{host:i,endpoint:`https://${i}${t}${r?`?${r}`:``}`,queryString:r,queryParams:n}}async function Au(e){let{client:t,baseUrl:n,action:r,path:i,method:a,queryParams:o}=e,{host:s}=ku(n,i,o);return t.openApiQueryJson({host:s,path:i,action:r,version:`2026-02-10`,method:a,queryParams:o})}const ju=`/tokenplan/subscription/seat-detail`;var Mu=w({description:`List Token Plan subscription seat details`,auth:`openapi`,usageArgs:`[flags]`,flags:{pageNo:{type:`number`,valueHint:`<n>`,description:`Page number (default: 1)`},pageSize:{type:`number`,valueHint:`<n>`,description:`Page size (default: 10)`},...Su,status:{type:`array`,valueHint:`<status>`,description:`Seat status filter (repeatable): CREATING, NORMAL, LIMIT, RELEASE, STOP, REFUNDED`},statusListStr:{type:`string`,valueHint:`<json>`,description:`StatusList as JSON string, e.g. '["NORMAL"]'`},seatId:{type:`string`,valueHint:`<id>`,description:`Filter by seat ID`},seatType:{type:`string`,valueHint:`<type>`,description:`Seat tier: standard, pro, or max`},queryAssigned:{type:`string`,valueHint:`<bool>`,description:`Filter by assignment: true=assigned, false=unassigned`}},exampleArgs:[``,`--page-size 20 --status NORMAL`,`--query-assigned true --seat-type standard`],async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=Nu(n);if(t.dryRun){let{endpoint:t,queryParams:n}=ku(e.client.baseUrl,ju,i);M({endpoint:t,query:n},r);return}let a=await Au({client:e.client,baseUrl:e.client.baseUrl,action:`GetSubscriptionSeatDetails`,path:ju,method:`GET`,queryParams:i}),o=a.Data?.Items??[];t.quiet||r===`text`?Pu(o,a.Data?.Total,a.Data?.PageNo,a.Data?.PageSize):M(a,r)}});function Nu(e){let n={};if(e.pageNo!==void 0&&(n.PageNo=String(e.pageNo)),e.pageSize!==void 0&&(n.PageSize=String(e.pageSize)),Ou(n,e),e.statusListStr&&(n.StatusListStr=e.statusListStr),e.status&&e.status.length>0&&(n.StatusList=e.status),e.seatId&&(n.SeatId=e.seatId),e.seatType&&(n.SeatType=e.seatType),typeof e.queryAssigned==`string`&&e.queryAssigned.length>0){let r=e.queryAssigned.toLowerCase();if(r!==`true`&&r!==`false`)throw new t(`--query-assigned must be 'true' or 'false'.`,a.USAGE);n.QueryAssigned=r}return n}function Pu(e,t,n,r){if(e.length===0){j(`No seats found.`);return}let i=[P(`SeatId`,18),P(`Type`,10),P(`Status`,10),P(`Assigned`,12),P(`Account`,20)].join(` `);j(i),j(`-`.repeat(i.length));for(let t of e)j([P(t.SeatId??`-`,18),P(t.SpecType??`-`,10),P(t.Status??`-`,10),P(t.AssignedStatus??`-`,12),P(t.AccountName??t.AccountId??`-`,20)].join(` `));t!==void 0&&(j(``),j(`Total: ${t}${n===void 0?``:` | Page: ${n}`}${r===void 0?``:` | PageSize: ${r}`}`))}const Fu=`/tokenplan/api-keys`;var Iu=w({description:`Create a Token Plan API key for a seat`,auth:`openapi`,usageArgs:`--account-id <id> --workspace-id <id> [flags]`,flags:{accountId:{type:`string`,valueHint:`<id>`,description:`Target member account ID`,required:!0},...Cu,description:{type:`string`,valueHint:`<text>`,description:`API key description`},...Su},exampleArgs:[`--account-id acc_123 --workspace-id ws_456`,`--account-id acc_123 --workspace-id ws_456 --description 'Dev key'`],async run(e){let{identity:t,settings:n,flags:r}=e,i=T(n.output),a=Du(n,r,t.binName),o=Lu(r,{accountId:r.accountId,workspaceId:a});if(n.dryRun){let{endpoint:t,queryParams:n}=ku(e.client.baseUrl,Fu,o);M({endpoint:t,query:n},i);return}let s=await Au({client:e.client,baseUrl:e.client.baseUrl,action:`CreateTokenPlanKey`,path:Fu,method:`POST`,queryParams:o});n.quiet||i===`text`?Ru(s):M(s,i)}});function Lu(e,t){let n={};return n.AccountId=t.accountId,n.WorkspaceId=t.workspaceId,e.description&&(n.Description=e.description),Ou(n,e),n}function Ru(e){let t=e.Data;if(!t){j(`API key created.`);return}j(`${P(`ApiKeyId`,14)} ${t.ApiKeyId??`-`}`),j(`${P(`MaskedApiKey`,14)} ${t.MaskedApiKey??`-`}`),t.Description&&j(`${P(`Description`,14)} ${t.Description}`),t.PlainApiKey&&(j(``),j(`PlainApiKey (shown once): ${t.PlainApiKey}`))}const zu=`/tokenplan/subscription/seat-assignments`;var Bu=w({description:`Batch assign Token Plan seats to members`,auth:`openapi`,usageArgs:`--workspace-id <id> --seat-type <type> --account-id <id> [flags]`,flags:{...Cu,seatType:{type:`string`,valueHint:`<type>`,description:`Seat tier: standard, pro, or max`,required:!0},accountId:{type:`array`,valueHint:`<id>`,description:`Target member account ID (repeatable)`},...Su,locale:{type:`string`,valueHint:`<locale>`,description:`Language: zh-CN or en-US`}},exampleArgs:[`--workspace-id ws_456 --seat-type standard --account-id acc_123`,`--workspace-id ws_456 --seat-type pro --account-id acc_1 --account-id acc_2`],validate:e=>e.accountId&&e.accountId.length>0?void 0:`Missing required flag: --account-id`,async run(e){let{identity:t,settings:n,flags:r}=e,i=T(n.output),a=Vu(r,Du(n,r,t.binName));if(n.dryRun){let{endpoint:t,queryParams:n}=ku(e.client.baseUrl,zu,a);M({endpoint:t,query:n},i);return}let o=await Au({client:e.client,baseUrl:e.client.baseUrl,action:`BatchAssignSeats`,path:zu,method:`POST`,queryParams:a});n.quiet||i===`text`?j(`Seats assigned successfully.`):M(o,i)}});function Vu(e,t){let n={};return n.WorkspaceId=t,e.seatType&&(n.SeatType=e.seatType),Ou(n,e),e.locale&&(n.Locale=e.locale),e.accountId&&e.accountId.length>0&&(n.AccountIds=e.accountId),n}const Hu=`/tokenplan/organization/member-additions`;var Uu=w({description:`Add a member to a Token Plan organization`,auth:`openapi`,usageArgs:`--account-name <name> --org-id <id> [flags]`,flags:{accountName:{type:`string`,valueHint:`<name>`,description:`Member display name`,required:!0},orgId:{type:`string`,valueHint:`<id>`,description:`Organization ID`,required:!0},orgRoleCode:{type:`string`,valueHint:`<code>`,description:`Organization role: ORG_ADMIN or ORG_MEMBER (default: ORG_MEMBER)`},specType:{type:`string`,valueHint:`<type>`,description:`Seat tier to assign on creation: standard, pro, or max`},...Su},exampleArgs:[`--account-name dev_user --org-id org_123`,`--account-name admin_user --org-id org_123 --org-role-code ORG_ADMIN`,`--account-name member1 --org-id org_123 --spec-type standard`],async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=Wu(n);if(t.dryRun){let{endpoint:t,queryParams:n}=ku(e.client.baseUrl,Hu,i);M({endpoint:t,query:n},r);return}let a=await Au({client:e.client,baseUrl:e.client.baseUrl,action:`AddOrganizationMember`,path:Hu,method:`POST`,queryParams:i});t.quiet||r===`text`?Gu(a):M(a,r)}});function Wu(e){let t={};return e.accountName&&(t.AccountName=e.accountName),e.orgId&&(t.OrgId=e.orgId),t.OrgRoleCode=e.orgRoleCode||`ORG_MEMBER`,e.specType&&(t.SpecType=e.specType),Ou(t,e),t}function Gu(e){let t=e.Data;if(!t){j(`Member added.`);return}j(`${P(`AccountId`,14)} ${t.AccountId??`-`}`),j(`${P(`SeatAssigned`,14)} ${String(t.SeatAssigned??`-`)}`)}const Ku=[`bailian`,`claude`,`qoder`,`ark`,`all`],qu={bailian:` bailian:
|
|
362
2704
|
# bl auth login --api-key <key> sets DASHSCOPE_API_KEY; --base-url <url> sets BAILIAN_BASE_URL
|
|
363
2705
|
api_key: \${DASHSCOPE_API_KEY}
|
|
364
2706
|
base_url: \${BAILIAN_BASE_URL}`,claude:` claude:
|
|
365
2707
|
api_key: \${ANTHROPIC_API_KEY}`,qoder:` qoder:
|
|
366
2708
|
api_key: \${QODER_PAT}
|
|
367
2709
|
gateway: "https://api.qoder.com/api/v1/cloud"`,ark:` ark:
|
|
368
|
-
api_key: \${ARK_API_KEY}`},
|
|
369
|
-
bailian: qwen3.
|
|
2710
|
+
api_key: \${ARK_API_KEY}`},Ju={bailian:` model: qwen3.8-max`,claude:` model: claude-sonnet-4-6`,qoder:` model: ultimate`,ark:` model: doubao-seed-2-1-pro-260628`};function Yu(e){let t=e.provider===`all`?`${qu.bailian}\n${qu.claude}\n${qu.qoder}\n${qu.ark}`:qu[e.provider],n=e.provider===`all`?` model:
|
|
2711
|
+
bailian: qwen3.8-max
|
|
370
2712
|
claude: claude-sonnet-4-6
|
|
371
2713
|
qoder: ultimate
|
|
372
|
-
ark: doubao-seed-2-1-pro-260628`:
|
|
2714
|
+
ark: doubao-seed-2-1-pro-260628`:Ju[e.provider],r=e.provider===`bailian`?`[bash, read, glob, grep]`:`[read, glob, grep, web_search, web_fetch]`;return`version: "1"
|
|
373
2715
|
|
|
374
2716
|
providers:
|
|
375
2717
|
${t}
|
|
@@ -393,15 +2735,15 @@ ${n}
|
|
|
393
2735
|
environment: dev
|
|
394
2736
|
tools:
|
|
395
2737
|
builtin: ${r}
|
|
396
|
-
`}var
|
|
2738
|
+
`}var Xu=w({description:`Create a new agents.yaml template`,auth:`none`,usageArgs:`[--provider <name>] [--agent-name <name>] [--file <path>] [--force]`,flags:{provider:{type:`string`,valueHint:`<name>`,description:`Provider: bailian, claude, qoder, ark, all (default: bailian)`,choices:Ku},agentName:{type:`string`,valueHint:`<name>`,description:`Name of the first agent (default: assistant)`},file:{type:`string`,valueHint:`<path>`,description:`Output config path (default: agents.yaml)`},force:{type:`switch`,description:`Overwrite an existing config file`}},exampleArgs:[``,`--provider bailian --agent-name assistant`,`--provider all`],async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.provider??`bailian`,s=r.agentName??`assistant`,c=r.file??`agents.yaml`;if(I(c)&&!r.force)throw new t(`${c} already exists.`,a.USAGE,`Pass --force to overwrite.`);let l=`.gitignore`;if(n.dryRun){let e=!0;I(l)&&(e=!(await En(l,`utf8`)).includes(`agents.state.json`)),M({would_create:c,provider:o,agent:s,would_update_gitignore:e},i);return}if(await Dn(c,Yu({provider:o,agentName:s}),`utf8`),I(l)){let e=await En(l,`utf8`);e.includes(`agents.state.json`)||await Dn(l,e+`
|
|
397
2739
|
# agents
|
|
398
2740
|
agents.state.json
|
|
399
2741
|
.env
|
|
400
|
-
`,`utf8`)}else await
|
|
2742
|
+
`,`utf8`)}else await Dn(l,`# agents
|
|
401
2743
|
agents.state.json
|
|
402
2744
|
.env
|
|
403
|
-
`,`utf8`);i===`json`?
|
|
2745
|
+
`,`utf8`);i===`json`?M({created:c,provider:o,agent:s},i):(j(`Created ${c}`),(o===`bailian`||o===`all`)&&j("Credentials: run `bl auth login --api-key <key> --base-url <url>`, or set DASHSCOPE_API_KEY / BAILIAN_BASE_URL."),j("Next: edit agents.yaml, then run `bl managed-agent plan`."))}});const Zu=`/api/v1/agentstudio`,Qu=[...new Set([...Object.values(Mn).flatMap(e=>e.map(e=>e.key)),`BAILIAN_API_KEY`,`BAILIAN_BASE_URL`,`CLAUDE_API_KEY`,`QODER_API_KEY`])],$u={bailian:"Run `bl auth login --api-key <key>`, pass --api-key, or set DASHSCOPE_API_KEY.",claude:`Set ANTHROPIC_API_KEY (or CLAUDE_API_KEY) in your shell or .env.`,ark:`Set ARK_API_KEY in your shell or .env.`,qoder:`Set QODER_PAT (or QODER_API_KEY) in your shell or .env.`},Y=["Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile).","Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json.",`Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env.`],ed=[`Runs fully offline against local files: no login or provider credentials required.`];function td(){In();for(let e of Qu)process.env[e]===void 0&&(process.env[e]=``)}function nd(e,t){let n=e.bailian;if(!n||typeof n!=`object`)return;let r=n,i=t.client.exportApiCredential();if(i&&(r.api_key=i.token),`base_url`in r&&!r.base_url){let e=t.client.baseUrl.replace(/\/+$/,``);r.base_url=e.endsWith(Zu)?e:`${e}${Zu}`}`workspace_id`in r&&!r.workspace_id&&t.settings.workspaceId&&(r.workspace_id=t.settings.workspaceId)}function rd(){for(let e of Qu)delete process.env[e]}function id(e){for(let t of Object.values(e)){if(!t||typeof t!=`object`)continue;let e=t;for(let[t,n]of Object.entries(e))n===null&&(e[t]=``)}}function ad(e){for(let[n,r]of Object.entries(e)){if(!r||typeof r!=`object`)continue;let e=r;if(!(`api_key`in e))continue;let i=e.api_key;if(!(typeof i==`string`&&i.trim()))throw new t(`Provider '${n}' is configured but its API key is empty.`,a.AUTH,$u[n]??`Provide credentials for provider '${n}'.`)}}function od(e,t){let n=R(e);return{projectId:t??hn(gn(n))}}async function sd(e,t,n){let r=R(e),i=new Nn({configPath:r,statePath:t}).getStatePath(od(r,n));return Pn.load(i)}let cd=!1;function ld(e){if(cd)return;let t=jn.setDefaultFetch;typeof t==`function`&&(t(te(e)),cd=!0)}async function ud(e,t,n={}){td();let r=await Zn(t,n);return id(r.config.providers),nd(r.config.providers,e),rd(),(n.credentials??`all`)!==`none`&&ad(r.config.providers),r}async function X(e,t,n={}){ld(e);let{config:r,configPath:i,projectName:a}=await ud(e,t,n);return{...Ln({projectName:a,config:r,state:await sd(i,n.statePath,a),configPath:i,providers:r.providers}),configPath:i}}function dd(e,t){if(!(!t||t===`all`)&&!e.providers.has(t))throw new Fn(`Provider '${t}' is not configured. Available providers: ${Array.from(e.providers.keys()).join(`, `)||`none`}.`)}function fd(e){let t=e;return typeof t.statusCode==`number`&&typeof t.responseBody==`string`}function pd(e){try{let t=JSON.parse(e);if(t&&typeof t==`object`)return t}catch{}return{message:e.trim()||void 0}}function md(e){return/did not complete within the timeout/i.test(e.message)}async function Z(e){try{return await e()}catch(e){throw e instanceof t?e:e instanceof Fn?md(e)?new t(e.message,a.TIMEOUT,"The session may still be running — check `bl managed-agent session get --session-id <id>` or `session events`."):new t(e.message,a.USAGE):e instanceof Error&&fd(e)?ze(e.statusCode,pd(e.responseBody)):e instanceof TypeError&&e.message===`fetch failed`?e:e instanceof Error?new t(e.message,a.GENERAL):e}}var hd=w({description:`Validate an agents.yaml configuration (offline)`,auth:`none`,usageArgs:`[--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`}},exampleArgs:[``,`--file agents.yaml`],notes:ed,async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`,s=await Z(async()=>{let{config:t}=await ud(e,o,{credentials:`none`});return nr(t)}),c=s.filter(e=>e.severity===`error`).length;if(i===`json`)M({valid:c===0,diagnostics:s},i);else{for(let e of s){let t=e.resource?` (${e.resource.type}.${e.resource.name})`:``;j(`[${e.severity}] ${e.message}${t}`)}c===0&&j(`Configuration is valid.`)}if(c>0)throw new t(`Validation failed with ${c} error(s).`,a.GENERAL)}});function gd(e){return`${e.type}.${e.name} (${e.provider})`}async function Q(e){let t=console.log,n=console.info,r=(...e)=>{process.stderr.write(`${e.map(e=>String(e)).join(` `)}\n`)};console.log=r,console.info=r;try{return await e()}finally{console.log=t,console.info=n}}function _d(e){process.stderr.write(`${e.message}\n`)}var vd=w({description:`Show what changes would be applied to agent infrastructure`,auth:`apiKey`,usageArgs:`[--file <path>] [--provider <name>] [--no-refresh] [--refresh-only]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider (default: all configured)`},noRefresh:{type:`switch`,description:`Skip refreshing state from remote before planning`},refreshOnly:{type:`switch`,description:`Refresh state and show drift without planning remote mutations`}},exampleArgs:[``,`--provider bailian`,`--no-refresh`],notes:[...Y,`--no-refresh and --dry-run plan offline from local config and state: no remote requests, no state writes, provider keys are not checked.`],async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`,s=!!r.noRefresh||n.dryRun,c=(await Z(()=>Q(async()=>{let t=await X(e,o,{credentials:s?`none`:`all`});return dd(t,r.provider),Xn(t,{provider:r.provider,refresh:!s,quiet:i===`json`,onFeedback:i===`json`?void 0:_d})}))).plan,l=c.diagnostics.some(e=>e.severity===`error`);if(i===`json`){if(M(c,i),l)throw new t(`Plan contains errors.`,a.GENERAL);return}for(let e of c.diagnostics)j(`[${e.severity}] ${e.code}: ${e.message}`);if(l)throw new t(`Plan contains errors.`,a.GENERAL);let u=c.actions.filter(e=>e.action===`create`),d=c.actions.filter(e=>e.action===`update`),f=c.actions.filter(e=>e.action===`delete`);if(u.length+d.length+f.length===0){j(`No changes. Infrastructure is up-to-date.`),r.refreshOnly&&j(`Refresh-only mode: no remote mutations were performed.`);return}j(`
|
|
404
2746
|
Planned actions:
|
|
405
|
-
`);for(let e of u)
|
|
2747
|
+
`);for(let e of u)j(` + ${gd(e.address)}`);for(let e of d)j(` ~ ${gd(e.address)}`),e.reason&&j(` ${e.reason}`);for(let e of f)j(` - ${gd(e.address)}`);j(`\nPlan: ${u.length} to create, ${d.length} to update, ${f.length} to destroy.`),r.refreshOnly&&j(`Refresh-only mode: no remote mutations will be performed.`)}}),yd=w({description:`Apply planned changes to create/update/delete agent resources`,auth:`apiKey`,usageArgs:`[--file <path>] [--provider <name>] [--yes] [--concurrency <n>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider (default: all configured)`},yes:{type:`switch`,description:`Confirm and apply without an interactive prompt (required to mutate)`},noRefresh:{type:`switch`,description:`Skip refreshing state from remote before planning`},concurrency:{type:`number`,valueHint:`<n>`,description:`Max independent resources to apply in parallel (default 6, max 10)`}},exampleArgs:[`--yes`,`--provider bailian --yes`],notes:Y,async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`;if(n.dryRun){M({would_apply:{provider:r.provider??`all`,refresh:!r.noRefresh,concurrency:r.concurrency},config_file:o,hint:"Run `managed-agent plan` to preview the exact resource changes."},i);return}let s=await Z(()=>Q(async()=>{let t=await X(e,o);return dd(t,r.provider),Xn(t,{provider:r.provider,refresh:!r.noRefresh,quiet:!0,onFeedback:_d})})),c=s.plan,l=e=>{i===`json`?process.stderr.write(`${e}\n`):j(e)};if(c.diagnostics.some(e=>e.severity===`error`)){for(let e of c.diagnostics)e.severity===`error`&&l(`[error] ${e.code}: ${e.message}`);throw new t(`Cannot apply: resolve the errors above first.`,a.GENERAL)}let u=c.actions.filter(e=>e.action!==`no-op`);if(u.length===0){i===`json`?M({succeeded:0,failed:0,skipped:0,results:[]},i):j(`No changes. Infrastructure is up-to-date.`);return}let d=u.filter(e=>e.action===`create`).length,f=u.filter(e=>e.action===`update`).length,p=s.destructiveActions;for(let e of u)l(` ${e.action===`create`?`+`:e.action===`update`?`~`:`-`} ${gd(e.address)}`);if(!r.yes)throw new t(`Refusing to apply ${u.length} change(s) (${d} create, ${f} update, ${p.length} destroy) without confirmation.`,a.USAGE,"Review with `bl managed-agent plan`, then re-run with --yes to apply.");let m=await Z(()=>Q(()=>Vn(s,{onFeedback:_d,policy:`force`,concurrency:r.concurrency}))),h=m.results.filter(e=>e.status===`success`).length,g=m.results.filter(e=>e.status===`failed`).length,_=m.results.filter(e=>e.status===`skipped`).length;if(i===`json`?M({succeeded:h,failed:g,skipped:_,results:m.results},i):j(`\nApply finished: ${h} succeeded, ${g} failed, ${_} skipped.`),g>0)throw new t(`Apply failed.`,a.GENERAL)}}),bd=w({description:`Destroy all managed agent resources tracked in state`,auth:`apiKey`,usageArgs:`[--file <path>] [--yes] [--cascade]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},yes:{type:`switch`,description:`Confirm and destroy without an interactive prompt (required)`},cascade:{type:`switch`,description:`Auto-delete dependent resources (e.g. sessions referencing an environment)`}},exampleArgs:[`--yes`,`--yes --cascade`],notes:Y,async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`;if(n.dryRun){M({would_destroy:{cascade:!!r.cascade},config_file:o,hint:"Run `managed-agent state list` to see the resources tracked in state."},i);return}let s=await Z(()=>Q(async()=>Yn(await X(e,o)))),c=s.resources;if(c.length===0){i===`json`?M({destroyed:0,total:0},i):j(`No resources in state. Nothing to destroy.`);return}for(let e of c){let t=` - ${gd(e.address)} [${e.remote_id}]`;i===`json`?process.stderr.write(`${t}\n`):j(t)}if(!r.yes)throw new t(`Refusing to destroy ${c.length} resource(s) without confirmation.`,a.USAGE,`Re-run with --yes to destroy (add --cascade to remove dependents).`);let l=await Z(()=>Q(()=>Bn(s,{cascade:r.cascade,onCascadeRequired:async()=>!!r.cascade,onResourceResult:e=>{let t=gd(e.resource.address);process.stderr.write(` ${e.status===`success`?`✓`:`✗`} ${t}\n`)}})));if(i===`json`?M({destroyed:l.destroyed,total:l.resources.length},i):j(`\n${l.partial?`Destroy incomplete`:`Destroy complete`}. ${l.destroyed}/${l.resources.length} resources removed.`),l.partial)throw new t(l.results.find(e=>e.status!==`success`)?.error||`Destroy incomplete: ${l.destroyed}/${l.resources.length} resources removed.`,a.GENERAL)}}),xd=w({description:`List resources tracked in agents state`,auth:`none`,usageArgs:`[--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`}},exampleArgs:[``,`--file agents.yaml`],notes:ed,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,a=await Z(()=>Q(async()=>(await X(e,i,{credentials:`none`})).state.listResources()));if(r===`json`){M({resources:a},r);return}if(a.length===0){j(`No resources tracked in state.`);return}let o=[`TYPE`,`NAME`,`PROVIDER`,`REMOTE ID`],s=a.map(e=>[e.address.type,e.address.name,e.address.provider,e.remote_id??`(local)`]);for(let e of N(o,s))j(e);j(`\nTotal: ${a.length}`)}}),Sd=w({description:`Show details of a resource in agents state`,auth:`none`,usageArgs:`--address <provider.type.name> [--file <path>]`,flags:{address:{type:`string`,valueHint:`<provider.type.name>`,description:`Resource state address (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`}},exampleArgs:[`--address bailian.agent.assistant`],notes:ed,async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`,s=await Z(()=>Q(async()=>{let t=await X(e,o,{credentials:`none`}),n=Jn(r.address,{requireProvider:!1});return t.state.findResource(n)}));if(!s)throw new t(`Resource not found: ${r.address}`,a.GENERAL);i===`json`?M(s,i):j(JSON.stringify(s,null,2))}}),Cd=w({description:`Remove a resource from state without destroying it remotely`,auth:`none`,usageArgs:`--address <provider.type.name> [--file <path>]`,flags:{address:{type:`string`,valueHint:`<provider.type.name>`,description:`Resource state address (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`}},exampleArgs:[`--address bailian.agent.assistant`],notes:ed,async run(e){let{settings:n,flags:r}=e,i=T(n.output),o=r.file??`agents.yaml`;if(n.dryRun){await Z(async()=>{Jn(r.address,{requireProvider:!1})}),M({would_remove:r.address,config_file:o},i);return}await Z(()=>Q(async()=>{let n=await X(e,o,{credentials:`none`}),i=Jn(r.address,{requireProvider:!1}),s=n.state.findResource(i);if(!s)throw new t(`Resource not found: ${r.address}`,a.GENERAL);n.state.removeResource(s.address),await n.state.save()}));let s=`Removed ${r.address} from state (remote resource not deleted).`;i===`json`?M({removed:r.address},i):j(s)}}),wd=w({description:`Import an existing remote resource into agents state`,auth:`apiKey`,usageArgs:`--address <provider.type.name> --remote-id <id> [--resource-version <n>] [--file <path>]`,flags:{address:{type:`string`,valueHint:`<provider.type.name>`,description:`Resource state address (required)`,required:!0},remoteId:{type:`string`,valueHint:`<id>`,description:`Existing remote resource ID to import (required)`,required:!0},resourceVersion:{type:`number`,valueHint:`<n>`,description:`Resource version (for versioned resources like agents)`},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`}},exampleArgs:[`--address bailian.agent.assistant --remote-id agent-abc123`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`;if(t.dryRun){await Z(async()=>{Jn(n.address,{requireProvider:!0})}),M({would_import:n.address,remote_id:n.remoteId,resource_version:n.resourceVersion,config_file:i},r);return}await Z(()=>Q(async()=>{let t=Jn(n.address,{requireProvider:!0});await Un(await X(e,i),t,n.remoteId,{resourceVersion:n.resourceVersion})})),r===`json`?M({imported:n.address,remote_id:n.remoteId},r):j(`Imported ${n.address} (remote_id: ${n.remoteId}) into state.`)}});function Td(e){return e.type!==`thinking`&&!(e.type===`message`&&e.role===`user`)}function Ed(e,t){t||process.stderr.write(`\n[session ${e}]\n`)}function Dd(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n?.type===`error`&&n.content?.trim())return n.content}}function Od(e,n){if(e===`failed`)throw new t(n??`Session failed.`,a.GENERAL)}async function kd(e,t,n={}){let r=[],i,a;for await(let n of e)if(t?r.push(n):Ad(n),n.type===`error`&&n.content?.trim()&&(a=n.content),n.type===`status`&&Wn(n.status)){i=n.status,Ed(n.status??``,t);break}t&&process.stdout.write(`${JSON.stringify({...n,events:rr(r)},null,2)}\n`),Od(i,a)}function Ad(e){if(Td(e))if(e.type===`message`&&e.content)process.stdout.write(e.content);else if(e.type===`tool_use`)process.stderr.write(`\n[tool] ${e.tool_name}\n`);else if(e.type===`tool_result`&&e.content){let t=e.content.length>200?`${e.content.slice(0,200)}...`:e.content;process.stderr.write(`${t}\n`)}else e.type===`status`?e.status===`running`&&process.stderr.write(`
|
|
406
2748
|
[session running]
|
|
407
|
-
`):e.type===`error`&&process.stderr.write(`\n[error] ${e.content??`unknown error`}\n`)}function Gl(e,t,n={}){if(t)process.stdout.write(`${JSON.stringify({...n,events:Un(e.result.events),has_more:e.result.has_more,next_page:e.result.next_page},null,2)}\n`);else{for(let t of e.result.events)Wl(t);Bl(e.terminalStatus,t)}Hl(e.terminalStatus,Vl(e.result.events))}function Kl(e){return e?e.split(`,`).map(e=>e.trim()).filter(Boolean):void 0}var ql=T({description:`Create a new session for an agent`,auth:`apiKey`,usageArgs:`[--agent <name>] [--environment <name>] [--title <title>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Agent name (auto-detected when only one agent is configured)`},environment:{type:`string`,valueHint:`<name>`,description:`Override agent's declared environment`},vault:{type:`string`,valueHint:`<name>`,description:`Override agent's declared vault`},memoryStores:{type:`string`,valueHint:`<names>`,description:`Override agent's memory stores (comma-separated)`},title:{type:`string`,valueHint:`<title>`,description:`Session title`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider (multi-provider agents)`}},exampleArgs:[``,`--agent assistant`,`--agent assistant --title 'debug run'`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`;if(t.dryRun){F({would_create_session:{agent:n.agent??`auto`,provider:n.provider??`auto`,environment:n.environment,vault:n.vault,memory_stores:Kl(n.memoryStores),title:n.title},config_file:i},r);return}let{agentName:a,session:o}=await Z(()=>Q(async()=>wn(await X(e,i),{agent:n.agent,provider:n.provider,environment:n.environment,vault:n.vault,memoryStores:Kl(n.memoryStores),title:n.title})));if(r===`json`){F({agent:a,session:o},r);return}P(`Session created: ${o.id}`),P(` Agent: ${a}`),P(` Environment: ${o.environment_id}`),P(` Status: ${o.status}`),o.vault_ids.length&&P(` Vaults: ${o.vault_ids.join(`, `)}`),o.memory_store_ids.length&&P(` Memory: ${o.memory_store_ids.join(`, `)}`)}});async function Jl(e,t){let n=await e(),r=[...n.items],i=n.hasMore,a=n.nextPage;for(;t&&a;){let t=await e(a);r.push(...t.items),i=t.hasMore,a=t.nextPage}return{items:r,hasMore:i,nextPage:a}}var Yl=T({description:`List sessions from the provider`,auth:`apiKey`,usageArgs:`[--agent <name>] [--all] [--provider <name>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Filter by agent name`},all:{type:`switch`,description:`Fetch all pages by following the cursor`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[``,`--agent assistant`,`--all`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,{items:a,hasMore:o}=await Z(()=>Q(async()=>{let t=await X(e,i);return Jl(async e=>{let r=await Mn(t,{agent:n.agent,provider:n.provider,filter:e?{page:e}:void 0});return{items:r.summaries,hasMore:r.hasMore,nextPage:r.nextPage}},n.all)})),s=a.map(e=>e.session);if(r===`json`){F({sessions:s,has_more:o},r);return}if(s.length===0){P(`No sessions found.`);return}let c=new Map(a.filter(e=>e.agentName).map(e=>[e.session.id,e.agentName])),l=[`ID`,`TITLE`,`AGENT`,`STATUS`,`CREATED`],u=s.map(e=>[e.id,(e.title??``).slice(0,20),c.get(e.id)??e.agent_id.slice(0,12),e.status,e.created_at]);for(let e of I(l,u))P(e);P(`\nTotal: ${s.length}`),o&&P(`More sessions available. Use --all to fetch all.`)}}),Xl=T({description:`Get details of a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--provider <name>] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[`--session-id sess_abc123`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,a=await Z(()=>Q(async()=>On(await X(e,i),n.sessionId,n.provider)));if(r===`json`){F(a,r);return}P(` ID: ${a.id}`),P(` Agent: ${a.agent_id}`),P(` Environment: ${a.environment_id}`),P(` Status: ${a.status}`),a.title&&P(` Title: ${a.title}`),P(` Created: ${a.created_at}`),P(` Updated: ${a.updated_at}`)}}),Zl=T({description:`Delete a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--provider <name>] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[`--session-id sess_abc123`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`;if(t.dryRun){F({would_delete_session:n.sessionId,provider:n.provider??`auto`,config_file:i},r);return}await Z(()=>Q(async()=>{await Tn(await X(e,i),n.sessionId,n.provider)})),r===`json`?F({deleted:n.sessionId},r):P(`Session ${n.sessionId} deleted.`)}}),Ql=T({description:`Create a session, send a message, and stream the response`,auth:`apiKey`,usageArgs:`--prompt <text> [--agent <name>] [--no-stream] [--file <path>]`,flags:{prompt:{type:`string`,valueHint:`<text>`,description:`Prompt to send (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Agent name (auto-detected when only one agent is configured)`},environment:{type:`string`,valueHint:`<name>`,description:`Override agent's declared environment`},vault:{type:`string`,valueHint:`<name>`,description:`Override agent's declared vault`},memoryStores:{type:`string`,valueHint:`<names>`,description:`Override agent's memory stores (comma-separated)`},title:{type:`string`,valueHint:`<title>`,description:`Session title`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},noStream:{type:`switch`,description:`Use polling instead of SSE streaming`}},exampleArgs:[`--prompt "hello"`,`--agent assistant --prompt "summarize this repo"`],notes:[...Y,"--output json emits one envelope: { session_id, provider, agent, events } — read session_id to chain `session send/get/events/delete`."],async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,a=r===`json`,o={agent:n.agent,provider:n.provider,environment:n.environment,vault:n.vault,memoryStores:Kl(n.memoryStores),title:n.title};if(t.dryRun){F({would_run:{prompt:n.prompt,agent:n.agent??`auto`,provider:n.provider??`auto`,environment:n.environment,vault:n.vault,memory_stores:o.memoryStores,title:n.title,mode:n.noStream?`polling`:`streaming`},config_file:i},r);return}await Z(()=>Q(async()=>{let t=await X(e,i);if(n.noStream){let e=await Vn(t,n.prompt,o);a||process.stderr.write(`Session created: ${e.session.id}\n`),Gl(e,a,{session_id:e.session.id,provider:e.provider,agent:e.agentName})}else{let e=await Bn(t,n.prompt,o);a||process.stderr.write(`Session created: ${e.session.id}\n`),await Ul(e.events,a,{session_id:e.session.id,provider:e.provider,agent:e.agentName})}}))}}),$l=T({description:`Send a message to an existing session and stream the response`,auth:`apiKey`,usageArgs:`--session-id <id> --message <text> [--no-stream] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},message:{type:`string`,valueHint:`<text>`,description:`Message to send (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},noStream:{type:`switch`,description:`Use polling instead of SSE streaming`}},exampleArgs:[`--session-id sess_abc123 --message "continue"`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,a=r===`json`;if(t.dryRun){F({would_send:{session_id:n.sessionId,message:n.message,provider:n.provider??`auto`,mode:n.noStream?`polling`:`streaming`},config_file:i},r);return}await Z(()=>Q(async()=>{let t=await X(e,i);n.noStream?Gl(await Rn(t,n.sessionId,n.message,{provider:n.provider}),a,{session_id:n.sessionId}):await Ul(await zn(t,n.sessionId,n.message,{provider:n.provider}),a,{session_id:n.sessionId})}))}}),eu=T({description:`List event history for a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--limit <n>] [--all] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},limit:{type:`number`,valueHint:`<n>`,description:`Maximum number of events to fetch`},all:{type:`switch`,description:`Fetch all pages by following the cursor`}},exampleArgs:[`--session-id sess_abc123`,`--session-id sess_abc123 --all`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,{items:a,hasMore:o}=await Z(()=>Q(async()=>{let t=await X(e,i);return Jl(async e=>{let r=await jn(t,n.sessionId,{provider:n.provider,limit:n.limit,page_token:e});return{items:r.events,hasMore:r.has_more,nextPage:r.next_page}},n.all)}));if(r===`json`){F({events:Un(a),has_more:o},r);return}if(a.length===0){P(`No events found.`);return}let s=[`#`,`TYPE`,`CONTENT`],c=a.map((e,t)=>{let n=``;return n=e.type===`message`?(e.content??``).slice(0,60):e.type===`tool_use`?e.tool_name??``:e.type===`tool_result`?(e.content??``).slice(0,60):e.type===`status`?e.status??``:e.type===`error`?(e.content??``).slice(0,60):e.raw_type,[String(t+1),e.type,n]});for(let e of I(s,c))P(e);P(`\nTotal: ${a.length}`),o&&P(`More events available. Use --all to fetch all.`)}});const tu=[`custom`,`official`,`all`];var nu=T({description:`List skills from the provider's skill catalog`,auth:`apiKey`,usageArgs:`[--source custom|official|all] [--provider <name>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},source:{type:`string`,valueHint:`<source>`,description:`Skill catalog: custom (workspace-uploaded, default), official (built-in), or all (both catalogs in one call)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[``,`--source official`,`--source all --output json`,`--source custom --provider bailian`],notes:[...Y,`Providers without a skill listing API (e.g. ark) return an empty list.`,"For agent-driven skill selection, use `--source all --output json`: one call returns both catalogs with per-skill `source` and `description` fields to pick from.",`When generating a task that needs a suitable skill, call this command to match official or custom skills before wiring them into the task.`],validate:e=>e.source&&!tu.includes(e.source)?`--source must be one of: custom, official, all.`:void 0,async run(e){let{settings:t,flags:n}=e,r=E(t.output),i=n.file??`agents.yaml`,a=n.source??`custom`,o=await Z(()=>Q(async()=>{let t=await X(e,i);if(a!==`all`)return Nn(t,{provider:n.provider,source:a});let[r,o]=await Promise.all([Nn(t,{provider:n.provider,source:`custom`}),Nn(t,{provider:n.provider,source:`official`})]);return[...r,...o]}));if(r===`json`){F({source:a,skills:o},r);return}if(o.length===0){P(a===`all`?`No skills found.`:`No ${a} skills found.`);return}let s=[`ID`,`NAME`,`SOURCE`,`STATUS`,`VERSION`,`CREATED`],c=o.map(e=>[e.id,e.name.slice(0,32),e.source,e.status,e.latest_version??`-`,e.created_at??`-`]);for(let e of I(s,c))P(e);P(`\nTotal: ${o.length} (${a})`)}});const $={loginInfo:`zeldaEasy.cornerstone-portal.cs-console.loginInfo`,initSpace:`zeldaEasy.bailian-dash-workspace.space.initSpace`,queryBuyResult:`zeldaEasy.bailian-commerce.bill.queryBuyPostpaidResult`,commodityOrderInfo:`zeldaEasy.bailian-commerce.bill.postpaidCommodityOrderInfo`,buyCommodity:`zeldaEasy.bailian-commerce.bill.buyPostpaidCommodity`},ru={accessKeyId:{type:`string`,valueHint:`<id>`,description:`Alibaba Cloud Access Key ID`},accessKeySecret:{type:`string`,valueHint:`<secret>`,description:`Alibaba Cloud Access Key Secret`},securityToken:{type:`string`,valueHint:`<token>`,description:`Alibaba Cloud STS Security Token (optional)`}},iu=1e3;function au(e){return new Promise(t=>setTimeout(t,e))}function ou(e){return e?.data?.DataV2?.data?.data}function su(e){let t=e?.data?.data;if(!Array.isArray(t)||t.length===0)return;let n=(t.find(e=>e?.defaultAgent===!0)??t[0])?.tenantId,r=typeof n==`string`?Number(n):n;return typeof r==`number`&&Number.isFinite(r)?r:void 0}var cu=T({description:`Initialize Bailian workspace and activate postpaid services`,auth:`none`,usageArgs:`--access-key-id <id> --access-key-secret <secret> [--security-token <token>]`,flags:ru,exampleArgs:[`--access-key-id LTAIxxxxx --access-key-secret xxxxx`],async run(e){let{settings:n,flags:r}=e,i=E(n.output);if(n.dryRun){F({apis:[{step:0,api:`GenerateCLIAccessToken`,description:`Generate CLI access token from AK/SK`},{step:1,api:$.loginInfo,description:`Check login & workspace status`},{step:2,api:$.initSpace,description:`Initialize workspace (if needed)`},{step:3,api:`CreateUser`,description:`Create console user via BailianControl OpenAPI (CreateUser)`},{step:4,api:`ListWorkspaces`,description:`List workspaces to resolve agentId`},{step:5,api:`ResetPolicies4Agent`,description:`Authorize user permissions`},{step:6,api:$.queryBuyResult,description:`Query postpaid order status`},{step:7,api:$.commodityOrderInfo,description:`Query commodity activation status`},{step:8,api:$.buyCommodity,description:`Activate postpaid commodities (if needed)`}]},i);return}let{accessKeyId:o,accessKeySecret:s}=r;if(!o||!s)throw new t(`workspace init requires --access-key-id and --access-key-secret.`,a.USAGE);let c=r.securityToken||void 0,l=(await he({identity:e.identity,settings:n,baseUrl:e.client.baseUrl,accessKeyId:o,accessKeySecret:s,securityToken:c})).cliAccessToken;if(!l)throw new t(`Failed to generate CLI access token from AK/SK.`,a.GENERAL);let u=se(n),d={region:u.consoleRegion,site:u.consoleSite,...u.consoleSwitchAgent==null?{}:{switchAgent:u.consoleSwitchAgent},token:l},f=n.verbose,p=async(e,r={})=>{f&&process.stderr.write(`> ${e}\n`);try{let t=await y(d,n.timeout,{api:e,data:r},n);return f&&process.stderr.write(`< ${JSON.stringify(t)}\n`),t}catch(e){if(f){let n=e instanceof t?e.rawResponse??e.message:String(e);process.stderr.write(`< ERROR: ${n}\n`)}throw e}};P(`Checking workspace status...`);let m=ou(await p($.loginInfo));m?.spaceInited===!0?P(`Workspace already initialized.`):(P(`Initializing workspace...`),await p($.initSpace),P(`Workspace initialized.`));let h=m?.aliyun?.uid;if(typeof h!=`string`||h.length===0)throw new t(`Console login info did not include aliyun.uid.`,a.GENERAL);let g={identity:e.identity,settings:n,baseUrl:e.client.baseUrl,regionId:u.consoleRegion,accessKeyId:o,accessKeySecret:s,securityToken:c};try{await S({...g,reqDTO:{outerKey:h,nickName:h,userName:h}})}catch(e){if(!(e instanceof t)||!/already exists/i.test(e.message))throw e;P(`Console user already exists, continuing.`)}P(`Resolving workspace agent...`);let _=su(await je(g));if(_==null)throw new t(`Could not resolve agentId from ListWorkspaces response.`,a.GENERAL,`Re-run with --verbose to inspect the ListWorkspaces response body.`);P(`Authorizing user permissions...`),await rt({...g,outerKey:h,agentId:_,policyIndexList:[1]}),await lu(p,i)}});async function lu(e,n){P(`Checking service activation status...`);let r;for(let t=0;t<20;t++){let n=ou(await e($.queryBuyResult));if(r=typeof n==`string`?n:n?.result,r!==`buying`)break;t===0&&P(`Service activation in progress, polling...`),await au(iu)}if(r===`fail`)throw new t(`Service activation failed.`,a.GENERAL);if(r===`success`){await fu(e,n);return}await du(e,n)}function uu(e){let t=ou(e);return Array.isArray(t)?t:[]}async function du(e,t){let n=uu(await e($.commodityOrderInfo)),r=n.filter(e=>e.status===11);if(r.length>0){P(`Warning: Some services are overdue:`);for(let e of r)P(` - ${e.commodityCode}`)}let i=n.filter(e=>e.status===1);if(i.length>0){P(`Activating ${i.length} postpaid services...`),await e($.buyCommodity),await fu(e,t);return}F({status:`ready`,activeServices:n.filter(e=>e.status===10).map(e=>e.commodityCode)},t)}async function fu(e,n){P(`Waiting for services to activate...`);for(let t=0;t<20;t++){let t=uu(await e($.commodityOrderInfo));if(t.filter(e=>e.status!==10&&e.status!==11).length===0){let e=t.filter(e=>e.status===11);if(e.length>0){P(`Warning: Some services are overdue:`);for(let t of e)P(` - ${t.commodityCode}`)}F({status:`ready`,activeServices:t.filter(e=>e.status===10).map(e=>e.commodityCode)},n);return}await au(iu)}throw new t(`Timed out waiting for services to activate.`,a.TIMEOUT)}var pu=T({description:`Install or upgrade an allowlisted Command Pack`,auth:`none`,usageArgs:`--package <name[@version]>`,flags:{package:{type:`string`,valueHint:`<name[@version]>`,description:`Allowlisted Command Pack package and optional version or tag`,required:!0}},exampleArgs:[`--package @ali/bailian-plugin-agent`,`--package @ali/bailian-plugin-agent@beta`],async run(e){F({installed:await e.commandPacks.install(e.flags.package)},E(e.settings.output))}}),mu=T({description:`Link an allowlisted local Command Pack for development`,auth:`none`,usageArgs:`--path <directory>`,flags:{path:{type:`string`,valueHint:`<directory>`,description:`Local Command Pack package directory`,required:!0}},exampleArgs:[`--path ../bailian-plugin-agent`],async run(e){F({linked:await e.commandPacks.link(e.flags.path)},E(e.settings.output))}}),hu=T({description:`List installed Command Packs and their load status`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let t=await e.commandPacks.list(),n=E(e.settings.output);if(n===`json`){F({command_packs:t},n);return}if(t.length===0){P(`No Command Packs installed.`);return}let r=t.map(e=>[e.name,e.version??`-`,e.source,e.status,e.commands.join(`, `)||e.error||`-`]);for(let e of I([`NAME`,`VERSION`,`SOURCE`,`STATUS`,`COMMANDS / ERROR`],r))P(e)}}),gu=T({description:`Remove an installed Command Pack`,auth:`none`,usageArgs:`--name <package>`,flags:{name:{type:`string`,valueHint:`<package>`,description:`Allowlisted Command Pack package name`,required:!0}},exampleArgs:[`--name @ali/bailian-plugin-agent`],async run(e){await e.commandPacks.remove(e.flags.name),F({removed:e.flags.name},E(e.settings.output))}});export{Wo as advisorRecommend,Wi as appCall,Ki as appList,hr as authGenerateAccessToken,fr as authLogin,mr as authLogout,pr as authStatus,zi as configAgent,Xr as configList,Yr as configSet,Jr as configShow,ii as configUi,Zr as configUse,Pa as consoleCall,zs as datasetDelete,Rs as datasetGet,Ls as datasetList,Is as datasetUpload,Vs as datasetValidate,Oc as deployAudioCreate,Fc as deployDelete,jc as deployGet,kc as deployImageCreate,Ac as deployList,Mc as deployModels,Nc as deployScale,Dc as deployTextCreate,Pc as deployUpdate,Na as fileUpload,tc as finetuneAudioCreate,ac as finetuneCancel,xc as finetuneCapability,dc as finetuneCheckpoints,oc as finetuneDelete,fc as finetuneExport,ic as finetuneGet,nc as finetuneImageCreate,rc as finetuneList,uc as finetuneLogs,ec as finetuneTextCreate,_c as finetuneWatch,Ar as imageEdit,Er as imageGenerate,ca as knowledgeChat,ea as knowledgeRetrieve,na as knowledgeSearch,Nl as managedAgentApply,Pl as managedAgentDestroy,ul as managedAgentInit,Ml as managedAgentPlan,ql as managedAgentSessionCreate,Zl as managedAgentSessionDelete,eu as managedAgentSessionEvents,Xl as managedAgentSessionGet,Yl as managedAgentSessionList,Ql as managedAgentSessionRun,$l as managedAgentSessionSend,nu as managedAgentSkillList,Rl as managedAgentStateImport,Fl as managedAgentStateList,Ll as managedAgentStateRm,Il as managedAgentStateShow,kl as managedAgentValidate,va as mcpCall,ba as mcpList,xa as mcpTools,qi as memoryAdd,Zi as memoryDelete,Yi as memoryList,Qi as memoryProfileCreate,$i as memoryProfileGet,Ji as memorySearch,Xi as memoryUpdate,ns as modelList,wo as pipelineRun,ko as pipelineValidate,pu as pluginInstall,mu as pluginLink,hu as pluginList,gu as pluginRemove,Fs as quotaCheck,Os as quotaHistory,hs as quotaList,xs as quotaRequest,Ca as searchWeb,ja as speechRecognize,Oa as speechSynthesize,vr as textChat,Tr as textOmni,rl as tokenPlanAddMember,el as tokenPlanAssignSeats,Xc as tokenPlanCreateKey,Kc as tokenPlanListSeats,Ui as update,eo as usageFree,ao as usageFreetier,xo as usageStats,So as usageSummary,Rr as videoDownload,Fr as videoEdit,Pr as videoGenerate,Ir as videoRef,Lr as videoTaskGet,Hr as visionDescribe,cu as workspaceInit,ss as workspaceList};
|
|
2749
|
+
`):e.type===`error`&&process.stderr.write(`\n[error] ${e.content??`unknown error`}\n`)}function jd(e,t,n={}){if(t)process.stdout.write(`${JSON.stringify({...n,events:rr(e.result.events),has_more:e.result.has_more,next_page:e.result.next_page},null,2)}\n`);else{for(let t of e.result.events)Ad(t);Ed(e.terminalStatus,t)}Od(e.terminalStatus,Dd(e.result.events))}function Md(e){return e?e.split(`,`).map(e=>e.trim()).filter(Boolean):void 0}var Nd=w({description:`Create a new session for an agent`,auth:`apiKey`,usageArgs:`[--agent <name>] [--environment <name>] [--title <title>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Agent name (auto-detected when only one agent is configured)`},environment:{type:`string`,valueHint:`<name>`,description:`Override agent's declared environment`},vault:{type:`string`,valueHint:`<name>`,description:`Override agent's declared vault`},memoryStores:{type:`string`,valueHint:`<names>`,description:`Override agent's memory stores (comma-separated)`},title:{type:`string`,valueHint:`<title>`,description:`Session title`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider (multi-provider agents)`}},exampleArgs:[``,`--agent assistant`,`--agent assistant --title 'debug run'`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`;if(t.dryRun){M({would_create_session:{agent:n.agent??`auto`,provider:n.provider??`auto`,environment:n.environment,vault:n.vault,memory_stores:Md(n.memoryStores),title:n.title},config_file:i},r);return}let{agentName:a,session:o}=await Z(()=>Q(async()=>Rn(await X(e,i),{agent:n.agent,provider:n.provider,environment:n.environment,vault:n.vault,memoryStores:Md(n.memoryStores),title:n.title})));if(r===`json`){M({agent:a,session:o},r);return}j(`Session created: ${o.id}`),j(` Agent: ${a}`),j(` Environment: ${o.environment_id}`),j(` Status: ${o.status}`),o.vault_ids.length&&j(` Vaults: ${o.vault_ids.join(`, `)}`),o.memory_store_ids.length&&j(` Memory: ${o.memory_store_ids.join(`, `)}`)}});async function Pd(e,t){let n=await e(),r=[...n.items],i=n.hasMore,a=n.nextPage;for(;t&&a;){let t=await e(a);r.push(...t.items),i=t.hasMore,a=t.nextPage}return{items:r,hasMore:i,nextPage:a}}var Fd=w({description:`List sessions from the provider`,auth:`apiKey`,usageArgs:`[--agent <name>] [--all] [--provider <name>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Filter by agent name`},all:{type:`switch`,description:`Fetch all pages by following the cursor`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[``,`--agent assistant`,`--all`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,{items:a,hasMore:o}=await Z(()=>Q(async()=>{let t=await X(e,i);return Pd(async e=>{let r=await Kn(t,{agent:n.agent,provider:n.provider,filter:e?{page:e}:void 0});return{items:r.summaries,hasMore:r.hasMore,nextPage:r.nextPage}},n.all)})),s=a.map(e=>e.session);if(r===`json`){M({sessions:s,has_more:o},r);return}if(s.length===0){j(`No sessions found.`);return}let c=new Map(a.filter(e=>e.agentName).map(e=>[e.session.id,e.agentName])),l=[`ID`,`TITLE`,`AGENT`,`STATUS`,`CREATED`],u=s.map(e=>[e.id,(e.title??``).slice(0,20),c.get(e.id)??e.agent_id.slice(0,12),e.status,e.created_at]);for(let e of N(l,u))j(e);j(`\nTotal: ${s.length}`),o&&j(`More sessions available. Use --all to fetch all.`)}}),Id=w({description:`Get details of a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--provider <name>] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[`--session-id sess_abc123`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,a=await Z(()=>Q(async()=>Hn(await X(e,i),n.sessionId,n.provider)));if(r===`json`){M(a,r);return}j(` ID: ${a.id}`),j(` Agent: ${a.agent_id}`),j(` Environment: ${a.environment_id}`),j(` Status: ${a.status}`),a.title&&j(` Title: ${a.title}`),j(` Created: ${a.created_at}`),j(` Updated: ${a.updated_at}`)}}),Ld=w({description:`Delete a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--provider <name>] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[`--session-id sess_abc123`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`;if(t.dryRun){M({would_delete_session:n.sessionId,provider:n.provider??`auto`,config_file:i},r);return}await Z(()=>Q(async()=>{await zn(await X(e,i),n.sessionId,n.provider)})),r===`json`?M({deleted:n.sessionId},r):j(`Session ${n.sessionId} deleted.`)}}),Rd=w({description:`Create a session, send a message, and stream the response`,auth:`apiKey`,usageArgs:`--prompt <text> [--agent <name>] [--no-stream] [--file <path>]`,flags:{prompt:{type:`string`,valueHint:`<text>`,description:`Prompt to send (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},agent:{type:`string`,valueHint:`<name>`,description:`Agent name (auto-detected when only one agent is configured)`},environment:{type:`string`,valueHint:`<name>`,description:`Override agent's declared environment`},vault:{type:`string`,valueHint:`<name>`,description:`Override agent's declared vault`},memoryStores:{type:`string`,valueHint:`<names>`,description:`Override agent's memory stores (comma-separated)`},title:{type:`string`,valueHint:`<title>`,description:`Session title`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},noStream:{type:`switch`,description:`Use polling instead of SSE streaming`}},exampleArgs:[`--prompt "hello"`,`--agent assistant --prompt "summarize this repo"`],notes:[...Y,"--output json emits one envelope: { session_id, provider, agent, events } — read session_id to chain `session send/get/events/delete`."],async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,a=r===`json`,o={agent:n.agent,provider:n.provider,environment:n.environment,vault:n.vault,memoryStores:Md(n.memoryStores),title:n.title};if(t.dryRun){M({would_run:{prompt:n.prompt,agent:n.agent??`auto`,provider:n.provider??`auto`,environment:n.environment,vault:n.vault,memory_stores:o.memoryStores,title:n.title,mode:n.noStream?`polling`:`streaming`},config_file:i},r);return}await Z(()=>Q(async()=>{let t=await X(e,i);if(n.noStream){let e=await tr(t,n.prompt,o);a||process.stderr.write(`Session created: ${e.session.id}\n`),jd(e,a,{session_id:e.session.id,provider:e.provider,agent:e.agentName})}else{let e=await er(t,n.prompt,o);a||process.stderr.write(`Session created: ${e.session.id}\n`),await kd(e.events,a,{session_id:e.session.id,provider:e.provider,agent:e.agentName})}}))}}),zd=w({description:`Send a message to an existing session and stream the response`,auth:`apiKey`,usageArgs:`--session-id <id> --message <text> [--no-stream] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},message:{type:`string`,valueHint:`<text>`,description:`Message to send (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},noStream:{type:`switch`,description:`Use polling instead of SSE streaming`}},exampleArgs:[`--session-id sess_abc123 --message "continue"`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,a=r===`json`;if(t.dryRun){M({would_send:{session_id:n.sessionId,message:n.message,provider:n.provider??`auto`,mode:n.noStream?`polling`:`streaming`},config_file:i},r);return}await Z(()=>Q(async()=>{let t=await X(e,i);n.noStream?jd(await Qn(t,n.sessionId,n.message,{provider:n.provider}),a,{session_id:n.sessionId}):await kd(await $n(t,n.sessionId,n.message,{provider:n.provider}),a,{session_id:n.sessionId})}))}}),Bd=w({description:`List event history for a session`,auth:`apiKey`,usageArgs:`--session-id <id> [--limit <n>] [--all] [--file <path>]`,flags:{sessionId:{type:`string`,valueHint:`<id>`,description:`Session ID (required)`,required:!0},file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`},limit:{type:`number`,valueHint:`<n>`,description:`Maximum number of events to fetch`},all:{type:`switch`,description:`Fetch all pages by following the cursor`}},exampleArgs:[`--session-id sess_abc123`,`--session-id sess_abc123 --all`],notes:Y,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,{items:a,hasMore:o}=await Z(()=>Q(async()=>{let t=await X(e,i);return Pd(async e=>{let r=await Gn(t,n.sessionId,{provider:n.provider,limit:n.limit,page_token:e});return{items:r.events,hasMore:r.has_more,nextPage:r.next_page}},n.all)}));if(r===`json`){M({events:rr(a),has_more:o},r);return}if(a.length===0){j(`No events found.`);return}let s=[`#`,`TYPE`,`CONTENT`],c=a.map((e,t)=>{let n=``;return n=e.type===`message`?(e.content??``).slice(0,60):e.type===`tool_use`?e.tool_name??``:e.type===`tool_result`?(e.content??``).slice(0,60):e.type===`status`?e.status??``:e.type===`error`?(e.content??``).slice(0,60):e.raw_type,[String(t+1),e.type,n]});for(let e of N(s,c))j(e);j(`\nTotal: ${a.length}`),o&&j(`More events available. Use --all to fetch all.`)}});const Vd=[`custom`,`official`,`all`];var Hd=w({description:`List skills from the provider's skill catalog`,auth:`apiKey`,usageArgs:`[--source custom|official|all] [--provider <name>] [--file <path>]`,flags:{file:{type:`string`,valueHint:`<path>`,description:`Config file path (default: agents.yaml)`},source:{type:`string`,valueHint:`<source>`,description:`Skill catalog: custom (workspace-uploaded, default), official (built-in), or all (both catalogs in one call)`},provider:{type:`string`,valueHint:`<name>`,description:`Target provider`}},exampleArgs:[``,`--source official`,`--source all --output json`,`--source custom --provider bailian`],notes:[...Y,`Providers without a skill listing API (e.g. ark) return an empty list.`,"For agent-driven skill selection, use `--source all --output json`: one call returns both catalogs with per-skill `source` and `description` fields to pick from.",`When generating a task that needs a suitable skill, call this command to match official or custom skills before wiring them into the task.`],validate:e=>e.source&&!Vd.includes(e.source)?`--source must be one of: custom, official, all.`:void 0,async run(e){let{settings:t,flags:n}=e,r=T(t.output),i=n.file??`agents.yaml`,a=n.source??`custom`,o=await Z(()=>Q(async()=>{let t=await X(e,i);if(a!==`all`)return qn(t,{provider:n.provider,source:a});let[r,o]=await Promise.all([qn(t,{provider:n.provider,source:`custom`}),qn(t,{provider:n.provider,source:`official`})]);return[...r,...o]}));if(r===`json`){M({source:a,skills:o},r);return}if(o.length===0){j(a===`all`?`No skills found.`:`No ${a} skills found.`);return}let s=[`ID`,`NAME`,`SOURCE`,`STATUS`,`VERSION`,`CREATED`],c=o.map(e=>[e.id,e.name.slice(0,32),e.source,e.status,e.latest_version??`-`,e.created_at??`-`]);for(let e of N(s,c))j(e);j(`\nTotal: ${o.length} (${a})`)}});const $={loginInfo:`zeldaEasy.cornerstone-portal.cs-console.loginInfo`,initSpace:`zeldaEasy.bailian-dash-workspace.space.initSpace`,queryBuyResult:`zeldaEasy.bailian-commerce.bill.queryBuyPostpaidResult`,commodityOrderInfo:`zeldaEasy.bailian-commerce.bill.postpaidCommodityOrderInfo`,buyCommodity:`zeldaEasy.bailian-commerce.bill.buyPostpaidCommodity`},Ud={accessKeyId:{type:`string`,valueHint:`<id>`,description:`Alibaba Cloud Access Key ID`},accessKeySecret:{type:`string`,valueHint:`<secret>`,description:`Alibaba Cloud Access Key Secret`},securityToken:{type:`string`,valueHint:`<token>`,description:`Alibaba Cloud STS Security Token (optional)`}},Wd=1e3;function Gd(e){return new Promise(t=>setTimeout(t,e))}function Kd(e){return e?.data?.DataV2?.data?.data}function qd(e){let t=e?.data?.data;if(!Array.isArray(t)||t.length===0)return;let n=(t.find(e=>e?.defaultAgent===!0)??t[0])?.tenantId,r=typeof n==`string`?Number(n):n;return typeof r==`number`&&Number.isFinite(r)?r:void 0}var Jd=w({description:`Initialize Bailian workspace and activate postpaid services`,auth:`none`,usageArgs:`--access-key-id <id> --access-key-secret <secret> [--security-token <token>]`,flags:Ud,exampleArgs:[`--access-key-id LTAIxxxxx --access-key-secret xxxxx`],async run(e){let{settings:n,flags:r}=e,i=T(n.output);if(n.dryRun){M({apis:[{step:0,api:`GenerateCLIAccessToken`,description:`Generate CLI access token from AK/SK`},{step:1,api:$.loginInfo,description:`Check login & workspace status`},{step:2,api:$.initSpace,description:`Initialize workspace (if needed)`},{step:3,api:`CreateUser`,description:`Create console user via BailianControl OpenAPI (CreateUser)`},{step:4,api:`ListWorkspaces`,description:`List workspaces to resolve agentId`},{step:5,api:`ResetPolicies4Agent`,description:`Authorize user permissions`},{step:6,api:$.queryBuyResult,description:`Query postpaid order status`},{step:7,api:$.commodityOrderInfo,description:`Query commodity activation status`},{step:8,api:$.buyCommodity,description:`Activate postpaid commodities (if needed)`}]},i);return}let{accessKeyId:o,accessKeySecret:s}=r;if(!o||!s)throw new t(`workspace init requires --access-key-id and --access-key-secret.`,a.USAGE);let c=r.securityToken||void 0,l=(await ge({identity:e.identity,settings:n,baseUrl:e.client.baseUrl,accessKeyId:o,accessKeySecret:s,securityToken:c})).cliAccessToken;if(!l)throw new t(`Failed to generate CLI access token from AK/SK.`,a.GENERAL);let u=ce(n),d={region:u.consoleRegion,site:u.consoleSite,...u.consoleSwitchAgent==null?{}:{switchAgent:u.consoleSwitchAgent},token:l},f=n.verbose,p=async(e,r={})=>{f&&process.stderr.write(`> ${e}\n`);try{let t=await y(d,n.timeout,{api:e,data:r},n);return f&&process.stderr.write(`< ${JSON.stringify(t)}\n`),t}catch(e){if(f){let n=e instanceof t?e.rawResponse??e.message:String(e);process.stderr.write(`< ERROR: ${n}\n`)}throw e}};j(`Checking workspace status...`);let m=Kd(await p($.loginInfo));m?.spaceInited===!0?j(`Workspace already initialized.`):(j(`Initializing workspace...`),await p($.initSpace),j(`Workspace initialized.`));let h=m?.aliyun?.uid;if(typeof h!=`string`||h.length===0)throw new t(`Console login info did not include aliyun.uid.`,a.GENERAL);let g={identity:e.identity,settings:n,baseUrl:e.client.baseUrl,regionId:u.consoleRegion,accessKeyId:o,accessKeySecret:s,securityToken:c};try{await S({...g,reqDTO:{outerKey:h,nickName:h,userName:h}})}catch(e){if(!(e instanceof t)||!/already exists/i.test(e.message))throw e;j(`Console user already exists, continuing.`)}j(`Resolving workspace agent...`);let _=qd(await Me(g));if(_==null)throw new t(`Could not resolve agentId from ListWorkspaces response.`,a.GENERAL,`Re-run with --verbose to inspect the ListWorkspaces response body.`);j(`Authorizing user permissions...`),await it({...g,outerKey:h,agentId:_,policyIndexList:[1]}),await Yd(p,i)}});async function Yd(e,n){j(`Checking service activation status...`);let r;for(let t=0;t<20;t++){let n=Kd(await e($.queryBuyResult));if(r=typeof n==`string`?n:n?.result,r!==`buying`)break;t===0&&j(`Service activation in progress, polling...`),await Gd(Wd)}if(r===`fail`)throw new t(`Service activation failed.`,a.GENERAL);if(r===`success`){await Qd(e,n);return}await Zd(e,n)}function Xd(e){let t=Kd(e);return Array.isArray(t)?t:[]}async function Zd(e,t){let n=Xd(await e($.commodityOrderInfo)),r=n.filter(e=>e.status===11);if(r.length>0){j(`Warning: Some services are overdue:`);for(let e of r)j(` - ${e.commodityCode}`)}let i=n.filter(e=>e.status===1);if(i.length>0){j(`Activating ${i.length} postpaid services...`),await e($.buyCommodity),await Qd(e,t);return}M({status:`ready`,activeServices:n.filter(e=>e.status===10).map(e=>e.commodityCode)},t)}async function Qd(e,n){j(`Waiting for services to activate...`);for(let t=0;t<20;t++){let t=Xd(await e($.commodityOrderInfo));if(t.filter(e=>e.status!==10&&e.status!==11).length===0){let e=t.filter(e=>e.status===11);if(e.length>0){j(`Warning: Some services are overdue:`);for(let t of e)j(` - ${t.commodityCode}`)}M({status:`ready`,activeServices:t.filter(e=>e.status===10).map(e=>e.commodityCode)},n);return}await Gd(Wd)}throw new t(`Timed out waiting for services to activate.`,a.TIMEOUT)}var $d=w({description:`Install or upgrade an allowlisted Command Pack`,auth:`none`,usageArgs:`--package <name[@version]>`,flags:{package:{type:`string`,valueHint:`<name[@version]>`,description:`Allowlisted Command Pack package and optional version or tag`,required:!0}},exampleArgs:[`--package @ali/bailian-plugin-agent`,`--package @ali/bailian-plugin-agent@beta`],async run(e){M({installed:await e.commandPacks.install(e.flags.package)},T(e.settings.output))}}),ef=w({description:`Link an allowlisted local Command Pack for development`,auth:`none`,usageArgs:`--path <directory>`,flags:{path:{type:`string`,valueHint:`<directory>`,description:`Local Command Pack package directory`,required:!0}},exampleArgs:[`--path ../bailian-plugin-agent`],async run(e){M({linked:await e.commandPacks.link(e.flags.path)},T(e.settings.output))}}),tf=w({description:`List installed Command Packs and their load status`,auth:`none`,exampleArgs:[``,`--output json`],async run(e){let t=await e.commandPacks.list(),n=T(e.settings.output);if(n===`json`){M({command_packs:t},n);return}if(t.length===0){j(`No Command Packs installed.`);return}let r=t.map(e=>[e.name,e.version??`-`,e.source,e.status,e.commands.join(`, `)||e.error||`-`]);for(let e of N([`NAME`,`VERSION`,`SOURCE`,`STATUS`,`COMMANDS / ERROR`],r))j(e)}}),nf=w({description:`Remove an installed Command Pack`,auth:`none`,usageArgs:`--name <package>`,flags:{name:{type:`string`,valueHint:`<package>`,description:`Allowlisted Command Pack package name`,required:!0}},exampleArgs:[`--name @ali/bailian-plugin-agent`],async run(e){await e.commandPacks.remove(e.flags.name),M({removed:e.flags.name},T(e.settings.output))}});export{Ac as advisorRecommend,Ao as appCall,Mo as appList,jr as authGenerateAccessToken,Or as authLogin,Ar as authLogout,kr as authStatus,To as configAgent,yi as configList,vi as configSet,_i as configShow,Ba as configUi,bi as configUse,bs as consoleCall,Tl as datasetDelete,wl as datasetGet,Cl as datasetList,Sl as datasetUpload,Dl as datasetValidate,mu as deployAudioCreate,xu as deployDelete,_u as deployGet,hu as deployImageCreate,gu as deployList,vu as deployModels,yu as deployScale,pu as deployTextCreate,bu as deployUpdate,ys as fileUpload,Vl as finetuneAudioCreate,Gl as finetuneCancel,su as finetuneCapability,Zl as finetuneCheckpoints,Kl as finetuneDelete,Ql as finetuneExport,Wl as finetuneGet,Hl as finetuneImageCreate,Ul as finetuneList,Xl as finetuneLogs,Bl as finetuneTextCreate,ru as finetuneWatch,Kr as imageEdit,Hr as imageGenerate,Jo as knowledgeChat,Bo as knowledgeRetrieve,Ho as knowledgeSearch,yd as managedAgentApply,bd as managedAgentDestroy,Xu as managedAgentInit,vd as managedAgentPlan,Nd as managedAgentSessionCreate,Ld as managedAgentSessionDelete,Bd as managedAgentSessionEvents,Id as managedAgentSessionGet,Fd as managedAgentSessionList,Rd as managedAgentSessionRun,zd as managedAgentSessionSend,Hd as managedAgentSkillList,wd as managedAgentStateImport,xd as managedAgentStateList,Cd as managedAgentStateRm,Sd as managedAgentStateShow,hd as managedAgentValidate,is as mcpCall,os as mcpList,ss as mcpTools,No as memoryAdd,Lo as memoryDelete,Fo as memoryList,Ro as memoryProfileCreate,zo as memoryProfileGet,Po as memorySearch,Io as memoryUpdate,Hc as modelList,uc as pipelineRun,hc as pipelineValidate,$d as pluginInstall,ef as pluginLink,tf as pluginList,nf as pluginRemove,xl as quotaCheck,ml as quotaHistory,tl as quotaList,sl as quotaRequest,ls as searchWeb,_s as speechRecognize,ms as speechSynthesize,Pr as textChat,Vr as textOmni,Uu as tokenPlanAddMember,Bu as tokenPlanAssignSeats,Iu as tokenPlanCreateKey,Mu as tokenPlanListSeats,ko as update,Vs as usageFree,Ks as usageFreetier,sc as usageStats,cc as usageSummary,ei as videoDownload,Zr as videoEdit,Xr as videoGenerate,Qr as videoRef,$r as videoTaskGet,ii as visionDescribe,Jd as workspaceInit,qc as workspaceList};
|