@zleap-ai/app-sdk 0.10.1 → 0.12.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/README.md +1 -1
- package/dist/build-info.json +6 -6
- package/dist/host.js +1 -1
- package/dist/index.js +1 -1
- package/dist/workspace.js +1 -1
- package/dist/zleap.css +582 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -37,4 +37,4 @@ const { data } = await db.collection('todos').orderBy('created_at', 'desc').limi
|
|
|
37
37
|
|
|
38
38
|
## 版本与许可
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
版本独立于 `@zleap-ai/app-cli`(SDK 只和 zleapOS 宿主握手,不依赖 CLI 版本)。专有许可,仅限在 zleapOS 应用中使用,见 [LICENSE](./LICENSE)。
|
package/dist/build-info.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@zleap-ai/app-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"source": "
|
|
5
|
-
"files":
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"source": "593b98bd6d4f1600d48579da161460f6e38403fd35164621668a31dfeecab21f",
|
|
5
|
+
"files": 22,
|
|
6
6
|
"outputs": {
|
|
7
7
|
"index": {
|
|
8
8
|
"bytes": 38237,
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "260761adced7464e2d9151f3eecb6768092b61a37f3f7a73c4f5e24b700c04bf"
|
|
10
10
|
},
|
|
11
11
|
"host": {
|
|
12
12
|
"bytes": 11622,
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "0b5c724abbd798c90a7743e21823fb4a8ae0e1332af7c3bfffc2d7bf4e59b8b8"
|
|
14
14
|
},
|
|
15
15
|
"workspace": {
|
|
16
16
|
"bytes": 2632,
|
|
17
|
-
"sha256": "
|
|
17
|
+
"sha256": "de9ca423763ce8007f2e4baf72b56f819c445b586cda92378e6ad8ac38cf785e"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
}
|
package/dist/host.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @zleap-ai/app-sdk v0.
|
|
1
|
+
/*! @zleap-ai/app-sdk v0.12.0 | (c) 2026 Zleap | 专有许可,仅限在 zleapOS 应用中使用,见 LICENSE */
|
|
2
2
|
var U=Object.defineProperty;var F=(e,t,s)=>t in e?U(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s;var V=(e,t,s)=>F(e,typeof t!="symbol"?t+"":t,s);var o=class extends Error{constructor(s,n){super(s);V(this,"code");this.code=n,this.name="SDKError"}},I=1024*1024,D=64*1024,z=16,$=2**31-1,K=/^[a-z0-9][a-z0-9._-]{0,127}$/,J=128,q=/[/\\:%?#<>|"*]/,Z=/\p{C}/u,L=new Set(["con","prn","aux","nul",".packageroot",".","..",...Array.from({length:9},(e,t)=>`com${t+1}`),...Array.from({length:9},(e,t)=>`lpt${t+1}`)]),P=new WeakMap,S=e=>!!(e&&typeof e=="object"&&!Array.isArray(e)),k=e=>new TextEncoder().encode(e).byteLength,A=e=>typeof e=="number"&&Number.isSafeInteger(e)&&e>=0;function O(e){if(typeof e!="string"||!K.test(e))throw new o(`KV 键不合法:须匹配 ${K.source}(首字符小写字母/数字,仅含小写字母/数字/._-,长度 1-128),收到 ${JSON.stringify(e)}`,42200)}function C(e){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>$)throw new o(`KV expectedVersion 不合法:须为 0..${$} 的整数(当前乐观锁版本,先 kv.get 取最新 version),收到 ${JSON.stringify(e)}`,42200)}function R(e){let t='文件名不合法:须为安全的根目录名称(非空、≤128 UTF-8 字节、无首尾空白、不以点结尾、不含 /\\:%?#<>|"* 与控制字符、非 con/com1-9 等系统保留名)',s=()=>{throw new o(t,42200)};if(typeof e!="string"||e.length===0)throw new o(t,42200);let n=e.normalize("NFC");Math.max(k(e),k(n))>J&&s(),(e!==e.trim()||e.endsWith("."))&&s(),(q.test(e)||Z.test(e))&&s();let a=n.toLowerCase(),f=a.split(".",1)[0]??a;(L.has(a)||L.has(f))&&s()}function X(e){let t=new Set,s=(n,a)=>{if(a>z)throw new o(`KV 值嵌套超过 ${z} 层上限`,42200);if(n===null)return"null";switch(typeof n){case"boolean":case"number":case"string":return JSON.stringify(n);case"bigint":throw new o("KV 值不支持 BigInt,请转换为 number 或 string",42200);case"undefined":case"function":case"symbol":return"";case"object":{if(t.has(n))throw new o("KV 值存在循环引用,无法序列化",42200);if(typeof n.toJSON=="function")throw new o("KV 值含带 toJSON 的对象(如 Date):请先显式转换(如 value.toISOString())后再写入",42200);t.add(n);try{return Array.isArray(n)?`[${n.map(f=>s(f,a+1)||"null").join(",")}]`:`{${Object.entries(n).filter(([,f])=>!["undefined","function","symbol"].includes(typeof f)).sort(([f],[d])=>f<d?-1:f>d?1:0).map(([f,d])=>`${JSON.stringify(f)}:${s(d,a+1)}`).join(",")}}`}finally{t.delete(n)}}default:throw new o(`KV 值含不支持的类型 ${typeof n}`,42200)}};return s(e,0)}function H(e){let t=X(e),s=new TextEncoder().encode(t).byteLength;if(s>D)throw new o(`KV 值过大:canonical JSON ${s} 字节,超过 64 KiB 上限`,42200)}function Q(e){switch(e){case 40400:return{code:e,retryable:!1,hint:"资源不存在:请确认 id / 路径正确后重试"};case 40900:return{code:e,retryable:!1,hint:"连接已关闭或请求 ID 冲突:请重新 connectHostedApp 后再试"};case 40901:return{code:e,retryable:!0,hint:"KV 版本冲突:请重新 kv.get 取最新 version 后以新的 expectedVersion 重试"};case 42200:return{code:e,retryable:!1,hint:"请求参数不合法:请检查键格式 / 值大小 / 文件上限后修正再提交"};case 42900:return{code:e,retryable:!0,hint:"并发请求过多:请降低并发(≤8)后重试"};case 40300:case 40301:case 40302:return{code:e,retryable:!1,hint:"宿主环境缺失或无权限:请确认从 Zleap OS 打开并已声明所需能力"};case 50200:return{code:e,retryable:!0,hint:"宿主响应异常:可重试;持续出现请向平台反馈"};case 50300:return{code:e,retryable:!0,hint:"连接不可用或超时:请检查宿主状态后重建连接重试"};default:return{code:e,retryable:!1,hint:"未识别的错误码:请结合 message 排查,必要时向平台反馈"}}}function j(e){if(!S(e)||typeof e.id!="string"||!/^[1-9]\d{0,19}$/.test(e.id)||typeof e.name!="string"||!e.name||e.name.length>512||e.mime_type!==null&&typeof e.mime_type!="string"||!A(e.size)||!A(e.version))throw new o("Invalid file response",50200);return{id:e.id,name:e.name,mime_type:e.mime_type,size:e.size,version:e.version}}function Y(e,t){if(!S(t))throw new o("Invalid runtime response",50200);if(e.startsWith("kv.")){if(typeof t.key!="string"||!A(t.version)||typeof t.exists!="boolean"||!Object.hasOwn(t,"value"))throw new o("Invalid KV response",50200);return{key:t.key,value:t.value,version:t.version,exists:t.exists}}if(e==="files.list"){if(!Array.isArray(t.list)||t.list.length>100||!A(t.total)||!A(t.page)||t.page<1||!A(t.page_size)||t.page_size<1||t.page_size>100)throw new o("Invalid file list response",50200);return{list:t.list.map(j),total:t.total,page:t.page,pageSize:t.page_size}}if(e==="files.read"){let s=j(t.file);if(typeof t.content_base64!="string"||t.content_base64.length>Math.ceil(I/3)*4||t.content_base64.length%4!==0||!/^[A-Za-z0-9+/]*={0,2}$/.test(t.content_base64))throw new o("Invalid file content",50200);let n=atob(t.content_base64);if(n.length>I||n.length!==s.size)throw new o("Invalid file content",50200);return{file:s,data:Uint8Array.from(n,a=>a.charCodeAt(0))}}return j(t)}function ee(e={}){let t=P.get(window);if(t)return t;let s=new URL(window.location.href),n=s.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\/.+/)?.[1];if(!n||window.parent===window||!["http:","https:"].includes(s.protocol))return Promise.reject(new o("Open this app from AgentOS",40300));let a=e.timeoutMs??3e4;if(!Number.isFinite(a)||a<1||a>12e4)return Promise.reject(new o("Invalid connection timeout",42200));let f,d,y=new Promise((i,p)=>{f=i,d=p});P.set(window,y);let m;try{m=new MessageChannel}catch{return P.delete(window),Promise.reject(new o("MessageChannel unavailable",50300))}let l=m.port1,g=!1,r=!1,c=new Map,h=(i=new o("App connection closed; reopen the app",40900),p=!0)=>{if(!g){g=!0,clearTimeout(M),p&&l.postMessage({type:"__zleap_hosted_close"}),l.onmessage=null,l.onmessageerror=null,l.close(),m.port2.close(),window.removeEventListener("pagehide",x),P.get(window)===y&&P.delete(window),d(i);for(let u of c.values())clearTimeout(u.timer),u.reject(i);c.clear()}},x=()=>h(),M=setTimeout(()=>h(new o("App connection timed out",50300)),a);function _(i,p,u=[]){if(g||!r)return Promise.reject(new o("App connection closed; reopen the app",40900));if(c.size>=8)return Promise.reject(new o("Too many concurrent app requests",42900));let w=crypto.randomUUID();try{let b={requestId:w,method:i,args:i==="files.write"&&S(p)?{...p,data:null}:p},v=JSON.stringify(b),E=i==="files.write"?4096:I;if(v.length>E||new TextEncoder().encode(v).byteLength>E)return Promise.reject(new o("App request too large",42200))}catch{return Promise.reject(new o("Invalid app request",42200))}return new Promise((b,v)=>{let E=setTimeout(()=>{c.delete(w),v(new o("App request timed out",50300))},a);c.set(w,{method:i,resolve:b,reject:v,timer:E});try{l.postMessage({requestId:w,method:i,args:p},u)}catch{clearTimeout(E),c.delete(w),v(new o("Invalid app request",42200))}})}let T=i=>{try{return i(),null}catch(p){return Promise.reject(p)}},B={kv:{get:i=>T(()=>O(i?.key))??_("kv.get",i),set:i=>T(()=>{O(i?.key),H(i?.value),C(i?.expectedVersion)})??_("kv.set",i),delete:i=>T(()=>{O(i?.key),C(i?.expectedVersion)})??_("kv.delete",i)},files:{list:(i={})=>_("files.list",i),read:i=>_("files.read",i),write:i=>{let p=T(()=>R(i?.name));if(p)return p;if(!(i.data instanceof ArrayBuffer)&&!(i.data instanceof Uint8Array))return Promise.reject(new o("File content must be binary",42200));if(i.data.byteLength>I)return Promise.reject(new o("Files must be at most 1 MiB",42200));let u=i.data instanceof ArrayBuffer?i.data.slice(0):new Uint8Array(i.data).buffer;return _("files.write",{...i,data:u},[u])}},close:()=>h()};l.onmessage=i=>{if(g||!S(i.data))return;let p=i.data;if(p.type==="__zleap_hosted_ready"&&p.protocol===1&&!r){r=!0,clearTimeout(M),f(B);return}if(p.type==="__zleap_hosted_closed"){h(new o("App connection closed; reopen the app",40900),!1);return}if(typeof p.requestId!="string")return;let u=c.get(p.requestId);if(u){c.delete(p.requestId),clearTimeout(u.timer);try{let w=u.method==="files.read"?I*1.5:I,b=JSON.stringify(p.result??null);if(b.length>w||k(b)>w)throw new o("App response too large",50200);S(p.error)&&Number.isSafeInteger(p.error.code)&&typeof p.error.message=="string"?u.reject(new o(p.error.message.slice(0,512),Number(p.error.code))):u.resolve(Y(u.method,p.result))}catch(w){u.reject(w instanceof o?w:new o("Invalid runtime response",50200))}}},l.onmessageerror=()=>h(new o("Invalid runtime message",50200)),l.start(),window.addEventListener("pagehide",x);try{window.parent.postMessage({type:"__zleap_hosted_connect",protocol:1,nonce:n},s.origin,[m.port2])}catch{h(new o("App connection unavailable",50300))}return y}var N=null;function te(){if(N)return N;let e=window.__ZLEAP_OS__;if(!e||typeof e!="object")throw new o("Zleap OS host bridge missing; open this app from Zleap OS",40301);let{auth:t,api:s,storage:n,notify:a,eventBus:f,app:d,invite:y,social:m}=e;if(!t||!s)throw new o("Zleap OS host bridge missing; open this app from Zleap OS",40301);let l=r=>()=>Promise.reject(new o(`宿主未提供 ${r} 能力域(宿主版本过旧),请升级 Zleap OS 后重试`,40302)),g={auth:{getToken:()=>t.getToken(),getUser:()=>t.getUser(),hasPermission:r=>t.hasPermission(r)},storage:{getItem:r=>n?n.getItem(r):l("storage")(),setItem:(r,c)=>n?n.setItem(r,c):l("storage")(),removeItem:r=>n?n.removeItem(r):l("storage")()},notify:{show:(r,c)=>a?a.show(r,c):l("notify")(),confirm:(r,c)=>a?a.confirm(r,c):l("notify")()},eventBus:{emit:(r,c)=>f?f.emit(r,c):l("eventBus")(),on:(r,c)=>f?f.on(r,c):l("eventBus")(),off:r=>f?f.off(r):l("eventBus")()},api:{get:(r,c)=>s.get(r,c),post:(r,c)=>s.post(r,c),put:(r,c)=>s.put(r,c),del:r=>s.del(r)},app:{getManifest:()=>d?d.getManifest():l("app")(),getAppId:()=>d?d.getAppId():l("app")()},invite:{send:r=>y?y.send(r):l("invite")()},social:{follow:(r,c)=>m?m.follow(r,c):l("social")(),unfollow:(r,c)=>m?m.unfollow(r,c):l("social")(),isFollowing:(r,c)=>m?m.isFollowing(r,c):l("social")(),pickUsers:r=>m?m.pickUsers(r):l("social")(),pickConversations:r=>m?m.pickConversations(r):l("social")(),shareToConversation:r=>m?m.shareToConversation(r):l("social")(),shareToDynamic:r=>m?m.shareToDynamic(r):l("social")(),createGroup:r=>m?m.createGroup(r):l("social")()}};return N=g,g}function G(e,t){if(!t)return e;let s=new URLSearchParams;for(let[a,f]of Object.entries(t))f!==void 0&&s.set(a,String(f));let n=s.toString();return n?`${e}${e.includes("?")?"&":"?"}${n}`:e}function ne(e,t={}){let s={auth:{getToken:()=>Promise.resolve(e.auth.getToken()),getUser:()=>Promise.resolve(e.auth.getUser())},storage:{getItem:n=>Promise.resolve(e.storage.getItem(n)),setItem:(n,a)=>Promise.resolve(e.storage.setItem(n,a)),removeItem:n=>Promise.resolve(e.storage.removeItem(n))},notify:{show:(n,a="info")=>Promise.resolve(e.notify(a,n)),confirm:(n,a)=>e.confirm({title:n,content:a})},api:{get:(n,a)=>e.apiProxy(G(n,a),{method:"GET"}),post:(n,a)=>e.apiProxy(n,{method:"POST",body:a}),put:(n,a)=>e.apiProxy(n,{method:"PUT",body:a}),del:n=>e.apiProxy(n,{method:"DELETE"})},app:{getAppId:()=>t.appId?Promise.resolve(t.appId):Promise.reject(new o("appId is unavailable in this host form",40302))}};return e.invite&&(s.invite=e.invite),e.social&&(s.social=e.social),s}export{o as SDKError,ne as connectHostCapabilities,ee as connectHostedApp,te as connectZleapOs,Q as describeError};
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @zleap-ai/app-sdk v0.
|
|
1
|
+
/*! @zleap-ai/app-sdk v0.12.0 | (c) 2026 Zleap | 专有许可,仅限在 zleapOS 应用中使用,见 LICENSE */
|
|
2
2
|
var Ue=Object.defineProperty;var Re=(t,e,n)=>e in t?Ue(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var O=(t,e,n)=>Re(t,typeof e!="symbol"?e+"":e,n);var re="__zleap_cloud_connect",oe="__zleap_cloud_ready",ie="__zleap_cloud_close",se="__zleap_cloud_closed",ae="__zleap_cloud_event",ce="__zleap_api_token",Pe=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,L=/^op_\d{10}_[0-9a-f]{32}$/,De={BACKGROUND_CAPABILITY_UNAVAILABLE:"App Cloud: BACKGROUND_CAPABILITY_UNAVAILABLE(后台能力未开启:请在应用窗口顶部的「权限」里勾选并保存,应用会自动重新加载;如果应用没有声明后台能力,开发者要先在 Manifest 中声明)"},o=class extends Error{constructor(n,s,r,f){super(n);O(this,"errCode");O(this,"errMsg");O(this,"requestId");O(this,"operationId");O(this,"retryable");O(this,"jobId");O(this,"invocationId");this.name="CloudError",this.errCode=n,this.errMsg=De[n]??`App Cloud: ${n}`,this.requestId=s,this.operationId=r,this.jobId=f?.jobId,this.invocationId=f?.invocationId,this.retryable=["CALL_TIMEOUT","RUNTIME_UNAVAILABLE","COMMIT_UNKNOWN"].includes(n)}};function h(t){return!!(t&&typeof t=="object"&&(Object.getPrototypeOf(t)===Object.prototype||Object.getPrototypeOf(t)===null))}function E(t,e){return Object.keys(t).every(n=>e.includes(n))}function T(t,e=256*1024){let n=new Set,s=0;function r(f,u){if(++s>1e4||u>24)return!1;if(f===null||typeof f=="boolean")return!0;if(typeof f=="number")return Number.isFinite(f);if(typeof f=="string")return f.length<=e;if(typeof f!="object"||!h(f)&&!Array.isArray(f)||n.has(f))return!1;n.add(f);let d=Object.entries(f).every(([i,l])=>!["__proto__","prototype","constructor"].includes(i)&&r(l,u+1));return n.delete(f),d}if(!r(t,0))return!1;try{return new TextEncoder().encode(JSON.stringify(t)).length<=e}catch{return!1}}function de(t){if(!h(t)||!E(t,["requestId","method","args"])||typeof t.requestId!="string"||!Pe.test(t.requestId)||!h(t.args)||!(t.method==="files.chunk"?k(t.args)&&T({...t,args:{...t.args,data:null}}):T(t)))return null;let{args:e,method:n,requestId:s}=t;if(typeof n=="string"&&n.startsWith("files.")){let r=typeof e.operation_id=="string"&&L.test(e.operation_id),f=typeof e.file_id=="string"&&e.file_id.length>=32&&e.file_id.length<=1024,u=w=>typeof w=="string"&&w.length>0&&w.length<=128,d=w=>typeof w=="string"&&/^[a-f0-9]{64}$/.test(w),i=(w,I,_)=>typeof w=="number"&&Number.isInteger(w)&&w>=I&&w<=_;return["files.operation","files.commit","files.cancel"].includes(n)&&r&&E(e,["operation_id"])||n==="files.stat"&&f&&E(e,["file_id"])||n==="files.read"&&f&&u(e.etag)&&i(e.offset,0,4194304)&&i(e.length,1,262144)&&E(e,["file_id","etag","offset","length"])||n==="files.delete"&&f&&r&&u(e.expected_etag)&&E(e,["file_id","expected_etag","operation_id"])||n==="files.chunk"&&r&&i(e.index,0,15)&&d(e.sha256)&&k(e)&&E(e,["operation_id","index","sha256","data"])||n==="files.begin"&&r&&typeof e.cloud_path=="string"&&e.cloud_path.length>0&&e.cloud_path.length<=512&&i(e.size_bytes,0,4194304)&&d(e.sha256)&&typeof e.mime_type=="string"&&e.mime_type.length<=128&&typeof e.overwrite=="boolean"&&e.overwrite===!!e.expected_etag&&(e.expected_etag===void 0||u(e.expected_etag))&&E(e,["cloud_path","size_bytes","mime_type","sha256","overwrite","expected_etag","operation_id"])?{requestId:s,method:n,args:e}:null}if(n==="execution.get"||n==="execution.cancel")return E(e,["job_id"])&&typeof e.job_id=="string"&&/^[1-9][0-9]{0,18}$/.test(e.job_id)?{requestId:s,method:n,args:e}:null;if(n==="execution.invoke"){let r=e.capability_key??e.function_name;return E(e,["capability_key","function_name","data","operation_id","wait_seconds"])&&e.capability_key!==void 0!=(e.function_name!==void 0)&&typeof r=="string"&&/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(r)&&h(e.data)&&T(e.data,65536)&&typeof e.operation_id=="string"&&L.test(e.operation_id)&&typeof e.wait_seconds=="number"&&Number.isInteger(e.wait_seconds)&&e.wait_seconds>=0&&e.wait_seconds<=25?{requestId:s,method:n,args:e}:null}return n==="operations.get"?E(e,["operation_id"])&&typeof e.operation_id=="string"&&L.test(e.operation_id)?{requestId:s,method:n,args:e}:null:typeof e.collection_key!="string"||!/^[a-z][a-z0-9_]{0,63}$/.test(e.collection_key)||/^(sys_|ac_|t_)/.test(e.collection_key)?null:n==="documents.query"&&E(e,["collection_key","operation","document_key","filter","order_by","projection","limit","skip"])&&["get","count"].includes(String(e.operation))?{requestId:s,method:n,args:e}:n==="documents.snapshot"&&E(e,["collection_key","query","cursor","max_docs"])&&h(e.query)&&E(e.query,["filter","order_by","projection","limit","skip"])&&(e.query.skip===void 0||e.query.skip===0)&&T(e.query,8192)&&typeof e.cursor=="number"&&Number.isSafeInteger(e.cursor)&&e.cursor>=0&&typeof e.max_docs=="number"&&Number.isSafeInteger(e.max_docs)&&e.max_docs>=1&&e.max_docs<=100?{requestId:s,method:n,args:e}:n==="documents.mutate"&&E(e,["collection_key","operation","document_key","data","value_types","field_operations","expected_version","operation_id"])&&["add","set","update","remove"].includes(String(e.operation))&&typeof e.operation_id=="string"&&L.test(e.operation_id)?{requestId:s,method:n,args:e}:null}function k(t){return h(t)&&t.data instanceof ArrayBuffer&&t.data.byteLength<=262144&&T({...t,data:null},16384)}function F(t){return["documents.mutate","execution.invoke","execution.cancel","files.begin","files.chunk","files.commit","files.cancel","files.delete"].includes(t)}var xe=60,ke=15e3;function qe(){if(typeof window>"u"||window.parent===window)return Promise.reject(new o("RUNTIME_UNAVAILABLE"));let t=window.location.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\//)?.[1];return t?new Promise((e,n)=>{let s=new MessageChannel,r=u=>{clearTimeout(f),s.port1.onmessage=null,s.port1.close(),u()},f=setTimeout(()=>r(()=>n(new o("CALL_TIMEOUT"))),ke);s.port1.onmessage=u=>{let d=u.data,i=h(d)?d.result:void 0;if(h(i)&&typeof i.token=="string"&&typeof i.base_url=="string"&&typeof i.expires_at=="number"){let w={token:i.token,baseUrl:i.base_url,expiresAt:i.expires_at};r(()=>e(w));return}let l=h(d)&&h(d.error)&&typeof d.error.errCode=="string"?d.error.errCode:"RUNTIME_UNAVAILABLE";r(()=>n(new o(l)))},window.parent.postMessage({type:ce,nonce:t},"*",[s.port2])}):Promise.reject(new o("RUNTIME_UNAVAILABLE"))}function fe(t=qe){let e=null,n=null;function s(){return n??(n=t().then(i=>(e=i,i)).finally(()=>{n=null})),n}async function r(){return e&&e.expiresAt-Date.now()/1e3>xe?{...e}:{...await s()}}function f(i,l){if(typeof l!="string"||!l.startsWith("/")||l.startsWith("//"))throw new o("SCHEMA_INVALID");let w=new URL(i),I=new URL(i+l);if(I.origin!==w.origin||!I.pathname.startsWith(w.pathname+"/"))throw new o("SCHEMA_INVALID");return I}function u(i,l,w){let I=new Headers(w.headers);return I.set("Authorization","Bearer "+i.token),typeof w.body=="string"&&!I.has("Content-Type")&&I.set("Content-Type","application/json"),fetch(f(i.baseUrl,l),{...w,headers:I,credentials:"omit",redirect:"error"})}async function d(i,l={}){let w=await u(await r(),i,l),I=(l.method??"GET").toUpperCase();return w.status!==401||I!=="GET"&&I!=="HEAD"?w:(e=null,u(await r(),i,l))}return{token:r,fetch:d}}var He="__zleap_app_connect",Ve="__zleap_app_ready",je="__zleap_app_event";var M=class extends Error{constructor(n,s){super(s??n);O(this,"errCode");this.name="AppError",this.errCode=n}},j=t=>!!(t&&typeof t=="object"&&!Array.isArray(t)),V=null;function v(){return V||(V=new Promise((t,e)=>{if(typeof window>"u"||window.parent===window)return e(new M("OPEN_IN_ZLEAP_OS","请从 AgentOS 中打开应用"));let n=window.location.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\//)?.[1];if(!n)return e(new M("OPEN_IN_ZLEAP_OS","请从 AgentOS 中打开应用"));let s=new MessageChannel,r=new Map,f=new Set,u=!1,d=setTimeout(()=>{u||(V=null,e(new M("HOST_UNAVAILABLE","宿主未响应,请升级 AgentOS 后重试")))},15e3);s.port1.onmessage=i=>{let l=i.data;if(!j(l))return;if(l.type===Ve&&l.protocol===1&&!u){u=!0,clearTimeout(d),t({call(I,_={},c=3e4){return new Promise((a,p)=>{if(r.size>=8)return p(new M("TOO_MANY_REQUESTS"));let y=crypto.randomUUID(),N=setTimeout(()=>{r.delete(y),p(new M("CALL_TIMEOUT"))},c);r.set(y,{resolve:a,reject:p,timer:N}),s.port1.postMessage({requestId:y,method:I,args:_})})},onEvent(I){return f.add(I),()=>f.delete(I)}});return}if(l.type===je&&typeof l.event=="string"){for(let I of f)try{I(l.event,l.data)}catch{}return}if(typeof l.requestId!="string")return;let w=r.get(l.requestId);w&&(r.delete(l.requestId),clearTimeout(w.timer),j(l.error)?w.reject(new M(typeof l.error.errCode=="string"?l.error.errCode:"RUNTIME_UNAVAILABLE",typeof l.error.message=="string"?l.error.message:void 0)):w.resolve(l.result))},s.port1.start(),window.parent.postMessage({type:He,protocol:1,nonce:n},"*",[s.port2])}),V.catch(()=>{}),V)}function Z(t){let e=j(t)?t:{};return{hasUpdate:e.hasUpdate===!0,currentVersion:typeof e.currentVersion=="string"?e.currentVersion:null,latestVersion:typeof e.latestVersion=="string"?e.latestVersion:null,notes:typeof e.notes=="string"?e.notes:null,deadline:typeof e.deadline=="number"?e.deadline:null}}var K=null;function ue(){if(K)return K;let t=new Set,e=new Set,n=new Set,s=null,r=!1,f=u=>{if(!(!u.hasUpdate||r)){r=!0;for(let d of e)d(u)}};return v().then(async u=>{u.onEvent((d,i)=>{d==="updateReady"&&(r=!1,f(Z(i)))}),s=Z(await u.call("app.checkUpdate"));for(let d of t)d(s);f(s)}).catch(u=>{let d=u instanceof M?u:new M("RUNTIME_UNAVAILABLE");for(let i of n)i(d)}),K={onCheckForUpdate(u){t.add(u),s&&u(s)},onUpdateReady(u){e.add(u),s?.hasUpdate&&r&&u(s)},onUpdateFailed(u){n.add(u)},async applyUpdate(){try{await(await v()).call("app.applyUpdate",{},6e4)}catch(u){let d=u instanceof M?u:new M("UPDATE_FAILED");for(let i of n)i(d);throw d}}},K}async function le(){return Z(await(await v()).call("app.checkUpdate"))}function pe(t){if(!j(t)||typeof t.openid!="string")throw new M("PROTOCOL_MISMATCH");let e={openid:t.openid,scopes:Array.isArray(t.scopes)?t.scopes.filter(n=>typeof n=="string"):[]};return j(t.profile)&&(e.profile={nickname:typeof t.profile.nickname=="string"?t.profile.nickname:"",avatarUrl:typeof t.profile.avatarUrl=="string"?t.profile.avatarUrl:null}),"phone"in t&&(e.phone=typeof t.phone=="string"?t.phone:null),"email"in t&&(e.email=typeof t.email=="string"?t.email:null),e}async function _e(t){if(!j(t)||!Array.isArray(t.scopes)||t.scopes.length===0||t.scopes.some(n=>!["profile","phone","email"].includes(n)))throw new M("SCHEMA_INVALID","scopes 只能是 profile、phone、email");if(t.reason!==void 0&&(typeof t.reason!="string"||t.reason.length>60))throw new M("SCHEMA_INVALID","reason 是不超过 60 字的用途说明");let e={scopes:t.scopes};return t.reason&&(e.reason=t.reason),pe(await(await v()).call("auth.authorize",e,3e5))}async function we(){return pe(await(await v()).call("auth.getIdentity"))}function he(t){if(typeof t.job_id!="string"||!/^\d+$/.test(t.job_id)||typeof t.invocation_id!="string"||!/^\d+$/.test(t.invocation_id)||typeof t.operation_id!="string"||!L.test(t.operation_id)||typeof t.status!="string"||!["accepted","queued","running","cancel_requested","cancelled","succeeded","failed","unknown"].includes(t.status)||!Array.isArray(t.committed_steps)||!t.committed_steps.every(e=>typeof e=="string"))throw new o("PROTOCOL_MISMATCH");return{jobId:t.job_id,invocationId:t.invocation_id,operationId:t.operation_id,status:t.status,result:t.result??null,errorCode:typeof t.error_code=="string"?t.error_code:null,committedSteps:t.committed_steps}}function ye(t){async function e(r,f,u,d=!1,i=0){if(typeof r!="string"||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(r)||!h(f)||!T(f,65536))throw new o("SCHEMA_INVALID");if(u!==void 0&&(typeof u!="string"||!L.test(u)))throw new o("SCHEMA_INVALID");let l=u??t.createId(),{value:w}=await t.request("execution.invoke",{[d?"function_name":"capability_key"]:r,data:f,operation_id:l,wait_seconds:i});return he(w)}async function n(r){if(!h(r)||!E(r,["jobId"])||typeof r.jobId!="string"||!/^[1-9][0-9]{0,18}$/.test(r.jobId))throw new o("SCHEMA_INVALID");return he((await t.request("execution.get",{job_id:r.jobId})).value)}async function s(r){if(!h(r)||!E(r,["jobId","timeoutSeconds","pollMilliseconds"])||typeof r.jobId!="string"||!/^[1-9][0-9]{0,18}$/.test(r.jobId)||r.timeoutSeconds!==void 0&&(!Number.isInteger(r.timeoutSeconds)||r.timeoutSeconds<0||r.timeoutSeconds>300)||r.pollMilliseconds!==void 0&&(!Number.isInteger(r.pollMilliseconds)||r.pollMilliseconds<100||r.pollMilliseconds>5e3))throw new o("SCHEMA_INVALID");let f=(r.timeoutSeconds??25)*1e3,u=r.pollMilliseconds??500,d=Date.now()+f,i=await n({jobId:r.jobId});for(;["accepted","queued","running","cancel_requested"].includes(i.status)&&Date.now()<d;)await new Promise(l=>setTimeout(l,Math.min(u,Math.max(0,d-Date.now())))),i=await n({jobId:r.jobId});if(["accepted","queued","running","cancel_requested"].includes(i.status))throw new o("CALL_TIMEOUT",void 0,i.operationId,{jobId:i.jobId,invocationId:i.invocationId});return i}return{capabilities:{invoke:async r=>{if(!h(r)||!E(r,["id","input","operationId","waitSeconds"]))throw new o("UNSUPPORTED_OPERATION");return e(r.id,r.input,r.operationId,!1,r.waitSeconds)}},jobs:{submit:async r=>{if(!h(r)||!E(r,["kind","capability","input","operationId","waitSeconds"])||r.kind!=="capability")throw new o("UNSUPPORTED_OPERATION");return e(r.capability,r.input,r.operationId,!1,r.waitSeconds)},get:n,result:n,wait:s,cancel:async r=>{if(!h(r)||!E(r,["jobId"])||typeof r.jobId!="string"||!/^[1-9][0-9]{0,18}$/.test(r.jobId))throw new o("SCHEMA_INVALID");let{value:f}=await t.request("execution.cancel",{job_id:r.jobId});if(f.cancel_requested!==!0)throw new o("PROTOCOL_MISMATCH");return{cancelRequested:!0}}},callFunction:async r=>{if(!h(r)||!E(r,["name","data","agentos","success","fail","complete"])||r.agentos!==void 0&&(!h(r.agentos)||!E(r.agentos,["operationId"])))throw new o("UNSUPPORTED_OPERATION");let f=await e(r.name,r.data??{},r.agentos?.operationId,!0,25);if(["accepted","queued","running","cancel_requested","unknown"].includes(f.status))throw new o(f.status==="unknown"?"COMMIT_UNKNOWN":"CALL_TIMEOUT",void 0,f.operationId,{jobId:f.jobId,invocationId:f.invocationId});if(f.status==="failed"||f.status==="cancelled")throw new o(f.errorCode??"EXECUTION_FAILED",void 0,f.operationId,{jobId:f.jobId,invocationId:f.invocationId});return f}}}var Ae=4*1024*1024,z=256*1024,me=16,ze=2,Be=new Set(["VERSION_CONFLICT","UPLOAD_INTEGRITY_FAILED"]);function $(t,e){let n=e??t.createId();if(!L.test(n))throw new o("SCHEMA_INVALID",void 0,n);return n}function Y(t){let e=t instanceof Uint8Array?t:new Uint8Array(t);return crypto.subtle.digest("SHA-256",e).then(n=>[...new Uint8Array(n)].map(s=>s.toString(16).padStart(2,"0")).join(""))}function Ie(t){if(!h(t))throw new o("PROTOCOL_MISMATCH");let e=t.size_bytes;if(typeof t.file_id!="string"||t.file_id.length<32||typeof t.etag!="string"||t.etag.length===0||typeof t.sha256!="string"||!/^[a-f0-9]{64}$/.test(t.sha256)||typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>Ae)throw new o("PROTOCOL_MISMATCH");return{fileID:t.file_id,etag:t.etag,sha256:t.sha256,size:e,errMsg:"ok"}}function W(t){if(!h(t)||typeof t.operation_id!="string"||!L.test(t.operation_id)||!["pending","succeeded","cancelled"].includes(String(t.state)))throw new o("PROTOCOL_MISMATCH");let e=t.received;if(e!==void 0&&(!Array.isArray(e)||!e.every(n=>Number.isInteger(n)&&n>=0&&n<me)))throw new o("PROTOCOL_MISMATCH");return{operation_id:t.operation_id,state:t.state,...typeof t.chunk_size=="number"?{chunk_size:t.chunk_size}:{},...e===void 0?{}:{received:e},...t.file===null||t.file===void 0?{file:null}:{file:t.file}}}function Oe(t){async function e(d){let i=$(t,d),l=await t.request("files.operation",{operation_id:i}),w=W(l.value);if(w.operation_id!==i)throw new o("PROTOCOL_MISMATCH",l.requestId,i);return w}async function n(d){if(!h(d)||typeof d.cloudPath!="string"||typeof Blob>"u"||!(d.filePath instanceof Blob)||d.filePath.size>Ae)throw new o("SCHEMA_INVALID");let i=$(t,d.agentos?.operationId),l=new Uint8Array(await d.filePath.arrayBuffer()),w=await Y(l),I=A=>{let g=Ie(A);if(g.size!==l.byteLength||g.sha256!==w)throw new o("PROTOCOL_MISMATCH");return g},_=Math.ceil(l.byteLength/z);if(_>me)throw new o("RESOURCE_EXHAUSTED",void 0,i);let c;try{let A=await t.request("files.begin",{cloud_path:d.cloudPath,size_bytes:l.byteLength,mime_type:d.filePath.type||"application/octet-stream",sha256:w,overwrite:d.agentos?.overwrite===!0,...d.agentos?.expectedETag?{expected_etag:d.agentos.expectedETag}:{},operation_id:i});c=W(A.value)}catch(A){if(!(A instanceof o)||A.errCode!=="COMMIT_UNKNOWN")throw A;c=await e(i)}if(c.operation_id!==i)throw new o("PROTOCOL_MISMATCH");if(c.state==="succeeded"){if(!c.file)throw new o("PROTOCOL_MISMATCH");return I(c.file)}if(c.state==="cancelled")throw new o("OPERATION_EXPIRED",void 0,i);if(c.chunk_size!==void 0&&c.chunk_size!==z)throw new o("PROTOCOL_MISMATCH",void 0,i);let a=new Set(c.received??[]),p=Array.from({length:_},(A,g)=>g).filter(A=>!a.has(A)),y,N=0;async function m(A){let g=l.slice(A*z,Math.min(l.length,(A+1)*z)),P=await Y(g);try{let b=await t.request("files.chunk",{operation_id:i,index:A,sha256:P,data:g.slice().buffer});if(b.value.operation_id!==i||b.value.index!==A||b.value.received!==!0)throw new o("PROTOCOL_MISMATCH",b.requestId,i);a.add(A)}catch(b){if(!(b instanceof o)||b.errCode!=="COMMIT_UNKNOWN")throw b;let x=await e(i);if(x.state==="succeeded"&&x.file){y=I(x.file);return}if(x.state==="cancelled")throw new o("OPERATION_EXPIRED",void 0,i);if(x.received?.forEach(C=>a.add(C)),a.has(A))return;let H=await t.request("files.chunk",{operation_id:i,index:A,sha256:P,data:g.slice().buffer});if(H.value.operation_id!==i||H.value.index!==A||H.value.received!==!0)throw new o("PROTOCOL_MISMATCH",H.requestId,i);a.add(A)}}async function S(){for(;N<p.length&&!y;){let A=p[N++];A!==void 0&&await m(A)}}if(await Promise.all(Array.from({length:Math.min(ze,p.length)},S)),y)return y;try{let A=await t.request("files.commit",{operation_id:i}),g=W(A.value);if(g.state!=="succeeded"||!g.file)throw new o("PROTOCOL_MISMATCH",A.requestId,i);return I(g.file)}catch(A){if(A instanceof o&&Be.has(A.errCode))throw await u(i).catch(()=>{}),A;if(!(A instanceof o)||A.errCode!=="COMMIT_UNKNOWN")throw A;let g=await e(i);if(g.state==="succeeded"&&g.file)return I(g.file);throw g.state==="cancelled"?new o("OPERATION_EXPIRED",void 0,i):A}}async function s(d){if(typeof d!="string"||d.length<32||d.length>1024)throw new o("SCHEMA_INVALID");let i=await t.request("files.stat",{file_id:d});return Ie(i.value)}async function r(d){let i=await s(d),l=[];for(let _=0;_<i.size;_+=z){let c=Math.min(z,i.size-_),a=await t.request("files.read",{file_id:d,etag:i.etag,offset:_,length:c});if(!(a.value.data instanceof ArrayBuffer)||a.value.etag!==i.etag||a.value.offset!==_||a.value.data.byteLength!==c)throw new o("PROTOCOL_MISMATCH",a.requestId);l.push(a.value.data)}let w=new Uint8Array(i.size),I=0;for(let _ of l)w.set(new Uint8Array(_),I),I+=_.byteLength;if(await Y(w)!==i.sha256)throw new o("PROTOCOL_MISMATCH");return{fileContent:new Blob([w],{type:"application/octet-stream"}),errMsg:"ok"}}async function f(d){if(!h(d)||!Array.isArray(d.fileList)||d.fileList.length===0||d.fileList.length>100||!h(d.agentos?.expectedETags))throw new o("SCHEMA_INVALID");let i=[],l=[],w=new Set;for(let I=0;I<d.fileList.length;I++){let _=d.fileList[I],c=d.agentos?.expectedETags?.[_];if(typeof c!="string"||c.length===0)throw new o("SCHEMA_INVALID");let a=$(t,I===0?d.agentos?.operationId:void 0);for(;w.has(a);)a=$(t);w.add(a);try{let p=await t.request("files.delete",{file_id:_,expected_etag:c,operation_id:a}),y=W(p.value);if(y.operation_id!==a||y.state!=="succeeded")throw new o("PROTOCOL_MISMATCH",p.requestId,a);i.push(_)}catch(p){if(p instanceof o&&p.errCode==="COMMIT_UNKNOWN")try{if((await e(a)).state==="succeeded"){i.push(_);continue}}catch{}l.push({fileID:_,error:p instanceof o?p:new o("RUNTIME_UNAVAILABLE",void 0,a)})}}return{deleted:i,failed:l,errMsg:l.length?"partial failure":"ok"}}async function u(d){let i=$(t,d),l=await t.request("files.cancel",{operation_id:i});return W(l.value)}return{upload:n,download:r,remove:f,stat:s,getOperation:e,cancel:u}}function Fe(t){if(!h(t)||typeof t.event!="string"||!/^[a-z][a-z0-9_.]{0,63}$/.test(t.event))return null;let e={event:t.event};for(let n of["app_id","collection_key","collection_id","document_key","change_seq","operation_id"])typeof t[n]=="string"&&(e[n]=t[n]);return e}function ge(t){if(typeof window>"u"||window.parent===window)throw new o("RUNTIME_UNAVAILABLE");let e=window.location.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\//)?.[1];if(!e)throw new o("RUNTIME_UNAVAILABLE");let n=new MessageChannel,s=!1,r=!1,f,u,d=new Promise((c,a)=>{f=c,u=a});d.catch(()=>{});let i=new Map,l=new Set,w=(c="RUNTIME_UNAVAILABLE")=>{if(!s){s=!0,clearTimeout(_),u(new o(c));for(let[a,p]of i)clearTimeout(p.timer),p.reject(new o(c,a,p.operationId));i.clear(),n.port1.postMessage({type:ie}),n.port1.onmessage=null,n.port1.close(),window.removeEventListener("pagehide",I)}},I=()=>w(),_=setTimeout(()=>w("CALL_TIMEOUT"),15e3);return n.port1.onmessageerror=()=>w("PROTOCOL_MISMATCH"),n.port1.onmessage=c=>{let a=c.data;if(!h(a)||!(T(a,1024*1024)||typeof a.requestId=="string"&&i.get(a.requestId)?.method==="files.read"&&k(a.result)&&T({...a,result:null},16384))){w("PROTOCOL_MISMATCH");return}if(a.type===se){w(typeof a.errCode=="string"?a.errCode:"RUNTIME_UNAVAILABLE");return}if(a.type===ae){let y=Fe(a.event);if(y)for(let N of l)N(y);return}if(a.type===oe&&!r){let y=a.capabilities;if(a.protocol!==2||!h(y)||!h(y.protocol)||y.protocol.major!==2||!Array.isArray(y.profiles)||!y.profiles.some(N=>["document-core/1","app-execution/1","storage-object/1"].includes(String(N)))||!Array.isArray(y.operators)||!h(y.limits)||typeof y.serverTime!="number"){w("PROTOCOL_MISMATCH");return}r=!0,clearTimeout(_),f(y);return}if(typeof a.requestId!="string"){w("PROTOCOL_MISMATCH");return}let p=i.get(a.requestId);p&&(clearTimeout(p.timer),i.delete(a.requestId),h(a.error)?p.reject(new o(typeof a.error.errCode=="string"?a.error.errCode:"RUNTIME_UNAVAILABLE",a.requestId,p.operationId)):p.resolve(a.result))},n.port1.start(),window.addEventListener("pagehide",I),window.parent.postMessage({type:re,protocol:2,nonce:e,environmentKey:t},"*",[n.port2]),{ready:()=>d,onEvent(c){return l.add(c),()=>l.delete(c)},request:async(c,a,p)=>{if(await d,s)throw new o("RUNTIME_UNAVAILABLE",p);if(i.size>=8)throw new o("RESOURCE_EXHAUSTED",p);return new Promise((y,N)=>{let m=typeof a.operation_id=="string"?a.operation_id:void 0,S=setTimeout(()=>{i.delete(p),N(new o(F(c)?"COMMIT_UNKNOWN":"CALL_TIMEOUT",p,m))},3e4);i.set(p,{resolve:y,reject:N,timer:S,operationId:m,method:c}),n.port1.postMessage({requestId:p,method:c,args:a},c==="files.chunk"&&a.data instanceof ArrayBuffer?[a.data]:[])})},close:()=>w()}}var q=class t{constructor(e){O(this,"filters");this.filters=e}and(e){return new t([{op:"and",filters:[...this.filters,...e.filters]}])}or(e){return new t([{op:"or",filters:[...this.filters,...e.filters]}])}},D=class{constructor(e,n,s=0){O(this,"op");O(this,"value");O(this,"offset");this.op=e,this.value=n,this.offset=s}};function U(t,e){let n=e instanceof Date;if(n&&!Number.isFinite(e.getTime()))throw new o("SCHEMA_INVALID");if(["in","nin"].includes(t)){if(!Array.isArray(e)||e.length>100||e.length===0)throw new o("SCHEMA_INVALID");let s=e.every(r=>r instanceof Date);if(e.some(r=>r instanceof Date)&&!s)throw new o("SCHEMA_INVALID");return new q([{op:t,value:s?e.map(r=>r.getTime()):e,...s?{value_type:"date"}:{}}])}if(!T(n?e.getTime():e))throw new o("SCHEMA_INVALID");return new q([{op:t,value:n?e.getTime():e,...n?{value_type:"date"}:{}}])}function Ce(t,e){if(e.length<1)throw new o("SCHEMA_INVALID");return new q([{op:t,filters:e.map(n=>X(n))}])}var Ne=Object.freeze({eq:t=>U("eq",t),neq:t=>U("neq",t),gt:t=>U("gt",t),gte:t=>U("gte",t),lt:t=>U("lt",t),lte:t=>U("lte",t),in:t=>U("in",t),nin:t=>U("nin",t),exists:t=>U("exists",t),and:(...t)=>Ce("and",t),or:(...t)=>Ce("or",t),inc:t=>{if(!Number.isFinite(t))throw new o("SCHEMA_INVALID");return new D("inc",t)},set:t=>new D("set",t),remove:()=>new D("remove")});function B(t,e=!1){let n=t.split(".");if(!t||n.length>16||n.some(s=>!/^[A-Za-z][A-Za-z0-9_]*$/.test(s)&&!(e&&n.length===1&&["_id","_openid","_version"].includes(s))||["__proto__","prototype","constructor"].includes(s)))throw new o("SCHEMA_INVALID")}function X(t,e){if(t instanceof q){let s=function(r){return r.filters?{...r,filters:r.filters.map(s)}:{...r,...e?{field:e}:{}}};return t.filters.length===1?s(t.filters[0]):{op:"and",filters:t.filters.map(s)}}if(!h(t)||!Object.keys(t).length)throw new o("SCHEMA_INVALID");let n=Object.entries(t).map(([s,r])=>(B(s,!0),X(r instanceof q?r:U("eq",r),s)));return n.length===1?n[0]:{op:"and",filters:n}}function J(t,e){if(!h(t))throw new o("SCHEMA_INVALID");let n={},s=[],r=new Set,f=0,u=[],d=_=>{if(u.some(c=>c===_||c.startsWith(`${_}.`)||_.startsWith(`${c}.`)))throw new o("SCHEMA_INVALID");u.push(_)};function i(_,c,a,p){if(++f>1e4||c.length>16)throw new o("SCHEMA_INVALID");let y=c.join(".");if(_ instanceof D){if(!p||e!=="update"&&_.op!=="serverDate")throw new o("UNSUPPORTED_OPERATION");if(d(y),_.op==="set"){let m={};s.push({op:"set",path:y,value:i(_.value,[],m,!1),value_types:m})}else s.push({op:_.op,path:y,..._.op==="inc"?{value:_.value}:{},..._.op==="serverDate"?{offset:_.offset}:{}});return}if(_ instanceof Date){if(!Number.isFinite(_.getTime()))throw new o("SCHEMA_INVALID");return a[c.length?`/${c.join("/")}`:""]="date",_.getTime()}if(_===null||typeof _=="boolean"||typeof _=="string"||typeof _=="number"&&Number.isFinite(_))return _;if(typeof _!="object"||_===null||!h(_)&&!Array.isArray(_)||r.has(_))throw new o("SCHEMA_INVALID");r.add(_);let N;if(Array.isArray(_))N=_.map((m,S)=>i(m,[...c,String(S)],a,!1));else{let m={};for(let[S,A]of Object.entries(_)){if(B(S),S.includes(".")&&e!=="update")throw new o("SCHEMA_INVALID");let g=[...c,...S.split(".")],P=i(A,g,a,p);P!==void 0&&(m[S]=P)}N=m}return r.delete(_),N}function l(_,c){for(let[a,p]of Object.entries(_)){B(a);let y=[...c,...a.split(".")];if(y.length>16)throw new o("SCHEMA_INVALID");if(h(p)&&Object.keys(p).length){if(r.has(p))throw new o("SCHEMA_INVALID");r.add(p),l(p,y),r.delete(p)}else if(p instanceof D)i(p,y,n,!0);else{d(y.join("."));let N={};s.push({op:"set",path:y.join("."),value:i(p,[],N,!1),value_types:N})}}}let w={};e==="update"?l(t,[]):w=i(t,[],n,!0);let I={data:w,value_types:n,field_operations:s};if(!T(I)||s.length>256)throw new o("SCHEMA_INVALID");return I}function Te(t,e){if(!T(t))throw new o("PROTOCOL_MISMATCH");function n(s,r){let f=e[`/${r.join("/")}`];if(f!==void 0){if(f!=="date"||typeof s!="number"||!Number.isSafeInteger(s)||Math.abs(s)>864e13)throw new o("PROTOCOL_MISMATCH");return new Date(s)}return Array.isArray(s)?s.map((u,d)=>n(u,[...r,String(d)])):h(s)?Object.fromEntries(Object.entries(s).map(([u,d])=>[u,n(d,[...r,u])])):s}return n(t,[])}function R(t,e){let n=Promise.resolve().then(e);if(!t||![t.success,t.fail,t.complete].some(s=>typeof s=="function"))return n;n.then(s=>{try{t.success?.(s)}finally{t.complete?.(s)}},s=>{let r=s instanceof o?s:new o("RUNTIME_UNAVAILABLE");try{t.fail?.(r)}finally{t.complete?.(r)}}).catch(()=>{})}function Me(t){if(!t||new TextEncoder().encode(t).length>128||[...t].some(e=>{let n=e.codePointAt(0)??0;return n<32||n===127||e==="/"||e==="\\"}))throw new o("SCHEMA_INVALID");return t}var Le="DYNAMIC_CURRENT_ENV";function ve(t){if(h(t)){let e=Object.values(t);if(!e.length||!e.every(n=>n===e[0]))throw new o("ENV_MISMATCH");t=e[0]}if(t===Le)return t;if(t!=="dev"&&t!=="prod")throw new o("ENV_MISMATCH");return t}function G(t,e){if(!h(t)||!h(e))throw new o("PROTOCOL_MISMATCH");let n=Te(t,e);if(n._version!==void 0){if(typeof n._version!="number"&&typeof n._version!="string")throw new o("PROTOCOL_MISMATCH");n._version=String(n._version)}return n}function ne(t,e,n){if(typeof t.operation_id!="string"||!L.test(t.operation_id)||n!==void 0&&t.operation_id!==n||!h(t.stats))throw new o("PROTOCOL_MISMATCH",e);let s=t.stats,r=l=>typeof l=="number"&&Number.isSafeInteger(l)&&l>=0,f=s.created===void 0?0:s.created,u=s.updated===void 0?0:s.updated,d=s.removed===void 0?0:s.removed;if(!r(f)||!r(u)||!r(d))throw new o("PROTOCOL_MISMATCH",e,t.operation_id);let i=h(t.document)?t.document:null;return{...typeof i?._id=="string"?{_id:i._id}:{},stats:{created:f,updated:u,removed:d},errMsg:"database:ok",_meta:{requestId:e,operationId:t.operation_id,...typeof i?._version=="number"||typeof i?._version=="string"?{version:String(i._version)}:{}}}}var Q=class t{constructor(e,n,s={}){O(this,"session");O(this,"key");O(this,"query");this.session=e,this.key=n,this.query=s}with(e){return new t(this.session,this.key,{...this.query,...e})}where(e){let n=X(e);return this.with({filter:this.query.filter?{op:"and",filters:[this.query.filter,n]}:n})}orderBy(e,n){if(B(e,!0),n!=="asc"&&n!=="desc")throw new o("SCHEMA_INVALID");let s=this.query.order_by??[];if(s.length>=4)throw new o("RESOURCE_EXHAUSTED");return this.with({order_by:[...s,{field:e,direction:n}]})}limit(e){if(!Number.isSafeInteger(e)||e<1||e>100)throw new o("RESOURCE_EXHAUSTED");return this.with({limit:e})}skip(e){if(!Number.isSafeInteger(e)||e<0||e>1e3)throw new o("RESOURCE_EXHAUSTED");return this.with({skip:e})}field(e){if(!h(e))throw new o("SCHEMA_INVALID");let n=new Set;for(let[s,r]of Object.entries(e)){if(B(s,!0),typeof r!="boolean")throw new o("SCHEMA_INVALID");s!=="_id"&&n.add(r)}if(n.size>1)throw new o("SCHEMA_INVALID");return this.with({projection:{...e}})}get(e){return R(e,async()=>{let{value:n,requestId:s}=await this.session.request("documents.query",{collection_key:this.key,operation:"get",limit:20,skip:0,...this.query});if(!Array.isArray(n.list)||!Array.isArray(n.value_types)||n.list.length!==n.value_types.length)throw new o("PROTOCOL_MISMATCH",s);let r=n.value_types;return{data:n.list.map((f,u)=>G(f,r[u])),errMsg:"collection.get:ok",_meta:{requestId:s}}})}count(e){return R(e,async()=>{let{value:n,requestId:s}=await this.session.request("documents.query",{collection_key:this.key,operation:"count",...this.query});if(!Number.isSafeInteger(n.total)||Number(n.total)<0)throw new o("PROTOCOL_MISMATCH",s);return{total:n.total,errMsg:"collection.count:ok",_meta:{requestId:s}}})}watch(e){return Promise.resolve().then(async()=>{let n=e?.cursor,s=n===void 0?0:Number(n);if(n!==void 0&&(typeof n!="string"||!/^(0|[1-9]\d*)$/.test(n)))throw new o("SCHEMA_INVALID");let r=e?.maxDocs??100;if(!Number.isSafeInteger(s)||s<0||!Number.isSafeInteger(r)||r<1||r>100)throw new o("SCHEMA_INVALID");if(e?.query!==void 0&&!h(e.query))throw new o("SCHEMA_INVALID");let f=e?.query===void 0?this.query:{...this.query,...e.query};if(!h(f)||!E(f,["filter","order_by","projection","limit","skip"]))throw new o("SCHEMA_INVALID");let{value:u,requestId:d}=await this.session.request("documents.snapshot",{collection_key:this.key,query:f,cursor:s,max_docs:r}),i=u;if(!Array.isArray(i.list)||!Array.isArray(i.value_types)||i.list.length!==i.value_types.length||typeof i.cursor!="string"||!/^(0|[1-9]\d*)$/.test(i.cursor)||!Number.isSafeInteger(Number(i.cursor))||typeof i.has_more!="boolean")throw new o("PROTOCOL_MISMATCH",d);return{data:i.list.map((l,w)=>G(l,i.value_types[w])),cursor:i.cursor,changed:i.cursor!==String(s),hasMore:i.has_more,errMsg:"collection.watch:ok",_meta:{requestId:d}}})}after(){throw new o("UNSUPPORTED_OPERATION")}onChange(e){if(typeof e!="function")throw new o("SCHEMA_INVALID");return this.session.onEvent?this.session.onEvent(n=>{n.collection_key!==void 0&&n.collection_key!==this.key||e(n)}):()=>{}}update(){throw new o("UNSUPPORTED_OPERATION")}remove(){throw new o("UNSUPPORTED_OPERATION")}},ee=class{constructor(e,n,s,r){O(this,"session");O(this,"collection");O(this,"id");O(this,"throwOnNotFound");this.session=e,this.collection=n,this.id=s,this.throwOnNotFound=r}get(e){return R(e,async()=>{try{let{value:n,requestId:s}=await this.session.request("documents.query",{collection_key:this.collection,document_key:this.id,operation:"get"});if(!Array.isArray(n.list)||n.list.length!==1||!Array.isArray(n.value_types))throw new o("PROTOCOL_MISMATCH",s);return{data:G(n.list[0],n.value_types[0]),errMsg:"document.get:ok",_meta:{requestId:s}}}catch(n){if(!this.throwOnNotFound&&n instanceof o&&n.errCode==="DOCUMENT_NOT_FOUND")return{data:null,errMsg:"document.get:ok",_meta:{requestId:n.requestId??""}};throw n}})}mutate(e,n,s){return R(s,async()=>{if(!h(n))throw new o("SCHEMA_INVALID");let r=n,f=r.agentos?.operationId??this.session.createId(),u=r.agentos?.expectedVersion;if(u!==void 0&&(!/^[1-9]\d*$/.test(u)||!Number.isSafeInteger(Number(u))))throw new o("SCHEMA_INVALID",void 0,f);let d={collection_key:this.collection,document_key:this.id,operation:e,operation_id:f,..."data"in r?J(r.data,e):{},...u===void 0?{}:{expected_version:u}},{value:i,requestId:l}=await this.session.request("documents.mutate",d);return ne(i,l,f)})}set(e){return this.mutate("set",e,e)}update(e){return this.mutate("update",e,e)}remove(e={}){return this.mutate("remove",e,e)}},te=class extends Q{constructor(n,s,r){super(n,s);O(this,"throwOnNotFound");this.throwOnNotFound=r}doc(n){return new ee(this.session,this.key,Me(n),this.throwOnNotFound)}add(n){return R(n,async()=>{if(!h(n)||!h(n.data))throw new o("SCHEMA_INVALID");let s=n.agentos?.operationId??this.session.createId(),{_id:r,...f}=n.data;if(r!==void 0&&typeof r!="string")throw new o("SCHEMA_INVALID",void 0,s);let{value:u,requestId:d}=await this.session.request("documents.mutate",{collection_key:this.key,operation:"add",operation_id:s,...J(f,"add"),...typeof r=="string"?{document_key:Me(r)}:{}});return ne(u,d,s)})}};function $e(t=ge){let e=null,n=null,s=0,r=null,f=0;function u(c,a,p){let y=c.limits[a];return typeof y=="number"&&Number.isSafeInteger(y)&&y>0?Math.min(p,y):p}function d(c){try{return new TextEncoder().encode(JSON.stringify(c)).byteLength}catch{return null}}let i={ready:()=>r??Promise.reject(new o("INIT_REQUIRED")),createId:()=>`op_${Math.floor((Date.now()+s)/1e3)}_${crypto.randomUUID().replaceAll("-","")}`,onEvent(c){return n?n.onEvent(c):()=>{}},request:async(c,a)=>{let p=await i.ready(),y=crypto.randomUUID(),N=c==="documents.snapshot"?"watch-snapshot/1":c.startsWith("execution.")?"app-execution/1":c.startsWith("files.")?"storage-object/1":"document-core/1";if(!p.profiles.includes(N))throw new o(c.startsWith("execution.")?"BACKGROUND_CAPABILITY_UNAVAILABLE":"UNSUPPORTED_OPERATION",y);let m=typeof a.operation_id=="string"?a.operation_id:void 0,S=u(p,"max_concurrent_requests",8);if(f>=S)throw new o("RESOURCE_EXHAUSTED",y,m);let A=u(p,"max_request_bytes",256*1024),g=d({method:c,args:a});if(g===null||g>A)throw new o("REQUEST_TOO_LARGE",y,m);if(!de({requestId:y,method:c,args:a})||m!==void 0&&!L.test(m))throw new o("SCHEMA_INVALID",y,m);function P(C){if(!p.operators.includes(C.op))throw new o("UNSUPPORTED_OPERATION",y,m);C.filters?.forEach(P)}if(h(a.filter)&&P(a.filter),c==="documents.snapshot"&&h(a.query)&&h(a.query.filter)&&P(a.query.filter),Array.isArray(a.field_operations)){for(let C of a.field_operations)if(!h(C)||!p.operators.includes(String(C.op)))throw new o("UNSUPPORTED_OPERATION",y,m)}let b=u(p,"max_query_limit",100),x=u(p,"max_query_skip",1e3),H=u(p,"max_watch_docs",100);if(typeof a.limit=="number"&&a.limit>b||typeof a.skip=="number"&&a.skip>x||c==="documents.snapshot"&&typeof a.max_docs=="number"&&a.max_docs>H)throw new o("RESOURCE_EXHAUSTED",y,m);f+=1;try{let C=await n.request(c,a,y);if(!h(C)||!(c==="files.read"?k(C):T(C,1024*1024)))throw new o("PROTOCOL_MISMATCH",y,m);return{value:C,requestId:y}}catch(C){let Se=C instanceof o?C.errCode:F(c)?"COMMIT_UNKNOWN":"RUNTIME_UNAVAILABLE",be=C instanceof o&&C.jobId&&C.invocationId?{jobId:C.jobId,invocationId:C.invocationId}:void 0;throw new o(Se,y,C instanceof o?C.operationId??m:m,be)}finally{f-=1}}},l=ye(i),w=fe(),I=Oe(i),_=c=>R(c,async()=>{throw await i.ready(),new o("UNSUPPORTED_OPERATION")});return{app:{getUpdateManager:ue,checkUpdate:le},auth:{authorize:_e,getIdentity:we},cloud:{DYNAMIC_CURRENT_ENV:Le,init(c){if(!h(c)||Object.keys(c).some(p=>!["env","traceUser"].includes(p)))throw new o("SCHEMA_INVALID");let a={env:ve(c.env),traceUser:c.traceUser??!1};if(e){if(JSON.stringify(e)!==JSON.stringify(a))throw new o("INIT_CONFLICT");return}e=a;try{n=t(a.env),r=n.ready().then(p=>{if(p.protocol.major!==2||!p.profiles.some(y=>["document-core/1","app-execution/1","storage-object/1","watch-snapshot/1"].includes(y)))throw new o("PROTOCOL_MISMATCH");return s=p.serverTime*1e3-Date.now(),p})}catch(p){r=Promise.reject(p instanceof o?p:new o("RUNTIME_UNAVAILABLE"))}r.catch(()=>{})},database(c={}){if(Object.keys(c).some(a=>a!=="throwOnNotFound"))throw new o("SCOPE_FORBIDDEN");return{command:Ne,collection:a=>{if(!/^[a-z][a-z0-9_]{0,63}$/.test(a)||/^(sys_|ac_|t_)/.test(a))throw new o("SCHEMA_INVALID");return new te(i,a,c.throwOnNotFound!==!1)},serverDate:(a={})=>{let p=a.offset??0;if(!Number.isSafeInteger(p)||Math.abs(p)>864e5)throw new o("SCHEMA_INVALID");return new D("serverDate",void 0,p)},runTransaction:_}},callFunction(c){return R(c,()=>l.callFunction(c))},uploadFile(c){return R(c,()=>I.upload(c))},downloadFile(c){return R(c,()=>I.download(c.fileID))},deleteFile(c){return R(c,()=>I.remove(c))},getTempFileURL:_,os:{files:{getOperation:I.getOperation,cancel:I.cancel,stat:I.stat},capabilities:l.capabilities,jobs:l.jobs,api:w,ready:()=>i.ready(),getCapabilities:async()=>structuredClone(await i.ready()),close:()=>n?.close(),operations:{createId:()=>i.createId(),get:async c=>{if(!L.test(c))throw new o("SCHEMA_INVALID");let{value:a,requestId:p}=await i.request("operations.get",{operation_id:c});if(a.operation_id!==c||a.state!=="succeeded"||!h(a.result))throw new o("PROTOCOL_MISMATCH",p,c);return{operationId:c,state:"succeeded",result:ne(a.result,p)}}}}}}}var wt=$e();export{M as AppError,o as CloudError,Le as DYNAMIC_CURRENT_ENV,k as boundedBinary,$e as createCloudClient,F as writesCloud,wt as zl};
|
package/dist/workspace.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @zleap-ai/app-sdk v0.
|
|
1
|
+
/*! @zleap-ai/app-sdk v0.12.0 | (c) 2026 Zleap | 专有许可,仅限在 zleapOS 应用中使用,见 LICENSE */
|
|
2
2
|
var I=Object.defineProperty;var E=(i,t,o)=>t in i?I(i,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):i[t]=o;var _=(i,t,o)=>E(i,typeof t!="symbol"?t+"":t,o);var a=class extends Error{constructor(o,u){super(o);_(this,"code");_(this,"operationId");this.name="WorkspaceError",this.code=o,this.operationId=u}};function y(){if(window.parent===window)return Promise.reject(new a("OPEN_IN_ZLEAP_OS"));let i=window.location.pathname.match(/^\/api\/v1\/app-packages\/runtime\/([A-Za-z0-9_-]{43})\//)?.[1];if(!i)return Promise.reject(new a("OPEN_IN_ZLEAP_OS"));let t=new MessageChannel,o=!1,u=!1,l=new Map;function w(){if(!o){o=!0;for(let e of l.values())clearTimeout(e.timer),e.reject(new a(e.operationId?"COMMIT_UNKNOWN":"CONNECTION_CLOSED",e.operationId));l.clear(),t.port1.postMessage({type:"__zleap_workspace_close"}),t.port1.close()}}window.addEventListener("pagehide",w,{once:!0});let m=new Promise((e,s)=>{let r=setTimeout(()=>{u||(u=!0,w(),s(new a("WORKSPACE_UNAVAILABLE")))},15e3);t.port1.onmessage=c=>{let n=c.data;if(!u&&n?.type==="__zleap_workspace_ready"&&n.protocol===1){u=!0,clearTimeout(r),e();return}if(typeof n?.requestId!="string")return;let p=l.get(n.requestId);p&&(l.delete(n.requestId),clearTimeout(p.timer),typeof n.error=="string"?p.reject(new a(n.error,p.operationId)):p.resolve(n.result))},t.port1.onmessageerror=()=>w(),t.port1.start(),window.parent.postMessage({type:"__zleap_workspace_connect",protocol:1,nonce:i},"*",[t.port2])});async function d(e,s={},r){if(await m,o)throw new a("CONNECTION_CLOSED",r);if(l.size>=4)throw new a("TOO_MANY_REQUESTS");return new Promise((c,n)=>{let p=crypto.randomUUID(),O=setTimeout(()=>{l.delete(p),n(new a(r?"COMMIT_UNKNOWN":"CALL_TIMEOUT",r))},e==="select"?18e4:3e4);l.set(p,{resolve:N=>c(N),reject:n,timer:O,operationId:r}),t.port1.postMessage({requestId:p,method:e,args:s})})}async function f(e,s,r=crypto.randomUUID()){let c=await d(e,{...s,operationId:r},r);if(c.status!=="succeeded")throw new a(c.status==="failed"?c.code??"MOVE_FAILED":"COMMIT_UNKNOWN",r);return c}return m.then(()=>({selectFolder:()=>d("select"),restoreFolder:()=>d("restore"),list:e=>d("list",{handle:e}),readImage:(e,s,r)=>d("image",{handle:e,fileId:s,expectedVersion:r}),createFolder:async(e,s,r)=>(await f("mkdir",{handle:e,name:s},r)).result,move:async(e,s,r,c)=>(await f("move",{source:e,destination:s,fileIds:r},c)).result,operation:e=>d("operation",{operationId:e}),createOperationId:()=>crypto.randomUUID(),close:w}))}export{a as WorkspaceError,y as connectWorkspace};
|
package/dist/zleap.css
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* zleap.css — zleapOS 应用官方样式(随 @zleap-ai/app-sdk 分发,包内引用,符合沙箱 CSP)
|
|
3
|
+
*
|
|
4
|
+
* 用法:vanilla 页面 <link rel="stylesheet" href="./sdk/zleap.css" />;React 里 import '@zleap-ai/app-sdk/zleap.css'。
|
|
5
|
+
* 颜色、圆角、字号与 zleapOS 桌面同源(tokens 段由 zleap-app-kit scripts/sync-style-tokens.mjs 从平台设计 token 生成,勿手改)。
|
|
6
|
+
* 亮 / 暗主题跟随 zleapOS:宿主把当前主题设到应用窗口上,页面里 prefers-color-scheme 随之变化,不需要写代码。
|
|
7
|
+
* 组件类都以 zl- 开头,可与自己的样式混用;覆盖时改 --zl-* 变量,不要改本文件。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* tokens:begin */
|
|
11
|
+
:root {
|
|
12
|
+
--zl-accent: #007AFF;
|
|
13
|
+
--zl-accent-text: #0066CC;
|
|
14
|
+
--zl-accent-subtle: rgb(0 122 255 / 12%);
|
|
15
|
+
--zl-danger: #EF4444;
|
|
16
|
+
--zl-success: #34C759;
|
|
17
|
+
--zl-warning: #8F6D00;
|
|
18
|
+
--zl-bg: #f9f9f9;
|
|
19
|
+
--zl-surface: #ffffff;
|
|
20
|
+
--zl-ink: #27272a;
|
|
21
|
+
--zl-ink-muted: #606066;
|
|
22
|
+
--zl-ink-faint: #73737a;
|
|
23
|
+
--zl-line: rgba(60, 60, 67, 0.22);
|
|
24
|
+
--zl-line-strong: rgba(60, 60, 67, 0.38);
|
|
25
|
+
--zl-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 4px 14px rgb(0 0 0 / 0.08);
|
|
26
|
+
--zl-radius-sm: 6px;
|
|
27
|
+
--zl-radius-md: 8px;
|
|
28
|
+
--zl-radius-lg: 10px;
|
|
29
|
+
--zl-radius-xl: 14px;
|
|
30
|
+
--zl-font-xs: 12px;
|
|
31
|
+
--zl-font-sm: 13px;
|
|
32
|
+
--zl-font-base: 15px;
|
|
33
|
+
--zl-font-lg: 17px;
|
|
34
|
+
--zl-font-xl: 22px;
|
|
35
|
+
}
|
|
36
|
+
/* 暗色:跟随 zleapOS(宿主把主题设到应用窗口,prefers-color-scheme 随之变化);页面也可以自己设 data-theme。 */
|
|
37
|
+
@media (prefers-color-scheme: dark) {
|
|
38
|
+
:root:not([data-theme='light']) {
|
|
39
|
+
--zl-accent: #0A84FF;
|
|
40
|
+
--zl-accent-text: #409CFF;
|
|
41
|
+
--zl-accent-subtle: rgb(10 132 255 / 18%);
|
|
42
|
+
--zl-danger: #F87171;
|
|
43
|
+
--zl-success: #30D158;
|
|
44
|
+
--zl-warning: #E5B13B;
|
|
45
|
+
--zl-bg: #232323;
|
|
46
|
+
--zl-surface: #242424;
|
|
47
|
+
--zl-ink: #f1f1f2;
|
|
48
|
+
--zl-ink-muted: #b8b8bd;
|
|
49
|
+
--zl-ink-faint: #9b9ba1;
|
|
50
|
+
--zl-line: #3a3a3a;
|
|
51
|
+
--zl-line-strong: #686868;
|
|
52
|
+
--zl-shadow: 0 1px 2px rgb(0 0 0 / 0.24), 0 10px 28px rgb(0 0 0 / 0.28);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
:root[data-theme='dark'] {
|
|
56
|
+
--zl-accent: #0A84FF;
|
|
57
|
+
--zl-accent-text: #409CFF;
|
|
58
|
+
--zl-accent-subtle: rgb(10 132 255 / 18%);
|
|
59
|
+
--zl-danger: #F87171;
|
|
60
|
+
--zl-success: #30D158;
|
|
61
|
+
--zl-warning: #E5B13B;
|
|
62
|
+
--zl-bg: #232323;
|
|
63
|
+
--zl-surface: #242424;
|
|
64
|
+
--zl-ink: #f1f1f2;
|
|
65
|
+
--zl-ink-muted: #b8b8bd;
|
|
66
|
+
--zl-ink-faint: #9b9ba1;
|
|
67
|
+
--zl-line: #3a3a3a;
|
|
68
|
+
--zl-line-strong: #686868;
|
|
69
|
+
--zl-shadow: 0 1px 2px rgb(0 0 0 / 0.24), 0 10px 28px rgb(0 0 0 / 0.28);
|
|
70
|
+
}
|
|
71
|
+
/* tokens:end */
|
|
72
|
+
|
|
73
|
+
:root {
|
|
74
|
+
--zl-font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', system-ui, 'Segoe UI',
|
|
75
|
+
'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
|
76
|
+
--zl-hover: color-mix(in srgb, var(--zl-ink) 6%, transparent);
|
|
77
|
+
--zl-pressed: color-mix(in srgb, var(--zl-ink) 10%, transparent);
|
|
78
|
+
--zl-success-subtle: color-mix(in srgb, var(--zl-success) 14%, transparent);
|
|
79
|
+
--zl-warning-subtle: color-mix(in srgb, var(--zl-warning) 14%, transparent);
|
|
80
|
+
--zl-danger-subtle: color-mix(in srgb, var(--zl-danger) 12%, transparent);
|
|
81
|
+
--zl-focus: 0 0 0 3px color-mix(in srgb, var(--zl-accent) 35%, transparent);
|
|
82
|
+
--zl-ease: cubic-bezier(0.2, 0, 0, 1);
|
|
83
|
+
color-scheme: light dark;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* ---------- 基础 ---------- */
|
|
87
|
+
*,
|
|
88
|
+
*::before,
|
|
89
|
+
*::after {
|
|
90
|
+
box-sizing: border-box;
|
|
91
|
+
}
|
|
92
|
+
html {
|
|
93
|
+
font-family: var(--zl-font-family);
|
|
94
|
+
font-size: var(--zl-font-base);
|
|
95
|
+
line-height: 1.5;
|
|
96
|
+
-webkit-font-smoothing: antialiased;
|
|
97
|
+
text-rendering: optimizeLegibility;
|
|
98
|
+
}
|
|
99
|
+
body {
|
|
100
|
+
margin: 0;
|
|
101
|
+
min-height: 100vh;
|
|
102
|
+
background: var(--zl-bg);
|
|
103
|
+
color: var(--zl-ink);
|
|
104
|
+
}
|
|
105
|
+
::selection {
|
|
106
|
+
background: var(--zl-accent-subtle);
|
|
107
|
+
}
|
|
108
|
+
:focus-visible {
|
|
109
|
+
outline: none;
|
|
110
|
+
box-shadow: var(--zl-focus);
|
|
111
|
+
}
|
|
112
|
+
h1, h2, h3, h4, p {
|
|
113
|
+
margin: 0;
|
|
114
|
+
}
|
|
115
|
+
code, kbd {
|
|
116
|
+
font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
|
117
|
+
font-size: 0.92em;
|
|
118
|
+
}
|
|
119
|
+
code {
|
|
120
|
+
padding: 1px 5px;
|
|
121
|
+
border-radius: var(--zl-radius-sm);
|
|
122
|
+
background: var(--zl-hover);
|
|
123
|
+
}
|
|
124
|
+
[hidden] {
|
|
125
|
+
display: none !important;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* ---------- 布局 ---------- */
|
|
129
|
+
.zl-page {
|
|
130
|
+
max-width: 760px;
|
|
131
|
+
margin: 0 auto;
|
|
132
|
+
padding: 28px 24px 48px;
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
gap: 20px;
|
|
136
|
+
}
|
|
137
|
+
.zl-page--wide { max-width: 1080px; }
|
|
138
|
+
.zl-page--full { max-width: none; }
|
|
139
|
+
/* 左列表右详情:<div class="zl-split"><aside>列表</aside><section>详情</section></div>,窄窗口上下排 */
|
|
140
|
+
.zl-split {
|
|
141
|
+
display: grid;
|
|
142
|
+
grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
|
|
143
|
+
gap: 20px;
|
|
144
|
+
align-items: start;
|
|
145
|
+
}
|
|
146
|
+
.zl-split > :first-child { position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow: auto; }
|
|
147
|
+
.zl-header {
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: flex-start;
|
|
150
|
+
justify-content: space-between;
|
|
151
|
+
gap: 16px;
|
|
152
|
+
}
|
|
153
|
+
.zl-title {
|
|
154
|
+
font-size: var(--zl-font-xl);
|
|
155
|
+
line-height: 1.3;
|
|
156
|
+
font-weight: 650;
|
|
157
|
+
letter-spacing: -0.01em;
|
|
158
|
+
}
|
|
159
|
+
.zl-subtitle {
|
|
160
|
+
margin-top: 4px;
|
|
161
|
+
color: var(--zl-ink-muted);
|
|
162
|
+
font-size: var(--zl-font-sm);
|
|
163
|
+
}
|
|
164
|
+
.zl-section {
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: column;
|
|
167
|
+
gap: 12px;
|
|
168
|
+
}
|
|
169
|
+
.zl-section-title {
|
|
170
|
+
display: flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
justify-content: space-between;
|
|
173
|
+
gap: 12px;
|
|
174
|
+
font-size: var(--zl-font-sm);
|
|
175
|
+
font-weight: 600;
|
|
176
|
+
color: var(--zl-ink-muted);
|
|
177
|
+
}
|
|
178
|
+
.zl-stack { display: flex; flex-direction: column; gap: 12px; }
|
|
179
|
+
.zl-stack--sm { gap: 6px; }
|
|
180
|
+
.zl-stack--lg { gap: 20px; }
|
|
181
|
+
.zl-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
182
|
+
.zl-row--between { justify-content: space-between; }
|
|
183
|
+
.zl-row--end { justify-content: flex-end; }
|
|
184
|
+
.zl-spacer { flex: 1; }
|
|
185
|
+
.zl-grid {
|
|
186
|
+
display: grid;
|
|
187
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
188
|
+
gap: 12px;
|
|
189
|
+
}
|
|
190
|
+
.zl-divider {
|
|
191
|
+
height: 1px;
|
|
192
|
+
border: 0;
|
|
193
|
+
margin: 0;
|
|
194
|
+
background: var(--zl-line);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* ---------- 卡片 ---------- */
|
|
198
|
+
.zl-card {
|
|
199
|
+
background: var(--zl-surface);
|
|
200
|
+
border: 1px solid var(--zl-line);
|
|
201
|
+
border-radius: var(--zl-radius-xl);
|
|
202
|
+
box-shadow: var(--zl-shadow);
|
|
203
|
+
padding: 16px;
|
|
204
|
+
}
|
|
205
|
+
.zl-card--flat { box-shadow: none; }
|
|
206
|
+
.zl-card--interactive {
|
|
207
|
+
cursor: pointer;
|
|
208
|
+
transition: border-color 0.15s var(--zl-ease), transform 0.15s var(--zl-ease);
|
|
209
|
+
}
|
|
210
|
+
.zl-card--interactive:hover { border-color: var(--zl-line-strong); }
|
|
211
|
+
.zl-card--interactive:active { transform: scale(0.995); }
|
|
212
|
+
.zl-card-title {
|
|
213
|
+
font-size: var(--zl-font-base);
|
|
214
|
+
font-weight: 600;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/* ---------- 文字 ---------- */
|
|
218
|
+
.zl-muted { color: var(--zl-ink-muted); }
|
|
219
|
+
.zl-faint { color: var(--zl-ink-faint); }
|
|
220
|
+
.zl-text-sm { font-size: var(--zl-font-sm); }
|
|
221
|
+
.zl-text-xs { font-size: var(--zl-font-xs); }
|
|
222
|
+
.zl-strong { font-weight: 600; }
|
|
223
|
+
.zl-num { font-variant-numeric: tabular-nums; }
|
|
224
|
+
.zl-text-success { color: var(--zl-success); }
|
|
225
|
+
.zl-text-danger { color: var(--zl-danger); }
|
|
226
|
+
.zl-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
227
|
+
.zl-prose {
|
|
228
|
+
line-height: 1.7;
|
|
229
|
+
overflow-wrap: anywhere;
|
|
230
|
+
white-space: pre-wrap;
|
|
231
|
+
}
|
|
232
|
+
.zl-prose ul, .zl-prose ol { margin: 4px 0; padding-left: 20px; }
|
|
233
|
+
|
|
234
|
+
/* ---------- 按钮 ---------- */
|
|
235
|
+
.zl-btn {
|
|
236
|
+
display: inline-flex;
|
|
237
|
+
align-items: center;
|
|
238
|
+
justify-content: center;
|
|
239
|
+
gap: 6px;
|
|
240
|
+
min-height: 34px;
|
|
241
|
+
padding: 0 14px;
|
|
242
|
+
border: 1px solid var(--zl-line-strong);
|
|
243
|
+
border-radius: var(--zl-radius-md);
|
|
244
|
+
background: var(--zl-surface);
|
|
245
|
+
color: var(--zl-ink);
|
|
246
|
+
font: inherit;
|
|
247
|
+
font-size: var(--zl-font-sm);
|
|
248
|
+
font-weight: 550;
|
|
249
|
+
line-height: 1;
|
|
250
|
+
white-space: nowrap;
|
|
251
|
+
cursor: pointer;
|
|
252
|
+
user-select: none;
|
|
253
|
+
transition: background 0.15s var(--zl-ease), border-color 0.15s var(--zl-ease), transform 0.1s var(--zl-ease);
|
|
254
|
+
}
|
|
255
|
+
.zl-btn:hover { background: var(--zl-hover); }
|
|
256
|
+
.zl-btn:active { transform: scale(0.97); }
|
|
257
|
+
.zl-btn:disabled,
|
|
258
|
+
.zl-btn[aria-disabled='true'] {
|
|
259
|
+
opacity: 0.5;
|
|
260
|
+
cursor: default;
|
|
261
|
+
transform: none;
|
|
262
|
+
}
|
|
263
|
+
.zl-btn--primary {
|
|
264
|
+
background: var(--zl-accent);
|
|
265
|
+
border-color: var(--zl-accent);
|
|
266
|
+
color: #fff;
|
|
267
|
+
}
|
|
268
|
+
.zl-btn--primary:hover { background: color-mix(in srgb, var(--zl-accent) 88%, #000); }
|
|
269
|
+
.zl-btn--danger {
|
|
270
|
+
color: var(--zl-danger);
|
|
271
|
+
border-color: color-mix(in srgb, var(--zl-danger) 40%, transparent);
|
|
272
|
+
}
|
|
273
|
+
.zl-btn--danger:hover { background: var(--zl-danger-subtle); }
|
|
274
|
+
.zl-btn--ghost {
|
|
275
|
+
border-color: transparent;
|
|
276
|
+
background: transparent;
|
|
277
|
+
color: var(--zl-ink-muted);
|
|
278
|
+
}
|
|
279
|
+
.zl-btn--ghost:hover { color: var(--zl-ink); background: var(--zl-hover); }
|
|
280
|
+
.zl-btn--sm { min-height: 28px; padding: 0 10px; font-size: var(--zl-font-xs); border-radius: var(--zl-radius-sm); }
|
|
281
|
+
.zl-btn--lg { min-height: 40px; padding: 0 18px; font-size: var(--zl-font-base); }
|
|
282
|
+
.zl-btn--block { width: 100%; }
|
|
283
|
+
/* 处理中:<button class="zl-btn" aria-busy="true">保存中…</button> */
|
|
284
|
+
.zl-btn[aria-busy='true']::before {
|
|
285
|
+
content: '';
|
|
286
|
+
width: 12px;
|
|
287
|
+
height: 12px;
|
|
288
|
+
border-radius: 50%;
|
|
289
|
+
border: 2px solid currentColor;
|
|
290
|
+
border-right-color: transparent;
|
|
291
|
+
animation: zl-spin 0.7s linear infinite;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* ---------- 表单 ---------- */
|
|
295
|
+
.zl-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
296
|
+
.zl-label { font-size: var(--zl-font-sm); font-weight: 550; }
|
|
297
|
+
.zl-hint { font-size: var(--zl-font-xs); color: var(--zl-ink-faint); }
|
|
298
|
+
.zl-input,
|
|
299
|
+
.zl-textarea,
|
|
300
|
+
.zl-select {
|
|
301
|
+
width: 100%;
|
|
302
|
+
min-height: 36px;
|
|
303
|
+
padding: 7px 11px;
|
|
304
|
+
border: 1px solid var(--zl-line-strong);
|
|
305
|
+
border-radius: var(--zl-radius-md);
|
|
306
|
+
background: var(--zl-surface);
|
|
307
|
+
color: var(--zl-ink);
|
|
308
|
+
font: inherit;
|
|
309
|
+
font-size: var(--zl-font-base);
|
|
310
|
+
transition: border-color 0.15s var(--zl-ease), box-shadow 0.15s var(--zl-ease);
|
|
311
|
+
}
|
|
312
|
+
.zl-input::placeholder,
|
|
313
|
+
.zl-textarea::placeholder { color: var(--zl-ink-faint); }
|
|
314
|
+
.zl-input:focus,
|
|
315
|
+
.zl-textarea:focus,
|
|
316
|
+
.zl-select:focus {
|
|
317
|
+
outline: none;
|
|
318
|
+
border-color: var(--zl-accent);
|
|
319
|
+
box-shadow: var(--zl-focus);
|
|
320
|
+
}
|
|
321
|
+
.zl-input[aria-invalid='true'],
|
|
322
|
+
.zl-textarea[aria-invalid='true'] { border-color: var(--zl-danger); }
|
|
323
|
+
.zl-textarea { min-height: 96px; resize: vertical; line-height: 1.6; }
|
|
324
|
+
.zl-input:disabled, .zl-textarea:disabled, .zl-select:disabled { opacity: 0.6; }
|
|
325
|
+
.zl-check {
|
|
326
|
+
width: 18px;
|
|
327
|
+
height: 18px;
|
|
328
|
+
margin: 0;
|
|
329
|
+
flex: none;
|
|
330
|
+
accent-color: var(--zl-accent);
|
|
331
|
+
cursor: pointer;
|
|
332
|
+
}
|
|
333
|
+
/* 行内可编辑字段:平时像文字,悬停 / 聚焦时显出边框;原生日期框 type="date" 在沙箱里可用,也跟随亮 / 暗 */
|
|
334
|
+
.zl-input--inline {
|
|
335
|
+
width: auto;
|
|
336
|
+
min-height: 28px;
|
|
337
|
+
padding: 3px 6px;
|
|
338
|
+
border-color: transparent;
|
|
339
|
+
background: transparent;
|
|
340
|
+
font-size: var(--zl-font-sm);
|
|
341
|
+
}
|
|
342
|
+
.zl-input--inline:hover { border-color: var(--zl-line-strong); }
|
|
343
|
+
.zl-input--inline:focus { background: var(--zl-surface); }
|
|
344
|
+
/* 一行输入 + 按钮 */
|
|
345
|
+
.zl-composer { display: flex; gap: 8px; }
|
|
346
|
+
.zl-composer > .zl-input { flex: 1; min-width: 0; }
|
|
347
|
+
|
|
348
|
+
/* 分段切换:<div class="zl-segmented"><button aria-pressed="true">全部</button>…</div>(不用原生 select 时首选) */
|
|
349
|
+
.zl-segmented {
|
|
350
|
+
display: inline-flex;
|
|
351
|
+
padding: 2px;
|
|
352
|
+
gap: 2px;
|
|
353
|
+
border-radius: var(--zl-radius-md);
|
|
354
|
+
background: var(--zl-hover);
|
|
355
|
+
}
|
|
356
|
+
.zl-segmented > button {
|
|
357
|
+
min-height: 28px;
|
|
358
|
+
padding: 0 12px;
|
|
359
|
+
border: 0;
|
|
360
|
+
border-radius: var(--zl-radius-sm);
|
|
361
|
+
background: transparent;
|
|
362
|
+
color: var(--zl-ink-muted);
|
|
363
|
+
font: inherit;
|
|
364
|
+
font-size: var(--zl-font-sm);
|
|
365
|
+
white-space: nowrap;
|
|
366
|
+
cursor: pointer;
|
|
367
|
+
}
|
|
368
|
+
.zl-segmented > button[aria-pressed='true'] {
|
|
369
|
+
background: var(--zl-surface);
|
|
370
|
+
color: var(--zl-ink);
|
|
371
|
+
font-weight: 600;
|
|
372
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / 0.08);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* ---------- 列表 ---------- */
|
|
376
|
+
.zl-list {
|
|
377
|
+
list-style: none;
|
|
378
|
+
margin: 0;
|
|
379
|
+
padding: 0;
|
|
380
|
+
background: var(--zl-surface);
|
|
381
|
+
border: 1px solid var(--zl-line);
|
|
382
|
+
border-radius: var(--zl-radius-xl);
|
|
383
|
+
overflow: hidden;
|
|
384
|
+
}
|
|
385
|
+
.zl-list-item {
|
|
386
|
+
display: flex;
|
|
387
|
+
align-items: center;
|
|
388
|
+
gap: 12px;
|
|
389
|
+
min-height: 52px;
|
|
390
|
+
padding: 10px 16px;
|
|
391
|
+
}
|
|
392
|
+
.zl-list-item + .zl-list-item { border-top: 1px solid var(--zl-line); }
|
|
393
|
+
.zl-list-item:hover { background: color-mix(in srgb, var(--zl-ink) 3%, transparent); }
|
|
394
|
+
.zl-item-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
395
|
+
.zl-item-title { font-weight: 550; overflow-wrap: anywhere; }
|
|
396
|
+
.zl-item-meta { font-size: var(--zl-font-xs); color: var(--zl-ink-faint); }
|
|
397
|
+
.zl-item-actions { display: flex; gap: 4px; flex: none; }
|
|
398
|
+
.zl-list-item.is-done .zl-item-title { color: var(--zl-ink-faint); text-decoration: line-through; }
|
|
399
|
+
/* 可点选的列表行(左列表右详情):<button class="zl-list-item" aria-current="true">;选中项用 aria-current */
|
|
400
|
+
button.zl-list-item {
|
|
401
|
+
width: 100%;
|
|
402
|
+
border: 0;
|
|
403
|
+
background: transparent;
|
|
404
|
+
color: inherit;
|
|
405
|
+
font: inherit;
|
|
406
|
+
text-align: left;
|
|
407
|
+
cursor: pointer;
|
|
408
|
+
}
|
|
409
|
+
button.zl-list-item:focus-visible { outline: none; box-shadow: inset var(--zl-focus); }
|
|
410
|
+
.zl-list-item[aria-current='true'] { background: var(--zl-accent-subtle); }
|
|
411
|
+
.zl-list-item[aria-current='true'] .zl-item-title { color: var(--zl-accent-text); }
|
|
412
|
+
@media (hover: hover) {
|
|
413
|
+
.zl-item-actions--hover { opacity: 0; transition: opacity 0.15s var(--zl-ease); }
|
|
414
|
+
.zl-list-item:hover .zl-item-actions--hover,
|
|
415
|
+
.zl-list-item:focus-within .zl-item-actions--hover { opacity: 1; }
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* ---------- 标签与状态 ---------- */
|
|
419
|
+
.zl-tag {
|
|
420
|
+
display: inline-flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
gap: 4px;
|
|
423
|
+
height: 22px;
|
|
424
|
+
padding: 0 8px;
|
|
425
|
+
border-radius: 999px;
|
|
426
|
+
background: var(--zl-hover);
|
|
427
|
+
color: var(--zl-ink-muted);
|
|
428
|
+
font-size: var(--zl-font-xs);
|
|
429
|
+
font-weight: 550;
|
|
430
|
+
white-space: nowrap;
|
|
431
|
+
}
|
|
432
|
+
.zl-tag--accent { background: var(--zl-accent-subtle); color: var(--zl-accent-text); }
|
|
433
|
+
.zl-tag--success { background: var(--zl-success-subtle); color: var(--zl-success); }
|
|
434
|
+
.zl-tag--warning { background: var(--zl-warning-subtle); color: var(--zl-warning); }
|
|
435
|
+
.zl-tag--danger { background: var(--zl-danger-subtle); color: var(--zl-danger); }
|
|
436
|
+
/* 连接状态:<span class="zl-status" data-state="connecting|ready|error|preview">…</span> */
|
|
437
|
+
.zl-status {
|
|
438
|
+
display: inline-flex;
|
|
439
|
+
align-items: center;
|
|
440
|
+
gap: 6px;
|
|
441
|
+
font-size: var(--zl-font-xs);
|
|
442
|
+
color: var(--zl-ink-muted);
|
|
443
|
+
white-space: nowrap;
|
|
444
|
+
}
|
|
445
|
+
.zl-status::before {
|
|
446
|
+
content: '';
|
|
447
|
+
width: 7px;
|
|
448
|
+
height: 7px;
|
|
449
|
+
border-radius: 50%;
|
|
450
|
+
background: var(--zl-ink-faint);
|
|
451
|
+
}
|
|
452
|
+
.zl-status[data-state='connecting']::before { animation: zl-pulse 1.2s ease-in-out infinite; }
|
|
453
|
+
.zl-status[data-state='ready']::before { background: var(--zl-success); }
|
|
454
|
+
.zl-status[data-state='error'] { color: var(--zl-danger); }
|
|
455
|
+
.zl-status[data-state='preview']::before { background: var(--zl-accent); }
|
|
456
|
+
.zl-status[data-state='error']::before { background: var(--zl-danger); }
|
|
457
|
+
|
|
458
|
+
/* ---------- 提示 ---------- */
|
|
459
|
+
.zl-alert {
|
|
460
|
+
display: flex;
|
|
461
|
+
align-items: flex-start;
|
|
462
|
+
gap: 12px;
|
|
463
|
+
padding: 12px 14px;
|
|
464
|
+
border-radius: var(--zl-radius-lg);
|
|
465
|
+
border: 1px solid var(--zl-line);
|
|
466
|
+
background: var(--zl-surface);
|
|
467
|
+
font-size: var(--zl-font-sm);
|
|
468
|
+
}
|
|
469
|
+
.zl-alert > :first-child { flex: 1; min-width: 0; }
|
|
470
|
+
.zl-alert strong { display: block; margin-bottom: 2px; }
|
|
471
|
+
.zl-alert--info { background: var(--zl-accent-subtle); border-color: transparent; }
|
|
472
|
+
.zl-alert--success { background: var(--zl-success-subtle); border-color: transparent; }
|
|
473
|
+
.zl-alert--warning { background: var(--zl-warning-subtle); border-color: transparent; }
|
|
474
|
+
.zl-alert--danger { background: var(--zl-danger-subtle); border-color: transparent; color: var(--zl-ink); }
|
|
475
|
+
.zl-alert--danger strong { color: var(--zl-danger); }
|
|
476
|
+
/* 轻提示:<div class="zl-toast" role="status">已保存</div>,2–3 秒后移除 */
|
|
477
|
+
.zl-toast {
|
|
478
|
+
position: fixed;
|
|
479
|
+
left: 50%;
|
|
480
|
+
bottom: 24px;
|
|
481
|
+
transform: translateX(-50%);
|
|
482
|
+
z-index: 10;
|
|
483
|
+
padding: 8px 16px;
|
|
484
|
+
border-radius: 999px;
|
|
485
|
+
background: var(--zl-ink);
|
|
486
|
+
color: var(--zl-bg);
|
|
487
|
+
font-size: var(--zl-font-sm);
|
|
488
|
+
box-shadow: var(--zl-shadow);
|
|
489
|
+
animation: zl-rise 0.2s var(--zl-ease);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/* ---------- 空 / 加载 ---------- */
|
|
493
|
+
.zl-empty {
|
|
494
|
+
display: flex;
|
|
495
|
+
flex-direction: column;
|
|
496
|
+
align-items: center;
|
|
497
|
+
gap: 8px;
|
|
498
|
+
padding: 40px 16px;
|
|
499
|
+
text-align: center;
|
|
500
|
+
color: var(--zl-ink-muted);
|
|
501
|
+
}
|
|
502
|
+
.zl-empty-icon {
|
|
503
|
+
width: 44px;
|
|
504
|
+
height: 44px;
|
|
505
|
+
display: grid;
|
|
506
|
+
place-items: center;
|
|
507
|
+
border-radius: 12px;
|
|
508
|
+
background: var(--zl-accent-subtle);
|
|
509
|
+
color: var(--zl-accent);
|
|
510
|
+
font-size: 22px;
|
|
511
|
+
}
|
|
512
|
+
.zl-empty-title { font-weight: 600; color: var(--zl-ink); }
|
|
513
|
+
.zl-empty-text { font-size: var(--zl-font-sm); max-width: 360px; }
|
|
514
|
+
.zl-skeleton {
|
|
515
|
+
display: block;
|
|
516
|
+
height: 14px;
|
|
517
|
+
border-radius: var(--zl-radius-sm);
|
|
518
|
+
background: linear-gradient(90deg, var(--zl-hover) 0%, var(--zl-pressed) 50%, var(--zl-hover) 100%);
|
|
519
|
+
background-size: 200% 100%;
|
|
520
|
+
animation: zl-shimmer 1.2s ease-in-out infinite;
|
|
521
|
+
}
|
|
522
|
+
.zl-spinner {
|
|
523
|
+
display: inline-block;
|
|
524
|
+
width: 16px;
|
|
525
|
+
height: 16px;
|
|
526
|
+
border-radius: 50%;
|
|
527
|
+
border: 2px solid var(--zl-line-strong);
|
|
528
|
+
border-top-color: var(--zl-accent);
|
|
529
|
+
animation: zl-spin 0.7s linear infinite;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* ---------- 数据展示 ---------- */
|
|
533
|
+
.zl-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
|
|
534
|
+
.zl-stat {
|
|
535
|
+
padding: 14px 16px;
|
|
536
|
+
border-radius: var(--zl-radius-xl);
|
|
537
|
+
background: var(--zl-surface);
|
|
538
|
+
border: 1px solid var(--zl-line);
|
|
539
|
+
}
|
|
540
|
+
.zl-stat-label { font-size: var(--zl-font-xs); color: var(--zl-ink-muted); }
|
|
541
|
+
.zl-stat-value {
|
|
542
|
+
margin-top: 4px;
|
|
543
|
+
font-size: var(--zl-font-xl);
|
|
544
|
+
font-weight: 650;
|
|
545
|
+
font-variant-numeric: tabular-nums;
|
|
546
|
+
line-height: 1.2;
|
|
547
|
+
}
|
|
548
|
+
.zl-progress {
|
|
549
|
+
height: 6px;
|
|
550
|
+
border-radius: 999px;
|
|
551
|
+
background: var(--zl-hover);
|
|
552
|
+
overflow: hidden;
|
|
553
|
+
}
|
|
554
|
+
.zl-progress > span {
|
|
555
|
+
display: block;
|
|
556
|
+
height: 100%;
|
|
557
|
+
border-radius: inherit;
|
|
558
|
+
background: var(--zl-accent);
|
|
559
|
+
transition: width 0.3s var(--zl-ease);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* ---------- 动效 ---------- */
|
|
563
|
+
@keyframes zl-spin { to { transform: rotate(360deg); } }
|
|
564
|
+
@keyframes zl-pulse { 50% { opacity: 0.35; } }
|
|
565
|
+
@keyframes zl-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
|
|
566
|
+
@keyframes zl-rise { from { opacity: 0; transform: translate(-50%, 8px); } }
|
|
567
|
+
.zl-enter { animation: zl-fade 0.2s var(--zl-ease); }
|
|
568
|
+
@keyframes zl-fade { from { opacity: 0; transform: translateY(4px); } }
|
|
569
|
+
@media (prefers-reduced-motion: reduce) {
|
|
570
|
+
*, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/* ---------- 窄窗口 ---------- */
|
|
574
|
+
@media (max-width: 560px) {
|
|
575
|
+
.zl-page { padding: 20px 14px 36px; }
|
|
576
|
+
.zl-header { flex-direction: column; }
|
|
577
|
+
.zl-composer { flex-direction: column; }
|
|
578
|
+
}
|
|
579
|
+
@media (max-width: 720px) {
|
|
580
|
+
.zl-split { grid-template-columns: minmax(0, 1fr); }
|
|
581
|
+
.zl-split > :first-child { position: static; max-height: none; }
|
|
582
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zleap-ai/app-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "zleapOS 云开发前端 SDK:Cloud 数据库 / 文件 / 云函数(zl.cloud)、宿主能力(connectHostedApp)与工作区连接",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"import": "./dist/workspace.js",
|
|
29
29
|
"default": "./dist/workspace.js"
|
|
30
30
|
},
|
|
31
|
+
"./zleap.css": "./dist/zleap.css",
|
|
31
32
|
"./package.json": "./package.json"
|
|
32
33
|
},
|
|
33
34
|
"files": [
|