syluno 0.1.0 → 0.2.0

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/syluno.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import e from"node:fs";import t from"node:os";import{spawn as n}from"node:child_process";import r from"node:path";import i from"node:readline";import a from"node:crypto";var o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=/* @__PURE__ */ o((e=>{
2
+ import e from"node:fs";import t from"node:os";import n from"node:path";import r from"node:readline";import i from"node:crypto";import{spawn as a}from"node:child_process";var o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=/* @__PURE__ */ o((e=>{
3
3
  /**
4
4
  * @license React
5
5
  * react.production.min.js
@@ -9,7 +9,7 @@ import e from"node:fs";import t from"node:os";import{spawn as n}from"node:child_
9
9
  * This source code is licensed under the MIT license found in the
10
10
  * LICENSE file in the root directory of this source tree.
11
11
  */
12
- var t=Symbol.for(`react.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.provider`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.iterator;function p(e){return typeof e!=`object`||!e?null:(e=f&&e[f]||e[`@@iterator`],typeof e==`function`?e:null)}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,g={};function _(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}_.prototype.isReactComponent={},_.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`setState(...): takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},_.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function v(){}v.prototype=_.prototype;function y(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}var b=y.prototype=new v;b.constructor=y,h(b,_.prototype),b.isPureReactComponent=!0;var x=Array.isArray,S=Object.prototype.hasOwnProperty,C={current:null},w={key:!0,ref:!0,__self:!0,__source:!0};function T(e,n,r){var i,a={},o=null,s=null;if(n!=null)for(i in n.ref!==void 0&&(s=n.ref),n.key!==void 0&&(o=``+n.key),n)S.call(n,i)&&!w.hasOwnProperty(i)&&(a[i]=n[i]);var c=arguments.length-2;if(c===1)a.children=r;else if(1<c){for(var l=Array(c),u=0;u<c;u++)l[u]=arguments[u+2];a.children=l}if(e&&e.defaultProps)for(i in c=e.defaultProps,c)a[i]===void 0&&(a[i]=c[i]);return{$$typeof:t,type:e,key:o,ref:s,props:a,_owner:C.current}}function ee(e,n){return{$$typeof:t,type:e.type,key:n,ref:e.ref,props:e.props,_owner:e._owner}}function E(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function te(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var D=/\/+/g;function O(e,t){return typeof e==`object`&&e&&e.key!=null?te(``+e.key):t.toString(36)}function k(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0}}if(c)return c=e,o=o(c),e=a===``?`.`+O(c,0):a,x(o)?(i=``,e!=null&&(i=e.replace(D,`$&/`)+`/`),k(o,r,i,``,function(e){return e})):o!=null&&(E(o)&&(o=ee(o,i+(!o.key||c&&c.key===o.key?``:(``+o.key).replace(D,`$&/`)+`/`)+e)),r.push(o)),1;if(c=0,a=a===``?`.`:a+`:`,x(e))for(var l=0;l<e.length;l++){s=e[l];var u=a+O(s,l);c+=k(s,r,i,u,o)}else if(u=p(e),typeof u==`function`)for(e=u.call(e),l=0;!(s=e.next()).done;)s=s.value,u=a+O(s,l++),c+=k(s,r,i,u,o);else if(s===`object`)throw r=String(e),Error(`Objects are not valid as a React child (found: `+(r===`[object Object]`?`object with keys {`+Object.keys(e).join(`, `)+`}`:r)+`). If you meant to render a collection of children, use an array instead.`);return c}function A(e,t,n){if(e==null)return e;var r=[],i=0;return k(e,r,``,``,function(e){return t.call(n,e,i++)}),r}function ne(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(t){(e._status===0||e._status===-1)&&(e._status=1,e._result=t)},function(t){(e._status===0||e._status===-1)&&(e._status=2,e._result=t)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var j={current:null},M={transition:null},N={ReactCurrentDispatcher:j,ReactCurrentBatchConfig:M,ReactCurrentOwner:C};function P(){throw Error(`act(...) is not supported in production builds of React.`)}e.Children={map:A,forEach:function(e,t,n){A(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return A(e,function(){t++}),t},toArray:function(e){return A(e,function(e){return e})||[]},only:function(e){if(!E(e))throw Error(`React.Children.only expected to receive a single React element child.`);return e}},e.Component=_,e.Fragment=r,e.Profiler=a,e.PureComponent=y,e.StrictMode=i,e.Suspense=l,e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=N,e.act=P,e.cloneElement=function(e,n,r){if(e==null)throw Error(`React.cloneElement(...): The argument must be a React element, but you passed `+e+`.`);var i=h({},e.props),a=e.key,o=e.ref,s=e._owner;if(n!=null){if(n.ref!==void 0&&(o=n.ref,s=C.current),n.key!==void 0&&(a=``+n.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(l in n)S.call(n,l)&&!w.hasOwnProperty(l)&&(i[l]=n[l]===void 0&&c!==void 0?c[l]:n[l])}var l=arguments.length-2;if(l===1)i.children=r;else if(1<l){c=Array(l);for(var u=0;u<l;u++)c[u]=arguments[u+2];i.children=c}return{$$typeof:t,type:e.type,key:a,ref:o,props:i,_owner:s}},e.createContext=function(e){return e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null},e.Provider={$$typeof:o,_context:e},e.Consumer=e},e.createElement=T,e.createFactory=function(e){var t=T.bind(null,e);return t.type=e,t},e.createRef=function(){return{current:null}},e.forwardRef=function(e){return{$$typeof:c,render:e}},e.isValidElement=E,e.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:ne}},e.memo=function(e,t){return{$$typeof:u,type:e,compare:t===void 0?null:t}},e.startTransition=function(e){var t=M.transition;M.transition={};try{e()}finally{M.transition=t}},e.unstable_act=P,e.useCallback=function(e,t){return j.current.useCallback(e,t)},e.useContext=function(e){return j.current.useContext(e)},e.useDebugValue=function(){},e.useDeferredValue=function(e){return j.current.useDeferredValue(e)},e.useEffect=function(e,t){return j.current.useEffect(e,t)},e.useId=function(){return j.current.useId()},e.useImperativeHandle=function(e,t,n){return j.current.useImperativeHandle(e,t,n)},e.useInsertionEffect=function(e,t){return j.current.useInsertionEffect(e,t)},e.useLayoutEffect=function(e,t){return j.current.useLayoutEffect(e,t)},e.useMemo=function(e,t){return j.current.useMemo(e,t)},e.useReducer=function(e,t,n){return j.current.useReducer(e,t,n)},e.useRef=function(e){return j.current.useRef(e)},e.useState=function(e){return j.current.useState(e)},e.useSyncExternalStore=function(e,t,n){return j.current.useSyncExternalStore(e,t,n)},e.useTransition=function(){return j.current.useTransition()},e.version=`18.3.1`})),c=/* @__PURE__ */ o(((e,t)=>{t.exports=s()}));c();var l=[`syluno {0}验证码:{1}`,`{0}不能超过 {1} 个字`,`不允许的模型 {0}`,`云端不可达:{0}`,`你的{0}验证码`,`你的验证码是 {0},10 分钟内有效。如果不是你本人操作,请忽略这封邮件。`,`单个文件不能超过 {0} MB`],u=/* @__PURE__ */ o((e=>{
12
+ var t=Symbol.for(`react.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.provider`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.iterator;function p(e){return typeof e!=`object`||!e?null:(e=f&&e[f]||e[`@@iterator`],typeof e==`function`?e:null)}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,g={};function _(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}_.prototype.isReactComponent={},_.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`setState(...): takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},_.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function v(){}v.prototype=_.prototype;function y(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}var b=y.prototype=new v;b.constructor=y,h(b,_.prototype),b.isPureReactComponent=!0;var x=Array.isArray,S=Object.prototype.hasOwnProperty,C={current:null},ee={key:!0,ref:!0,__self:!0,__source:!0};function w(e,n,r){var i,a={},o=null,s=null;if(n!=null)for(i in n.ref!==void 0&&(s=n.ref),n.key!==void 0&&(o=``+n.key),n)S.call(n,i)&&!ee.hasOwnProperty(i)&&(a[i]=n[i]);var c=arguments.length-2;if(c===1)a.children=r;else if(1<c){for(var l=Array(c),u=0;u<c;u++)l[u]=arguments[u+2];a.children=l}if(e&&e.defaultProps)for(i in c=e.defaultProps,c)a[i]===void 0&&(a[i]=c[i]);return{$$typeof:t,type:e,key:o,ref:s,props:a,_owner:C.current}}function te(e,n){return{$$typeof:t,type:e.type,key:n,ref:e.ref,props:e.props,_owner:e._owner}}function ne(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function T(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var re=/\/+/g;function ie(e,t){return typeof e==`object`&&e&&e.key!=null?T(``+e.key):t.toString(36)}function ae(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0}}if(c)return c=e,o=o(c),e=a===``?`.`+ie(c,0):a,x(o)?(i=``,e!=null&&(i=e.replace(re,`$&/`)+`/`),ae(o,r,i,``,function(e){return e})):o!=null&&(ne(o)&&(o=te(o,i+(!o.key||c&&c.key===o.key?``:(``+o.key).replace(re,`$&/`)+`/`)+e)),r.push(o)),1;if(c=0,a=a===``?`.`:a+`:`,x(e))for(var l=0;l<e.length;l++){s=e[l];var u=a+ie(s,l);c+=ae(s,r,i,u,o)}else if(u=p(e),typeof u==`function`)for(e=u.call(e),l=0;!(s=e.next()).done;)s=s.value,u=a+ie(s,l++),c+=ae(s,r,i,u,o);else if(s===`object`)throw r=String(e),Error(`Objects are not valid as a React child (found: `+(r===`[object Object]`?`object with keys {`+Object.keys(e).join(`, `)+`}`:r)+`). If you meant to render a collection of children, use an array instead.`);return c}function E(e,t,n){if(e==null)return e;var r=[],i=0;return ae(e,r,``,``,function(e){return t.call(n,e,i++)}),r}function oe(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(t){(e._status===0||e._status===-1)&&(e._status=1,e._result=t)},function(t){(e._status===0||e._status===-1)&&(e._status=2,e._result=t)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var D={current:null},O={transition:null},se={ReactCurrentDispatcher:D,ReactCurrentBatchConfig:O,ReactCurrentOwner:C};function k(){throw Error(`act(...) is not supported in production builds of React.`)}e.Children={map:E,forEach:function(e,t,n){E(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return E(e,function(){t++}),t},toArray:function(e){return E(e,function(e){return e})||[]},only:function(e){if(!ne(e))throw Error(`React.Children.only expected to receive a single React element child.`);return e}},e.Component=_,e.Fragment=r,e.Profiler=a,e.PureComponent=y,e.StrictMode=i,e.Suspense=l,e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=se,e.act=k,e.cloneElement=function(e,n,r){if(e==null)throw Error(`React.cloneElement(...): The argument must be a React element, but you passed `+e+`.`);var i=h({},e.props),a=e.key,o=e.ref,s=e._owner;if(n!=null){if(n.ref!==void 0&&(o=n.ref,s=C.current),n.key!==void 0&&(a=``+n.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(l in n)S.call(n,l)&&!ee.hasOwnProperty(l)&&(i[l]=n[l]===void 0&&c!==void 0?c[l]:n[l])}var l=arguments.length-2;if(l===1)i.children=r;else if(1<l){c=Array(l);for(var u=0;u<l;u++)c[u]=arguments[u+2];i.children=c}return{$$typeof:t,type:e.type,key:a,ref:o,props:i,_owner:s}},e.createContext=function(e){return e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null},e.Provider={$$typeof:o,_context:e},e.Consumer=e},e.createElement=w,e.createFactory=function(e){var t=w.bind(null,e);return t.type=e,t},e.createRef=function(){return{current:null}},e.forwardRef=function(e){return{$$typeof:c,render:e}},e.isValidElement=ne,e.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:oe}},e.memo=function(e,t){return{$$typeof:u,type:e,compare:t===void 0?null:t}},e.startTransition=function(e){var t=O.transition;O.transition={};try{e()}finally{O.transition=t}},e.unstable_act=k,e.useCallback=function(e,t){return D.current.useCallback(e,t)},e.useContext=function(e){return D.current.useContext(e)},e.useDebugValue=function(){},e.useDeferredValue=function(e){return D.current.useDeferredValue(e)},e.useEffect=function(e,t){return D.current.useEffect(e,t)},e.useId=function(){return D.current.useId()},e.useImperativeHandle=function(e,t,n){return D.current.useImperativeHandle(e,t,n)},e.useInsertionEffect=function(e,t){return D.current.useInsertionEffect(e,t)},e.useLayoutEffect=function(e,t){return D.current.useLayoutEffect(e,t)},e.useMemo=function(e,t){return D.current.useMemo(e,t)},e.useReducer=function(e,t,n){return D.current.useReducer(e,t,n)},e.useRef=function(e){return D.current.useRef(e)},e.useState=function(e){return D.current.useState(e)},e.useSyncExternalStore=function(e,t,n){return D.current.useSyncExternalStore(e,t,n)},e.useTransition=function(){return D.current.useTransition()},e.version=`18.3.1`})),c=/* @__PURE__ */ o(((e,t)=>{t.exports=s()}));c();var l=[`syluno {0}验证码:{1}`,`{0}不能超过 {1} 个字`,`不允许的模型 {0}`,`云端不可达:{0}`,`你的{0}验证码`,`你的验证码是 {0},10 分钟内有效。如果不是你本人操作,请忽略这封邮件。`,`单个文件不能超过 {0} MB`],u=/* @__PURE__ */ o((e=>{
13
13
  /**
14
14
  * @license React
15
15
  * react-jsx-runtime.production.min.js
@@ -19,10 +19,10 @@ var t=Symbol.for(`react.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`rea
19
19
  * This source code is licensed under the MIT license found in the
20
20
  * LICENSE file in the root directory of this source tree.
21
21
  */
22
- c().__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner}));(/* @__PURE__ */ o(((e,t)=>{t.exports=u()})))();const d=[{code:`zh-CN`,name:`简体中文`},{code:`zh-TW`,name:`繁體中文`},{code:`en`,name:`English`},{code:`ja`,name:`日本語`},{code:`ko`,name:`한국어`},{code:`es`,name:`Español`},{code:`fr`,name:`Français`},{code:`de`,name:`Deutsch`},{code:`pt`,name:`Português`},{code:`it`,name:`Italiano`},{code:`ru`,name:`Русский`},{code:`tr`,name:`Türkçe`},{code:`ar`,name:`العربية`,rtl:!0},{code:`hi`,name:`हिन्दी`},{code:`id`,name:`Bahasa Indonesia`},{code:`vi`,name:`Tiếng Việt`},{code:`th`,name:`ไทย`}];try{import.meta.glob(`./locales/[a-z]*.json`)}catch{}let f={};function p(e){let t=e.toLowerCase().replace(`_`,`-`);return t.startsWith(`zh`)?/tw|hk|mo|hant/.test(t)?`zh-TW`:`zh-CN`:d.find(e=>e.code===t.split(/[-.]/)[0])?.code??null}function m(e,t){f=t}function h(e,t){let n=f[e]??e;return t?n.replace(/\{(\d+)\}/g,(e,n)=>String(t[+n]??``)):n}const g=e=>e,_=l.map(e=>({k:e,re:RegExp(`^`+e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`).replace(/\\\{(\d+)\\\}/g,`([\\s\\S]*?)`)+`$`)}));function v(e){if(!e)return``;if(f[e])return f[e];for(let t of _){let n=e.match(t.re);if(n)return h(t.k,n.slice(1))}return e}function y(){let e=process.argv.findIndex(e=>e===`--lang`||e.startsWith(`--lang=`)),t=e<0?``:process.argv[e].includes(`=`)?process.argv[e].split(`=`)[1]:process.argv[e+1]??``;e>=0&&process.argv.splice(e,process.argv[e].includes(`=`)?1:2);for(let e of[t,process.env.SYLUNO_LANG,process.env.LC_ALL,process.env.LC_MESSAGES,process.env.LANG]){if(!e||e===`C`||e.startsWith(`C.`)||e===`POSIX`)continue;let t=p(e);if(t)return t}return`en`}const b=y();let x={};try{x=JSON.parse(e.readFileSync(new URL(`./locales.json`,import.meta.url),`utf8`))}catch{}m(b,x[b]??{});const S=[{id:`voice`,label:h(`语音`),hint:h(`转写、同传、朗读、语音问答`)},{id:`weather`,label:h(`天气`),hint:h(`天气、预报、空气`)},{id:`todo`,label:h(`待办与笔记`),hint:h(`待办、备忘、习惯打卡`)},{id:`time`,label:h(`计时与闹钟`),hint:h(`时钟、计时器、秒表、番茄钟、闹钟`)},{id:`health`,label:h(`健康运动`),hint:h(`心率、步数、喝水、呼吸`)},{id:`relax`,label:h(`放松睡眠`),hint:h(`白噪音、冥想、睡前`)},{id:`comm`,label:h(`通讯`),hint:h(`电话、短信、消息`)},{id:`work`,label:h(`会议办公`),hint:h(`会议纪要、专注、效率`)},{id:`travel`,label:h(`出行`),hint:h(`翻译、导航、行程`)},{id:`home`,label:h(`家居环境`),hint:h(`温湿度、灯光、家电`)},{id:`tools`,label:h(`实用工具`),hint:h(`计算、换算、随机决定`)},{id:`logic`,label:h(`编排控制`),hint:h(`变量、条件、循环:让树能记住状态、做判断、反复执行`)}],C=[{id:`figure`,label:h(`大数字`),hint:h(`一屏一个主要数值`)},{id:`ring`,label:h(`圆环表盘`),hint:h(`进度环、表盘`)},{id:`list`,label:h(`列表`),hint:h(`一条一条的记录`)},{id:`grid`,label:h(`宫格按键`),hint:h(`按键、格子、拨号盘`)},{id:`text`,label:h(`文字流`),hint:h(`字幕、对话、长文本`)},{id:`motion`,label:h(`动效图形`),hint:h(`动画、波形、转盘`)},{id:`form`,label:h(`设置面板`),hint:h(`开关、选项、输入`)}];h(`场景`),h(`界面风格`);function w(e){let t={};try{t=JSON.parse(e[`manifest.json`]??``)}catch{}let n=e=>Array.isArray(t[e])?t[e].map(String):null;return{scenes:n(`scenes`),styles:n(`styles`)}}function T(e,t){try{let n=JSON.parse(e[`manifest.json`]);for(let[e,r]of Object.entries(t))r&&(n[e]=r);return{...e,"manifest.json":JSON.stringify(n,null,2)+`
23
- `}}catch{return e}}function ee(e,t){let n=e===`scenes`?S:C,r=h(e===`scenes`?`场景`:`界面风格`);if(t===null)return h(`还没有勾选{0}`,[r]);let i=t.filter(e=>!n.some(t=>t.id===e));return i.length?h(`{0}不在预置表里:{1}`,[r,i.join(h(`、`))]):t.length>3?h(`{0}最多选 3 个`,[r]):null}h(`热门`),h(`按收藏数从高到低;收藏数相同时,最近发布的在前`),h(`新上架`),h(`按第一颗种子的发布时间,从新到旧`),h(`最近更新`),h(`按最新一颗种子的发布时间,从新到旧`);const E={chars:500,nodes:200,depth:24,listItems:200,textChars:2e3},te={len:[`(x)`,h(`文本长度或列表长度`)],min:[`(a, b, …)`,h(`最小值`)],max:[`(a, b, …)`,h(`最大值`)],abs:[`(x)`,h(`绝对值`)],floor:[`(x)`,h(`向下取整`)],ceil:[`(x)`,h(`向上取整`)],round:[`(x)`,h(`四舍五入`)],num:[`(x)`,h(`转成数字,失败为 0`)],text:[`(x)`,h(`转成文本`)],contains:[h(`(文本或列表, x)`),h(`是否包含`)],has:[`(x)`,h(`是否有值(不是空、不是 null)`)],now:[`()`,h(`当前时间戳(毫秒)`)],hour:[`()`,h(`当前小时 0~23`)],first:[h(`(列表)`),h(`第一项`)],last:[h(`(列表)`),h(`最后一项`)],push:[h(`(列表, x)`),h(`在末尾加一项后的新列表`)],rest:[h(`(列表)`),h(`去掉第一项后的新列表`)],join:[h(`(列表, 分隔符)`),h(`拼成文本`)]},D=[`||`,`&&`,`==`,`!=`,`<=`,`>=`,`<`,`>`,`+`,`-`,`*`,`/`,`%`,`!`,`?`,`:`,`(`,`)`,`[`,`]`,`,`,`.`,`@`];function O(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n++;continue}if(/\d/.test(r)||r===`.`&&/\d/.test(e[n+1]??``)){let r=e.slice(n).match(/^\d*\.?\d+(e[+-]?\d+)?/i);t.push({k:`num`,v:r[0]}),n+=r[0].length;continue}if(r===`"`||r===`'`){let i=n+1,a=``;for(;i<e.length&&e[i]!==r;)e[i]===`\\`&&i+1<e.length&&i++,a+=e[i++];if(i>=e.length)throw Error(h(`文本缺少结尾引号`));t.push({k:`str`,v:a}),n=i+1;continue}if(/[A-Za-z_一-龥]/.test(r)){let r=e.slice(n).match(/^[A-Za-z_一-龥][\w一-龥]*/);t.push({k:`id`,v:r[0]}),n+=r[0].length;continue}let i=D.find(t=>e.startsWith(t,n));if(!i)throw Error(h(`不认识的符号 {0}`,[r]));t.push({k:`op`,v:i}),n+=i.length}return t}function k(e){if(e.length>E.chars)throw Error(h(`表达式超过 {0} 个字符`,[E.chars]));let t=O(e),n=0,r=0,i=e=>t[n]&&(e===void 0||t[n].k===`op`&&t[n].v===e)?t[n]:null,a=e=>{if(!i(e))throw Error(h(`缺少 {0}`,[e]));n++},o=(e,t)=>{if(++r>E.nodes)throw Error(h(`表达式太长`));if(t>E.depth)throw Error(h(`表达式嵌套太深`));return e},s=(e,r)=>i=>{let a=e(i+1);for(;t[n]?.k===`op`&&r.includes(t[n].v);){let r=t[n++].v;a=o({t:`bin`,op:r,a,b:e(i+1)},i)}return a},c=e=>{let r=t[n];if(!r)throw Error(h(`表达式不完整`));if(r.k===`num`)return n++,o({t:`lit`,v:+r.v},e);if(r.k===`str`)return n++,o({t:`lit`,v:r.v},e);if(r.k===`op`&&r.v===`(`){n++;let t=f(e+1);return a(`)`),t}if(r.k===`op`&&r.v===`[`){n++;let t=[];if(!i(`]`))for(t.push(f(e+1));i(`,`);)n++,t.push(f(e+1));return a(`]`),o({t:`list`,items:t},e)}if(r.k===`op`&&r.v===`@`){n++;let r=t[n++];a(`.`);let i=t[n++];if(r?.k!==`id`||i?.k!==`id`)throw Error(h(`引用写成 @节点.输出`));return o({t:`ref`,node:r.v,out:i.v},e)}if(r.k===`id`){if(n++,r.v===`true`||r.v===`false`)return o({t:`lit`,v:r.v===`true`},e);if(r.v===`null`)return o({t:`lit`,v:null},e);if(i(`(`)){if(!te[r.v])throw Error(h(`没有函数 {0}`,[r.v]));n++;let t=[];if(!i(`)`))for(t.push(f(e+1));i(`,`);)n++,t.push(f(e+1));return a(`)`),o({t:`call`,fn:r.v,args:t},e)}return o({t:`id`,name:r.v},e)}throw Error(h(`这里不能出现 {0}`,[r.v]))},l=e=>{let r=c(e);for(;;){if(i(`.`)){n++;let i=t[n++];if(i?.k!==`id`)throw Error(h(`. 后面要写字段名`));r=o({t:`get`,a:r,k:{t:`lit`,v:i.v}},e);continue}if(i(`[`)){n++;let t=f(e+1);a(`]`),r=o({t:`get`,a:r,k:t},e);continue}return r}},u=e=>i(`!`)||i(`-`)?(()=>{let r=t[n++].v;return o({t:`un`,op:r,a:u(e+1)},e)})():l(e),d=s(s(s(s(s(s(u,[`*`,`/`,`%`]),[`+`,`-`]),[`<`,`<=`,`>`,`>=`]),[`==`,`!=`]),[`&&`]),[`||`]);function f(e){let t=d(e);if(!i(`?`))return t;n++;let r=f(e+1);a(`:`);let s=f(e+1);return o({t:`if`,c:t,a:r,b:s},e)}let p=f(0);if(n<t.length)throw Error(h(`多余的 {0}`,[t[n].v]));return p}const A=/* @__PURE__ */ new Map;function ne(e){let t=A.get(e);if(!t){try{t=k(e)}catch(e){t=e}A.set(e,t)}if(t instanceof Error)throw t;return t}function j(e){try{return ne(e),null}catch(e){return e.message}}function M(e){let t=[],n=e=>{e.t===`ref`&&t.push({node:e.node,out:e.out}),`a`in e&&e.a&&n(e.a),`b`in e&&e.b&&n(e.b),`c`in e&&e.c&&n(e.c),`k`in e&&e.k&&n(e.k),e.t===`call`&&e.args.forEach(n),e.t===`list`&&e.items.forEach(n)};try{n(ne(e))}catch{}return t}h(`叶`),h(`季`),h(`树`),h(`林`),h(`所有公开发布的叶、季、树汇集的地方,在这里发现、引用、种下`),h(`森林`),h(`创作者中心:自己和所在组织的叶、季、树在这里新建、编写、预览、勾选分类、发布`),h(`种子`),h(`一次发布产生的不可变包,带校验值;树的种子还锁定所用叶和季的版本。设备通过种子安装`),h(`土壤`),h(`设备的硬件与系统。种子落在什么土壤上,就按土壤的条件生长`),h(`树`),h(`一个完整的应用,由根、枝、叶和一个季组成`),h(`根`),h(`树的触发方式:打开、定时、语音唤起或到达某处`),h(`枝`),h(`叶与叶之间的连接:决定界面上的从属,也承载事件到动作、输出到输入的联动`),h(`叶`),h(`最小的功能单元,带有标准化的接口声明`),h(`季`),h(`外观。同一棵树换一个季,结构不变,样子改变`);const N={text:h(`文本`),number:h(`数字`),bool:h(`是否`),time:h(`时刻`),date:h(`日期`),duration:h(`时长(秒)`),enum:h(`选项`),list:h(`列表`),any:h(`任意`)},P={"°C":{dim:`temp`,k:1,b:0},"°F":{dim:`temp`,k:5/9,b:-160/9},"%":{dim:`ratio`},bpm:{dim:`rate`},lux:{dim:`light`},hPa:{dim:`pressure`},m:{dim:`len`,k:1},km:{dim:`len`,k:1e3},g:{dim:`mass`,k:1},kg:{dim:`mass`,k:1e3},ml:{dim:`vol`,k:1},L:{dim:`vol`,k:1e3},天:{dim:`day`},kcal:{dim:`energy`},次:{dim:`count`},个:{dim:`count`},杯:{dim:`count`},步:{dim:`count`},项:{dim:`count`},条:{dim:`count`}},re=/^[a-z][a-zA-Z0-9]{0,23}$/,F={payloadBytes:8192,listItems:200,textChars:2e3,queue:10,actionTimeoutMs:3e3,chainDepth:8,perBranchPerSec:20,htmlKB:64,minDelayMs:50,maxDelayMs:864e5};function I(e,t){if(t.type===`any`||e.type===`any`)return{ok:!0,how:e.type===t.type?`exact`:`loose`};if(e.type===t.type){if(e.type===`number`&&e.unit&&t.unit&&e.unit!==t.unit){let n=P[e.unit],r=P[t.unit];return n&&r&&n.dim===r.dim&&n.k!==void 0&&r.k!==void 0?{ok:!0,how:`convert`,note:`${e.unit} → ${t.unit}`}:{ok:!1,note:h(`单位 {0} 与 {1} 不同`,[e.unit,t.unit])}}return e.type===`list`&&e.of&&t.of&&e.of!==t.of&&t.of!==`text`?{ok:!1,note:h(`列表元素类型不同`)}:e.type===`enum`&&t.values&&e.values?.some(e=>!t.values.includes(e))?{ok:!0,how:`loose`,note:h(`部分选项对方不认识`)}:{ok:!0,how:`exact`}}return t.type===`text`?{ok:!0,how:`convert`,note:h(`{0} → 文本`,[N[e.type]])}:t.type===`list`&&(t.of??`any`)===e.type?{ok:!0,how:`convert`,note:h(`单值放入列表`)}:e.type===`duration`&&t.type===`number`?{ok:!0,how:`convert`,note:h(`时长 → 秒`)}:e.type===`number`&&t.type===`duration`?{ok:!0,how:`loose`,note:h(`按秒理解`)}:e.type===`text`&&[`number`,`bool`,`enum`,`date`,`time`,`duration`].includes(t.type)?{ok:!0,how:`loose`,note:h(`运行时解析文本`)}:e.type===`bool`&&t.type===`number`?{ok:!0,how:`convert`}:{ok:!1,note:h(`{0} 不能接到 {1}`,[N[e.type],N[t.type]])}}function ie(e,t,n){try{if(e==null)return t.default===void 0?{ok:!1,error:h(`缺少值`)}:{ok:!0,value:t.default};switch(t.type){case`any`:return{ok:!0,value:e};case`text`:return{ok:!0,value:(Array.isArray(e)?e.join(h(`、`)):typeof e==`object`?JSON.stringify(e):String(e)).slice(0,F.textChars)};case`number`:case`duration`:{let r=typeof e==`boolean`?+e:typeof e==`number`?e:parseFloat(String(e).replace(/[^\d.+-eE]/g,``));if(!Number.isFinite(r))return{ok:!1,error:h(`不是数字`)};if(n?.unit&&t.unit&&n.unit!==t.unit){let e=P[n.unit],i=P[t.unit];e?.dim===i?.dim&&e.k!==void 0&&i.k!==void 0&&(r=(r*e.k+(e.b??0)-(i.b??0))/i.k)}return t.min!==void 0&&(r=Math.max(t.min,r)),t.max!==void 0&&(r=Math.min(t.max,r)),{ok:!0,value:r}}case`bool`:return{ok:!0,value:typeof e==`string`?/^(true|1|是|yes|开)$/i.test(e.trim()):!!e};case`enum`:{let n=String(e);return t.values?.length&&!t.values.includes(n)?{ok:!1,error:h(`不在选项 {0} 内`,[t.values.join(`/`)])}:{ok:!0,value:n}}case`date`:{let t=new Date(String(e));return isNaN(+t)?{ok:!1,error:h(`不是日期`)}:{ok:!0,value:t.toISOString().slice(0,10)}}case`time`:{let t=String(e).match(/^(\d{1,2}):(\d{2})/);return t?{ok:!0,value:`${t[1].padStart(2,`0`)}:${t[2]}`}:{ok:!1,error:h(`不是时刻`)}}case`list`:{let n=(Array.isArray(e)?e:[e]).slice(0,F.listItems);return!t.of||t.of===`any`?{ok:!0,value:n}:{ok:!0,value:n.map(e=>ie(e,{type:t.of})).filter(e=>e.ok).map(e=>e.value)}}}}catch(e){return{ok:!1,error:String(e)}}}const ae=e=>{let[t,n]=e.split(`:`);return{kind:t,name:n}};function oe(e,t){let n=ae(t);if(n.kind===`event`){let t=e?.events?.[n.name];return t?t.payload??{}:null}if(n.kind===`output`){let t=e?.outputs?.[n.name];return t?{value:t}:null}return null}function se(e,t){let n=ae(t);if(n.kind===`action`){let t=e?.actions?.[n.name];return t?t.params??{}:null}if(n.kind===`input`){let t=e?.inputs?.[n.name];return t?{value:t}:null}return null}function ce(e,t){let n={},r=Object.keys(e);for(let[i,a]of Object.entries(t)){if(e[i]&&I(e[i],a).ok){n[i]=i;continue}let t=r.filter(t=>I(e[t],a).how===`exact`);t.length===1?n[i]=t[0]:!t.length&&r.length===1&&I(e[r[0]],a).ok&&(n[i]=r[0])}return n}function le(e,t,n){let r=[],i=oe(t,e.on),a=se(n,e.do);if(i||r.push(h(`来源 {0} 未声明`,[e.on])),a||r.push(h(`目标 {0} 未声明`,[e.do])),!i||!a)return{ok:!1,problems:r,map:{}};let o={...ce(i,a),...e.map??{}};if(e.when){let t=j(e.when);t&&r.push(h(`条件:{0}`,[t]))}e.delay!==void 0&&e.delay!==0&&!(e.delay>=F.minDelayMs&&e.delay<=F.maxDelayMs)&&r.push(h(`延迟要在 {0} 毫秒到 24 小时之间`,[F.minDelayMs]));for(let[e,t]of Object.entries(a)){let n=o[e];if(n===void 0){t.default===void 0&&r.push(h(`{0} 没有来源也没有默认值`,[e]));continue}if(n.startsWith(`=`)){ie(n.slice(1),t).ok||r.push(h(`{0} 的常量不符合 {1}`,[e,N[t.type]]));continue}if(n.startsWith(`$`)){let t=j(n.slice(1));t&&r.push(h(`{0} 的表达式:{1}`,[e,t]));continue}if(!i[n]){r.push(h(`{0} 对应的 {1} 不存在`,[e,n]));continue}let a=I(i[n],t);a.ok||r.push(h(`{0}:{1}`,[e,a.note]))}return{ok:!r.length,problems:r,map:o}}const ue=e=>e.filter(e=>!e.ok&&e.severity===`error`),de=[h(`清单完整:规范版本、类别、名称、版本号、描述、图标、权限、硬件要求、资源占用都要写明`),h(`版本号遵循“主.次.修订”;删除或改动已有接口属于不兼容变更,必须升主版本号`),h(`接口声明合法:名称以小写字母开头,类型和单位来自规范表,输入和动作参数都带默认值`),h(`声明与实现一致:代码里用到的输出、事件、动作、输入都已声明,声明了的都有实现`),h(`权限最小:代码调用的系统能力都已声明权限,声明了却没用到的会被提示`),h(`界面遵循规范:用 .sy-app 容器搭界面,颜色只引用变量,不引用任何外部资源`),h(`两种显示模式:完整界面与小卡片都要处理`),h(`资源预算:页面不超过 64 KB,内存与存储的声明不超过系统上限`),h(`云端能力已声明:代码调用的转写、同传、翻译、朗读、对话、看图都写在 services 里,并声明所需权限(转写与同传要麦克风,看图要摄像头,翻译与对话要网络)`),h(`分类已勾选:场景(scenes)和界面风格(styles)都从平台预置表里选,每组最多 3 个;可以是空列表(暂不分类),但字段不能没有`)],fe=[h(`有且只有一个根`),h(`枝构成一棵树:每片叶只有一个上游,所有叶都连到根,没有环(枝只决定界面上的从属)`),h(`指定一个季,主色来自这个季的调色板`),h(`用到的叶和季都已在林中发布,且与本树所用规范版本一致`),h(`联动合法:两端是这棵树上的叶,来源和目标都已声明,类型兼容,必填参数都有来源或默认值,条件与表达式语法正确、引用的节点存在`),h(`联动可以成环,但环上至少有一条带延迟的联动;不带延迟的连续联动不超过 8 层`),h(`场景已勾选:场景(scenes)从平台预置表里选,最多 3 个;可以是空列表(暂不分类),但字段不能没有`)];function pe(e){let t=ee(`scenes`,w(e).scenes);return{rule:fe.length-1,ok:!t,severity:`error`,detail:t??void 0}}const me=[h(`种子一经发布不可修改,只能发布新版本`),h(`每颗种子带内容校验值,安装时校验,不一致则拒绝安装`),h(`树的种子锁定所用叶和季的版本;依赖升了主版本时,按锁定版本安装`),h(`种子声明所需的规范版本;设备的规范版本更低时拒绝安装并提示更新系统`)];h(`每次传递的数据都按接口声明校验:类型不符先做安全转换,失败则丢弃并记录`),h(`未声明的字段被丢弃,缺失的字段用默认值,单次数据不超过 8 KB`),h(`动作 3 秒内没有回应视为失败,不阻塞其他叶`),h(`目标叶尚未运行时,动作进入队列(最多 10 条),运行后按顺序送达`),h(`不带延迟的连续联动超过 8 层时熔断并记录;带延迟的联动到点后开启新的一轮,层数从 1 重新计算`),h(`同一条联动每秒最多触发 20 次,超出的丢弃并记录`),h(`条件为假时这次联动不触发;条件或表达式求值出错时丢弃这次联动并记录,不影响其他联动`),h(`同一次事件或输出触发的多条联动,条件与表达式都按触发那一刻的输出快照求值,再按添加顺序送达`),h(`延迟最短 50 毫秒、最长 24 小时;树停止运行时,还没送达的延迟联动一并取消`),h(`一片叶出错只影响它自己,树的其他部分照常运行`),h(`权限不随联动传递:动作在目标叶内执行,只用目标叶自己的权限`),h(`读到不认识的字段一律忽略,不认识的类型按任意值处理,保证新旧版本共存`),h(`同一片叶可能同时以小卡片和完整界面运行:动作的结果必须写入存储或输出,不能只留在界面上`);const he=[[/syluno\.audio\./,`microphone`],[/syluno\.storage\./,`storage`],[/syluno\.notify\(/,`notifications`],[/syluno\.sensors\./,`sensors`],[/syluno\.net\./,`network`],[/syluno\.telephony\./,`phone`]];function ge(e){let t=t=>new Set([...e.matchAll(t)].map(e=>e[1]));return{events:t(/syluno\.io\.emit\(\s*['"]([\w]+)['"]/g),outputs:t(/syluno\.io\.set\(\s*['"]([\w]+)['"]/g),actions:t(/syluno\.io\.on\(\s*['"]([\w]+)['"]/g),inputs:/* @__PURE__ */ new Set([...t(/syluno\.io\.onInput\(\s*['"]([\w]+)['"]/g),...t(/syluno\.inputs\.([a-zA-Z]\w*)/g),...t(/syluno\.inputs\[\s*['"](\w+)['"]\s*\]/g)])}}const _e=(e,t)=>!!e&&e.type in N&&(!e.unit||e.unit in P)&&(e.type!==`enum`||!!e.values?.length)&&(!t||e.default!==void 0),ve=e=>/^\d+\.\d+\.\d+$/.test(e),ye=e=>+(e.split(`.`)[0]??0);function be(e,t){if(!e)return[];let n=[];for(let r of[`inputs`,`outputs`,`events`,`actions`])for(let[i,a]of Object.entries(e[r]??{})){let e=t?.[r]?.[i];if(!e){n.push(h(`删除了 {0}.{1}`,[r,i]));continue}(r===`inputs`||r===`outputs`)&&a.type!==e.type&&n.push(h(`{0}.{1} 类型变了`,[r,i]))}return n}function xe(e,t){let n={};try{n=JSON.parse(e[`manifest.json`]??``)}catch{}let r=e[`index.html`]??``,i=n.io??{},a=[],o=[`spec`,`kind`,`name`,`version`,`description`,`icon`,`permissions`,`requires`,`requirements`].filter(e=>n[e]===void 0||n[e]===``);a.push({rule:0,ok:!o.length,severity:`error`,detail:o.length?h(`缺少 {0}`,[o.join(h(`、`))]):void 0});let s=null;try{s=t?JSON.parse(t[`manifest.json`]):null}catch{s=null}let c=be(s?.io,i),l=ve(String(n.version??``))&&(!c.length||!s||ye(n.version)>ye(s.version));a.push({rule:1,ok:l,severity:`error`,detail:ve(String(n.version??``))?c.length&&!l?h(`{0},需升主版本`,[c.join(h(`,`))]):void 0:h(`版本号格式不对`)});let u=[];for(let[e,t]of Object.entries(i.inputs??{}))(!re.test(e)||!_e(t,!0))&&u.push(h(`输入 {0}`,[e]));for(let[e,t]of Object.entries(i.outputs??{}))(!re.test(e)||!_e(t,!1))&&u.push(h(`输出 {0}`,[e]));for(let[e,t]of Object.entries(i.events??{}))(!re.test(e)||Object.values(t.payload??{}).some(e=>!_e(e,!1)))&&u.push(h(`事件 {0}`,[e]));for(let[e,t]of Object.entries(i.actions??{}))(!re.test(e)||Object.values(t.params??{}).some(e=>!_e(e,!0)))&&u.push(h(`动作 {0}`,[e]));a.push({rule:2,ok:!u.length,severity:`error`,detail:u.length?u.slice(0,4).join(h(`、`)):void 0});let d=ge(r),f=[...[...d.events].filter(e=>!i.events?.[e]).map(e=>h(`事件 {0}`,[e])),...[...d.outputs].filter(e=>!i.outputs?.[e]).map(e=>h(`输出 {0}`,[e])),...[...d.actions].filter(e=>!i.actions?.[e]).map(e=>h(`动作 {0}`,[e])),...[...d.inputs].filter(e=>!i.inputs?.[e]).map(e=>h(`输入 {0}`,[e]))],p=[...Object.keys(i.events??{}).filter(e=>!d.events.has(e)).map(e=>h(`事件 {0}`,[e])),...Object.keys(i.outputs??{}).filter(e=>!d.outputs.has(e)).map(e=>h(`输出 {0}`,[e])),...Object.keys(i.actions??{}).filter(e=>!d.actions.has(e)).map(e=>h(`动作 {0}`,[e]))];a.push({rule:3,ok:!f.length&&!p.length,severity:f.length||p.length?`error`:`warn`,detail:f.length?h(`未声明:{0}`,[f.join(h(`、`))]):p.length?h(`未实现:{0}`,[p.join(h(`、`))]):void 0});let m=Array.isArray(n.permissions)?n.permissions:[],g=he.filter(([e])=>e.test(r)).map(([,e])=>e),_=g.filter(e=>!m.includes(e)),v=m.filter(e=>!g.includes(e)&&![`microphone`,`camera`,`location`,`network`].includes(e));a.push({rule:4,ok:!_.length&&!v.length,severity:_.length?`error`:`warn`,detail:_.length?h(`缺少权限 {0}`,[_.join(h(`、`))]):v.length?h(`未用到 {0}`,[v.join(h(`、`))]):void 0});let y=[...r.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/gi)].map(e=>e[1]).join(`
24
- `).match(/#[0-9a-f]{3,8}\b|rgba?\(\s*\d/gi),b=/(src|href)\s*=\s*["']?(https?:)?\/\/|url\(\s*["']?(https?:)?\/\/|@import/i.test(r),x=/class=["'][^"']*\bsy-app\b/.test(r);a.push({rule:5,ok:x&&!y&&!b,severity:`error`,detail:x?b?h(`引用了外部资源`):y?h(`写死了颜色 {0}`,[[...new Set(y)].slice(0,3).join(` `)]):void 0:h(`没有使用 .sy-app`)});let S=/syluno\.mode\s*===?\s*['"]widget['"]/.test(r);a.push({rule:6,ok:S,severity:`error`,detail:S?void 0:h(`没有处理小卡片模式`)});let C={transcribe:`speech.transcribe`,interpret:`speech.interpret`,translate:`text.translate`,say:`speech.synthesize`,chat:`text.chat`,describe:`vision.describe`},T={"speech.transcribe":`microphone`,"speech.interpret":`microphone`,"vision.describe":`camera`,"text.translate":`network`,"text.chat":`network`},E=new Set([...r.matchAll(/syluno\.ai\.(\w+)\(/g)].map(e=>C[e[1]]).filter(Boolean)),te=Array.isArray(n.services)?n.services:[],D=te.filter(e=>!Object.values(C).includes(e)),O=[...E].filter(e=>!te.includes(e)),k=[...E].map(e=>T[e]).filter(e=>e&&!m.includes(e)),A=te.filter(e=>!E.has(e)&&!D.includes(e)&&!(e===`text.translate`&&E.has(`speech.interpret`))),ne=D.length?h(`未知能力 {0}`,[D.join(h(`、`))]):O.length?h(`未声明 {0}`,[O.join(h(`、`))]):k.length?h(`缺少权限 {0}`,[[...new Set(k)].join(h(`、`))]):void 0,j=new Blob([r]).size/1024,M=n.requirements??{},N=j<=F.htmlKB&&(M.ramKB??0)<=4096&&(M.flashKB??0)<=8192;a.push({rule:7,ok:N,severity:`error`,detail:N?void 0:j>F.htmlKB?h(`页面 {0} KB`,[j.toFixed(1)]):h(`资源声明过大`)}),a.push({rule:8,ok:!ne&&!A.length,severity:ne?`error`:`warn`,detail:ne??(A.length?h(`声明了未使用 {0}`,[A.join(h(`、`))]):void 0)});let P=w(e),I=ee(`scenes`,P.scenes)??ee(`styles`,P.styles);return a.push({rule:9,ok:!I,severity:`error`,detail:I??void 0}),a}function Se(e){let t=[];for(let n of e.links??[])n.to&&t.push(n);for(let n of e.edges)for(let e of n.links??[])t.push({...e,to:e.to??(e.from===n.from?n.to:n.from)});return t}function Ce(e,t,n,r){let i=[],a=e.nodes.filter(e=>e.type===`root`);i.push({rule:0,ok:a.length===1,severity:`error`,detail:a.length===1?void 0:h(`现有 {0} 个`,[a.length])});let o=/* @__PURE__ */ new Map;for(let t of e.edges)o.set(t.to,(o.get(t.to)??0)+1);let s=e.nodes.filter(e=>(o.get(e.id)??0)>1),c=/* @__PURE__ */ new Set,l=(t,n)=>{if(n.has(t))return!0;if(c.has(t))return!1;c.add(t),n.add(t);let r=e.edges.filter(e=>e.from===t).some(e=>l(e.to,n));return n.delete(t),r},u=a[0]?l(a[0].id,/* @__PURE__ */ new Set):!1,d=e.nodes.filter(e=>e.type===`leaf`&&!c.has(e.id));i.push({rule:1,ok:!s.length&&!u&&!d.length,severity:`error`,detail:s.length?h(`有叶不止一个上游`):u?h(`存在环`):d.length?h(`{0} 片叶未连到根`,[d.length]):void 0});let f=t?r(t):void 0,p=!!f&&f.kind===`season`&&(!n||!f.palette?.length||f.palette.map(e=>e.toLowerCase()).includes(n.toLowerCase()));i.push({rule:2,ok:p,severity:`error`,detail:f?p?void 0:h(`主色不在季的调色板里`):h(`没有可用的季`)});let m=e.nodes.filter(e=>e.type===`leaf`&&!r(e.leaf)).map(e=>e.leaf),g=e.nodes.filter(e=>e.type===`leaf`&&(r(e.leaf)?.spec??1)>1).map(e=>e.leaf);i.push({rule:3,ok:!m.length&&!g.length,severity:`error`,detail:m.length?h(`未发布:{0}`,[m.join(h(`、`))]):g.length?h(`规范版本过新:{0}`,[g.join(h(`、`))]):void 0});let _=[],v=Se(e),y=t=>e.nodes.find(e=>e.id===t&&e.type===`leaf`);for(let e of v){let t=y(e.from),n=y(e.to);if(!t||!n){_.push(h(`联动的一端不是这棵树上的叶`));continue}if(t.id===n.id&&!e.delay){_.push(h(`联动接回自己时必须带延迟`));continue}let i=le(e,r(t.leaf)?.io,r(n.leaf)?.io);if(!i.ok){_.push(i.problems[0]);continue}let a=[e.when??``,...Object.values(e.map??{}).filter(e=>e.startsWith(`$`)).map(e=>e.slice(1))].flatMap(M).find(e=>!y(e.node));a&&_.push(h(`表达式引用的节点 {0} 不存在`,[a.node]))}i.push({rule:4,ok:!_.length,severity:`error`,detail:_.length?_.slice(0,2).join(h(`;`)):void 0});let b=/* @__PURE__ */ new Map;for(let e of v)!e.delay&&e.to&&b.set(e.from,[...b.get(e.from)??[],e.to]);let x=/* @__PURE__ */ new Map,S=/* @__PURE__ */ new Map,C=!1,w=e=>{if(x.get(e)===1)return C=!0,0;if(x.get(e)===2)return S.get(e);x.set(e,1);let t=0;for(let n of b.get(e)??[])t=Math.max(t,1+w(n));return x.set(e,2),S.set(e,t),t},T=!1;for(let e of b.keys())w(e)>F.chainDepth&&(T=!0);return i.push({rule:5,ok:!T&&!C,severity:`error`,detail:C?h(`有不带延迟的环:给环上的一条联动加延迟`):T?h(`不带延迟的连续联动超过 {0} 层`,[F.chainDepth]):void 0}),i}function we(e){let t=2166136261,n=Object.keys(e).sort().map(t=>`${t}\n${e[t]}`).join(`
25
- \0`);for(let e=0;e<n.length;e++)t^=n.charCodeAt(e),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,`0`)}const Te=[Object.keys(N).join(`, `),Object.keys(P).join(`, `)],Ee=g(`接口声明(写在 manifest.json 的 io 字段,是叶与其他叶协作的唯一方式):
22
+ c().__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner}));(/* @__PURE__ */ o(((e,t)=>{t.exports=u()})))();const d=[{code:`zh-CN`,name:`简体中文`},{code:`zh-TW`,name:`繁體中文`},{code:`en`,name:`English`},{code:`ja`,name:`日本語`},{code:`ko`,name:`한국어`},{code:`es`,name:`Español`},{code:`fr`,name:`Français`},{code:`de`,name:`Deutsch`},{code:`pt`,name:`Português`},{code:`it`,name:`Italiano`},{code:`ru`,name:`Русский`},{code:`tr`,name:`Türkçe`},{code:`ar`,name:`العربية`,rtl:!0},{code:`hi`,name:`हिन्दी`},{code:`id`,name:`Bahasa Indonesia`},{code:`vi`,name:`Tiếng Việt`},{code:`th`,name:`ไทย`}];try{import.meta.glob(`./locales/[a-z]*.json`)}catch{}let f={};function p(e){let t=e.toLowerCase().replace(`_`,`-`);return t.startsWith(`zh`)?/tw|hk|mo|hant/.test(t)?`zh-TW`:`zh-CN`:d.find(e=>e.code===t.split(/[-.]/)[0])?.code??null}function m(e,t){f=t}function h(e,t){let n=f[e]??e;return t?n.replace(/\{(\d+)\}/g,(e,n)=>String(t[+n]??``)):n}const g=e=>e,_=l.map(e=>({k:e,re:RegExp(`^`+e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`).replace(/\\\{(\d+)\\\}/g,`([\\s\\S]*?)`)+`$`)}));function v(e){if(!e)return``;if(f[e])return f[e];for(let t of _){let n=e.match(t.re);if(n)return h(t.k,n.slice(1))}return e}function y(){let e=process.argv.findIndex(e=>e===`--lang`||e.startsWith(`--lang=`)),t=e<0?``:process.argv[e].includes(`=`)?process.argv[e].split(`=`)[1]:process.argv[e+1]??``;e>=0&&process.argv.splice(e,process.argv[e].includes(`=`)?1:2);for(let e of[t,process.env.SYLUNO_LANG,process.env.LC_ALL,process.env.LC_MESSAGES,process.env.LANG]){if(!e||e===`C`||e.startsWith(`C.`)||e===`POSIX`)continue;let t=p(e);if(t)return t}return`en`}const b=y();let x={};try{x=JSON.parse(e.readFileSync(new URL(`./locales.json`,import.meta.url),`utf8`))}catch{}m(b,x[b]??{});const S=[{id:`voice`,label:h(`语音`),hint:h(`转写、同传、朗读、语音问答`)},{id:`weather`,label:h(`天气`),hint:h(`天气、预报、空气`)},{id:`todo`,label:h(`待办与笔记`),hint:h(`待办、备忘、习惯打卡`)},{id:`time`,label:h(`计时与闹钟`),hint:h(`时钟、计时器、秒表、番茄钟、闹钟`)},{id:`health`,label:h(`健康运动`),hint:h(`心率、步数、喝水、呼吸`)},{id:`relax`,label:h(`放松睡眠`),hint:h(`白噪音、冥想、睡前`)},{id:`comm`,label:h(`通讯`),hint:h(`电话、短信、消息`)},{id:`work`,label:h(`会议办公`),hint:h(`会议纪要、专注、效率`)},{id:`travel`,label:h(`出行`),hint:h(`翻译、导航、行程`)},{id:`home`,label:h(`家居环境`),hint:h(`温湿度、灯光、家电`)},{id:`tools`,label:h(`实用工具`),hint:h(`计算、换算、随机决定`)},{id:`logic`,label:h(`编排控制`),hint:h(`变量、条件、循环:让树能记住状态、做判断、反复执行`)}],C=[{id:`figure`,label:h(`大数字`),hint:h(`一屏一个主要数值`)},{id:`ring`,label:h(`圆环表盘`),hint:h(`进度环、表盘`)},{id:`list`,label:h(`列表`),hint:h(`一条一条的记录`)},{id:`grid`,label:h(`宫格按键`),hint:h(`按键、格子、拨号盘`)},{id:`text`,label:h(`文字流`),hint:h(`字幕、对话、长文本`)},{id:`motion`,label:h(`动效图形`),hint:h(`动画、波形、转盘`)},{id:`form`,label:h(`设置面板`),hint:h(`开关、选项、输入`)}];h(`场景`),h(`界面风格`);const ee=(e,t)=>(e===`scenes`?S:C).find(e=>e.id===t)?.label??t;function w(e){let t={};try{t=JSON.parse(e[`manifest.json`]??``)}catch{}let n=e=>Array.isArray(t[e])?t[e].map(String):null;return{scenes:n(`scenes`),styles:n(`styles`)}}function te(e,t){try{let n=JSON.parse(e[`manifest.json`]);for(let[e,r]of Object.entries(t))r&&(n[e]=r);return{...e,"manifest.json":JSON.stringify(n,null,2)+`
23
+ `}}catch{return e}}function ne(e,t){let n=e===`scenes`?S:C,r=h(e===`scenes`?`场景`:`界面风格`);if(t===null)return h(`还没有勾选{0}`,[r]);let i=t.filter(e=>!n.some(t=>t.id===e));return i.length?h(`{0}不在预置表里:{1}`,[r,i.join(h(`、`))]):t.length>3?h(`{0}最多选 3 个`,[r]):null}h(`热门`),h(`按收藏数从高到低;收藏数相同时,最近发布的在前`),h(`新上架`),h(`按第一颗种子的发布时间,从新到旧`),h(`最近更新`),h(`按最新一颗种子的发布时间,从新到旧`);const T={chars:500,nodes:200,depth:24,listItems:200,textChars:2e3},re={len:[`(x)`,h(`文本长度或列表长度`)],min:[`(a, b, …)`,h(`最小值`)],max:[`(a, b, …)`,h(`最大值`)],abs:[`(x)`,h(`绝对值`)],floor:[`(x)`,h(`向下取整`)],ceil:[`(x)`,h(`向上取整`)],round:[`(x)`,h(`四舍五入`)],num:[`(x)`,h(`转成数字,失败为 0`)],text:[`(x)`,h(`转成文本`)],contains:[h(`(文本或列表, x)`),h(`是否包含`)],has:[`(x)`,h(`是否有值(不是空、不是 null)`)],now:[`()`,h(`当前时间戳(毫秒)`)],hour:[`()`,h(`当前小时 0~23`)],first:[h(`(列表)`),h(`第一项`)],last:[h(`(列表)`),h(`最后一项`)],push:[h(`(列表, x)`),h(`在末尾加一项后的新列表`)],rest:[h(`(列表)`),h(`去掉第一项后的新列表`)],join:[h(`(列表, 分隔符)`),h(`拼成文本`)]},ie=[`||`,`&&`,`==`,`!=`,`<=`,`>=`,`<`,`>`,`+`,`-`,`*`,`/`,`%`,`!`,`?`,`:`,`(`,`)`,`[`,`]`,`,`,`.`,`@`];function ae(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(/\s/.test(r)){n++;continue}if(/\d/.test(r)||r===`.`&&/\d/.test(e[n+1]??``)){let r=e.slice(n).match(/^\d*\.?\d+(e[+-]?\d+)?/i);t.push({k:`num`,v:r[0]}),n+=r[0].length;continue}if(r===`"`||r===`'`){let i=n+1,a=``;for(;i<e.length&&e[i]!==r;)e[i]===`\\`&&i+1<e.length&&i++,a+=e[i++];if(i>=e.length)throw Error(h(`文本缺少结尾引号`));t.push({k:`str`,v:a}),n=i+1;continue}if(/[A-Za-z_一-龥]/.test(r)){let r=e.slice(n).match(/^[A-Za-z_一-龥][\w一-龥]*/);t.push({k:`id`,v:r[0]}),n+=r[0].length;continue}let i=ie.find(t=>e.startsWith(t,n));if(!i)throw Error(h(`不认识的符号 {0}`,[r]));t.push({k:`op`,v:i}),n+=i.length}return t}function E(e){if(e.length>T.chars)throw Error(h(`表达式超过 {0} 个字符`,[T.chars]));let t=ae(e),n=0,r=0,i=e=>t[n]&&(e===void 0||t[n].k===`op`&&t[n].v===e)?t[n]:null,a=e=>{if(!i(e))throw Error(h(`缺少 {0}`,[e]));n++},o=(e,t)=>{if(++r>T.nodes)throw Error(h(`表达式太长`));if(t>T.depth)throw Error(h(`表达式嵌套太深`));return e},s=(e,r)=>i=>{let a=e(i+1);for(;t[n]?.k===`op`&&r.includes(t[n].v);){let r=t[n++].v;a=o({t:`bin`,op:r,a,b:e(i+1)},i)}return a},c=e=>{let r=t[n];if(!r)throw Error(h(`表达式不完整`));if(r.k===`num`)return n++,o({t:`lit`,v:+r.v},e);if(r.k===`str`)return n++,o({t:`lit`,v:r.v},e);if(r.k===`op`&&r.v===`(`){n++;let t=f(e+1);return a(`)`),t}if(r.k===`op`&&r.v===`[`){n++;let t=[];if(!i(`]`))for(t.push(f(e+1));i(`,`);)n++,t.push(f(e+1));return a(`]`),o({t:`list`,items:t},e)}if(r.k===`op`&&r.v===`@`){n++;let r=t[n++];a(`.`);let i=t[n++];if(r?.k!==`id`||i?.k!==`id`)throw Error(h(`引用写成 @节点.输出`));return o({t:`ref`,node:r.v,out:i.v},e)}if(r.k===`id`){if(n++,r.v===`true`||r.v===`false`)return o({t:`lit`,v:r.v===`true`},e);if(r.v===`null`)return o({t:`lit`,v:null},e);if(i(`(`)){if(!re[r.v])throw Error(h(`没有函数 {0}`,[r.v]));n++;let t=[];if(!i(`)`))for(t.push(f(e+1));i(`,`);)n++,t.push(f(e+1));return a(`)`),o({t:`call`,fn:r.v,args:t},e)}return o({t:`id`,name:r.v},e)}throw Error(h(`这里不能出现 {0}`,[r.v]))},l=e=>{let r=c(e);for(;;){if(i(`.`)){n++;let i=t[n++];if(i?.k!==`id`)throw Error(h(`. 后面要写字段名`));r=o({t:`get`,a:r,k:{t:`lit`,v:i.v}},e);continue}if(i(`[`)){n++;let t=f(e+1);a(`]`),r=o({t:`get`,a:r,k:t},e);continue}return r}},u=e=>i(`!`)||i(`-`)?(()=>{let r=t[n++].v;return o({t:`un`,op:r,a:u(e+1)},e)})():l(e),d=s(s(s(s(s(s(u,[`*`,`/`,`%`]),[`+`,`-`]),[`<`,`<=`,`>`,`>=`]),[`==`,`!=`]),[`&&`]),[`||`]);function f(e){let t=d(e);if(!i(`?`))return t;n++;let r=f(e+1);a(`:`);let s=f(e+1);return o({t:`if`,c:t,a:r,b:s},e)}let p=f(0);if(n<t.length)throw Error(h(`多余的 {0}`,[t[n].v]));return p}const oe=/* @__PURE__ */ new Map;function D(e){let t=oe.get(e);if(!t){try{t=E(e)}catch(e){t=e}oe.set(e,t)}if(t instanceof Error)throw t;return t}function O(e){try{return D(e),null}catch(e){return e.message}}function se(e){let t=[],n=e=>{e.t===`ref`&&t.push({node:e.node,out:e.out}),`a`in e&&e.a&&n(e.a),`b`in e&&e.b&&n(e.b),`c`in e&&e.c&&n(e.c),`k`in e&&e.k&&n(e.k),e.t===`call`&&e.args.forEach(n),e.t===`list`&&e.items.forEach(n)};try{n(D(e))}catch{}return t}h(`叶`),h(`季`),h(`树`),h(`林`),h(`所有公开发布的叶、季、树汇集的地方,在这里发现、引用、种下`),h(`森林`),h(`创作者中心:自己和所在组织的叶、季、树在这里新建、编写、预览、勾选分类、发布`),h(`种子`),h(`一次发布产生的不可变包,带校验值;树的种子还锁定所用叶和季的版本。设备通过种子安装`),h(`土壤`),h(`设备的硬件与系统。种子落在什么土壤上,就按土壤的条件生长`),h(`树`),h(`一个完整的应用,由根、枝、叶和一个季组成`),h(`根`),h(`树的触发方式:打开、定时、语音唤起或到达某处`),h(`枝`),h(`叶与叶之间的连接:决定界面上的从属,也承载事件到动作、输出到输入的联动`),h(`叶`),h(`最小的功能单元,带有标准化的接口声明`),h(`季`),h(`外观。同一棵树换一个季,结构不变,样子改变`);const k={text:h(`文本`),number:h(`数字`),bool:h(`是否`),time:h(`时刻`),date:h(`日期`),duration:h(`时长(秒)`),enum:h(`选项`),list:h(`列表`),any:h(`任意`)},A={"°C":{dim:`temp`,k:1,b:0},"°F":{dim:`temp`,k:5/9,b:-160/9},"%":{dim:`ratio`},bpm:{dim:`rate`},lux:{dim:`light`},hPa:{dim:`pressure`},m:{dim:`len`,k:1},km:{dim:`len`,k:1e3},g:{dim:`mass`,k:1},kg:{dim:`mass`,k:1e3},ml:{dim:`vol`,k:1},L:{dim:`vol`,k:1e3},天:{dim:`day`},kcal:{dim:`energy`},次:{dim:`count`},个:{dim:`count`},杯:{dim:`count`},步:{dim:`count`},项:{dim:`count`},条:{dim:`count`}},ce=/^[a-z][a-zA-Z0-9]{0,23}$/,j={payloadBytes:8192,listItems:200,textChars:2e3,queue:10,actionTimeoutMs:3e3,chainDepth:8,perBranchPerSec:20,htmlKB:64,minDelayMs:50,maxDelayMs:864e5};function le(e,t){if(t.type===`any`||e.type===`any`)return{ok:!0,how:e.type===t.type?`exact`:`loose`};if(e.type===t.type){if(e.type===`number`&&e.unit&&t.unit&&e.unit!==t.unit){let n=A[e.unit],r=A[t.unit];return n&&r&&n.dim===r.dim&&n.k!==void 0&&r.k!==void 0?{ok:!0,how:`convert`,note:`${e.unit} → ${t.unit}`}:{ok:!1,note:h(`单位 {0} 与 {1} 不同`,[e.unit,t.unit])}}return e.type===`list`&&e.of&&t.of&&e.of!==t.of&&t.of!==`text`?{ok:!1,note:h(`列表元素类型不同`)}:e.type===`enum`&&t.values&&e.values?.some(e=>!t.values.includes(e))?{ok:!0,how:`loose`,note:h(`部分选项对方不认识`)}:{ok:!0,how:`exact`}}return t.type===`text`?{ok:!0,how:`convert`,note:h(`{0} → 文本`,[k[e.type]])}:t.type===`list`&&(t.of??`any`)===e.type?{ok:!0,how:`convert`,note:h(`单值放入列表`)}:e.type===`duration`&&t.type===`number`?{ok:!0,how:`convert`,note:h(`时长 → 秒`)}:e.type===`number`&&t.type===`duration`?{ok:!0,how:`loose`,note:h(`按秒理解`)}:e.type===`text`&&[`number`,`bool`,`enum`,`date`,`time`,`duration`].includes(t.type)?{ok:!0,how:`loose`,note:h(`运行时解析文本`)}:e.type===`bool`&&t.type===`number`?{ok:!0,how:`convert`}:{ok:!1,note:h(`{0} 不能接到 {1}`,[k[e.type],k[t.type]])}}function ue(e,t,n){try{if(e==null)return t.default===void 0?{ok:!1,error:h(`缺少值`)}:{ok:!0,value:t.default};switch(t.type){case`any`:return{ok:!0,value:e};case`text`:return{ok:!0,value:(Array.isArray(e)?e.join(h(`、`)):typeof e==`object`?JSON.stringify(e):String(e)).slice(0,j.textChars)};case`number`:case`duration`:{let r=typeof e==`boolean`?+e:typeof e==`number`?e:parseFloat(String(e).replace(/[^\d.+-eE]/g,``));if(!Number.isFinite(r))return{ok:!1,error:h(`不是数字`)};if(n?.unit&&t.unit&&n.unit!==t.unit){let e=A[n.unit],i=A[t.unit];e?.dim===i?.dim&&e.k!==void 0&&i.k!==void 0&&(r=(r*e.k+(e.b??0)-(i.b??0))/i.k)}return t.min!==void 0&&(r=Math.max(t.min,r)),t.max!==void 0&&(r=Math.min(t.max,r)),{ok:!0,value:r}}case`bool`:return{ok:!0,value:typeof e==`string`?/^(true|1|是|yes|开)$/i.test(e.trim()):!!e};case`enum`:{let n=String(e);return t.values?.length&&!t.values.includes(n)?{ok:!1,error:h(`不在选项 {0} 内`,[t.values.join(`/`)])}:{ok:!0,value:n}}case`date`:{let t=new Date(String(e));return isNaN(+t)?{ok:!1,error:h(`不是日期`)}:{ok:!0,value:t.toISOString().slice(0,10)}}case`time`:{let t=String(e).match(/^(\d{1,2}):(\d{2})/);return t?{ok:!0,value:`${t[1].padStart(2,`0`)}:${t[2]}`}:{ok:!1,error:h(`不是时刻`)}}case`list`:{let n=(Array.isArray(e)?e:[e]).slice(0,j.listItems);return!t.of||t.of===`any`?{ok:!0,value:n}:{ok:!0,value:n.map(e=>ue(e,{type:t.of})).filter(e=>e.ok).map(e=>e.value)}}}}catch(e){return{ok:!1,error:String(e)}}}const de=e=>{let[t,n]=e.split(`:`);return{kind:t,name:n}};function fe(e,t){let n=de(t);if(n.kind===`event`){let t=e?.events?.[n.name];return t?t.payload??{}:null}if(n.kind===`output`){let t=e?.outputs?.[n.name];return t?{value:t}:null}return null}function pe(e,t){let n=de(t);if(n.kind===`action`){let t=e?.actions?.[n.name];return t?t.params??{}:null}if(n.kind===`input`){let t=e?.inputs?.[n.name];return t?{value:t}:null}return null}function me(e,t){let n={},r=Object.keys(e);for(let[i,a]of Object.entries(t)){if(e[i]&&le(e[i],a).ok){n[i]=i;continue}let t=r.filter(t=>le(e[t],a).how===`exact`);t.length===1?n[i]=t[0]:!t.length&&r.length===1&&le(e[r[0]],a).ok&&(n[i]=r[0])}return n}function he(e,t,n){let r=[],i=fe(t,e.on),a=pe(n,e.do);if(i||r.push(h(`来源 {0} 未声明`,[e.on])),a||r.push(h(`目标 {0} 未声明`,[e.do])),!i||!a)return{ok:!1,problems:r,map:{}};let o={...me(i,a),...e.map??{}};if(e.when){let t=O(e.when);t&&r.push(h(`条件:{0}`,[t]))}e.delay!==void 0&&e.delay!==0&&!(e.delay>=j.minDelayMs&&e.delay<=j.maxDelayMs)&&r.push(h(`延迟要在 {0} 毫秒到 24 小时之间`,[j.minDelayMs]));for(let[e,t]of Object.entries(a)){let n=o[e];if(n===void 0){t.default===void 0&&r.push(h(`{0} 没有来源也没有默认值`,[e]));continue}if(n.startsWith(`=`)){ue(n.slice(1),t).ok||r.push(h(`{0} 的常量不符合 {1}`,[e,k[t.type]]));continue}if(n.startsWith(`$`)){let t=O(n.slice(1));t&&r.push(h(`{0} 的表达式:{1}`,[e,t]));continue}if(!i[n]){r.push(h(`{0} 对应的 {1} 不存在`,[e,n]));continue}let a=le(i[n],t);a.ok||r.push(h(`{0}:{1}`,[e,a.note]))}return{ok:!r.length,problems:r,map:o}}const ge=e=>e.filter(e=>!e.ok&&e.severity===`error`),_e=[h(`清单完整:规范版本、类别、名称、版本号、描述、图标、权限、硬件要求、资源占用都要写明`),h(`版本号遵循“主.次.修订”;删除或改动已有接口属于不兼容变更,必须升主版本号`),h(`接口声明合法:名称以小写字母开头,类型和单位来自规范表,输入和动作参数都带默认值`),h(`声明与实现一致:代码里用到的输出、事件、动作、输入都已声明,声明了的都有实现`),h(`权限最小:代码调用的系统能力都已声明权限,声明了却没用到的会被提示`),h(`界面遵循规范:用 .sy-app 容器搭界面,颜色只引用变量,不引用任何外部资源`),h(`两种显示模式:完整界面与小卡片都要处理`),h(`资源预算:页面不超过 64 KB,内存与存储的声明不超过系统上限`),h(`云端能力已声明:代码调用的转写、同传、翻译、朗读、对话、看图都写在 services 里,并声明所需权限(转写与同传要麦克风,看图要摄像头,翻译与对话要网络)`),h(`分类已勾选:场景(scenes)和界面风格(styles)都从平台预置表里选,每组最多 3 个;可以是空列表(暂不分类),但字段不能没有`)],ve=[h(`有且只有一个根`),h(`枝构成一棵树:每片叶只有一个上游,所有叶都连到根,没有环(枝只决定界面上的从属)`),h(`指定一个季,主色来自这个季的调色板`),h(`用到的叶和季都已在林中发布,且与本树所用规范版本一致`),h(`联动合法:两端是这棵树上的叶,来源和目标都已声明,类型兼容,必填参数都有来源或默认值,条件与表达式语法正确、引用的节点存在`),h(`联动可以成环,但环上至少有一条带延迟的联动;不带延迟的连续联动不超过 8 层`),h(`场景已勾选:场景(scenes)从平台预置表里选,最多 3 个;可以是空列表(暂不分类),但字段不能没有`)];function ye(e){let t=ne(`scenes`,w(e).scenes);return{rule:ve.length-1,ok:!t,severity:`error`,detail:t??void 0}}const be=[h(`种子一经发布不可修改,只能发布新版本`),h(`每颗种子带内容校验值,安装时校验,不一致则拒绝安装`),h(`树的种子锁定所用叶和季的版本;依赖升了主版本时,按锁定版本安装`),h(`种子声明所需的规范版本;设备的规范版本更低时拒绝安装并提示更新系统`)];h(`每次传递的数据都按接口声明校验:类型不符先做安全转换,失败则丢弃并记录`),h(`未声明的字段被丢弃,缺失的字段用默认值,单次数据不超过 8 KB`),h(`动作 3 秒内没有回应视为失败,不阻塞其他叶`),h(`目标叶尚未运行时,动作进入队列(最多 10 条),运行后按顺序送达`),h(`不带延迟的连续联动超过 8 层时熔断并记录;带延迟的联动到点后开启新的一轮,层数从 1 重新计算`),h(`同一条联动每秒最多触发 20 次,超出的丢弃并记录`),h(`条件为假时这次联动不触发;条件或表达式求值出错时丢弃这次联动并记录,不影响其他联动`),h(`同一次事件或输出触发的多条联动,条件与表达式都按触发那一刻的输出快照求值,再按添加顺序送达`),h(`延迟最短 50 毫秒、最长 24 小时;树停止运行时,还没送达的延迟联动一并取消`),h(`一片叶出错只影响它自己,树的其他部分照常运行`),h(`权限不随联动传递:动作在目标叶内执行,只用目标叶自己的权限`),h(`读到不认识的字段一律忽略,不认识的类型按任意值处理,保证新旧版本共存`),h(`同一片叶可能同时以小卡片和完整界面运行:动作的结果必须写入存储或输出,不能只留在界面上`);const xe=[[/syluno\.audio\./,`microphone`],[/syluno\.storage\./,`storage`],[/syluno\.notify\(/,`notifications`],[/syluno\.sensors\./,`sensors`],[/syluno\.net\./,`network`],[/syluno\.telephony\./,`phone`]];function Se(e){let t=t=>new Set([...e.matchAll(t)].map(e=>e[1]));return{events:t(/syluno\.io\.emit\(\s*['"]([\w]+)['"]/g),outputs:t(/syluno\.io\.set\(\s*['"]([\w]+)['"]/g),actions:t(/syluno\.io\.on\(\s*['"]([\w]+)['"]/g),inputs:/* @__PURE__ */ new Set([...t(/syluno\.io\.onInput\(\s*['"]([\w]+)['"]/g),...t(/syluno\.inputs\.([a-zA-Z]\w*)/g),...t(/syluno\.inputs\[\s*['"](\w+)['"]\s*\]/g)])}}const Ce=(e,t)=>!!e&&e.type in k&&(!e.unit||e.unit in A)&&(e.type!==`enum`||!!e.values?.length)&&(!t||e.default!==void 0),we=e=>/^\d+\.\d+\.\d+$/.test(e),Te=e=>+(e.split(`.`)[0]??0);function Ee(e,t){if(!e)return[];let n=[];for(let r of[`inputs`,`outputs`,`events`,`actions`])for(let[i,a]of Object.entries(e[r]??{})){let e=t?.[r]?.[i];if(!e){n.push(h(`删除了 {0}.{1}`,[r,i]));continue}(r===`inputs`||r===`outputs`)&&a.type!==e.type&&n.push(h(`{0}.{1} 类型变了`,[r,i]))}return n}function De(e,t){let n={};try{n=JSON.parse(e[`manifest.json`]??``)}catch{}let r=e[`index.html`]??``,i=n.io??{},a=[],o=[`spec`,`kind`,`name`,`version`,`description`,`icon`,`permissions`,`requires`,`requirements`].filter(e=>n[e]===void 0||n[e]===``);a.push({rule:0,ok:!o.length,severity:`error`,detail:o.length?h(`缺少 {0}`,[o.join(h(`、`))]):void 0});let s=null;try{s=t?JSON.parse(t[`manifest.json`]):null}catch{s=null}let c=Ee(s?.io,i),l=we(String(n.version??``))&&(!c.length||!s||Te(n.version)>Te(s.version));a.push({rule:1,ok:l,severity:`error`,detail:we(String(n.version??``))?c.length&&!l?h(`{0},需升主版本`,[c.join(h(`,`))]):void 0:h(`版本号格式不对`)});let u=[];for(let[e,t]of Object.entries(i.inputs??{}))(!ce.test(e)||!Ce(t,!0))&&u.push(h(`输入 {0}`,[e]));for(let[e,t]of Object.entries(i.outputs??{}))(!ce.test(e)||!Ce(t,!1))&&u.push(h(`输出 {0}`,[e]));for(let[e,t]of Object.entries(i.events??{}))(!ce.test(e)||Object.values(t.payload??{}).some(e=>!Ce(e,!1)))&&u.push(h(`事件 {0}`,[e]));for(let[e,t]of Object.entries(i.actions??{}))(!ce.test(e)||Object.values(t.params??{}).some(e=>!Ce(e,!0)))&&u.push(h(`动作 {0}`,[e]));a.push({rule:2,ok:!u.length,severity:`error`,detail:u.length?u.slice(0,4).join(h(`、`)):void 0});let d=Se(r),f=[...[...d.events].filter(e=>!i.events?.[e]).map(e=>h(`事件 {0}`,[e])),...[...d.outputs].filter(e=>!i.outputs?.[e]).map(e=>h(`输出 {0}`,[e])),...[...d.actions].filter(e=>!i.actions?.[e]).map(e=>h(`动作 {0}`,[e])),...[...d.inputs].filter(e=>!i.inputs?.[e]).map(e=>h(`输入 {0}`,[e]))],p=[...Object.keys(i.events??{}).filter(e=>!d.events.has(e)).map(e=>h(`事件 {0}`,[e])),...Object.keys(i.outputs??{}).filter(e=>!d.outputs.has(e)).map(e=>h(`输出 {0}`,[e])),...Object.keys(i.actions??{}).filter(e=>!d.actions.has(e)).map(e=>h(`动作 {0}`,[e]))];a.push({rule:3,ok:!f.length&&!p.length,severity:f.length||p.length?`error`:`warn`,detail:f.length?h(`未声明:{0}`,[f.join(h(`、`))]):p.length?h(`未实现:{0}`,[p.join(h(`、`))]):void 0});let m=Array.isArray(n.permissions)?n.permissions:[],g=xe.filter(([e])=>e.test(r)).map(([,e])=>e),_=g.filter(e=>!m.includes(e)),v=m.filter(e=>!g.includes(e)&&![`microphone`,`camera`,`location`,`network`].includes(e));a.push({rule:4,ok:!_.length&&!v.length,severity:_.length?`error`:`warn`,detail:_.length?h(`缺少权限 {0}`,[_.join(h(`、`))]):v.length?h(`未用到 {0}`,[v.join(h(`、`))]):void 0});let y=[...r.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/gi)].map(e=>e[1]).join(`
24
+ `).match(/#[0-9a-f]{3,8}\b|rgba?\(\s*\d/gi),b=/(src|href)\s*=\s*["']?(https?:)?\/\/|url\(\s*["']?(https?:)?\/\/|@import/i.test(r),x=/class=["'][^"']*\bsy-app\b/.test(r);a.push({rule:5,ok:x&&!y&&!b,severity:`error`,detail:x?b?h(`引用了外部资源`):y?h(`写死了颜色 {0}`,[[...new Set(y)].slice(0,3).join(` `)]):void 0:h(`没有使用 .sy-app`)});let S=/syluno\.mode\s*===?\s*['"]widget['"]/.test(r);a.push({rule:6,ok:S,severity:`error`,detail:S?void 0:h(`没有处理小卡片模式`)});let C={transcribe:`speech.transcribe`,interpret:`speech.interpret`,translate:`text.translate`,say:`speech.synthesize`,chat:`text.chat`,describe:`vision.describe`},ee={"speech.transcribe":`microphone`,"speech.interpret":`microphone`,"vision.describe":`camera`,"text.translate":`network`,"text.chat":`network`},te=new Set([...r.matchAll(/syluno\.ai\.(\w+)\(/g)].map(e=>C[e[1]]).filter(Boolean)),T=Array.isArray(n.services)?n.services:[],re=T.filter(e=>!Object.values(C).includes(e)),ie=[...te].filter(e=>!T.includes(e)),ae=[...te].map(e=>ee[e]).filter(e=>e&&!m.includes(e)),E=T.filter(e=>!te.has(e)&&!re.includes(e)&&!(e===`text.translate`&&te.has(`speech.interpret`))),oe=re.length?h(`未知能力 {0}`,[re.join(h(`、`))]):ie.length?h(`未声明 {0}`,[ie.join(h(`、`))]):ae.length?h(`缺少权限 {0}`,[[...new Set(ae)].join(h(`、`))]):void 0,D=new Blob([r]).size/1024,O=n.requirements??{},se=D<=j.htmlKB&&(O.ramKB??0)<=4096&&(O.flashKB??0)<=8192;a.push({rule:7,ok:se,severity:`error`,detail:se?void 0:D>j.htmlKB?h(`页面 {0} KB`,[D.toFixed(1)]):h(`资源声明过大`)}),a.push({rule:8,ok:!oe&&!E.length,severity:oe?`error`:`warn`,detail:oe??(E.length?h(`声明了未使用 {0}`,[E.join(h(`、`))]):void 0)});let k=w(e),A=ne(`scenes`,k.scenes)??ne(`styles`,k.styles);return a.push({rule:9,ok:!A,severity:`error`,detail:A??void 0}),a}function Oe(e){let t=[];for(let n of e.links??[])n.to&&t.push(n);for(let n of e.edges)for(let e of n.links??[])t.push({...e,to:e.to??(e.from===n.from?n.to:n.from)});return t}function ke(e,t,n,r){let i=[],a=e.nodes.filter(e=>e.type===`root`);i.push({rule:0,ok:a.length===1,severity:`error`,detail:a.length===1?void 0:h(`现有 {0} 个`,[a.length])});let o=/* @__PURE__ */ new Map;for(let t of e.edges)o.set(t.to,(o.get(t.to)??0)+1);let s=e.nodes.filter(e=>(o.get(e.id)??0)>1),c=/* @__PURE__ */ new Set,l=(t,n)=>{if(n.has(t))return!0;if(c.has(t))return!1;c.add(t),n.add(t);let r=e.edges.filter(e=>e.from===t).some(e=>l(e.to,n));return n.delete(t),r},u=a[0]?l(a[0].id,/* @__PURE__ */ new Set):!1,d=e.nodes.filter(e=>e.type===`leaf`&&!c.has(e.id));i.push({rule:1,ok:!s.length&&!u&&!d.length,severity:`error`,detail:s.length?h(`有叶不止一个上游`):u?h(`存在环`):d.length?h(`{0} 片叶未连到根`,[d.length]):void 0});let f=t?r(t):void 0,p=!!f&&f.kind===`season`&&(!n||!f.palette?.length||f.palette.map(e=>e.toLowerCase()).includes(n.toLowerCase()));i.push({rule:2,ok:p,severity:`error`,detail:f?p?void 0:h(`主色不在季的调色板里`):h(`没有可用的季`)});let m=e.nodes.filter(e=>e.type===`leaf`&&!r(e.leaf)).map(e=>e.leaf),g=e.nodes.filter(e=>e.type===`leaf`&&(r(e.leaf)?.spec??1)>1).map(e=>e.leaf);i.push({rule:3,ok:!m.length&&!g.length,severity:`error`,detail:m.length?h(`未发布:{0}`,[m.join(h(`、`))]):g.length?h(`规范版本过新:{0}`,[g.join(h(`、`))]):void 0});let _=[],v=Oe(e),y=t=>e.nodes.find(e=>e.id===t&&e.type===`leaf`);for(let e of v){let t=y(e.from),n=y(e.to);if(!t||!n){_.push(h(`联动的一端不是这棵树上的叶`));continue}if(t.id===n.id&&!e.delay){_.push(h(`联动接回自己时必须带延迟`));continue}let i=he(e,r(t.leaf)?.io,r(n.leaf)?.io);if(!i.ok){_.push(i.problems[0]);continue}let a=[e.when??``,...Object.values(e.map??{}).filter(e=>e.startsWith(`$`)).map(e=>e.slice(1))].flatMap(se).find(e=>!y(e.node));a&&_.push(h(`表达式引用的节点 {0} 不存在`,[a.node]))}i.push({rule:4,ok:!_.length,severity:`error`,detail:_.length?_.slice(0,2).join(h(`;`)):void 0});let b=/* @__PURE__ */ new Map;for(let e of v)!e.delay&&e.to&&b.set(e.from,[...b.get(e.from)??[],e.to]);let x=/* @__PURE__ */ new Map,S=/* @__PURE__ */ new Map,C=!1,ee=e=>{if(x.get(e)===1)return C=!0,0;if(x.get(e)===2)return S.get(e);x.set(e,1);let t=0;for(let n of b.get(e)??[])t=Math.max(t,1+ee(n));return x.set(e,2),S.set(e,t),t},w=!1;for(let e of b.keys())ee(e)>j.chainDepth&&(w=!0);return i.push({rule:5,ok:!w&&!C,severity:`error`,detail:C?h(`有不带延迟的环:给环上的一条联动加延迟`):w?h(`不带延迟的连续联动超过 {0} 层`,[j.chainDepth]):void 0}),i}function Ae(e){let t=2166136261,n=Object.keys(e).sort().map(t=>`${t}\n${e[t]}`).join(`
25
+ \0`);for(let e=0;e<n.length;e++)t^=n.charCodeAt(e),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,`0`)}const je=[Object.keys(k).join(`, `),Object.keys(A).join(`, `)],Me=g(`接口声明(写在 manifest.json 的 io 字段,是叶与其他叶协作的唯一方式):
26
26
  {"inputs": {名称: 端口}, "outputs": {名称: 端口}, "events": {名称: {"label": 说明, "payload": {字段: 端口}}}, "actions": {名称: {"label": 说明, "params": {参数: 端口}}}}
27
27
  端口:{"type": 类型, "label": 中文名, "unit": 单位(可选), "default": 默认值(输入和动作参数必须有), "min"/"max"(可选), "of": 列表元素类型(列表时), "values": 选项(enum 时)}
28
28
  类型只能是:{0};时长一律以秒为单位。单位只能是:{1}。
@@ -32,8 +32,8 @@ c().__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner}));(/*
32
32
  syluno.io.set('名称', 值) 更新输出
33
33
  syluno.io.emit('名称', {字段: 值}) 发出事件
34
34
  syluno.io.on('名称', params => { … }) 实现动作,params 已按声明校验并补齐默认值
35
- 同一片叶可能同时以小卡片和完整界面运行,动作的结果必须写入 syluno.storage 或输出,不能只改界面。`),De=(e=!1)=>e?h(Ee,Te):Ee.replace(/\{(\d+)\}/g,(e,t)=>Te[+t]);De();const Oe={"--bg":`color`,"--fg":`color`,"--dim":`color`,"--line":`color`,"--card":`color`,"--acc2":`color`,"--r":`length`,"--stroke":`length`,"--num-w":`weight`,"--title-w":`weight`,"--title-fg":`color`,"--title-tf":`case`,"--title-ls":`length`,"--font":`font`,"--btn-bg":`color`,"--btn-fg":`color`,"--btn-bd":`color`,"--pri-bg":`color`,"--pri-fg":`color`,"--item-bg":`color`,"--input-bg":`color`,"--input-bd":`color`,"--key-bg":`color`,"--key-fg":`color`,"--key-r":`length`},ke=[`--bg`,`--fg`,`--dim`,`--line`,`--card`,`--r`],Ae=/* @__PURE__ */ new Set(/* @__PURE__ */ `color.background.background-color.background-image.border.border-color.border-style.border-width.border-radius.border-top.border-bottom.box-shadow.text-shadow.filter.opacity.stroke.stroke-width.stroke-linecap.stroke-dasharray.fill.font-weight.letter-spacing.text-transform.text-decoration.transition.animation.outline.backdrop-filter`.split(`.`)),je=/^(body|i|b|span|small|svg|circle|path|\.sy-[\w-]+|\.widget|\.on|\.done|\.primary|\.danger|\.wide|\.alt|\.op|\.bg|\.fg|\.big|\.col)$/,Me=[`清单声明类别为季,并写明名称、描述、变量和调色板`,`变量只能用规范列出的名字,值的类型要对(颜色、长度、字重)`,`必须提供背景、文字、次要文字、线条、卡片、圆角六个基础变量`,`调色板 3~8 个十六进制颜色,每个与背景的对比度不低于 3:1`,`文字与背景对比度不低于 7:1,次要文字不低于 3:1`,`补充样式只能选中规范里的 .sy-* 类`,`补充样式只能改外观(颜色、边框、圆角、阴影、字重等),不能改布局和尺寸`,`不能引用外部资源,不能使用 !important,补充样式不超过 80 行`],L=e=>/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(e.trim()),Ne=e=>L(e)||/^(rgba?|hsla?|color-mix)\(.+\)$|^var\(--[\w-]+\)$|^transparent$|^linear-gradient\(.+\)$/i.test(e.trim()),Pe=e=>/^-?[\d.]+(px|em|rem|%)?$|^var\(--[\w-]+\)$/.test(e.trim());function Fe(e){let t=e.replace(`#`,``);t.length===3&&(t=t.split(``).map(e=>e+e).join(``));let[n,r,i]=[0,2,4].map(e=>{let n=parseInt(t.slice(e,e+2),16)/255;return n<=.03928?n/12.92:((n+.055)/1.055)**2.4});return .2126*n+.7152*r+.0722*i}const Ie=(e,t)=>{let[n,r]=[Fe(e),Fe(t)].sort((e,t)=>t-e);return(n+.05)/(r+.05)};function Le(e){let t=[],n={};try{n=JSON.parse(e[`manifest.json`]??``)}catch{}let r=n.tokens??{},i=n.palette??[],a=[`name`,`description`,`tokens`,`palette`].filter(e=>!n[e]);t.push({rule:0,ok:n.kind===`season`&&!a.length,detail:n.kind===`season`?a.length?`缺少 ${a.join(`、`)}`:void 0:`类别不是季`});let o=Object.entries(r).filter(([e,t])=>{let n=Oe[e];if(!n)return!0;let r=String(t);return n===`color`?!Ne(r):n===`length`?!Pe(r):n===`weight`?!/^[1-9]00$/.test(r):n===`case`?!/^(none|uppercase|lowercase)$/.test(r):!/^[\w\s",\-]+$/.test(r)}).map(([e])=>e);t.push({rule:1,ok:!o.length,detail:o.length?o.join(`、`):void 0});let s=ke.filter(e=>!r[e]);t.push({rule:2,ok:!s.length,detail:s.length?`缺少 ${s.join(`、`)}`:void 0});let c=L(r[`--bg`]??``)?r[`--bg`]:null,l=i.filter(e=>!L(e)||c&&Ie(e,c)<3);t.push({rule:3,ok:i.length>=3&&i.length<=8&&!l.length,detail:i.length<3||i.length>8?`现有 ${i.length} 个`:l.length?l.join(` `):void 0});let u=r[`--fg`],d=r[`--dim`],f=c&&L(u??``)?Ie(u,c)>=7:!1,p=c&&L(d??``)?Ie(d,c)>=3:!1;t.push({rule:4,ok:f&&p,detail:c?[!f&&`文字 ${L(u??``)?Ie(u,c).toFixed(1):`?`}:1`,!p&&`次要文字 ${L(d??``)?Ie(d,c).toFixed(1):`?`}:1`].filter(Boolean).join(`,`)||void 0:`背景需为十六进制颜色`});let m=(e[`season.css`]??``).replace(/\/\*[\s\S]*?\*\//g,``),h=[...m.replace(/@keyframes[^{]+\{(?:[^{}]*\{[^}]*\})*[^}]*\}/g,``).matchAll(/([^{}]+)\{([^}]*)\}/g)],g=[],_=[];for(let[,e,t]of h){for(let t of e.split(`,`)){let e=t.trim().replace(/::?[\w-]+(\([^)]*\))?/g,e=>e.startsWith(`:has(`)||e.startsWith(`:not(`)?` `+e.slice(e.indexOf(`(`)+1,-1)+` `:``).split(/[\s>+~]+|(?=\.)/).filter(Boolean);(!e.length||!e.every(e=>je.test(e))||!e.some(e=>e.startsWith(`.sy-`)||e===`body`))&&g.push(t.trim())}for(let e of t.split(`;`)){let t=e.split(`:`)[0].trim().toLowerCase();t&&!t.startsWith(`--`)&&!Ae.has(t)&&_.push(t)}}t.push({rule:5,ok:!g.length,detail:g.length?[...new Set(g)].slice(0,3).join(`,`):void 0}),t.push({rule:6,ok:!_.length,detail:_.length?[...new Set(_)].slice(0,4).join(`、`):void 0});let v=m.split(`
36
- `).filter(e=>e.trim()).length,y=/@import|url\(|!important|@font-face/i.test(m);return t.push({rule:7,ok:!y&&v<=80,detail:y?`含外部引用或 !important`:v>80?`${v} 行`:void 0}),t.map(e=>({...e,severity:`error`}))}const Re=()=>[[`login [--terminal] [--code]`,h(`登录平台:有桌面的电脑打开浏览器授权;服务器、SSH 等没有桌面的设备在终端里输入密码,或加 --code 用邮箱验证码`)],[`logout`,h(`退出并作废这台电脑上的令牌`)],[`whoami`,h(`当前登录的账户`)],[`list`,h(`我能写的仓库`)],[`create <${h(`名称`)}> [--kind leaf|tree|season] [--org ${h(`组织`)}] [--private]`,h(`在平台上新建仓库并拉取到本地,自带 RULES.md`)],[`clone <${h(`所有者/名称`)}> [${h(`目录`)}]`,h(`拉取平台上的仓库`)],[`status`,h(`本地改动,以及平台上有没有新改动`)],[`pull [--theirs]`,h(`拉取平台上的新改动`)],[`push -m <${h(`说明`)}>`,h(`推送本地改动(会顺带检查,有问题会提示)`)],[`check`,h(`按发布规则检查,不通过时退出码为 1`)],[`publish <${h(`版本`)}> -m <${h(`说明`)}> [--scenes a,b] [--styles c]`,h(`检查通过后结一颗种子,公开仓库自动上架到林`)],[`log`,h(`种子和提交记录`)],[`rules [--update]`,h(`查看本仓库的规则;--update 按当前规范重写 RULES.md`)],[`tags`,h(`可选的场景与界面风格`)]],ze=e=>({"manifest.json":JSON.stringify({spec:1,kind:`leaf`,name:e,version:`0.1.0`,description:h(`计数`),icon:{glyph:`leaf`,colors:[`#4FB3A9`,`#5A9FE2`]},permissions:[],requirements:{ramKB:32,flashKB:16,cpu:`low`},requires:{screen:!0},modes:[`app`,`widget`],io:{outputs:{count:{type:`number`,label:h(`次数`),unit:`次`}},actions:{add:{label:h(`加一`)}}}},null,2)+`
35
+ 同一片叶可能同时以小卡片和完整界面运行,动作的结果必须写入 syluno.storage 或输出,不能只改界面。`),Ne=(e=!1)=>e?h(Me,je):Me.replace(/\{(\d+)\}/g,(e,t)=>je[+t]);Ne();const Pe={"--bg":`color`,"--fg":`color`,"--dim":`color`,"--line":`color`,"--card":`color`,"--acc2":`color`,"--r":`length`,"--stroke":`length`,"--num-w":`weight`,"--title-w":`weight`,"--title-fg":`color`,"--title-tf":`case`,"--title-ls":`length`,"--font":`font`,"--btn-bg":`color`,"--btn-fg":`color`,"--btn-bd":`color`,"--pri-bg":`color`,"--pri-fg":`color`,"--item-bg":`color`,"--input-bg":`color`,"--input-bd":`color`,"--key-bg":`color`,"--key-fg":`color`,"--key-r":`length`},Fe=[`--bg`,`--fg`,`--dim`,`--line`,`--card`,`--r`],Ie=/* @__PURE__ */ new Set(/* @__PURE__ */ `color.background.background-color.background-image.border.border-color.border-style.border-width.border-radius.border-top.border-bottom.box-shadow.text-shadow.filter.opacity.stroke.stroke-width.stroke-linecap.stroke-dasharray.fill.font-weight.letter-spacing.text-transform.text-decoration.transition.animation.outline.backdrop-filter`.split(`.`)),Le=/^(body|i|b|span|small|svg|circle|path|\.sy-[\w-]+|\.widget|\.on|\.done|\.primary|\.danger|\.wide|\.alt|\.op|\.bg|\.fg|\.big|\.col)$/,Re=[`清单声明类别为季,并写明名称、描述、变量和调色板`,`变量只能用规范列出的名字,值的类型要对(颜色、长度、字重)`,`必须提供背景、文字、次要文字、线条、卡片、圆角六个基础变量`,`调色板 3~8 个十六进制颜色,每个与背景的对比度不低于 3:1`,`文字与背景对比度不低于 7:1,次要文字不低于 3:1`,`补充样式只能选中规范里的 .sy-* 类`,`补充样式只能改外观(颜色、边框、圆角、阴影、字重等),不能改布局和尺寸`,`不能引用外部资源,不能使用 !important,补充样式不超过 80 行`],ze=e=>/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(e.trim()),Be=e=>ze(e)||/^(rgba?|hsla?|color-mix)\(.+\)$|^var\(--[\w-]+\)$|^transparent$|^linear-gradient\(.+\)$/i.test(e.trim()),Ve=e=>/^-?[\d.]+(px|em|rem|%)?$|^var\(--[\w-]+\)$/.test(e.trim());function He(e){let t=e.replace(`#`,``);t.length===3&&(t=t.split(``).map(e=>e+e).join(``));let[n,r,i]=[0,2,4].map(e=>{let n=parseInt(t.slice(e,e+2),16)/255;return n<=.03928?n/12.92:((n+.055)/1.055)**2.4});return .2126*n+.7152*r+.0722*i}const Ue=(e,t)=>{let[n,r]=[He(e),He(t)].sort((e,t)=>t-e);return(n+.05)/(r+.05)};function We(e){let t=[],n={};try{n=JSON.parse(e[`manifest.json`]??``)}catch{}let r=n.tokens??{},i=n.palette??[],a=[`name`,`description`,`tokens`,`palette`].filter(e=>!n[e]);t.push({rule:0,ok:n.kind===`season`&&!a.length,detail:n.kind===`season`?a.length?`缺少 ${a.join(`、`)}`:void 0:`类别不是季`});let o=Object.entries(r).filter(([e,t])=>{let n=Pe[e];if(!n)return!0;let r=String(t);return n===`color`?!Be(r):n===`length`?!Ve(r):n===`weight`?!/^[1-9]00$/.test(r):n===`case`?!/^(none|uppercase|lowercase)$/.test(r):!/^[\w\s",\-]+$/.test(r)}).map(([e])=>e);t.push({rule:1,ok:!o.length,detail:o.length?o.join(`、`):void 0});let s=Fe.filter(e=>!r[e]);t.push({rule:2,ok:!s.length,detail:s.length?`缺少 ${s.join(`、`)}`:void 0});let c=ze(r[`--bg`]??``)?r[`--bg`]:null,l=i.filter(e=>!ze(e)||c&&Ue(e,c)<3);t.push({rule:3,ok:i.length>=3&&i.length<=8&&!l.length,detail:i.length<3||i.length>8?`现有 ${i.length} 个`:l.length?l.join(` `):void 0});let u=r[`--fg`],d=r[`--dim`],f=c&&ze(u??``)?Ue(u,c)>=7:!1,p=c&&ze(d??``)?Ue(d,c)>=3:!1;t.push({rule:4,ok:f&&p,detail:c?[!f&&`文字 ${ze(u??``)?Ue(u,c).toFixed(1):`?`}:1`,!p&&`次要文字 ${ze(d??``)?Ue(d,c).toFixed(1):`?`}:1`].filter(Boolean).join(`,`)||void 0:`背景需为十六进制颜色`});let m=(e[`season.css`]??``).replace(/\/\*[\s\S]*?\*\//g,``),h=[...m.replace(/@keyframes[^{]+\{(?:[^{}]*\{[^}]*\})*[^}]*\}/g,``).matchAll(/([^{}]+)\{([^}]*)\}/g)],g=[],_=[];for(let[,e,t]of h){for(let t of e.split(`,`)){let e=t.trim().replace(/::?[\w-]+(\([^)]*\))?/g,e=>e.startsWith(`:has(`)||e.startsWith(`:not(`)?` `+e.slice(e.indexOf(`(`)+1,-1)+` `:``).split(/[\s>+~]+|(?=\.)/).filter(Boolean);(!e.length||!e.every(e=>Le.test(e))||!e.some(e=>e.startsWith(`.sy-`)||e===`body`))&&g.push(t.trim())}for(let e of t.split(`;`)){let t=e.split(`:`)[0].trim().toLowerCase();t&&!t.startsWith(`--`)&&!Ie.has(t)&&_.push(t)}}t.push({rule:5,ok:!g.length,detail:g.length?[...new Set(g)].slice(0,3).join(`,`):void 0}),t.push({rule:6,ok:!_.length,detail:_.length?[...new Set(_)].slice(0,4).join(`、`):void 0});let v=m.split(`
36
+ `).filter(e=>e.trim()).length,y=/@import|url\(|!important|@font-face/i.test(m);return t.push({rule:7,ok:!y&&v<=80,detail:y?`含外部引用或 !important`:v>80?`${v} 行`:void 0}),t.map(e=>({...e,severity:`error`}))}const Ge=()=>[[`login [--terminal] [--code]`,h(`登录平台:有桌面的电脑打开浏览器授权;服务器、SSH 等没有桌面的设备在终端里输入密码,或加 --code 用邮箱验证码`)],[`logout`,h(`退出并作废这台电脑上的令牌`)],[`whoami`,h(`当前登录的账户`)],[`list`,h(`我能写的仓库`)],[`create <${h(`名称`)}> [--kind leaf|tree|season] [--org ${h(`组织`)}] [--private]`,h(`在平台上新建仓库并拉取到本地,自带 RULES.md`)],[`init [${h(`名称`)}] [--kind leaf|tree|season]`,h(`把当前目录(已有代码)建成平台上的新仓库,缺的文件按模板补上`)],[`clone <${h(`所有者/名称`)}> [${h(`目录`)}]`,h(`拉取平台上的仓库`)],[`status`,h(`本地改动,以及平台上有没有新改动`)],[`diff [${h(`文件`)}…]`,h(`逐行查看本地改动`)],[`restore <${h(`文件`)}…> | --all`,h(`撤销本地改动,回到上次拉取或推送时的内容`)],[`pull [--theirs]`,h(`拉取平台上的新改动`)],[`push -m <${h(`说明`)}>`,h(`推送本地改动(会顺带检查,有问题会提示)`)],[`check`,h(`按发布规则检查,不通过时退出码为 1`)],[`publish <${h(`版本`)}> -m <${h(`说明`)}> [--scenes a,b] [--styles c]`,h(`检查通过后结一颗种子,公开仓库自动上架到林`)],[`log`,h(`种子和提交记录`)],[`io [${h(`所有者/名称`)}]`,h(`查看叶的接口:输入、输出、事件、动作`)],[`search <${h(`关键词`)}> [--kind leaf|tree|season] [--scene ${h(`场景`)}]`,h(`在林里搜索公开发布的作品`)],[`info [${h(`所有者/名称`)}]`,h(`作品详情:最新种子、分类、权限、资源、硬件要求`)],[`fork <${h(`所有者/名称`)}> [${h(`新名称`)}]`,h(`把别人的作品复制到自己名下并拉取,提交里记下来源`)],[`star [${h(`所有者/名称`)}]`,h(`收藏或取消收藏`)],[`open [${h(`所有者/名称`)}] [code|io|flow|releases|preview|settings]`,h(`在浏览器里打开仓库页面`)],[`seed <${h(`所有者/名称`)}>@<${h(`版本`)}> [${h(`目录`)}]`,h(`下载一颗种子并核对校验值`)],[`set [--public|--private] [--description <${h(`说明`)}>]`,h(`修改仓库的可见性和描述(维护者及以上)`)],[`members`,h(`仓库成员与待接受的邀请`)],[`invite <${h(`用户名或邮箱`)}> [--role maintainer|writer|reader]`,h(`邀请协作者(维护者及以上)`)],[`machine <${h(`程序文件`)}> [--set c1=3,c2=0]`,h(`把计数器机程序编进当前的树(图灵完备的构造),并给出参考结果`)],[`rules [--update]`,h(`查看本仓库的规则;--update 按当前规范重写 RULES.md`)],[`tags`,h(`可选的场景与界面风格`)],[`completion [zsh|bash]`,h(`生成命令补全脚本,按 Tab 补全命令`)]],Ke=e=>({"manifest.json":JSON.stringify({spec:1,kind:`leaf`,name:e,version:`0.1.0`,description:h(`计数`),icon:{glyph:`leaf`,colors:[`#4FB3A9`,`#5A9FE2`]},permissions:[],requirements:{ramKB:32,flashKB:16,cpu:`low`},requires:{screen:!0},modes:[`app`,`widget`],io:{outputs:{count:{type:`number`,label:h(`次数`),unit:`次`}},actions:{add:{label:h(`加一`)}}}},null,2)+`
37
37
  `,"index.html":`<!doctype html>
38
38
  <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
39
39
  </head><body>
@@ -49,16 +49,16 @@ function add(){n.textContent=++k;syluno.io.set('count',k)}
49
49
  document.getElementById('b').onclick=add;
50
50
  syluno.io.on('add',add);
51
51
  <\/script></body></html>
52
- `,"README.md":`# ${e}\n`}),Be=e=>({"manifest.json":JSON.stringify({spec:1,kind:`season`,name:e,version:`0.1.0`,description:h(`新的季`),icon:{glyph:`leaf`,colors:[`#6CC4A8`,`#4FB3A9`]},permissions:[],requirements:{ramKB:4,flashKB:4,cpu:`low`},requires:{screen:!0},tokens:{"--bg":`#000000`,"--fg":`#ffffff`,"--dim":`#8e8e93`,"--line":`rgba(255,255,255,.14)`,"--card":`#111614`,"--r":`14px`,"--num-w":`200`,"--stroke":`6px`},palette:[`#6CC4A8`,`#64D2FF`,`#FF9F0A`,`#FF375F`]},null,2)+`
53
- `,"season.css":`/* ${h(`在界面规范之上、只改外观的补充样式`)} */\n`,"README.md":`# ${e}\n\n${h(`季`)}\n`}),Ve=e=>({"manifest.json":JSON.stringify({spec:1,kind:`tree`,name:e,version:`0.1.0`,description:``,icon:{glyph:`trees`,colors:[`#9CCD80`,`#4FB3A9`]},permissions:[],requirements:{ramKB:32,flashKB:8,cpu:`low`},requires:{},leaves:[`syluno/notes`],season:`syluno/line`},null,2)+`
54
- `,"README.md":`# ${e}\n`}),He=`https://www.syluno.com`,Ue=[`check`,`push`,`pull`,`publish`,`rules`],We=e=>Re().find(([t])=>t===e||t.startsWith(e+` `))?.[1]??``,Ge=(e,t=!1)=>e.map((e,n)=>t?`${n+1}. ${e}`:`- ${e}`).join(`
55
- `);function Ke(e,t){let n=h(e===`leaf`?`叶`:e===`tree`?`树`:`季`),r=e===`leaf`?[h(`manifest.json:清单,声明名称、版本、接口、权限、硬件要求、分类`),h(`index.html:界面与逻辑,单个页面,不超过 64 KB,不能引用外部资源`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)]:e===`tree`?[h(`manifest.json:清单,声明用到的叶(leaves)、季(season)、根与枝(flow)、联动(flow.links)、分类`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)]:[h(`manifest.json:清单,声明配色变量(tokens)与调色板(palette)`),h(`season.css:在界面规范之上、只改外观的补充样式`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)],i=e===`leaf`?de:e===`tree`?fe:Me,a=[e===`leaf`?`${He}/#/help/io`:e===`tree`?`${He}/#/help/flow`:`${He}/#/help/ui`,`${He}/#/help/publish`,`${He}/#/help/cli`];return[h(`# {0} 的开发规则`,[t]),h(`这是 syluno 平台上的一个{0}仓库。这份文件由平台按当前规范(版本 {1})生成,写明这个仓库要满足的规则。本地的 syl check 和平台发布时都按同样的规则检查,不满足的不能发布、不能上架到林。`,[n,1]),h(`## 文件`),Ge(r),...e===`leaf`?[h(`## 输入与输出`),De(!0)]:[],h(`## 发布前的检查`),Ge(i,!0),h(`## 种子`),Ge(me),h(`## 用命令行开发`),"```\n"+Ue.map(e=>`# ${We(e)}\n${e===`push`?`syl push -m "${h(`第一版`)}"`:e===`publish`?`syl publish 0.1.0 -m "${h(`首个版本`)}" --scenes time --styles figure`:e===`rules`?`syl rules --update`:`syl ${e}`}`).join(`
52
+ `,"README.md":`# ${e}\n`}),qe=e=>({"manifest.json":JSON.stringify({spec:1,kind:`season`,name:e,version:`0.1.0`,description:h(`新的季`),icon:{glyph:`leaf`,colors:[`#6CC4A8`,`#4FB3A9`]},permissions:[],requirements:{ramKB:4,flashKB:4,cpu:`low`},requires:{screen:!0},tokens:{"--bg":`#000000`,"--fg":`#ffffff`,"--dim":`#8e8e93`,"--line":`rgba(255,255,255,.14)`,"--card":`#111614`,"--r":`14px`,"--num-w":`200`,"--stroke":`6px`},palette:[`#6CC4A8`,`#64D2FF`,`#FF9F0A`,`#FF375F`]},null,2)+`
53
+ `,"season.css":`/* ${h(`在界面规范之上、只改外观的补充样式`)} */\n`,"README.md":`# ${e}\n\n${h(`季`)}\n`}),Je=e=>({"manifest.json":JSON.stringify({spec:1,kind:`tree`,name:e,version:`0.1.0`,description:``,icon:{glyph:`trees`,colors:[`#9CCD80`,`#4FB3A9`]},permissions:[],requirements:{ramKB:32,flashKB:8,cpu:`low`},requires:{},leaves:[`syluno/notes`],season:`syluno/line`},null,2)+`
54
+ `,"README.md":`# ${e}\n`}),Ye=`https://www.syluno.com`,Xe=[`check`,`push`,`pull`,`publish`,`rules`],Ze=e=>Ge().find(([t])=>t===e||t.startsWith(e+` `))?.[1]??``,Qe=(e,t=!1)=>e.map((e,n)=>t?`${n+1}. ${e}`:`- ${e}`).join(`
55
+ `);function $e(e,t){let n=h(e===`leaf`?`叶`:e===`tree`?`树`:`季`),r=e===`leaf`?[h(`manifest.json:清单,声明名称、版本、接口、权限、硬件要求、分类`),h(`index.html:界面与逻辑,单个页面,不超过 64 KB,不能引用外部资源`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)]:e===`tree`?[h(`manifest.json:清单,声明用到的叶(leaves)、季(season)、根与枝(flow)、联动(flow.links)、分类`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)]:[h(`manifest.json:清单,声明配色变量(tokens)与调色板(palette)`),h(`season.css:在界面规范之上、只改外观的补充样式`),h(`README.md:给使用者看的说明`),h(`RULES.md:本文件`)],i=e===`leaf`?_e:e===`tree`?ve:Re,a=[e===`leaf`?`${Ye}/#/help/io`:e===`tree`?`${Ye}/#/help/flow`:`${Ye}/#/help/ui`,`${Ye}/#/help/publish`,`${Ye}/#/help/cli`];return[h(`# {0} 的开发规则`,[t]),h(`这是 syluno 平台上的一个{0}仓库。这份文件由平台按当前规范(版本 {1})生成,写明这个仓库要满足的规则。本地的 syl check 和平台发布时都按同样的规则检查,不满足的不能发布、不能上架到林。`,[n,1]),h(`## 文件`),Qe(r),...e===`leaf`?[h(`## 输入与输出`),Ne(!0)]:[],h(`## 发布前的检查`),Qe(i,!0),h(`## 种子`),Qe(be),h(`## 用命令行开发`),"```\n"+Xe.map(e=>`# ${Ze(e)}\n${e===`push`?`syl push -m "${h(`第一版`)}"`:e===`publish`?`syl publish 0.1.0 -m "${h(`首个版本`)}" --scenes time --styles figure`:e===`rules`?`syl rules --update`:`syl ${e}`}`).join(`
56
56
 
57
- `)+"\n```",h(`## 完整说明`),Ge(a)].join(`
57
+ `)+"\n```",h(`## 完整说明`),Qe(a)].join(`
58
58
 
59
59
  `)+`
60
- `}function qe(e,t){return{...e===`tree`?Ve(t):e===`season`?Be(t):ze(t),"RULES.md":Ke(e,t)}}function Je(e){try{let t=JSON.parse(e[`manifest.json`]??``),n=t.requirements??{};return{name:t.name?h(t.name):h(`未命名`),version:t.version??`0.0.0`,description:t.description?h(t.description):t.description,icon:{glyph:t.icon?.glyph??`leaf`,colors:t.icon?.colors??[`#4FB3A9`,`#5A9FE2`]},permissions:Array.isArray(t.permissions)?t.permissions:[],requirements:{ramKB:n.ramKB??(n.ramMB?n.ramMB*1024:128),flashKB:n.flashKB??(n.storageMB?n.storageMB*1024:64),cpu:n.cpu??`low`},requires:t.requires??(t.leaves?{}:{screen:!0}),spec:typeof t.spec==`number`?t.spec:1,scenes:Array.isArray(t.scenes)?t.scenes:void 0,styles:Array.isArray(t.styles)?t.styles:void 0,kind:t.kind===`leaf`||t.kind===`season`||t.kind===`tree`?t.kind:t.type===`style`?`season`:t.leaves?`tree`:`leaf`,io:t.io&&typeof t.io==`object`?t.io:void 0,services:Array.isArray(t.services)?t.services:void 0,tokens:t.tokens&&typeof t.tokens==`object`?t.tokens:void 0,palette:Array.isArray(t.palette)?t.palette:void 0,leaves:t.leaves,season:t.season??t.ui?.style,flow:t.flow,ui:t.ui}}catch{return null}}h(`主区块`),h(`卡片`),h(`快捷按钮`),h(`后台`);function Ye(e){if(e.flow?.nodes?.length){let t=structuredClone(e.flow);for(let e of t.nodes)e.type===`trigger`&&(e.type=`root`);t.links=Se(t);for(let e of t.edges)delete e.links;return t}let t=[{id:`start`,type:`root`,x:0,y:0,label:h(`打开`)}],n=[];return(e.leaves??[]).forEach((e,r)=>{let i=`n${r+1}`;t.push({id:i,type:`leaf`,leaf:e,x:0,y:0}),n.push({id:`e${r+1}`,from:`start`,to:i})}),Xe({nodes:t,edges:n})}function Xe(e,t=280,n=128){let r=structuredClone(e),i=new Map(r.nodes.map(e=>[e.id,e])),a=0,o=/* @__PURE__ */ new Set,s=(e,c)=>{let l=i.get(e);if(o.has(e))return l.y;o.add(e);let u=r.edges.filter(t=>t.from===e).map(e=>e.to).filter(e=>i.has(e)),d;if(!u.length)d=a*n,a++;else{let e=u.map(e=>s(e,c+1));d=(Math.min(...e)+Math.max(...e))/2}return l.x=c*t,l.y=d,d},c=r.nodes.find(e=>e.type===`root`);c&&s(c.id,0);for(let e of r.nodes)o.has(e.id)||(e.x=0,e.y=a*n+60,a++);return r}function Ze(e,t,n,r,i,a){let o=Je(e),s=o?.kind===`tree`?[...o.leaves??[],...o.season?[o.season]:[]]:[],c=Object.fromEntries(s.map(e=>[e,a.find(t=>t.id===e)?.releases[0]?.version]).filter(([,e])=>e));return{version:t,notes:n,files:{...e},publishedAt:i,publishedBy:r,hash:we(e),spec:o?.spec??1,...s.length?{lock:c}:{}}}function Qe(e,t){try{let n=JSON.parse(e[`manifest.json`]);return n.version=t,{...e,"manifest.json":JSON.stringify(n,null,2)+`
61
- `}}catch{return{...e}}}const $e={"./leaves/alarm/README.md":`# 闹钟
60
+ `}function et(e,t){return{...e===`tree`?Je(t):e===`season`?qe(t):Ke(t),"RULES.md":$e(e,t)}}function M(e){try{let t=JSON.parse(e[`manifest.json`]??``),n=t.requirements??{};return{name:t.name?h(t.name):h(`未命名`),version:t.version??`0.0.0`,description:t.description?h(t.description):t.description,icon:{glyph:t.icon?.glyph??`leaf`,colors:t.icon?.colors??[`#4FB3A9`,`#5A9FE2`]},permissions:Array.isArray(t.permissions)?t.permissions:[],requirements:{ramKB:n.ramKB??(n.ramMB?n.ramMB*1024:128),flashKB:n.flashKB??(n.storageMB?n.storageMB*1024:64),cpu:n.cpu??`low`},requires:t.requires??(t.leaves?{}:{screen:!0}),spec:typeof t.spec==`number`?t.spec:1,scenes:Array.isArray(t.scenes)?t.scenes:void 0,styles:Array.isArray(t.styles)?t.styles:void 0,kind:t.kind===`leaf`||t.kind===`season`||t.kind===`tree`?t.kind:t.type===`style`?`season`:t.leaves?`tree`:`leaf`,io:t.io&&typeof t.io==`object`?t.io:void 0,services:Array.isArray(t.services)?t.services:void 0,tokens:t.tokens&&typeof t.tokens==`object`?t.tokens:void 0,palette:Array.isArray(t.palette)?t.palette:void 0,leaves:t.leaves,season:t.season??t.ui?.style,flow:t.flow,ui:t.ui}}catch{return null}}h(`主区块`),h(`卡片`),h(`快捷按钮`),h(`后台`);function tt(e){if(e.flow?.nodes?.length){let t=structuredClone(e.flow);for(let e of t.nodes)e.type===`trigger`&&(e.type=`root`);t.links=Oe(t);for(let e of t.edges)delete e.links;return t}let t=[{id:`start`,type:`root`,x:0,y:0,label:h(`打开`)}],n=[];return(e.leaves??[]).forEach((e,r)=>{let i=`n${r+1}`;t.push({id:i,type:`leaf`,leaf:e,x:0,y:0}),n.push({id:`e${r+1}`,from:`start`,to:i})}),nt({nodes:t,edges:n})}function nt(e,t=280,n=128){let r=structuredClone(e),i=new Map(r.nodes.map(e=>[e.id,e])),a=0,o=/* @__PURE__ */ new Set,s=(e,c)=>{let l=i.get(e);if(o.has(e))return l.y;o.add(e);let u=r.edges.filter(t=>t.from===e).map(e=>e.to).filter(e=>i.has(e)),d;if(!u.length)d=a*n,a++;else{let e=u.map(e=>s(e,c+1));d=(Math.min(...e)+Math.max(...e))/2}return l.x=c*t,l.y=d,d},c=r.nodes.find(e=>e.type===`root`);c&&s(c.id,0);for(let e of r.nodes)o.has(e.id)||(e.x=0,e.y=a*n+60,a++);return r}function rt(e,t,n,r,i,a){let o=M(e),s=o?.kind===`tree`?[...o.leaves??[],...o.season?[o.season]:[]]:[],c=Object.fromEntries(s.map(e=>[e,a.find(t=>t.id===e)?.releases[0]?.version]).filter(([,e])=>e));return{version:t,notes:n,files:{...e},publishedAt:i,publishedBy:r,hash:Ae(e),spec:o?.spec??1,...s.length?{lock:c}:{}}}function it(e,t){try{let n=JSON.parse(e[`manifest.json`]);return n.version=t,{...e,"manifest.json":JSON.stringify(n,null,2)+`
61
+ `}}catch{return{...e}}}const at={"./leaves/alarm/README.md":`# 闹钟
62
62
 
63
63
  几个闹钟,按星期重复,到点提醒
64
64
  `,"./leaves/alarm/index.html":`<!doctype html>
@@ -4740,9 +4740,27 @@ syluno.io.on('refresh',load);syluno.io.onInput('city',v=>{city=v||city;load()});
4740
4740
  }
4741
4741
  }
4742
4742
  }
4743
- `};function et(e){let t={};for(let[n,r]of Object.entries($e)){let i=n.match(/^\.\/leaves\/([^/]+)\/(.+)$/);i&&i[1]===e&&(t[i[2]]=r)}return t}const tt=Date.UTC(2026,9,7,2);let nt=0;const rt=()=>(Date.now().toString(36)+(nt++).toString(36)+Math.random().toString(36).slice(2,6)).slice(-10);function R(e,t,n,r,i,a={}){let o=et(n),s=Je(o),c=tt-i*864e5;return{id:`${e}/${t}`,owner:e,name:t,kind:r,description:s.description??``,visibility:`public`,files:o,commits:[{id:rt(),message:`初始提交`,author:e,at:c,changed:Object.keys(o)}],releases:[Ze(o,s.version,`首个版本`,e,c+36e5,[])],members:[{username:e,role:`owner`}],stars:[],updatedAt:c,...a}}const it=[R(`syluno`,`weather`,`weather`,`leaf`,9,{stars:[`chen-yu`,`li-wei`]}),R(`syluno`,`notes`,`notes`,`leaf`,12,{stars:[`chen-yu`]}),R(`syluno`,`timer`,`timer`,`leaf`,15,{stars:[]}),R(`syluno`,`calculator`,`calculator`,`leaf`,30),R(`chen-yu`,`todo`,`todo`,`leaf`,6,{stars:[`li-wei`],members:[{username:`chen-yu`,role:`owner`},{username:`li-wei`,role:`writer`}]}),R(`chen-yu`,`pomodoro`,`pomodoro`,`leaf`,3),R(`syluno`,`phone`,`phone`,`leaf`,20,{stars:[`li-wei`]}),R(`syluno`,`sms`,`sms`,`leaf`,20),R(`syluno`,`heart-rate`,`heart-rate`,`leaf`,8,{stars:[`chen-yu`]}),R(`syluno`,`climate`,`climate`,`leaf`,4),R(`syluno`,`line`,`season-line`,`season`,25,{stars:[`chen-yu`]}),R(`syluno`,`soft`,`season-soft`,`season`,7,{stars:[`li-wei`]}),R(`chen-yu`,`mono`,`season-mono`,`season`,4,{stars:[]}),R(`chen-yu`,`glow`,`season-glow`,`season`,2),R(`syluno`,`transcribe`,`transcribe`,`leaf`,3,{stars:[`chen-yu`,`li-wei`]}),R(`syluno`,`interpret`,`interpret`,`leaf`,3,{stars:[`li-wei`]}),R(`syluno`,`translate`,`translate`,`leaf`,4,{stars:[`chen-yu`]}),R(`syluno`,`voice-clean`,`voice-clean`,`leaf`,5,{stars:[]}),R(`syluno`,`read-aloud`,`read-aloud`,`leaf`,6),R(`syluno`,`minutes`,`minutes`,`leaf`,2,{stars:[`chen-yu`]}),R(`syluno`,`ask`,`ask`,`leaf`,2,{stars:[`li-wei`]}),R(`syluno`,`clock`,`clock`,`leaf`,18,{stars:[`chen-yu`]}),R(`syluno`,`alarm`,`alarm`,`leaf`,16),R(`syluno`,`stopwatch`,`stopwatch`,`leaf`,14),R(`syluno`,`water`,`water`,`leaf`,6,{stars:[`li-wei`]}),R(`chen-yu`,`habits`,`habits`,`leaf`,5,{stars:[]}),R(`syluno`,`steps`,`steps`,`leaf`,9),R(`chen-yu`,`noise`,`noise`,`leaf`,4,{stars:[`li-wei`]}),R(`syluno`,`breathe`,`breathe`,`leaf`,7),R(`syluno`,`convert`,`convert`,`leaf`,11),R(`chen-yu`,`pick`,`pick`,`leaf`,3),R(`syluno`,`meeting-kit`,`meeting-kit`,`tree`,1,{stars:[]}),R(`syluno`,`travel-kit`,`travel-kit`,`tree`,1,{stars:[`li-wei`]}),R(`chen-yu`,`sleep-kit`,`sleep-kit`,`tree`,2),R(`syluno`,`morning-kit`,`morning-kit`,`tree`,2,{stars:[`chen-yu`]}),R(`syluno`,`health-band`,`health-band`,`tree`,3,{stars:[`li-wei`]}),R(`syluno`,`comm-kit`,`comm-kit`,`tree`,5),R(`chen-yu`,`focus-kit`,`focus-kit`,`tree`,1),R(`syluno`,`var`,`var`,`leaf`,1,{stars:[`chen-yu`]}),R(`syluno`,`loop`,`loop`,`leaf`,1),R(`syluno`,`branch`,`branch`,`leaf`,1),R(`syluno`,`fib`,`fib`,`tree`,0),R(`syluno`,`minsky`,`minsky`,`tree`,0)];for(let e of it)e.kind===`tree`&&(e.releases[0]=Ze(e.files,e.releases[0].version,e.releases[0].notes,e.owner,e.releases[0].publishedAt,it));function at(e){let t=new Set(e.map(e=>e.id));return[...e,...it.filter(e=>!t.has(e.id))]}function ot(e){let t=/* @__PURE__ */ new Map;for(let n of at(e)){if(n.visibility!==`public`||!n.releases.length)continue;let e=Je(n.releases[0].files);e&&t.set(n.id,{io:e.io,spec:e.spec,palette:e.palette,kind:n.kind})}return e=>t.get(e)}function st(e,t,n,r){let i=Je(t);return i?e===`season`?{rules:Me,results:Le(t)}:e===`tree`?{rules:fe,results:[...Ce(Ye(i),i.season,i.ui?.accent,ot(r)),pe(t)]}:{rules:de,results:xe(t,n)}:{rules:[h(`清单可以解析`)],results:[{rule:0,ok:!1,severity:`error`,detail:h(`manifest.json 无法解析`)}]}}function ct(e,t,n,r){let{rules:i,results:a}=st(e,t,n,r);return ue(a).map(e=>({rule:e.rule+1,text:i[e.rule],detail:e.detail}))}const lt=process.stdout.isTTY&&!process.env.NO_COLOR,ut=(e,t)=>n=>lt?`\x1b[${e}m${n}\x1b[${t}m`:String(n),z=ut(1,22),B=ut(2,22),V=ut(31,39),dt=ut(32,39),H=ut(33,39),U=ut(36,39),W=dt(`✓`),ft=V(`✗`),pt=H(`!`),G=(...e)=>console.log(...e);var K=class extends Error{code;constructor(e,t=1){super(e),this.code=t}};const q=e=>{throw new K(e)},mt=e=>[...e.replace(/\x1b\[\d+m/g,``)].reduce((e,t)=>e+(/[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe30-\ufe4f\uff00-\uff60\uffe0-\uffe6]/.test(t)?2:1),0),ht=(e,t)=>e+` `.repeat(Math.max(0,t-mt(e)));function gt(e){let t=e[0]?.map((t,n)=>Math.max(...e.map(e=>mt(e[n]??``))))??[];for(let n of e)G(n.map((e,r)=>r===n.length-1?e:ht(e,t[r])).join(` `))}async function _t(e){process.stdin.isTTY||q(h(`这里需要输入,但当前不是交互终端`));let t=i.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>t.question(e,e=>{t.close(),n(e.trim())}))}async function vt(e){process.stdin.isTTY||q(h(`这里需要输入,但当前不是交互终端`)),process.stdout.write(e);let t=process.stdin;return t.setRawMode(!0),t.resume(),t.setEncoding(`utf8`),new Promise((e,n)=>{let r=``,i=t=>{for(let i of t){if(i===`\r`||i===`
4744
- `){a(),e(r);return}if(i===``){a(),n(new K(h(`已取消`),130));return}i===``||i===`\b`?r=r.slice(0,-1):r+=i}},a=()=>{t.off(`data`,i),t.setRawMode(!1),t.pause(),process.stdout.write(`
4745
- `)};t.on(`data`,i)})}function yt(e,t){let n={_:[]},r={m:`message`,h:`help`,v:`version`,k:`kind`};for(let i=0;i<e.length;i++){let a=e[i];if(a===`--`){n._.push(...e.slice(i+1));break}let o=/^--?([a-zA-Z][\w-]*)(?:=(.*))?$/.exec(a);if(!o){n._.push(a);continue}let s=r[o[1]]??o[1];o[2]===void 0?t.includes(s)?n[s]=!0:i+1<e.length?n[s]=e[++i]:q(h(`{0} 后面缺少值`,[a])):n[s]=o[2]}return n}const bt=process.env.SYLUNO_HOME??r.join(t.homedir(),`.syluno`),xt=r.join(bt,`config.json`);function J(){try{return JSON.parse(e.readFileSync(xt,`utf8`))}catch{return{}}}function St(t){e.mkdirSync(bt,{recursive:!0,mode:448}),e.writeFileSync(xt,JSON.stringify(t,null,2)+`
4746
- `,{mode:384}),e.chmodSync(xt,384)}let Ct;const wt=e=>{Ct=e?.replace(/\/+$/,``)},Y=e=>Ct??process.env.SYLUNO_SERVER?.replace(/\/+$/,``)??e??J().server??`https://www.syluno.com`,Tt=()=>process.env.SYLUNO_TOKEN??J().token;var Et=class extends Error{status;failures;constructor(e,t,n){super(e),this.status=t,this.failures=n}};async function X(e,t,n,r={}){let i=r.auth===!1?void 0:Tt(),a=Y(r.base)+t,o;try{o=await fetch(a,{method:e,headers:{"Content-Type":`application/json`,"X-Lang":b,"User-Agent":`syluno-cli/0.1.0`,...i?{Authorization:`Bearer ${i}`}:{}},body:n===void 0?void 0:JSON.stringify(n),signal:AbortSignal.timeout(3e4)})}catch(e){return q(h(`连不上平台 {0}:{1}`,[Y(r.base),e.message]))}let s=await o.json().catch(()=>({}));if(!o.ok)throw o.status===401?new Et(h(`还没有登录或登录已过期,请先运行 syl login`),401):new Et(v(s.error)||`HTTP ${o.status}`,o.status,s.failures);return s}const Z=(e,t)=>X(`GET`,`/api/repos/${e}`,void 0,{base:t}),Dt=async e=>(await X(`GET`,`/api/hub`,void 0,{base:e})).repos,Ot=[` ▄▄███▄▄ `,` ▄█████████▄ `,`█████████████`,`▀███████████▀`,` ▀▀█████▀▀ `,` ███ `,` ▄▄███▄▄ `],kt=[`███████ ██ ██ ██ ██ ██ ███ ██ ██████ `,`██ ██ ██ ██ ██ ██ ████ ██ ██ ██`,`███████ ████ ██ ██ ██ ██ ██ ██ ██ ██`,` ██ ██ ██ ██ ██ ██ ██ ██ ██ ██`,`███████ ██ ███████ ██████ ██ ████ ██████ `],At=e=>[1,3,5].map(t=>parseInt(e.slice(t,t+2),16)),jt=(e,t,n)=>e.map((e,r)=>Math.round(e+(t[r]-e)*n)),Mt=At(`#9CCD80`),Nt=At(`#4DABC4`),Pt=At(`#C49E78`),Ft=!!process.stdout.isTTY&&!process.env.NO_COLOR,It=/truecolor|24bit/i.test(process.env.COLORTERM??``)||process.env.TERM_PROGRAM===`iTerm.app`||process.env.TERM_PROGRAM===`vscode`,Lt=([e,t,n])=>16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(n/255*5),Rt=(e,t)=>!Ft||!e.trim()?e:It?`\x1b[38;2;${t[0]};${t[1]};${t[2]}m${e}\x1b[39m`:`\x1b[38;5;${Lt(t)}m${e}\x1b[39m`;function zt(e,t,n,r){return[...e].map((e,i)=>Rt(e,jt(t,n,i/Math.max(1,r-1)))).join(``)}const Bt=()=>{let e=h(`扎根于此,`),t=h(`自由生长`);return/[,、。!?]$/.test(e)?e+t:`${e} ${t}`};function Vt(e,t,n){let r=process.stdout.columns||80;if(G(``),r>=Ot[0].length+4+kt[0].length+2){let e=Math.floor((Ot.length-kt.length)/2);Ot.forEach((t,n)=>{let r=n>=5?Rt(t,Pt):zt(t,jt(Mt,Nt,n/5*.5),jt(Mt,Nt,.5+n/5*.5),t.length),i=kt[n-e];G(` `+r+` `+(i?zt(i,Mt,Nt,i.length):``))})}else Ot.forEach((e,t)=>G(` `+(t>=5?Rt(e,Pt):zt(e,Mt,Nt,e.length))));G(``),G(` `+z(Bt())),G(``),G(` `+h(`欢迎,{0}(@{1})。已经连上 {2}`,[z(t),e,n])),G(``),G(` `+z(h(`接下来可以:`)));let i=e=>Re().find(([t])=>t===e||t.startsWith(e+` `))?.[1]??``,a=[[`syl create my-leaf --kind leaf`,i(`create`)],[`syl clone syluno/notes`,h(`拉取一片官方的叶作参考`)],[`syl list`,i(`list`)],[`syl help`,h(`全部命令`)]],o=Math.max(...a.map(([e])=>e.length));for(let[e,t]of a)G(` `+U(ht(e,o))+` `+B(t));G(``),G(` `+B(h(`完整说明:{0}`,[`${n}/#/help/cli`]))),G(``)}const Q=`.syluno`,Ht=/* @__PURE__ */ new Set([Q,`.git`,`node_modules`,`.DS_Store`,`Thumbs.db`]),Ut=e=>a.createHash(`sha1`).update(e).digest(`hex`).slice(0,16),Wt=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Ut(t)]));function $(t=process.cwd()){let n=r.resolve(t);for(;;){let t=r.join(n,Q,`repo.json`);if(e.existsSync(t))return{dir:n,state:JSON.parse(e.readFileSync(t,`utf8`))};let i=r.dirname(n);if(i===n)return q(h(`这里不是 syluno 仓库(没有找到 .syluno/)。用 syl clone 拉取一个,或用 syl create 新建`));n=i}}function Gt(t){e.mkdirSync(r.join(t.dir,Q),{recursive:!0}),e.writeFileSync(r.join(t.dir,Q,`repo.json`),JSON.stringify(t.state,null,2)+`
4747
- `)}function Kt(t,n){let i=r.join(t.dir,Q,`seed.json`);n?e.writeFileSync(i,JSON.stringify(n)):e.rmSync(i,{force:!0})}function qt(t){try{return JSON.parse(e.readFileSync(r.join(t.dir,Q,`seed.json`),`utf8`))}catch{return}}function Jt(t){try{return e.readFileSync(r.join(t,`.sylunoignore`),`utf8`).split(`
4748
- `).map(e=>e.trim()).filter(e=>e&&!e.startsWith(`#`)).map(e=>RegExp(`^`+e.replace(/\/$/,``).replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`)+`(/|$)`))}catch{return[]}}function Yt(t){let n={},i=[],a=Jt(t),o=0,s=c=>{for(let l of e.readdirSync(r.join(t,c),{withFileTypes:!0})){if(Ht.has(l.name))continue;let u=c?`${c}/${l.name}`:l.name;if(u===`.sylunoignore`||a.some(e=>e.test(u)))continue;if(l.isDirectory()){s(u);continue}if(!l.isFile())continue;let d=e.readFileSync(r.join(t,u));if(d.includes(0)){i.push(u);continue}o+=d.length,o>12582912&&q(h(`仓库文件总共超过 12 MB`)),n[u]=d.toString(`utf8`)}};return s(``),{files:n,skipped:i}}const Xt=e=>!!e&&!e.startsWith(`/`)&&!e.includes(`\\`)&&!e.split(`/`).some(e=>e===`..`||e===``||e===Q);function Zt(t,n,i){Xt(n)||q(h(`文件名不安全:{0}`,[n]));let a=r.join(t,n);e.mkdirSync(r.dirname(a),{recursive:!0}),e.writeFileSync(a,i)}function Qt(t,n){if(Xt(n)){e.rmSync(r.join(t,n),{force:!0});for(let i=r.dirname(r.join(t,n));i.startsWith(t)&&i!==t;i=r.dirname(i))try{e.rmdirSync(i)}catch{break}}}function $t(e,t){let n=[],r=[],i=[];for(let[i,a]of Object.entries(t))i in e?e[i]!==Ut(a)&&r.push(i):n.push(i);for(let n of Object.keys(e))n in t||i.push(n);return{added:n.sort(),modified:r.sort(),deleted:i.sort(),any:!!(n.length+r.length+i.length)}}function en(t,n,i){e.existsSync(t)&&e.readdirSync(t).length&&q(h(`目录 {0} 已存在且不是空的`,[t])),e.mkdirSync(t,{recursive:!0});for(let[e,r]of Object.entries(n.files))Zt(t,e,r);let a={dir:r.resolve(t),state:{server:i,id:n.id,kind:n.kind,base:n.updatedAt,files:Wt(n.files)}};return Gt(a),Kt(a,n.releases[0]?.files),a}const tn=[`leaf`,`tree`,`season`],nn=e=>h(e===`leaf`?`叶`:e===`tree`?`树`:`季`),rn=/^[a-z0-9][a-z0-9-]{0,38}$/,an=/^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]{0,38}$/,on=/^\d+\.\d+\.\d+$/,sn=(e,t)=>{let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++)if(n[e]!==r[e])return n[e]>r[e];return!1},cn=()=>(Date.now().toString(36)+Math.random().toString(36).slice(2,6)).slice(-10),ln=e=>new Date(e).toLocaleString(void 0,{year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}),un=(e,t)=>`${e}/#/${t}`,dn=e=>String(e??``).split(`,`).map(e=>e.trim()).filter(Boolean);let fn=``;async function pn(){if(fn)return fn;let e=J();return e.user&&!process.env.SYLUNO_TOKEN?fn=e.user:(!e.token&&!process.env.SYLUNO_TOKEN&&q(h(`还没有登录或登录已过期,请先运行 syl login`)),fn=(await X(`GET`,`/api/me`)).user.username)}function mn(e,t,n,r){let{rules:i,results:a}=st(e,t,n,r),o=0,s=0;for(let e of a){let t=e.ok?W:e.severity===`warn`?pt:ft;e.ok||(e.severity===`warn`?s++:o++),G(`${t} ${e.ok?B(`${e.rule+1}.`):z(`${e.rule+1}.`)} ${e.ok?i[e.rule]:z(i[e.rule])}`),e.detail&&!e.ok&&G(` ${e.severity===`warn`?H(e.detail):V(e.detail)}`)}return G(``),G(o?V(h(`{0} 条规则没有通过,修好之后才能发布`,[o])):dt(s?h(`检查通过,有 {0} 条提示`,[s]):h(`检查全部通过`))),o>0}async function hn(e){try{return await Dt(e?.state.server)}catch{return null}}function gn(e,t){t.updatedAt!==e.state.base&&q(h(`平台上有新的改动,请先拉取(syl pull)`))}function _n(){return process.env.SSH_CONNECTION||process.env.SSH_TTY||process.env.CI?!1:process.platform===`darwin`||process.platform===`win32`||!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY)}function vn(e){if(process.env.BROWSER===`none`)return!1;let[t,r]=process.platform===`darwin`?[`open`,[e]]:process.platform===`win32`?[`cmd`,[`/c`,`start`,``,e]]:[`xdg-open`,[e]];try{let e=n(t,r,{stdio:`ignore`,detached:!0});return e.on(`error`,()=>{}),e.unref(),!0}catch{return!1}}const yn=e=>new Promise(t=>setTimeout(t,e));async function bn(e){let t=Y(),n=e.web||!e.terminal&&!e.code&&_n()?await xn(t):await Sn(e,t);St({...J(),server:t,token:n.token,tokenId:n.id,user:n.user.username}),G(``),G(`${W} ${z(h(`登录成功`))} ${B(h(`令牌 {0} 天内有效,保存在 ~/.syluno/config.json`,[n.days]))}`),Vt(n.user.username,n.user.name,t)}async function xn(e){let n=await X(`POST`,`/api/cli/login`,{name:`syluno CLI · ${t.hostname()}`},{auth:!1}),r=`${e}/#/cli-login/${n.id}`,i=vn(r);G(z(h(i?`已在浏览器里打开 syluno,登录后点「授权」`:`请在浏览器里打开下面的链接,登录后点「授权」`))),G(` `+U(r)),G(``),G(h(`核对验证码:网页上显示的应该是 {0}`,[z(n.code)])),G(B(h(`浏览器没有打开的话,复制上面的链接;没有浏览器的设备用 syl login --terminal`))),G(``);let a=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],o=process.stdout.isTTY,s=h(`等待网页授权…(Ctrl+C 取消)`),c=Date.now()+n.expiresIn*1e3;for(let e=0;Date.now()<c;e++){if(o?process.stdout.write(`\r${U(a[e%a.length])} ${s}`):e===0&&G(s),await yn(o?250:2e3),o&&e%8!=7)continue;let t=await X(`POST`,`/api/cli/login/${n.id}/poll`,{secret:n.secret},{auth:!1});if(t.status!==`pending`){if(o&&process.stdout.write(`\r\x1B[2K`),t.status===`approved`)return t;q(t.status===`denied`?h(`已在网页上取消授权`):h(`登录请求已过期,请重新运行 syl login`))}}return o&&process.stdout.write(`\r\x1B[2K`),q(h(`登录请求已过期,请重新运行 syl login`))}async function Sn(e,n){G(B(h(`登录 {0}`,[n])));let r=String(e._[0]??``)||await _t(h(`邮箱或用户名:`));r||q(h(`请输入邮箱或用户名`));let i={email:r,name:`syluno CLI · ${t.hostname()}`};return e.code?(await X(`POST`,`/api/auth/code`,{email:r,purpose:`login`},{auth:!1}),G(h(`验证码已发送到 {0}`,[r])),i.code=await _t(h(`验证码:`))):i.password=await vt(h(`密码(没有设置密码的账户加 --code 用邮箱验证码登录):`)),X(`POST`,`/api/auth/token`,i,{auth:!1})}async function Cn(){let e=J();if(!e.token)return G(h(`没有登录`));try{e.tokenId&&await X(`DELETE`,`/api/tokens/${e.tokenId}`)}catch{}St({server:e.server}),G(`${W} ${h(`已退出,令牌已作废`)}`)}async function wn(){let{user:e}=await X(`GET`,`/api/me`);process.env.SYLUNO_TOKEN||St({...J(),user:e.username}),G(`${z(e.username)} ${e.name}${e.email?B(` <${e.email}>`):``} ${B(Y())}`)}async function Tn(e){let t=String(e._[0]??``);rn.test(t)||q(h(`名称需为小写字母、数字或连字符`));let n=String(e.kind??`leaf`);tn.includes(n)||q(h(`类别只能是 leaf、tree 或 season`));let r=await pn(),i=String(e.org??r),a=`${i}/${t}`,o=qe(n,t),s=Date.now(),c={id:a,owner:i,name:t,kind:n,description:``,visibility:e.private?`private`:`public`,files:o,commits:[{id:cn(),message:h(`初始提交`),author:r,at:s,changed:Object.keys(o)}],releases:[],members:[],stars:[],updatedAt:s};await X(`PUT`,`/api/repos/${a}`,{repo:c,create:!0});let{repo:l}=await Z(a),u=String(e.dir??t);en(u,l,Y()),G(`${W} ${h(`已在平台上创建{0} {1},并拉取到 {2}/`,[nn(n),z(a),u])}`),G(``),G(h(`仓库里的 RULES.md 写明了平台对这个{0}的全部规则。接下来:`,[nn(n)])),G(U(` cd ${u}`)),G(U(` syl check`)+B(` # `+h(`按发布规则检查`))),G(U(` syl push -m "${h(`第一版`)}"`)),G(U(` syl publish 0.1.0 -m "${h(`首个版本`)}"`)),G(B(un(Y(),a)))}async function En(e){let t=String(e._[0]??``).replace(/^https?:\/\/[^#]*#\//,``).replace(/\/+$/,``);an.test(t)||q(h(`请写成 所有者/名称,例如 syluno/notes`));let{repo:n}=await Z(t),r=String(e._[1]??n.name);en(r,n,Y()),G(`${W} ${h(`已拉取{0} {1} 到 {2}/({3} 个文件{4})`,[nn(n.kind),z(t),r,Object.keys(n.files).length,n.releases[0]?h(`,最新种子 {0}`,[n.releases[0].version]):``])}`)}async function Dn(){let{repos:e}=await X(`GET`,`/api/repos`);if(!e.length)return G(h(`还没有仓库。用 syl create <名称> 新建一个`));gt([[B(h(`仓库`)),B(h(`类别`)),B(h(`最新种子`)),B(h(`角色`)),B(h(`更新时间`))],...e.sort((e,t)=>t.updatedAt-e.updatedAt).map(e=>[z(e.id)+(e.visibility===`private`?B(` 🔒`):``),nn(e.kind),e.version??B(`—`),e.role,B(ln(e.updatedAt))])])}async function On(){let e=$(),{files:t,skipped:n}=Yt(e.dir),r=$t(e.state.files,t);G(h(`{0}「{1}」 {2}`,[nn(e.state.kind),z(e.state.id),B(e.state.server)]));try{let{repo:t}=await Z(e.state.id,e.state.server);t.updatedAt===e.state.base?G(B(h(`和平台同步({0})`,[ln(t.updatedAt)]))):G(H(h(`平台上有新的改动,运行 syl pull 拉取`)))}catch(e){G(B(h(`没能连上平台:{0}`,[e.message])))}if(!r.any)G(h(`本地没有改动`));else{G(h(`本地改动(还没推送):`));for(let e of r.added)G(dt(` + ${e}`));for(let e of r.modified)G(H(` ~ ${e}`));for(let e of r.deleted)G(V(` - ${e}`))}n.length&&G(B(h(`跳过的二进制文件:{0}`,[n.join(`, `)])))}async function kn(t){let n=$(),{repo:i}=await Z(n.state.id,n.state.server);if(i.updatedAt===n.state.base)return G(h(`已是最新`));let a=Yt(n.dir).files,o=n.state.files,s=Wt(i.files),c=/* @__PURE__ */ new Set([...Object.keys(o),...Object.keys(a),...Object.keys(i.files)]),l=[],u=[];for(let e of c){let t=a[e]===void 0?void 0:Wt({x:a[e]}).x;s[e]!==o[e]&&(t===o[e]||t===s[e]?l.push(e):u.push(e))}if(u.length&&!t.theirs){G(V(h(`这些文件本地和平台上都改了:`)));for(let e of u)G(` ${e}`);q(h(`先推送或撤销本地改动;或用 syl pull --theirs 采用平台上的版本(本地的会备份到 .syluno/backup/)`))}if(u.length){let t=r.join(n.dir,`.syluno`,`backup`,(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g,`-`));for(let n of u)a[n]!==void 0&&(e.mkdirSync(r.dirname(r.join(t,n)),{recursive:!0}),e.writeFileSync(r.join(t,n),a[n]));l.push(...u),G(H(h(`本地版本已备份到 {0}`,[r.relative(process.cwd(),t)||t])))}for(let e of l.sort())i.files[e]===void 0?(Qt(n.dir,e),G(V(` - ${e}`))):(Zt(n.dir,e,i.files[e]),G(dt(` ${o[e]?`~`:`+`} ${e}`)));n.state={...n.state,kind:i.kind,base:i.updatedAt,files:s},Gt(n),Kt(n,i.releases[0]?.files),G(`${W} ${h(`已拉取 {0} 处改动`,[l.length])}`)}async function An(e){let t=$(),n=typeof e.message==`string`?e.message.trim():``;n||q(h(`请用 -m 写一句这次改了什么`));let{files:r,skipped:i}=Yt(t.dir),a=$t(t.state.files,r);if(!a.any)return G(h(`本地没有改动`));i.length&&G(B(h(`跳过的二进制文件:{0}`,[i.join(`, `)])));let{results:o}=st(t.state.kind,r,qt(t),await hn(t)??[]),s=o.filter(e=>!e.ok&&e.severity===`error`).length,{repo:c}=await Z(t.state.id,t.state.server);gn(t,c);let l=await pn(),u={id:cn(),message:n,author:l,at:Date.now(),changed:[...a.added,...a.modified,...a.deleted]},d={...c,files:r,commits:[u,...c.commits],updatedAt:Date.now()},f=await X(`PUT`,`/api/repos/${t.state.id}`,{repo:d,base:t.state.base},{base:t.state.server});t.state={...t.state,base:f.updatedAt,files:Wt(r)},Gt(t),G(`${W} ${h(`已推送 {0}:{1}`,[z(t.state.id),n])} ${B(`+${a.added.length} ~${a.modified.length} -${a.deleted.length}`)}`),s&&G(H(h(`有 {0} 条发布规则没有通过,发布前需要修好(syl check 查看)`,[s])))}async function jn(){let e=$(),{files:t}=Yt(e.dir),n=await hn(e);if(n===null&&e.state.kind===`tree`&&G(H(h(`没能连上平台,依赖的叶和季无法核对`))),G(h(`按平台规则(规范版本 {0})检查{1} {2}:`,[1,nn(e.state.kind),z(e.state.id)])),G(``),mn(e.state.kind,t,qt(e),n??[]))throw new K(``,1)}async function Mn(e){let t=$(),n=String(e._[0]??``),r=typeof e.message==`string`?e.message.trim():``;on.test(n)||q(h(`版本号要写成 主.次.修订,例如 1.2.0`)),r||q(h(`请用 -m 写这个版本的说明`));let i=Yt(t.dir).files;$t(t.state.files,i).any&&q(h(`有还没推送的改动,先运行 syl push`));let{repo:a,role:o}=await Z(t.state.id,t.state.server);gn(t,a),o!==`owner`&&o!==`maintainer`&&q(h(`发布需要维护者及以上的权限`));let s=a.releases[0];s&&!sn(n,s.version)&&q(h(`新版本号要大于上一颗种子 {0}`,[s.version]));let c={};e.scenes!==void 0&&(c.scenes=dn(e.scenes)),e.styles!==void 0&&(c.styles=dn(e.styles)),t.state.kind===`season`&&(delete c.scenes,delete c.styles),t.state.kind===`tree`&&delete c.styles;let l=Qe(Object.keys(c).length?T(a.files,c):a.files,n),u=at(await Dt(t.state.server));if(ct(a.kind,l,s?.files,u).length){G(V(h(`发布检查没有通过:`))),G(``),mn(a.kind,l,s?.files,u);let e=w(l);throw a.kind!==`season`&&(!e.scenes||a.kind===`leaf`&&!e.styles)&&G(B(h(`分类用 --scenes 和 --styles 指定,可选值见 syl tags;暂不分类可以写 --scenes ""`))),new K(``,1)}let d=Ze(l,n,r,await pn(),Date.now(),u),f={...a,files:l,releases:[d,...a.releases],updatedAt:Date.now()},p;try{p=await X(`PUT`,`/api/repos/${t.state.id}`,{repo:f,base:t.state.base},{base:t.state.server})}catch(e){if(e instanceof Et&&e.failures?.length){G(V(e.message));for(let t of e.failures)G(`${ft} ${z(`${t.rule}.`)} ${h(t.text)}${t.detail?`\n ${V(t.detail)}`:``}`);throw new K(``,1)}throw e}Zt(t.dir,`manifest.json`,l[`manifest.json`]),t.state={...t.state,base:p.updatedAt,files:Wt(l)},Gt(t),Kt(t,l),G(`${W} ${h(`已发布 {0} 的种子 {1}(校验值 {2})`,[z(t.state.id),z(n),d.hash])}`),a.visibility===`private`?G(H(h(`仓库是私有的,种子不会出现在林里;改成公开后自动上架`))):G(h(`已上架到林:{0}`,[U(un(t.state.server,t.state.id))]))}async function Nn(){let e=$(),{repo:t}=await Z(e.state.id,e.state.server);t.releases.length&&(G(z(h(`种子`))),gt(t.releases.map(e=>[dt(e.version),B(ln(e.publishedAt)),e.publishedBy,e.notes])),G(``)),G(z(h(`提交`))),gt(t.commits.slice(0,30).map(e=>[H(e.id.slice(-7)),B(ln(e.at)),e.author,e.message])),t.commits.length>30&&G(B(h(`…… 还有 {0} 条`,[t.commits.length-30])))}function Pn(e){let t=$(),n=t.state.id.split(`/`)[1],r=Ke(t.state.kind,n);if(!e.update){process.stdout.write(r);return}Zt(t.dir,`RULES.md`,r),G(`${W} ${h(`已按当前规范重新生成 RULES.md,推送后生效`)}`)}function Fn(){let e=(()=>{try{return $()}catch{return null}})();for(let[e,t]of[[h(`场景(--scenes)`),S],[h(`界面风格(--styles,只有叶需要)`),C]])G(z(e)),gt(t.map(e=>[U(` `+e.id),e.label,B(e.hint)])),G(``);if(e){let t=w(Yt(e.dir).files);G(B(h(`当前清单:scenes = {0},styles = {1}`,[JSON.stringify(t.scenes),JSON.stringify(t.styles)])))}G(B(h(`每组最多 3 个,用逗号分隔,例如 --scenes time,study`)))}function In(){G(`${z(`syl`)} ${B(`0.1.0`)} — ${h(`在终端里开发叶、树、季,并按平台规则发布`)}`),G(``),G(z(h(`用法`))+` syl <`+h(`命令`)+`> [`+h(`参数`)+`]`),G(``);for(let[e,t]of Re())G(` ${U(e)}\n ${t}`);G(``),G(z(h(`通用参数`))),gt([[U(` --server <URL>`),h(`平台地址,默认 https://www.syluno.com(也可用环境变量 SYLUNO_SERVER)`)],[U(` --lang <${h(`代码`)}>`),h(`输出语言,例如 en、zh-CN(默认跟随系统)`)],[U(` SYLUNO_TOKEN`),h(`环境变量:在持续集成里代替登录,令牌在网页「账户 → 命令行」里生成`)]]),G(``),G(B(h(`完整说明:{0}`,[`${Y()}/#/help/cli`])))}async function Ln(){let e=J();if(!(e.checkedAt&&Date.now()-e.checkedAt<864e5))try{let e=await X(`GET`,`/api/cli`,void 0,{auth:!1});St({...J(),checkedAt:Date.now()}),e.version&&sn(e.version,`0.1.0`)&&console.error(H(h(`syluno 有新版本 {0}(当前 {1}):{2}`,[e.version,`0.1.0`,e.install??``]))),e.spec&&e.spec>1&&console.error(H(h(`平台规范已更新到版本 {0},请升级命令行工具,本地检查才会和平台一致`,[e.spec])))}catch{}}const Rn=[`code`,`web`,`terminal`,`private`,`theirs`,`update`,`help`,`version`],zn={login:bn,logout:Cn,whoami:wn,list:Dn,ls:Dn,create:Tn,new:Tn,clone:En,status:On,st:On,pull:kn,push:An,check:jn,publish:Mn,log:Nn,rules:Pn,tags:Fn};async function Bn(){let e=yt(process.argv.slice(2),Rn);if(typeof e.server==`string`&&wt(e.server),e.version)return G(`0.1.0`);let t=e._.shift();if(!t||e.help||t===`help`)return In();let n=zn[t];n||q(h(`没有这个命令:{0}。运行 syl help 查看全部命令`,[t])),[`help`,`rules`,`tags`].includes(t)||await Ln(),await n(e)}Bn().catch(e=>{e instanceof K&&(e.message&&console.error(V(e.message)),process.exit(e.code)),e instanceof Et&&(console.error(V(e.message)),process.exit(1)),console.error(e),process.exit(1)});export{};
4743
+ `};function ot(e){let t={};for(let[n,r]of Object.entries(at)){let i=n.match(/^\.\/leaves\/([^/]+)\/(.+)$/);i&&i[1]===e&&(t[i[2]]=r)}return t}const st=Date.UTC(2026,9,7,2);let ct=0;const lt=()=>(Date.now().toString(36)+(ct++).toString(36)+Math.random().toString(36).slice(2,6)).slice(-10);function N(e,t,n,r,i,a={}){let o=ot(n),s=M(o),c=st-i*864e5;return{id:`${e}/${t}`,owner:e,name:t,kind:r,description:s.description??``,visibility:`public`,files:o,commits:[{id:lt(),message:`初始提交`,author:e,at:c,changed:Object.keys(o)}],releases:[rt(o,s.version,`首个版本`,e,c+36e5,[])],members:[{username:e,role:`owner`}],stars:[],updatedAt:c,...a}}const ut=[N(`syluno`,`weather`,`weather`,`leaf`,9,{stars:[`chen-yu`,`li-wei`]}),N(`syluno`,`notes`,`notes`,`leaf`,12,{stars:[`chen-yu`]}),N(`syluno`,`timer`,`timer`,`leaf`,15,{stars:[]}),N(`syluno`,`calculator`,`calculator`,`leaf`,30),N(`chen-yu`,`todo`,`todo`,`leaf`,6,{stars:[`li-wei`],members:[{username:`chen-yu`,role:`owner`},{username:`li-wei`,role:`writer`}]}),N(`chen-yu`,`pomodoro`,`pomodoro`,`leaf`,3),N(`syluno`,`phone`,`phone`,`leaf`,20,{stars:[`li-wei`]}),N(`syluno`,`sms`,`sms`,`leaf`,20),N(`syluno`,`heart-rate`,`heart-rate`,`leaf`,8,{stars:[`chen-yu`]}),N(`syluno`,`climate`,`climate`,`leaf`,4),N(`syluno`,`line`,`season-line`,`season`,25,{stars:[`chen-yu`]}),N(`syluno`,`soft`,`season-soft`,`season`,7,{stars:[`li-wei`]}),N(`chen-yu`,`mono`,`season-mono`,`season`,4,{stars:[]}),N(`chen-yu`,`glow`,`season-glow`,`season`,2),N(`syluno`,`transcribe`,`transcribe`,`leaf`,3,{stars:[`chen-yu`,`li-wei`]}),N(`syluno`,`interpret`,`interpret`,`leaf`,3,{stars:[`li-wei`]}),N(`syluno`,`translate`,`translate`,`leaf`,4,{stars:[`chen-yu`]}),N(`syluno`,`voice-clean`,`voice-clean`,`leaf`,5,{stars:[]}),N(`syluno`,`read-aloud`,`read-aloud`,`leaf`,6),N(`syluno`,`minutes`,`minutes`,`leaf`,2,{stars:[`chen-yu`]}),N(`syluno`,`ask`,`ask`,`leaf`,2,{stars:[`li-wei`]}),N(`syluno`,`clock`,`clock`,`leaf`,18,{stars:[`chen-yu`]}),N(`syluno`,`alarm`,`alarm`,`leaf`,16),N(`syluno`,`stopwatch`,`stopwatch`,`leaf`,14),N(`syluno`,`water`,`water`,`leaf`,6,{stars:[`li-wei`]}),N(`chen-yu`,`habits`,`habits`,`leaf`,5,{stars:[]}),N(`syluno`,`steps`,`steps`,`leaf`,9),N(`chen-yu`,`noise`,`noise`,`leaf`,4,{stars:[`li-wei`]}),N(`syluno`,`breathe`,`breathe`,`leaf`,7),N(`syluno`,`convert`,`convert`,`leaf`,11),N(`chen-yu`,`pick`,`pick`,`leaf`,3),N(`syluno`,`meeting-kit`,`meeting-kit`,`tree`,1,{stars:[]}),N(`syluno`,`travel-kit`,`travel-kit`,`tree`,1,{stars:[`li-wei`]}),N(`chen-yu`,`sleep-kit`,`sleep-kit`,`tree`,2),N(`syluno`,`morning-kit`,`morning-kit`,`tree`,2,{stars:[`chen-yu`]}),N(`syluno`,`health-band`,`health-band`,`tree`,3,{stars:[`li-wei`]}),N(`syluno`,`comm-kit`,`comm-kit`,`tree`,5),N(`chen-yu`,`focus-kit`,`focus-kit`,`tree`,1),N(`syluno`,`var`,`var`,`leaf`,1,{stars:[`chen-yu`]}),N(`syluno`,`loop`,`loop`,`leaf`,1),N(`syluno`,`branch`,`branch`,`leaf`,1),N(`syluno`,`fib`,`fib`,`tree`,0),N(`syluno`,`minsky`,`minsky`,`tree`,0)];for(let e of ut)e.kind===`tree`&&(e.releases[0]=rt(e.files,e.releases[0].version,e.releases[0].notes,e.owner,e.releases[0].publishedAt,ut));function dt(e){let t=new Set(e.map(e=>e.id));return[...e,...ut.filter(e=>!t.has(e.id))]}function ft(e){let t=/* @__PURE__ */ new Map;for(let n of dt(e)){if(n.visibility!==`public`||!n.releases.length)continue;let e=M(n.releases[0].files);e&&t.set(n.id,{io:e.io,spec:e.spec,palette:e.palette,kind:n.kind})}return e=>t.get(e)}function pt(e,t,n,r){let i=M(t);return i?e===`season`?{rules:Re,results:We(t)}:e===`tree`?{rules:ve,results:[...ke(tt(i),i.season,i.ui?.accent,ft(r)),ye(t)]}:{rules:_e,results:De(t,n)}:{rules:[h(`清单可以解析`)],results:[{rule:0,ok:!1,severity:`error`,detail:h(`manifest.json 无法解析`)}]}}function mt(e,t,n,r){let{rules:i,results:a}=pt(e,t,n,r);return ge(a).map(e=>({rule:e.rule+1,text:i[e.rule],detail:e.detail}))}const ht=process.stdout.isTTY&&!process.env.NO_COLOR,gt=(e,t)=>n=>ht?`\x1b[${e}m${n}\x1b[${t}m`:String(n),P=gt(1,22),F=gt(2,22),I=gt(31,39),_t=gt(32,39),L=gt(33,39),R=gt(36,39),z=_t(`✓`),vt=I(`✗`),yt=L(`!`),B=(...e)=>console.log(...e);var bt=class extends Error{code;constructor(e,t=1){super(e),this.code=t}};const V=e=>{throw new bt(e)},xt=e=>[...e.replace(/\x1b\[\d+m/g,``)].reduce((e,t)=>e+(/[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\ufe30-\ufe4f\uff00-\uff60\uffe0-\uffe6]/.test(t)?2:1),0),St=(e,t)=>e+` `.repeat(Math.max(0,t-xt(e)));function H(e){let t=e[0]?.map((t,n)=>Math.max(...e.map(e=>xt(e[n]??``))))??[];for(let n of e)B(n.map((e,r)=>r===n.length-1?e:St(e,t[r])).join(` `))}async function Ct(e){process.stdin.isTTY||V(h(`这里需要输入,但当前不是交互终端`));let t=r.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>t.question(e,e=>{t.close(),n(e.trim())}))}async function wt(e){process.stdin.isTTY||V(h(`这里需要输入,但当前不是交互终端`)),process.stdout.write(e);let t=process.stdin;return t.setRawMode(!0),t.resume(),t.setEncoding(`utf8`),new Promise((e,n)=>{let r=``,i=t=>{for(let i of t){if(i===`\r`||i===`
4744
+ `){a(),e(r);return}if(i===``){a(),n(new bt(h(`已取消`),130));return}i===``||i===`\b`?r=r.slice(0,-1):r+=i}},a=()=>{t.off(`data`,i),t.setRawMode(!1),t.pause(),process.stdout.write(`
4745
+ `)};t.on(`data`,i)})}function Tt(e,t){let n={_:[]},r={m:`message`,h:`help`,v:`version`,k:`kind`};for(let i=0;i<e.length;i++){let a=e[i];if(a===`--`){n._.push(...e.slice(i+1));break}let o=/^--?([a-zA-Z][\w-]*)(?:=(.*))?$/.exec(a);if(!o){n._.push(a);continue}let s=r[o[1]]??o[1];o[2]===void 0?t.includes(s)?n[s]=!0:i+1<e.length?n[s]=e[++i]:V(h(`{0} 后面缺少值`,[a])):n[s]=o[2]}return n}const Et=process.env.SYLUNO_HOME??n.join(t.homedir(),`.syluno`),Dt=n.join(Et,`config.json`);function U(){try{return JSON.parse(e.readFileSync(Dt,`utf8`))}catch{return{}}}function Ot(t){e.mkdirSync(Et,{recursive:!0,mode:448}),e.writeFileSync(Dt,JSON.stringify(t,null,2)+`
4746
+ `,{mode:384}),e.chmodSync(Dt,384)}let kt;const At=e=>{kt=e?.replace(/\/+$/,``)},W=e=>kt??process.env.SYLUNO_SERVER?.replace(/\/+$/,``)??e??U().server??`https://www.syluno.com`,jt=()=>process.env.SYLUNO_TOKEN??U().token;var Mt=class extends Error{status;failures;constructor(e,t,n){super(e),this.status=t,this.failures=n}};async function G(e,t,n,r={}){let i=r.auth===!1?void 0:jt(),a=W(r.base)+t,o;try{o=await fetch(a,{method:e,headers:{"Content-Type":`application/json`,"X-Lang":b,"User-Agent":`syluno-cli/0.2.0`,...i?{Authorization:`Bearer ${i}`}:{}},body:n===void 0?void 0:JSON.stringify(n),signal:AbortSignal.timeout(3e4)})}catch(e){return V(h(`连不上平台 {0}:{1}`,[W(r.base),e.message]))}let s=await o.json().catch(()=>({}));if(!o.ok)throw o.status===401?new Mt(h(`还没有登录或登录已过期,请先运行 syl login`),401):new Mt(v(s.error)||`HTTP ${o.status}`,o.status,s.failures);return s}const K=(e,t)=>G(`GET`,`/api/repos/${e}`,void 0,{base:t}),Nt=async e=>(await G(`GET`,`/api/hub`,void 0,{base:e})).repos,Pt=[` ▄▄███▄▄ `,` ▄█████████▄ `,`█████████████`,`▀███████████▀`,` ▀▀█████▀▀ `,` ███ `,` ▄▄███▄▄ `],Ft=[`███████ ██ ██ ██ ██ ██ ███ ██ ██████ `,`██ ██ ██ ██ ██ ██ ████ ██ ██ ██`,`███████ ████ ██ ██ ██ ██ ██ ██ ██ ██`,` ██ ██ ██ ██ ██ ██ ██ ██ ██ ██`,`███████ ██ ███████ ██████ ██ ████ ██████ `],It=e=>[1,3,5].map(t=>parseInt(e.slice(t,t+2),16)),Lt=(e,t,n)=>e.map((e,r)=>Math.round(e+(t[r]-e)*n)),Rt=It(`#9CCD80`),zt=It(`#4DABC4`),Bt=It(`#C49E78`),Vt=!!process.stdout.isTTY&&!process.env.NO_COLOR,Ht=/truecolor|24bit/i.test(process.env.COLORTERM??``)||process.env.TERM_PROGRAM===`iTerm.app`||process.env.TERM_PROGRAM===`vscode`,Ut=([e,t,n])=>16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(n/255*5),Wt=(e,t)=>!Vt||!e.trim()?e:Ht?`\x1b[38;2;${t[0]};${t[1]};${t[2]}m${e}\x1b[39m`:`\x1b[38;5;${Ut(t)}m${e}\x1b[39m`;function Gt(e,t,n,r){return[...e].map((e,i)=>Wt(e,Lt(t,n,i/Math.max(1,r-1)))).join(``)}const Kt=()=>{let e=h(`扎根于此,`),t=h(`自由生长`);return/[,、。!?]$/.test(e)?e+t:`${e} ${t}`};function qt(e,t,n){let r=process.stdout.columns||80;if(B(``),r>=Pt[0].length+4+Ft[0].length+2){let e=Math.floor((Pt.length-Ft.length)/2);Pt.forEach((t,n)=>{let r=n>=5?Wt(t,Bt):Gt(t,Lt(Rt,zt,n/5*.5),Lt(Rt,zt,.5+n/5*.5),t.length),i=Ft[n-e];B(` `+r+` `+(i?Gt(i,Rt,zt,i.length):``))})}else Pt.forEach((e,t)=>B(` `+(t>=5?Wt(e,Bt):Gt(e,Rt,zt,e.length))));B(``),B(` `+P(Kt())),B(``),B(` `+h(`欢迎,{0}(@{1})。已经连上 {2}`,[P(t),e,n])),B(``),B(` `+P(h(`接下来可以:`)));let i=e=>Ge().find(([t])=>t===e||t.startsWith(e+` `))?.[1]??``,a=[[`syl create my-leaf --kind leaf`,i(`create`)],[`syl clone syluno/notes`,h(`拉取一片官方的叶作参考`)],[`syl list`,i(`list`)],[`syl help`,h(`全部命令`)]],o=Math.max(...a.map(([e])=>e.length));for(let[e,t]of a)B(` `+R(St(e,o))+` `+F(t));B(``),B(` `+F(h(`完整说明:{0}`,[`${n}/#/help/cli`]))),B(``)}const Jt=/^[a-z][a-z0-9]{0,15}$/,Yt=/* @__PURE__ */ new Set([`pc`,`clock`,`start`]);function Xt(e){let t=[];for(let n of e.split(`
4747
+ `)){let e=n.replace(/#.*/,``).trim();if(!e)continue;let[r,...i]=e.split(/\s+/),a=e=>{if(!/^\d+$/.test(e??``))throw Error(`第 ${t.length} 条:跳转目标要是数字`);return+e};if(/^inc$/i.test(r)&&i.length===2)t.push({op:`inc`,c:i[0],next:a(i[1])});else if(/^jzdec$/i.test(r)&&i.length===3)t.push({op:`jzdec`,c:i[0],zero:a(i[1]),next:a(i[2])});else if(/^halt$/i.test(r)&&i.length===0)t.push({op:`halt`});else throw Error(`第 ${t.length} 条看不懂:${e}`)}return Zt(t),t}function Zt(e){if(!e.some(e=>e.op===`halt`))throw Error(`程序里至少要有一条 HALT`);e.forEach((t,n)=>{if(t.op!==`halt`){if(!Jt.test(t.c)||Yt.has(t.c))throw Error(`第 ${n} 条:计数器名要小写字母开头,且不能叫 pc、clock、start`);for(let r of t.op===`inc`?[t.next]:[t.zero,t.next])if(r<0||r>=e.length)throw Error(`第 ${n} 条:跳转目标 ${r} 不存在`)}})}const Qt=e=>[...new Set(e.flatMap(e=>e.op===`halt`?[]:[e.c]))];function $t(e,t,n=1e5){let r=Object.fromEntries(Qt(e).map(e=>[e,t[e]??0])),i=0,a=0;for(;a<n;){let t=e[i];if(t.op===`halt`)return{halted:!0,steps:a,pc:i,regs:r};t.op===`inc`?(r[t.c]++,i=t.next):r[t.c]===0?i=t.zero:(r[t.c]--,i=t.next),a++}return{halted:!1,steps:a,pc:i,regs:r}}function en(e,t,n){Zt(e);let r=Qt(e),i=(e,t,n,r,i=`card`)=>({id:e,type:`leaf`,leaf:t,x:280,y:n,role:i,inputs:r}),a=[{id:`start`,type:`root`,x:0,y:64*(r.length+1),label:`打开`},i(`clock`,`syluno/loop`,0,{interval:n.interval??.1,times:0,auto:!0}),i(`pc`,`syluno/var`,128,{name:`pc`,initial:0,keep:!1}),...r.map((e,n)=>i(e,`syluno/var`,256+128*n,{name:e,initial:t[e]??0,keep:!1},n===r.length-1?`hero`:`card`))],o=a.filter(e=>e.id!==`start`).map((e,t)=>({id:`e${t}`,from:`start`,to:e.id})),s=[],c=(e,t,n,r,i,a={})=>s.push({id:e,from:`clock`,to:t,on:`event:tick`,do:n,when:r,map:i,...a});e.forEach((e,t)=>{let n=`@pc.value == ${t}`;e.op===`inc`?(c(`l${t}a`,e.c,`action:add`,n,{by:`=1`}),c(`l${t}b`,`pc`,`action:set`,n,{value:`=${e.next}`})):e.op===`jzdec`?(c(`l${t}z`,`pc`,`action:set`,`${n} && @${e.c}.value == 0`,{value:`=${e.zero}`}),c(`l${t}a`,e.c,`action:add`,`${n} && @${e.c}.value > 0`,{by:`=-1`}),c(`l${t}b`,`pc`,`action:set`,`${n} && @${e.c}.value > 0`,{value:`=${e.next}`})):c(`l${t}h`,`clock`,`action:stop`,n,{},{delay:50})});let l=e.map((e,t)=>`${t} ${e.op===`inc`?`INC ${e.c} ${e.next}`:e.op===`jzdec`?`JZDEC ${e.c} ${e.zero} ${e.next}`:`HALT`}`).join(`
4748
+ `),u={spec:1,kind:`tree`,name:n.title??n.name,version:`0.1.0`,description:`计数器机编成的树:${e.length} 条指令,计数器 ${r.join(`、`)}`,scenes:[`logic`],icon:{glyph:`variable`,colors:[`#5E5CE6`,`#64D2FF`]},permissions:[],requirements:{ramKB:16+4*r.length,flashKB:8,cpu:`low`},requires:{},leaves:[`syluno/loop`,`syluno/var`],flow:{nodes:a,edges:o,links:s},ui:{layout:`auto`,accent:`#6CC4A8`,greeting:!0},season:`syluno/line`};return{"manifest.json":JSON.stringify(u,null,2)+`
4749
+ `,"README.md":`# ${n.title??n.name}\n\n由计数器机程序编译而成(初始值 ${r.map(e=>`${e}=${t[e]??0}`).join(`,`)}):\n\n\`\`\`\n${l}\n\`\`\`\n`}}const q=`.syluno`,tn=/* @__PURE__ */ new Set([q,`.git`,`node_modules`,`.DS_Store`,`Thumbs.db`]),nn=e=>i.createHash(`sha1`).update(e).digest(`hex`).slice(0,16),rn=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,nn(t)]));function J(t=process.cwd()){let r=n.resolve(t);for(;;){let t=n.join(r,q,`repo.json`);if(e.existsSync(t))return{dir:r,state:JSON.parse(e.readFileSync(t,`utf8`))};let i=n.dirname(r);if(i===r)return V(h(`这里不是 syluno 仓库(没有找到 .syluno/)。用 syl clone 拉取一个,或用 syl create 新建`));r=i}}function an(t){e.mkdirSync(n.join(t.dir,q),{recursive:!0}),e.writeFileSync(n.join(t.dir,q,`repo.json`),JSON.stringify(t.state,null,2)+`
4750
+ `)}function on(t,r){e.writeFileSync(n.join(t.dir,q,`base.json`),JSON.stringify(r))}function sn(t){try{return JSON.parse(e.readFileSync(n.join(t.dir,q,`base.json`),`utf8`))}catch{return null}}function cn(t,r){let i=n.join(t.dir,q,`seed.json`);r?e.writeFileSync(i,JSON.stringify(r)):e.rmSync(i,{force:!0})}function ln(t){try{return JSON.parse(e.readFileSync(n.join(t.dir,q,`seed.json`),`utf8`))}catch{return}}function un(t){try{return e.readFileSync(n.join(t,`.sylunoignore`),`utf8`).split(`
4751
+ `).map(e=>e.trim()).filter(e=>e&&!e.startsWith(`#`)).map(e=>RegExp(`^`+e.replace(/\/$/,``).replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`[^/]*`)+`(/|$)`))}catch{return[]}}function Y(t){let r={},i=[],a=un(t),o=0,s=c=>{for(let l of e.readdirSync(n.join(t,c),{withFileTypes:!0})){if(tn.has(l.name))continue;let u=c?`${c}/${l.name}`:l.name;if(u===`.sylunoignore`||a.some(e=>e.test(u)))continue;if(l.isDirectory()){s(u);continue}if(!l.isFile())continue;let d=e.readFileSync(n.join(t,u));if(d.includes(0)){i.push(u);continue}o+=d.length,o>12582912&&V(h(`仓库文件总共超过 12 MB`)),r[u]=d.toString(`utf8`)}};return s(``),{files:r,skipped:i}}const dn=e=>!!e&&!e.startsWith(`/`)&&!e.includes(`\\`)&&!e.split(`/`).some(e=>e===`..`||e===``||e===q);function X(t,r,i){dn(r)||V(h(`文件名不安全:{0}`,[r]));let a=n.join(t,r);e.mkdirSync(n.dirname(a),{recursive:!0}),e.writeFileSync(a,i)}function fn(t,r){if(dn(r)){e.rmSync(n.join(t,r),{force:!0});for(let i=n.dirname(n.join(t,r));i.startsWith(t)&&i!==t;i=n.dirname(i))try{e.rmdirSync(i)}catch{break}}}function pn(e,t){let n=[],r=[],i=[];for(let[i,a]of Object.entries(t))i in e?e[i]!==nn(a)&&r.push(i):n.push(i);for(let n of Object.keys(e))n in t||i.push(n);return{added:n.sort(),modified:r.sort(),deleted:i.sort(),any:!!(n.length+r.length+i.length)}}function mn(t,r,i){e.existsSync(t)&&e.readdirSync(t).length&&V(h(`目录 {0} 已存在且不是空的`,[t])),e.mkdirSync(t,{recursive:!0});for(let[e,n]of Object.entries(r.files))X(t,e,n);let a={dir:n.resolve(t),state:{server:i,id:r.id,kind:r.kind,base:r.updatedAt,files:rn(r.files)}};return an(a),on(a,r.files),cn(a,r.releases[0]?.files),a}const hn=[`leaf`,`tree`,`season`],Z=e=>h(e===`leaf`?`叶`:e===`tree`?`树`:`季`),gn=/^[a-z0-9][a-z0-9-]{0,38}$/,Q=/^[a-z0-9][a-z0-9-]*\/[a-z0-9][a-z0-9-]{0,38}$/,_n=/^\d+\.\d+\.\d+$/,vn=(e,t)=>{let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++)if(n[e]!==r[e])return n[e]>r[e];return!1},yn=()=>(Date.now().toString(36)+Math.random().toString(36).slice(2,6)).slice(-10),bn=e=>new Date(e).toLocaleString(void 0,{year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}),xn=(e,t)=>`${e}/#/${t}`,Sn=e=>String(e??``).split(`,`).map(e=>e.trim()).filter(Boolean);let Cn=``;async function wn(){if(Cn)return Cn;let e=U();return e.user&&!process.env.SYLUNO_TOKEN?Cn=e.user:(!e.token&&!process.env.SYLUNO_TOKEN&&V(h(`还没有登录或登录已过期,请先运行 syl login`)),Cn=(await G(`GET`,`/api/me`)).user.username)}function Tn(){return process.env.SSH_CONNECTION||process.env.SSH_TTY||process.env.CI?!1:process.platform===`darwin`||process.platform===`win32`||!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY)}function En(e){if(process.env.BROWSER===`none`)return!1;let[t,n]=process.platform===`darwin`?[`open`,[e]]:process.platform===`win32`?[`cmd`,[`/c`,`start`,``,e]]:[`xdg-open`,[e]];try{let e=a(t,n,{stdio:`ignore`,detached:!0});return e.on(`error`,()=>{}),e.unref(),!0}catch{return!1}}const Dn=e=>new Promise(t=>setTimeout(t,e)),$=e=>String(e??``).replace(/^https?:\/\/[^#]*#\//,``).replace(/\/+$/,``),On=()=>{try{return J()}catch{return null}};async function kn(e){let t=sn(e);if(t)return t;let{repo:n}=await K(e.state.id,e.state.server);return n.updatedAt!==e.state.base&&V(h(`本地没有拉取时的快照,平台上也已有新改动;先运行 syl pull`)),n.files}function An(e,t){let n=e.length,r=t.length;if(n*r>4e6)return[...e.map(e=>[`-`,e]),...t.map(e=>[`+`,e])];let i=Array.from({length:n+1},()=>new Uint32Array(r+1));for(let a=n-1;a>=0;a--)for(let n=r-1;n>=0;n--)i[a][n]=e[a]===t[n]?i[a+1][n+1]+1:Math.max(i[a+1][n],i[a][n+1]);let a=[],o=0,s=0;for(;o<n&&s<r;)e[o]===t[s]?(a.push([` `,e[o]]),o++,s++):i[o+1][s]>=i[o][s+1]?a.push([`-`,e[o++]]):a.push([`+`,t[s++]]);for(;o<n;)a.push([`-`,e[o++]]);for(;s<r;)a.push([`+`,t[s++]]);return a}function jn(e,t,n){B(P(`--- ${t===void 0?`/dev/null`:`a/`+e}`)),B(P(`+++ ${n===void 0?`/dev/null`:`b/`+e}`));let r=e=>e===void 0?[]:e.replace(/\n$/,``).split(`
4752
+ `),i=An(r(t),r(n)),a=i.map((e,t)=>e[0]!==` `||i.slice(Math.max(0,t-3),t+4).some(e=>e[0]!==` `)),o=1,s=1,c=!1;i.forEach((e,t)=>{a[t]?((c||t===0)&&B(R(`@@ -${o} +${s} @@`)),c=!1,B(e[0]===`+`?_t(`+`+e[1]):e[0]===`-`?I(`-`+e[1]):` `+e[1])):c=!0,e[0]!==`+`&&o++,e[0]!==`-`&&s++})}async function Mn(e){let t=J(),{files:n}=Y(t.dir),r=pn(t.state.files,n),i=new Set(e._.map(String)),a=[...r.added,...r.modified,...r.deleted].filter(e=>!i.size||i.has(e)).sort();if(!a.length)return B(h(`本地没有改动`));let o=await kn(t);for(let e of a)jn(e,o[e],n[e]),B(``);B(F(h(`{0} 个文件有改动`,[a.length])))}async function Nn(e){let t=J(),{files:n}=Y(t.dir),r=pn(t.state.files,n);if(e.all&&!r.any)return B(h(`本地没有改动`));let i=e.all?[...r.modified,...r.deleted,...r.added]:e._.map(String);i.length||V(h(`写出要撤销改动的文件,或加 --all 撤销全部`));let a=await kn(t),o=0;for(let e of i){if(a[e]===void 0){n[e]===void 0?B(I(h(`没有这个文件:{0}`,[e]))):B(L(h(`{0} 是新加的文件,平台上没有,保留不动(要删除请手动删)`,[e])));continue}n[e]!==a[e]&&(X(t.dir,e,a[e]),o++,B(` ${_t(`↺`)} ${e}`))}B(o?`${z} ${h(`已撤销 {0} 个文件的改动`,[o])}`:h(`没有需要撤销的改动`))}async function Pn(e){On()&&V(h(`这里已经是 syluno 仓库了`));let t=process.cwd(),r=Y(t).files,i=M(r),a=String(e._[0]??n.basename(t)).toLowerCase().replace(/[^a-z0-9-]+/g,`-`).replace(/^-+|-+$/g,``);gn.test(a)||V(h(`名称需为小写字母、数字或连字符`));let o=String(e.kind??i?.kind??`leaf`);hn.includes(o)||V(h(`类别只能是 leaf、tree 或 season`));let s=await wn(),c=String(e.org??s),l=`${c}/${a}`,u=et(o,a),d=Object.keys(u).filter(e=>r[e]===void 0),f={...u,...r},p=Date.now(),m={id:l,owner:c,name:a,kind:o,description:i?.description??``,visibility:e.private?`private`:`public`,files:f,commits:[{id:yn(),message:h(`初始提交`),author:s,at:p,changed:Object.keys(f)}],releases:[],members:[],stars:[],updatedAt:p};await G(`PUT`,`/api/repos/${l}`,{repo:m,create:!0});for(let e of d)X(t,e,u[e]);let{repo:g}=await K(l),_={dir:t,state:{server:W(),id:l,kind:o,base:g.updatedAt,files:rn(g.files)}};an(_),on(_,g.files),cn(_,void 0),B(`${z} ${h(`已把当前目录建成平台上的{0} {1}({2} 个文件)`,[Z(o),P(l),Object.keys(f).length])}`),d.length&&B(F(h(`按模板补上了:{0}`,[d.join(`, `)]))),B(F(xn(W(),l)))}const Fn=(e,t)=>{let n=t.type===`list`&&t.of?`${k.list}<${k[t.of]}>`:k[t.type]??t.type,r=[t.unit&&h(`单位 {0}`,[t.unit]),t.default!==void 0&&h(`默认 {0}`,[JSON.stringify(t.default)]),(t.min!==void 0||t.max!==void 0)&&`${t.min??``}~${t.max??``}`,t.values&&t.values.join(`|`)].filter(Boolean).join(F(` · `));return[` ${R(e)}`,n,t.label??``,F(r)]};function In(e){let t=[[h(`输入`),e?.inputs,!1],[h(`输出`),e?.outputs,!1],[h(`事件`),e?.events,!0],[h(`动作`),e?.actions,!0]];for(let[e,n,r]of t){let t=Object.keys(n??{});if(B(P(` ${e}`)+F(` ${t.length}`)),!t.length){B(F(` —`));continue}let i=[];for(let e of t){let t=n[e];if(r){i.push([` ${R(e)}`,``,t.label??``,``]);for(let[e,n]of Object.entries(t.payload??t.params??{})){let t=Fn(e,n);t[0]=` ${F(`·`)} ${e}`,i.push(t)}}else i.push(Fn(e,t))}H(i)}}async function Ln(e){let t,n;if(e._[0]){let r=$(e._[0]),{repo:i}=await K(r);t=M(i.releases[0]?.files??i.files),n=`${r}${i.releases[0]?`@`+i.releases[0].version:``}`}else{let e=J();t=M(Y(e.dir).files),n=h(`{0}(本地)`,[e.state.id])}t||V(h(`manifest.json 无法解析`)),t.kind!==`leaf`&&V(h(`只有叶有接口;树的联动见 manifest.json 的 flow.links`)),B(`${P(t.name)} ${F(n)}`),B(``),In(t.io)}async function Rn(e){let t=e._.map(String).join(` `).toLowerCase(),n=e.kind?String(e.kind):null,r=e.scene?String(e.scene):null;r&&!S.some(e=>e.id===r)&&V(h(`没有这个场景:{0}。可选值见 syl tags`,[r]));let i=dt(await Nt()).filter(e=>e.visibility===`public`&&e.releases.length).map(e=>({r:e,m:M(e.releases[0].files)})).filter(({r:e,m:i})=>!i||n&&e.kind!==n||r&&!(w(e.releases[0].files).scenes??[]).includes(r)?!1:!t||[e.id,i.name,i.description??``].some(e=>e.toLowerCase().includes(t))).sort((e,t)=>t.r.stars.length-e.r.stars.length||t.r.releases[0].publishedAt-e.r.releases[0].publishedAt);if(!i.length)return B(h(`林里没有找到匹配的作品`));H([[F(h(`仓库`)),F(h(`类别`)),F(h(`最新种子`)),F(`★`),F(h(`名称`))],...i.slice(0,30).map(({r:e,m:t})=>[P(e.id),Z(e.kind),e.releases[0].version,String(e.stars.length),`${t.name} ${F(t.description??``)}`])]),i.length>30&&B(F(h(`…… 还有 {0} 条,换个关键词缩小范围`,[i.length-30])))}async function zn(e){let t=$(e._[0]??On()?.state.id??``);Q.test(t)||V(h(`请写成 所有者/名称,例如 syluno/notes`));let{repo:n,role:r}=await K(t),i=n.releases[0],a=M(i?.files??n.files),o=w(i?.files??n.files);B(`${P(n.id)} ${Z(n.kind)}${n.visibility===`private`?F(` 🔒`):``} ${F(`★ `+n.stars.length)}`),a&&B(`${a.name} ${F(a.description??``)}`),B(``);let s=[[F(h(`最新种子`)),i?`${i.version} ${F(bn(i.publishedAt)+` · `+i.publishedBy+` · `+i.hash)}`:F(h(`还没有发布`))],[F(h(`种子数`)),String(n.releases.length)],[F(h(`提交数`)),String(n.commits.length)]];if(o.scenes&&s.push([F(h(`场景`)),o.scenes.map(e=>ee(`scenes`,e)).join(`, `)||F(h(`暂不分类`))]),o.styles&&s.push([F(h(`界面风格`)),o.styles.map(e=>ee(`styles`,e)).join(`, `)||F(h(`暂不分类`))]),a){s.push([F(h(`权限`)),a.permissions.join(`, `)||F(h(`无`))]),s.push([F(h(`资源`)),`RAM ${a.requirements.ramKB} KB · Flash ${a.requirements.flashKB} KB · CPU ${a.requirements.cpu}`]);let e=Object.entries(a.requires??{}).filter(([,e])=>e&&(!Array.isArray(e)||e.length)).map(([e,t])=>Array.isArray(t)?`${e}(${t.join(`,`)})`:e);s.push([F(h(`硬件要求`)),e.join(`, `)||F(h(`无`))]),n.kind===`tree`&&s.push([F(h(`用到的叶`)),(a.leaves??[]).join(`, `)],[F(h(`季`)),a.season??``]),i?.lock&&s.push([F(h(`锁定版本`)),Object.entries(i.lock).map(([e,t])=>`${e}@${t}`).join(`, `)])}r&&s.push([F(h(`我的角色`)),r]),H(s),B(``),B(F(xn(W(),n.id)))}async function Bn(e){let t=$(e._[0]);Q.test(t)||V(h(`请写成 所有者/名称,例如 syluno/notes`));let{repo:n}=await K(t),r=await wn(),i=String(e.org??r),a=String(e._[1]??n.name);gn.test(a)||V(h(`名称需为小写字母、数字或连字符`));let o=`${i}/${a}`,s=n.releases[0],c={...s?.files??n.files},l=Date.now(),u=s?h(`复制自 {0}@{1}`,[t,s.version]):h(`复制自 {0}`,[t]),d={id:o,owner:i,name:a,kind:n.kind,description:n.description,visibility:`public`,files:c,commits:[{id:yn(),message:u,author:r,at:l,changed:Object.keys(c)}],releases:[],members:[],stars:[],updatedAt:l};await G(`PUT`,`/api/repos/${o}`,{repo:d,create:!0});let{repo:f}=await K(o),p=String(e.dir??a);mn(p,f,W()),B(`${z} ${h(`已把 {0} 复制为 {1},并拉取到 {2}/`,[t,P(o),p])}`),B(F(h(`改好后 syl push,再 syl publish 发布成自己的版本`)))}async function Vn(e){let t=$(e._[0]??On()?.state.id??``);Q.test(t)||V(h(`请写成 所有者/名称,例如 syluno/notes`));let n=await G(`POST`,`/api/repos/${t}/star`);B(n.starred?`${z} ${h(`已收藏 {0}`,[P(t)])}`:h(`已取消收藏 {0}`,[P(t)]))}const Hn=[`code`,`io`,`flow`,`releases`,`preview`,`discuss`,`settings`];function Un(e){let t=On(),n=t?.state.id??``,r=``;for(let t of e._.map(String))Hn.includes(t)?r=t:n=$(t);Q.test(n)||V(h(`请写成 所有者/名称,或在仓库目录里运行`));let i=`${t?.state.server??W()}/#/${n}${r&&r!==`code`?`/`+r:``}`;B(En(i)?h(`已在浏览器里打开 {0}`,[R(i)]):R(i))}async function Wn(t){let[n,r]=String(t._[0]??``).split(`@`),i=$(n);Q.test(i)||V(h(`请写成 所有者/名称@版本,例如 syluno/notes@2.0.0`));let{repo:a}=await K(i),o=r?a.releases.find(e=>e.version===r):a.releases[0];o||V(a.releases.length?h(`没有这个版本。已发布:{0}`,[a.releases.map(e=>e.version).join(`, `)]):h(`还没有发布`));let s=Ae(o.files);s!==o.hash&&V(h(`校验值不一致(应为 {0},实际 {1}),种子可能被篡改,已停止`,[o.hash,s]));let c=String(t._[1]??`${a.name}-${o.version}`);e.existsSync(c)&&e.readdirSync(c).length&&V(h(`目录 {0} 已存在且不是空的`,[c]));for(let[e,t]of Object.entries(o.files))X(c,e,t);B(`${z} ${h(`已下载 {0}@{1} 到 {2}/,校验值 {3} 一致`,[P(i),o.version,c,o.hash])}`),o.lock&&B(F(h(`锁定的依赖:{0}`,[Object.entries(o.lock).map(([e,t])=>`${e}@${t}`).join(`, `)]))),B(F(h(`这是种子的只读副本;要修改请用 syl fork`)))}async function Gn(e){let t=On(),n=$(e._[0]??t?.state.id??``);Q.test(n)||V(h(`请写成 所有者/名称,或在仓库目录里运行`)),!e.public&&!e.private&&e.description===void 0&&V(h(`要改什么?--public、--private 或 --description "说明"`)),e.public&&e.private&&V(h(`--public 和 --private 只能选一个`));let{repo:r}=await K(n),i={...r,visibility:e.private?`private`:e.public?`public`:r.visibility,description:e.description===void 0?r.description:String(e.description)},a=await G(`PUT`,`/api/repos/${n}`,{repo:i,base:r.updatedAt});t&&t.state.id===n&&t.state.base===r.updatedAt&&(t.state.base=a.updatedAt,an(t)),B(`${z} ${h(`已更新 {0}:{1},{2}`,[P(n),i.visibility===`private`?h(`私有`):h(`公开`),i.description||F(h(`(无描述)`))])}`),i.visibility===`private`&&r.visibility===`public`&&r.releases.length&&B(L(h(`改成私有后,种子不再出现在林里`)))}async function Kn(e){let t=$(e._[0]??On()?.state.id??``);Q.test(t)||V(h(`请写成 所有者/名称,或在仓库目录里运行`));let{repo:n}=await K(t),r=[[P(n.owner),`owner`]];for(let e of n.members??[])e.username!==n.owner&&r.push([e.username,e.role]);H(r);try{let{invites:e}=await G(`GET`,`/api/repos/${t}/invites`);e?.length&&(B(``),B(F(h(`待接受的邀请`))),H(e.map(e=>[e.who.replace(/^email:/,``),e.role,F(h(`由 {0} 于 {1} 邀请`,[e.by,bn(e.at)]))])))}catch{}}async function qn(e){let t=On(),n=String(e._[0]??``);n||V(h(`写出要邀请的用户名或邮箱`));let r=String(e.role??`writer`);[`maintainer`,`writer`,`reader`].includes(r)||V(h(`角色只能是 maintainer、writer 或 reader`));let i=$(e.repo??t?.state.id??``);Q.test(i)||V(h(`请在仓库目录里运行,或用 --repo 所有者/名称 指定`)),await G(`POST`,`/api/repos/${i}/invites`,{who:n,role:r}),B(`${z} ${h(`已邀请 {0} 以 {1} 身份加入 {2},对方接受后生效`,[P(n),r,i])}`)}function Jn(t){let n=J();n.state.kind!==`tree`&&V(h(`只有树仓库能装计数器机,先 syl create <名称> --kind tree`));let r=String(t._[0]??``);(!r||!e.existsSync(r))&&V(h(`写出程序文件,每行一条:INC c j | JZDEC c j l | HALT`));let i;try{i=Xt(e.readFileSync(r,`utf8`))}catch(e){return V(h(`程序有误:{0}`,[e.message]))}let a={};for(let e of String(t.set??``).split(`,`).filter(Boolean)){let[t,n]=e.split(`=`);/^\d+$/.test(n??``)||V(h(`初始值写成 --set c1=3,c2=0(非负整数)`)),a[t.trim()]=+n}let o=en(i,a,{name:n.state.id.split(`/`)[1]});for(let[e,t]of Object.entries(o))X(n.dir,e,t);let s=JSON.parse(o[`manifest.json`]).flow.links.length,c=$t(i,a,1e5);B(`${z} ${h(`已编进 manifest.json:{0} 条指令、{1} 个计数器 → {2} 条联动`,[i.length,Qt(i).length,s])}`),B(c.halted?h(`参考解释器:{0} 步停机,结果 {1}`,[c.steps,Object.entries(c.regs).map(([e,t])=>`${e}=${t}`).join(` `)]):L(h(`参考解释器:{0} 步内没有停机(树也会一直运行)`,[c.steps]))),B(F(h(`接下来 syl check、syl push,再 syl open preview 在模拟器里运行,对照结果`)))}function Yn(e){let t=String(e._[0]??(process.env.SHELL?.includes(`zsh`)?`zsh`:`bash`)),n=Ge().map(([e,t])=>[e.split(` `)[0],t]);if(t===`zsh`){let e=n.map(([e,t])=>` '${e}:${t.replace(/[':]/g,` `).slice(0,60)}'`).join(`
4753
+ `);process.stdout.write(`#compdef syl syluno
4754
+ # ${h(`syl 命令补全:在 ~/.zshrc 里加一行`)} eval "$(syl completion zsh)"
4755
+ _syl() {
4756
+ local -a cmds
4757
+ cmds=(
4758
+ ${e}
4759
+ )
4760
+ if (( CURRENT == 2 )); then _describe 'command' cmds; else _files; fi
4761
+ }
4762
+ (( $+functions[compdef] )) || { autoload -Uz compinit && compinit; }
4763
+ compdef _syl syl syluno
4764
+ `)}else t===`bash`?process.stdout.write(`# ${h(`syl 命令补全:在 ~/.bashrc 里加一行`)} eval "$(syl completion bash)"
4765
+ complete -o default -W "${n.map(([e])=>e).join(` `)}" syl syluno
4766
+ `):V(h(`只支持 zsh 和 bash`));process.stdout.isTTY&&console.error(F(h(`把上面的脚本加到 shell 配置里:eval "$(syl completion {0})"`,[t])))}function Xn(e,t,n,r){let{rules:i,results:a}=pt(e,t,n,r),o=0,s=0;for(let e of a){let t=e.ok?z:e.severity===`warn`?yt:vt;e.ok||(e.severity===`warn`?s++:o++),B(`${t} ${e.ok?F(`${e.rule+1}.`):P(`${e.rule+1}.`)} ${e.ok?i[e.rule]:P(i[e.rule])}`),e.detail&&!e.ok&&B(` ${e.severity===`warn`?L(e.detail):I(e.detail)}`)}return B(``),B(o?I(h(`{0} 条规则没有通过,修好之后才能发布`,[o])):_t(s?h(`检查通过,有 {0} 条提示`,[s]):h(`检查全部通过`))),o>0}async function Zn(e){try{return await Nt(e?.state.server)}catch{return null}}function Qn(e,t){t.updatedAt!==e.state.base&&V(h(`平台上有新的改动,请先拉取(syl pull)`))}async function $n(e){let t=W(),n=e.web||!e.terminal&&!e.code&&Tn()?await er(t):await tr(e,t);Ot({...U(),server:t,token:n.token,tokenId:n.id,user:n.user.username}),B(``),B(`${z} ${P(h(`登录成功`))} ${F(h(`令牌 {0} 天内有效,保存在 ~/.syluno/config.json`,[n.days]))}`),qt(n.user.username,n.user.name,t)}async function er(e){let n=await G(`POST`,`/api/cli/login`,{name:`syluno CLI · ${t.hostname()}`},{auth:!1}),r=`${e}/#/cli-login/${n.id}`,i=En(r);B(P(h(i?`已在浏览器里打开 syluno,登录后点「授权」`:`请在浏览器里打开下面的链接,登录后点「授权」`))),B(` `+R(r)),B(``),B(h(`核对验证码:网页上显示的应该是 {0}`,[P(n.code)])),B(F(h(`浏览器没有打开的话,复制上面的链接;没有浏览器的设备用 syl login --terminal`))),B(``);let a=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`],o=process.stdout.isTTY,s=h(`等待网页授权…(Ctrl+C 取消)`),c=Date.now()+n.expiresIn*1e3;for(let e=0;Date.now()<c;e++){if(o?process.stdout.write(`\r${R(a[e%a.length])} ${s}`):e===0&&B(s),await Dn(o?250:2e3),o&&e%8!=7)continue;let t=await G(`POST`,`/api/cli/login/${n.id}/poll`,{secret:n.secret},{auth:!1});if(t.status!==`pending`){if(o&&process.stdout.write(`\r\x1B[2K`),t.status===`approved`)return t;V(t.status===`denied`?h(`已在网页上取消授权`):h(`登录请求已过期,请重新运行 syl login`))}}return o&&process.stdout.write(`\r\x1B[2K`),V(h(`登录请求已过期,请重新运行 syl login`))}async function tr(e,n){B(F(h(`登录 {0}`,[n])));let r=String(e._[0]??``)||await Ct(h(`邮箱或用户名:`));r||V(h(`请输入邮箱或用户名`));let i={email:r,name:`syluno CLI · ${t.hostname()}`};return e.code?(await G(`POST`,`/api/auth/code`,{email:r,purpose:`login`},{auth:!1}),B(h(`验证码已发送到 {0}`,[r])),i.code=await Ct(h(`验证码:`))):i.password=await wt(h(`密码(没有设置密码的账户加 --code 用邮箱验证码登录):`)),G(`POST`,`/api/auth/token`,i,{auth:!1})}async function nr(){let e=U();if(!e.token)return B(h(`没有登录`));try{e.tokenId&&await G(`DELETE`,`/api/tokens/${e.tokenId}`)}catch{}Ot({server:e.server}),B(`${z} ${h(`已退出,令牌已作废`)}`)}async function rr(){let{user:e}=await G(`GET`,`/api/me`);process.env.SYLUNO_TOKEN||Ot({...U(),user:e.username}),B(`${P(e.username)} ${e.name}${e.email?F(` <${e.email}>`):``} ${F(W())}`)}async function ir(e){let t=String(e._[0]??``);gn.test(t)||V(h(`名称需为小写字母、数字或连字符`));let n=String(e.kind??`leaf`);hn.includes(n)||V(h(`类别只能是 leaf、tree 或 season`));let r=await wn(),i=String(e.org??r),a=`${i}/${t}`,o=et(n,t),s=Date.now(),c={id:a,owner:i,name:t,kind:n,description:``,visibility:e.private?`private`:`public`,files:o,commits:[{id:yn(),message:h(`初始提交`),author:r,at:s,changed:Object.keys(o)}],releases:[],members:[],stars:[],updatedAt:s};await G(`PUT`,`/api/repos/${a}`,{repo:c,create:!0});let{repo:l}=await K(a),u=String(e.dir??t);mn(u,l,W()),B(`${z} ${h(`已在平台上创建{0} {1},并拉取到 {2}/`,[Z(n),P(a),u])}`),B(``),B(h(`仓库里的 RULES.md 写明了平台对这个{0}的全部规则。接下来:`,[Z(n)])),B(R(` cd ${u}`)),B(R(` syl check`)+F(` # `+h(`按发布规则检查`))),B(R(` syl push -m "${h(`第一版`)}"`)),B(R(` syl publish 0.1.0 -m "${h(`首个版本`)}"`)),B(F(xn(W(),a)))}async function ar(e){let t=String(e._[0]??``).replace(/^https?:\/\/[^#]*#\//,``).replace(/\/+$/,``);Q.test(t)||V(h(`请写成 所有者/名称,例如 syluno/notes`));let{repo:n}=await K(t),r=String(e._[1]??n.name);mn(r,n,W()),B(`${z} ${h(`已拉取{0} {1} 到 {2}/({3} 个文件{4})`,[Z(n.kind),P(t),r,Object.keys(n.files).length,n.releases[0]?h(`,最新种子 {0}`,[n.releases[0].version]):``])}`)}async function or(){let{repos:e}=await G(`GET`,`/api/repos`);if(!e.length)return B(h(`还没有仓库。用 syl create <名称> 新建一个`));H([[F(h(`仓库`)),F(h(`类别`)),F(h(`最新种子`)),F(h(`角色`)),F(h(`更新时间`))],...e.sort((e,t)=>t.updatedAt-e.updatedAt).map(e=>[P(e.id)+(e.visibility===`private`?F(` 🔒`):``),Z(e.kind),e.version??F(`—`),e.role,F(bn(e.updatedAt))])])}async function sr(){let e=J(),{files:t,skipped:n}=Y(e.dir),r=pn(e.state.files,t);B(h(`{0}「{1}」 {2}`,[Z(e.state.kind),P(e.state.id),F(e.state.server)]));try{let{repo:t}=await K(e.state.id,e.state.server);t.updatedAt===e.state.base?B(F(h(`和平台同步({0})`,[bn(t.updatedAt)]))):B(L(h(`平台上有新的改动,运行 syl pull 拉取`)))}catch(e){B(F(h(`没能连上平台:{0}`,[e.message])))}if(!r.any)B(h(`本地没有改动`));else{B(h(`本地改动(还没推送):`));for(let e of r.added)B(_t(` + ${e}`));for(let e of r.modified)B(L(` ~ ${e}`));for(let e of r.deleted)B(I(` - ${e}`))}n.length&&B(F(h(`跳过的二进制文件:{0}`,[n.join(`, `)])))}async function cr(t){let r=J(),{repo:i}=await K(r.state.id,r.state.server);if(i.updatedAt===r.state.base)return B(h(`已是最新`));let a=Y(r.dir).files,o=r.state.files,s=rn(i.files),c=/* @__PURE__ */ new Set([...Object.keys(o),...Object.keys(a),...Object.keys(i.files)]),l=[],u=[];for(let e of c){let t=a[e]===void 0?void 0:rn({x:a[e]}).x;s[e]!==o[e]&&(t===o[e]||t===s[e]?l.push(e):u.push(e))}if(u.length&&!t.theirs){B(I(h(`这些文件本地和平台上都改了:`)));for(let e of u)B(` ${e}`);V(h(`先推送或撤销本地改动;或用 syl pull --theirs 采用平台上的版本(本地的会备份到 .syluno/backup/)`))}if(u.length){let t=n.join(r.dir,`.syluno`,`backup`,(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g,`-`));for(let r of u)a[r]!==void 0&&(e.mkdirSync(n.dirname(n.join(t,r)),{recursive:!0}),e.writeFileSync(n.join(t,r),a[r]));l.push(...u),B(L(h(`本地版本已备份到 {0}`,[n.relative(process.cwd(),t)||t])))}for(let e of l.sort())i.files[e]===void 0?(fn(r.dir,e),B(I(` - ${e}`))):(X(r.dir,e,i.files[e]),B(_t(` ${o[e]?`~`:`+`} ${e}`)));r.state={...r.state,kind:i.kind,base:i.updatedAt,files:s},an(r),on(r,i.files),cn(r,i.releases[0]?.files),B(`${z} ${h(`已拉取 {0} 处改动`,[l.length])}`)}async function lr(e){let t=J(),n=typeof e.message==`string`?e.message.trim():``;n||V(h(`请用 -m 写一句这次改了什么`));let{files:r,skipped:i}=Y(t.dir),a=pn(t.state.files,r);if(!a.any)return B(h(`本地没有改动`));i.length&&B(F(h(`跳过的二进制文件:{0}`,[i.join(`, `)])));let{results:o}=pt(t.state.kind,r,ln(t),await Zn(t)??[]),s=o.filter(e=>!e.ok&&e.severity===`error`).length,{repo:c}=await K(t.state.id,t.state.server);Qn(t,c);let l=await wn(),u={id:yn(),message:n,author:l,at:Date.now(),changed:[...a.added,...a.modified,...a.deleted]},d={...c,files:r,commits:[u,...c.commits],updatedAt:Date.now()},f=await G(`PUT`,`/api/repos/${t.state.id}`,{repo:d,base:t.state.base},{base:t.state.server});t.state={...t.state,base:f.updatedAt,files:rn(r)},an(t),on(t,r),B(`${z} ${h(`已推送 {0}:{1}`,[P(t.state.id),n])} ${F(`+${a.added.length} ~${a.modified.length} -${a.deleted.length}`)}`),s&&B(L(h(`有 {0} 条发布规则没有通过,发布前需要修好(syl check 查看)`,[s])))}async function ur(){let e=J(),{files:t}=Y(e.dir),n=await Zn(e);if(n===null&&e.state.kind===`tree`&&B(L(h(`没能连上平台,依赖的叶和季无法核对`))),B(h(`按平台规则(规范版本 {0})检查{1} {2}:`,[1,Z(e.state.kind),P(e.state.id)])),B(``),Xn(e.state.kind,t,ln(e),n??[]))throw new bt(``,1)}async function dr(e){let t=J(),n=String(e._[0]??``),r=typeof e.message==`string`?e.message.trim():``;_n.test(n)||V(h(`版本号要写成 主.次.修订,例如 1.2.0`)),r||V(h(`请用 -m 写这个版本的说明`));let i=Y(t.dir).files;pn(t.state.files,i).any&&V(h(`有还没推送的改动,先运行 syl push`));let{repo:a,role:o}=await K(t.state.id,t.state.server);Qn(t,a),o!==`owner`&&o!==`maintainer`&&V(h(`发布需要维护者及以上的权限`));let s=a.releases[0];s&&!vn(n,s.version)&&V(h(`新版本号要大于上一颗种子 {0}`,[s.version]));let c={};e.scenes!==void 0&&(c.scenes=Sn(e.scenes)),e.styles!==void 0&&(c.styles=Sn(e.styles)),t.state.kind===`season`&&(delete c.scenes,delete c.styles),t.state.kind===`tree`&&delete c.styles;let l=it(Object.keys(c).length?te(a.files,c):a.files,n),u=dt(await Nt(t.state.server));if(mt(a.kind,l,s?.files,u).length){B(I(h(`发布检查没有通过:`))),B(``),Xn(a.kind,l,s?.files,u);let e=w(l);throw a.kind!==`season`&&(!e.scenes||a.kind===`leaf`&&!e.styles)&&B(F(h(`分类用 --scenes 和 --styles 指定,可选值见 syl tags;暂不分类可以写 --scenes ""`))),new bt(``,1)}let d=rt(l,n,r,await wn(),Date.now(),u),f={...a,files:l,releases:[d,...a.releases],updatedAt:Date.now()},p;try{p=await G(`PUT`,`/api/repos/${t.state.id}`,{repo:f,base:t.state.base},{base:t.state.server})}catch(e){if(e instanceof Mt&&e.failures?.length){B(I(e.message));for(let t of e.failures)B(`${vt} ${P(`${t.rule}.`)} ${h(t.text)}${t.detail?`\n ${I(t.detail)}`:``}`);throw new bt(``,1)}throw e}X(t.dir,`manifest.json`,l[`manifest.json`]),t.state={...t.state,base:p.updatedAt,files:rn(l)},an(t),on(t,l),cn(t,l),B(`${z} ${h(`已发布 {0} 的种子 {1}(校验值 {2})`,[P(t.state.id),P(n),d.hash])}`),a.visibility===`private`?B(L(h(`仓库是私有的,种子不会出现在林里;改成公开后自动上架`))):B(h(`已上架到林:{0}`,[R(xn(t.state.server,t.state.id))]))}async function fr(){let e=J(),{repo:t}=await K(e.state.id,e.state.server);t.releases.length&&(B(P(h(`种子`))),H(t.releases.map(e=>[_t(e.version),F(bn(e.publishedAt)),e.publishedBy,e.notes])),B(``)),B(P(h(`提交`))),H(t.commits.slice(0,30).map(e=>[L(e.id.slice(-7)),F(bn(e.at)),e.author,e.message])),t.commits.length>30&&B(F(h(`…… 还有 {0} 条`,[t.commits.length-30])))}function pr(e){let t=J(),n=t.state.id.split(`/`)[1],r=$e(t.state.kind,n);if(!e.update){process.stdout.write(r);return}X(t.dir,`RULES.md`,r),B(`${z} ${h(`已按当前规范重新生成 RULES.md,推送后生效`)}`)}function mr(){let e=(()=>{try{return J()}catch{return null}})();for(let[e,t]of[[h(`场景(--scenes)`),S],[h(`界面风格(--styles,只有叶需要)`),C]])B(P(e)),H(t.map(e=>[R(` `+e.id),e.label,F(e.hint)])),B(``);if(e){let t=w(Y(e.dir).files);B(F(h(`当前清单:scenes = {0},styles = {1}`,[JSON.stringify(t.scenes),JSON.stringify(t.styles)])))}B(F(h(`每组最多 3 个,用逗号分隔,例如 --scenes time,study`)))}function hr(){B(`${P(`syl`)} ${F(`0.2.0`)} — ${h(`在终端里开发叶、树、季,并按平台规则发布`)}`),B(``),B(P(h(`用法`))+` syl <`+h(`命令`)+`> [`+h(`参数`)+`]`),B(``);for(let[e,t]of Ge())B(` ${R(e)}\n ${t}`);B(``),B(P(h(`通用参数`))),H([[R(` --server <URL>`),h(`平台地址,默认 https://www.syluno.com(也可用环境变量 SYLUNO_SERVER)`)],[R(` --lang <${h(`代码`)}>`),h(`输出语言,例如 en、zh-CN(默认跟随系统)`)],[R(` SYLUNO_TOKEN`),h(`环境变量:在持续集成里代替登录,令牌在网页「账户 → 命令行」里生成`)]]),B(``),B(F(h(`完整说明:{0}`,[`${W()}/#/help/cli`])))}async function gr(){let e=U();if(!(e.checkedAt&&Date.now()-e.checkedAt<864e5))try{let e=await G(`GET`,`/api/cli`,void 0,{auth:!1});Ot({...U(),checkedAt:Date.now()}),e.version&&vn(e.version,`0.2.0`)&&console.error(L(h(`syluno 有新版本 {0}(当前 {1}):{2}`,[e.version,`0.2.0`,e.install??``]))),e.spec&&e.spec>1&&console.error(L(h(`平台规范已更新到版本 {0},请升级命令行工具,本地检查才会和平台一致`,[e.spec])))}catch{}}const _r=[`code`,`web`,`terminal`,`private`,`public`,`all`,`theirs`,`update`,`help`,`version`],vr={login:$n,logout:nr,whoami:rr,list:or,ls:or,create:ir,new:ir,init:Pn,clone:ar,status:sr,st:sr,diff:Mn,restore:Nn,pull:cr,push:lr,check:ur,publish:dr,log:fr,rules:pr,tags:mr,io:Ln,search:Rn,info:zn,fork:Bn,star:Vn,open:Un,seed:Wn,set:Gn,members:Kn,invite:qn,machine:Jn,completion:Yn};async function yr(){let e=Tt(process.argv.slice(2),_r);if(typeof e.server==`string`&&At(e.server),e.version)return B(`0.2.0`);let t=e._.shift();if(!t||e.help||t===`help`)return hr();let n=vr[t];n||V(h(`没有这个命令:{0}。运行 syl help 查看全部命令`,[t])),[`help`,`rules`,`tags`,`completion`,`diff`,`restore`].includes(t)||await gr(),await n(e)}yr().catch(e=>{e instanceof bt&&(e.message&&console.error(I(e.message)),process.exit(e.code)),e instanceof Mt&&(console.error(I(e.message)),process.exit(1)),console.error(e),process.exit(1)});export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "syluno",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "syluno CLI (command: syl): create, clone, push, check and publish Leaves, Trees and Seasons from the terminal(在终端里开发并发布 syluno 的叶、树、季,命令 syl)",
5
5
  "type": "module",
6
6
  "bin": {