@linkshell/gateway 0.6.11 → 0.6.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkshell/gateway",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "LinkShell gateway: relays end-to-end encrypted frames between computers and devices, and brokers pairing.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,2 +1,2 @@
1
- import{a as i,j as s}from"./markdown-SZOrMO_3.js";import{d as U,i as gs,a as Ns,I as a,C as Y,b as bs,M as vs,o as ds,v as ks}from"./index-E4E6ovrQ.js";import"./account-R7yD1rZE.js";import"./terminal-DWFexEE4.js";const Cs=[{id:"auth",title:"完善登录续期与断线恢复",project:"linkshell",agent:"Claude",status:"waiting",detail:"等待确认 · 执行连接恢复测试",time:"刚刚"},{id:"web",title:"搭建网页端的会话工作区",project:"linkshell",agent:"Codex",status:"running",detail:"正在调整会话布局与响应式样式",time:"2 分钟前"},{id:"search",title:"优化文档搜索的键盘导航",project:"itool",agent:"Claude",status:"running",detail:"正在检查焦点切换与快捷键",time:"8 分钟前"},{id:"billing",title:"修复订阅页面的状态显示",project:"itool",agent:"Codex",status:"done",detail:"已完成 · 3 个文件变更",time:"32 分钟前"},{id:"docs",title:"补充自托管网关部署说明",project:"linkshell",agent:"Claude",status:"done",detail:"已完成 · 1 个文件变更",time:"1 小时前"}],B={waiting:"需要你",running:"进行中",done:"已完成"},hs=["src/auth/session.ts","src/connection/retry.ts","test/session.test.ts"];function ws({status:t}){return s.jsxs("span",{className:`badge ${t}`,children:[s.jsx("span",{className:"status-dot"}),B[t]]})}function I({agent:t}){const m=bs[t.toLowerCase()];return s.jsx("span",{className:`agent-mark ${t.toLowerCase()} ${m.full?"full-mark":""}`,children:s.jsx("img",{src:`data:image/svg+xml,${encodeURIComponent(m.svg)}`,alt:t})})}function js({title:t,subtitle:m,children:h,close:k}){return s.jsxs(vs,{title:t,close:k,children:[m&&s.jsx("p",{className:"muted modal-subtitle",children:m}),h]})}function ys({source:t,gateway:m,onConnect:h,close:k}){const[d,w]=i.useState(t),[u,y]=i.useState(t==="self-hosted"?m:""),[c,E]=i.useState(""),[N,p]=i.useState("");function S(f){if(f.preventDefault(),d==="official")return h(d,ds);try{const v=ks(u);if(v===ds)throw new Error("这是官方网关,请选择官方服务;私有部署请填写自己的网关地址");if(!/^\d{6}$/.test(c))throw new Error("请输入 6 位配对码;原型中可填写任意 6 位数字");h(d,v)}catch(v){p(v instanceof Error?v.message:"请检查网关设置")}}return s.jsxs(js,{title:"连接你的电脑",subtitle:"选择连接方式,工作台始终属于你。",close:k,children:[U==="official"?s.jsxs("div",{className:"source-options",children:[s.jsxs("button",{className:d==="official"?"source-option selected":"source-option",onClick:()=>{w("official"),p("")},"aria-pressed":d==="official",children:[s.jsx(a,{name:"globe",size:23}),s.jsx("strong",{children:"官方服务"}),s.jsx("span",{children:"登录账号,发现你的电脑"}),s.jsx("span",{className:"selection-dot"})]}),s.jsxs("button",{className:d==="self-hosted"?"source-option selected":"source-option",onClick:()=>{w("self-hosted"),p("")},"aria-pressed":d==="self-hosted",children:[s.jsx(a,{name:"server",size:23}),s.jsx("strong",{children:"自托管网关"}),s.jsx("span",{children:"使用自己的服务器与配对码"}),s.jsx("span",{className:"selection-dot"})]})]}):s.jsxs("div",{className:"private-note",children:[s.jsx(a,{name:"server"}),s.jsxs("div",{children:[s.jsx("strong",{children:"私有部署"}),s.jsx("p",{children:"此站点使用你配置的网关,无需 iTool 账号或官方订阅。"})]})]}),s.jsxs("form",{onSubmit:S,children:[d==="official"?s.jsxs("div",{className:"official-entry",children:[s.jsx("div",{className:"entry-symbol",children:s.jsx(a,{name:"computer",size:32})}),s.jsx("h3",{children:"你的电脑,登录后就在这里"}),s.jsxs("p",{children:["电脑端运行 ",s.jsx("code",{children:"linkshell login"}),",网页使用同一 iTool 账号。电脑接入官方网关需要有效的 Pro 订阅。"]}),s.jsxs("div",{className:"endpoint",children:[s.jsx("span",{className:"status-dot"}),"gateway.itool.tech ",s.jsx("span",{children:"官方网关"})]})]}):s.jsxs("div",{className:"pairing-form",children:[s.jsx("label",{htmlFor:"gateway",children:"网关地址"}),s.jsx("input",{id:"gateway",placeholder:"wss://gateway.example.com",value:u,onChange:f=>{y(f.target.value),p("")},autoComplete:"off",spellCheck:!1,required:!0}),s.jsx("p",{className:"field-hint",children:"填写部署网关的地址,不是当前网页的地址。"}),s.jsx("label",{htmlFor:"pairing-code",children:"电脑上的配对码"}),s.jsx("input",{id:"pairing-code",className:"code-input",inputMode:"numeric",placeholder:"000000",maxLength:6,value:c,onChange:f=>{E(f.target.value.replace(/\D/g,"")),p("")},required:!0}),s.jsxs("p",{className:"field-hint",children:["电脑连接该网关后运行 ",s.jsx("code",{children:"linkshell pair"})," 获取。真实配对码 10 分钟内有效。"]}),s.jsxs("div",{className:"private-note",children:[s.jsx(a,{name:"shield"}),s.jsx("span",{children:"无需官方账号与订阅。正式版仅与指定网关交换配对信息,不向它发送 iTool 登录凭证。"})]})]}),N&&s.jsx("p",{role:"alert",className:"form-error",children:N}),s.jsxs("button",{className:"button primary full",type:"submit",children:[d==="official"?"预览账号登录后的工作台":"预览配对后的工作台",s.jsx(a,{name:"arrow"})]}),s.jsx("p",{className:"prototype-note",children:"交互原型 · 不发起真实登录、配对或网络连接"})]})]})}function Ss({close:t,create:m}){const[h,k]=i.useState(""),[d,w]=i.useState("linkshell"),[u,y]=i.useState("Claude");return s.jsx(js,{title:"开始一个新任务",subtitle:"告诉 Agent 你想完成什么。",close:t,children:s.jsxs("form",{className:"new-form",onSubmit:c=>{c.preventDefault(),h.trim()&&m(h.trim(),d,u)},children:[s.jsx("label",{htmlFor:"task-prompt",children:"任务描述"}),s.jsx("textarea",{id:"task-prompt",autoFocus:!0,value:h,onChange:c=>k(c.target.value),placeholder:"例如:帮我检查这个项目的登录流程…",required:!0,rows:4}),s.jsxs("div",{className:"form-columns",children:[s.jsxs("label",{children:["项目",s.jsx(Y,{label:"项目",value:d,onValueChange:w,options:[{value:"linkshell",label:"linkshell"},{value:"itool",label:"itool"}]})]}),s.jsxs("label",{children:["Agent",s.jsx(Y,{label:"Agent",value:u,onValueChange:c=>y(c),options:[{value:"Claude",label:"Claude"},{value:"Codex",label:"Codex"}]})]})]}),s.jsxs("div",{className:"computer-inline",children:[s.jsx(a,{name:"computer"}),s.jsx("span",{children:"Studio Mac"}),s.jsx("span",{className:"online-dot"}),"演示电脑"]}),s.jsxs("button",{className:"button primary full",disabled:!h.trim(),children:["创建演示任务",s.jsx(a,{name:"arrow"})]}),s.jsx("p",{className:"prototype-note",children:"任务仅保存在本页,不会启动真实 Agent"})]})})}function Es(){const[t,m]=i.useState(U),[h,k]=i.useState(()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");i.useEffect(()=>{document.documentElement.dataset.theme=h},[h]);const[d,w]=i.useState(gs),[u,y]=i.useState(Cs),[c,E]=i.useState("home"),[N,p]=i.useState(null),[S,f]=i.useState("all"),[v,W]=i.useState(""),[_,x]=i.useState(U==="self-hosted"?"connect":null),[b,G]=i.useState("online"),[o,T]=i.useState(null),[M,J]=i.useState(!1),[q,Q]=i.useState(""),[X,xs]=i.useState([]),[L,Z]=i.useState({}),[ms,us]=i.useState({}),[ps,K]=i.useState({}),[D,z]=i.useState(""),[ss,F]=i.useState(!1),[R,es]=i.useState(!1),[O,fs]=i.useState(hs[0]),as=i.useRef(null),ns=i.useRef(null),ls=i.useRef(null),H=i.useRef(null),r=u.find(e=>e.id===c),j=b==="online",is=ms[c]??[],$=ps[c]??[],cs=u.filter(e=>e.status==="waiting"),ts=u.filter(e=>(!N||e.project===N)&&(S==="all"||e.status===S)&&`${e.title} ${e.project} ${e.agent}`.toLowerCase().includes(v.toLowerCase()));i.useEffect(()=>{const e=n=>{(n.metaKey||n.ctrlKey)&&n.key==="k"&&!document.querySelector("dialog[open]")&&(n.preventDefault(),E("home"),F(!1),requestAnimationFrame(()=>as.current?.focus()))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[]),i.useEffect(()=>{if(!D)return;const e=setTimeout(()=>z(""),3500);return()=>clearTimeout(e)},[D]),i.useEffect(()=>{H.current?.scrollTo({top:H.current.scrollHeight,behavior:"smooth"})},[c,is.length]);function g(e){E(e),F(!1),es(!1)}function rs(e,n,l){y(A=>A.map(C=>C.id===e?{...C,status:n,detail:l,time:"刚刚"}:C))}function V(e,n){us(l=>({...l,[e]:[...l[e]??[],n]}))}function P(e,n){j&&(rs(e,n?"running":"done",n?"已允许测试 · 演示运行中":"已拒绝本次测试 · 等待新指令"),V(e,{role:"assistant",text:n?"已记录允许执行。在正式连接中,这一步会交给电脑上的 Agent 继续处理。":"已记录拒绝执行。你可以补充要求,让 Agent 调整下一步计划。"}),z(n?"演示审批已通过":"演示审批已拒绝"))}function os(){if(!r||!j||!L[c]?.trim()&&!$.length)return;const e=[L[c]?.trim(),...$.map(n=>`附件:${n}(未上传)`)].filter(Boolean).join(`
1
+ import{a as i,j as s}from"./markdown-SZOrMO_3.js";import{d as U,i as gs,a as Ns,I as a,C as Y,b as bs,M as vs,o as ds,v as ks}from"./index-BcMPXmMB.js";import"./account-R7yD1rZE.js";import"./terminal-DWFexEE4.js";const Cs=[{id:"auth",title:"完善登录续期与断线恢复",project:"linkshell",agent:"Claude",status:"waiting",detail:"等待确认 · 执行连接恢复测试",time:"刚刚"},{id:"web",title:"搭建网页端的会话工作区",project:"linkshell",agent:"Codex",status:"running",detail:"正在调整会话布局与响应式样式",time:"2 分钟前"},{id:"search",title:"优化文档搜索的键盘导航",project:"itool",agent:"Claude",status:"running",detail:"正在检查焦点切换与快捷键",time:"8 分钟前"},{id:"billing",title:"修复订阅页面的状态显示",project:"itool",agent:"Codex",status:"done",detail:"已完成 · 3 个文件变更",time:"32 分钟前"},{id:"docs",title:"补充自托管网关部署说明",project:"linkshell",agent:"Claude",status:"done",detail:"已完成 · 1 个文件变更",time:"1 小时前"}],B={waiting:"需要你",running:"进行中",done:"已完成"},hs=["src/auth/session.ts","src/connection/retry.ts","test/session.test.ts"];function ws({status:t}){return s.jsxs("span",{className:`badge ${t}`,children:[s.jsx("span",{className:"status-dot"}),B[t]]})}function I({agent:t}){const m=bs[t.toLowerCase()];return s.jsx("span",{className:`agent-mark ${t.toLowerCase()} ${m.full?"full-mark":""}`,children:s.jsx("img",{src:`data:image/svg+xml,${encodeURIComponent(m.svg)}`,alt:t})})}function js({title:t,subtitle:m,children:h,close:k}){return s.jsxs(vs,{title:t,close:k,children:[m&&s.jsx("p",{className:"muted modal-subtitle",children:m}),h]})}function ys({source:t,gateway:m,onConnect:h,close:k}){const[d,w]=i.useState(t),[u,y]=i.useState(t==="self-hosted"?m:""),[c,E]=i.useState(""),[N,p]=i.useState("");function S(f){if(f.preventDefault(),d==="official")return h(d,ds);try{const v=ks(u);if(v===ds)throw new Error("这是官方网关,请选择官方服务;私有部署请填写自己的网关地址");if(!/^\d{6}$/.test(c))throw new Error("请输入 6 位配对码;原型中可填写任意 6 位数字");h(d,v)}catch(v){p(v instanceof Error?v.message:"请检查网关设置")}}return s.jsxs(js,{title:"连接你的电脑",subtitle:"选择连接方式,工作台始终属于你。",close:k,children:[U==="official"?s.jsxs("div",{className:"source-options",children:[s.jsxs("button",{className:d==="official"?"source-option selected":"source-option",onClick:()=>{w("official"),p("")},"aria-pressed":d==="official",children:[s.jsx(a,{name:"globe",size:23}),s.jsx("strong",{children:"官方服务"}),s.jsx("span",{children:"登录账号,发现你的电脑"}),s.jsx("span",{className:"selection-dot"})]}),s.jsxs("button",{className:d==="self-hosted"?"source-option selected":"source-option",onClick:()=>{w("self-hosted"),p("")},"aria-pressed":d==="self-hosted",children:[s.jsx(a,{name:"server",size:23}),s.jsx("strong",{children:"自托管网关"}),s.jsx("span",{children:"使用自己的服务器与配对码"}),s.jsx("span",{className:"selection-dot"})]})]}):s.jsxs("div",{className:"private-note",children:[s.jsx(a,{name:"server"}),s.jsxs("div",{children:[s.jsx("strong",{children:"私有部署"}),s.jsx("p",{children:"此站点使用你配置的网关,无需 iTool 账号或官方订阅。"})]})]}),s.jsxs("form",{onSubmit:S,children:[d==="official"?s.jsxs("div",{className:"official-entry",children:[s.jsx("div",{className:"entry-symbol",children:s.jsx(a,{name:"computer",size:32})}),s.jsx("h3",{children:"你的电脑,登录后就在这里"}),s.jsxs("p",{children:["电脑端运行 ",s.jsx("code",{children:"linkshell login"}),",网页使用同一 iTool 账号。电脑接入官方网关需要有效的 Pro 订阅。"]}),s.jsxs("div",{className:"endpoint",children:[s.jsx("span",{className:"status-dot"}),"gateway.itool.tech ",s.jsx("span",{children:"官方网关"})]})]}):s.jsxs("div",{className:"pairing-form",children:[s.jsx("label",{htmlFor:"gateway",children:"网关地址"}),s.jsx("input",{id:"gateway",placeholder:"wss://gateway.example.com",value:u,onChange:f=>{y(f.target.value),p("")},autoComplete:"off",spellCheck:!1,required:!0}),s.jsx("p",{className:"field-hint",children:"填写部署网关的地址,不是当前网页的地址。"}),s.jsx("label",{htmlFor:"pairing-code",children:"电脑上的配对码"}),s.jsx("input",{id:"pairing-code",className:"code-input",inputMode:"numeric",placeholder:"000000",maxLength:6,value:c,onChange:f=>{E(f.target.value.replace(/\D/g,"")),p("")},required:!0}),s.jsxs("p",{className:"field-hint",children:["电脑连接该网关后运行 ",s.jsx("code",{children:"linkshell pair"})," 获取。真实配对码 10 分钟内有效。"]}),s.jsxs("div",{className:"private-note",children:[s.jsx(a,{name:"shield"}),s.jsx("span",{children:"无需官方账号与订阅。正式版仅与指定网关交换配对信息,不向它发送 iTool 登录凭证。"})]})]}),N&&s.jsx("p",{role:"alert",className:"form-error",children:N}),s.jsxs("button",{className:"button primary full",type:"submit",children:[d==="official"?"预览账号登录后的工作台":"预览配对后的工作台",s.jsx(a,{name:"arrow"})]}),s.jsx("p",{className:"prototype-note",children:"交互原型 · 不发起真实登录、配对或网络连接"})]})]})}function Ss({close:t,create:m}){const[h,k]=i.useState(""),[d,w]=i.useState("linkshell"),[u,y]=i.useState("Claude");return s.jsx(js,{title:"开始一个新任务",subtitle:"告诉 Agent 你想完成什么。",close:t,children:s.jsxs("form",{className:"new-form",onSubmit:c=>{c.preventDefault(),h.trim()&&m(h.trim(),d,u)},children:[s.jsx("label",{htmlFor:"task-prompt",children:"任务描述"}),s.jsx("textarea",{id:"task-prompt",autoFocus:!0,value:h,onChange:c=>k(c.target.value),placeholder:"例如:帮我检查这个项目的登录流程…",required:!0,rows:4}),s.jsxs("div",{className:"form-columns",children:[s.jsxs("label",{children:["项目",s.jsx(Y,{label:"项目",value:d,onValueChange:w,options:[{value:"linkshell",label:"linkshell"},{value:"itool",label:"itool"}]})]}),s.jsxs("label",{children:["Agent",s.jsx(Y,{label:"Agent",value:u,onValueChange:c=>y(c),options:[{value:"Claude",label:"Claude"},{value:"Codex",label:"Codex"}]})]})]}),s.jsxs("div",{className:"computer-inline",children:[s.jsx(a,{name:"computer"}),s.jsx("span",{children:"Studio Mac"}),s.jsx("span",{className:"online-dot"}),"演示电脑"]}),s.jsxs("button",{className:"button primary full",disabled:!h.trim(),children:["创建演示任务",s.jsx(a,{name:"arrow"})]}),s.jsx("p",{className:"prototype-note",children:"任务仅保存在本页,不会启动真实 Agent"})]})})}function Es(){const[t,m]=i.useState(U),[h,k]=i.useState(()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");i.useEffect(()=>{document.documentElement.dataset.theme=h},[h]);const[d,w]=i.useState(gs),[u,y]=i.useState(Cs),[c,E]=i.useState("home"),[N,p]=i.useState(null),[S,f]=i.useState("all"),[v,W]=i.useState(""),[_,x]=i.useState(U==="self-hosted"?"connect":null),[b,G]=i.useState("online"),[o,T]=i.useState(null),[M,J]=i.useState(!1),[q,Q]=i.useState(""),[X,xs]=i.useState([]),[L,Z]=i.useState({}),[ms,us]=i.useState({}),[ps,K]=i.useState({}),[D,z]=i.useState(""),[ss,F]=i.useState(!1),[R,es]=i.useState(!1),[O,fs]=i.useState(hs[0]),as=i.useRef(null),ns=i.useRef(null),ls=i.useRef(null),H=i.useRef(null),r=u.find(e=>e.id===c),j=b==="online",is=ms[c]??[],$=ps[c]??[],cs=u.filter(e=>e.status==="waiting"),ts=u.filter(e=>(!N||e.project===N)&&(S==="all"||e.status===S)&&`${e.title} ${e.project} ${e.agent}`.toLowerCase().includes(v.toLowerCase()));i.useEffect(()=>{const e=n=>{(n.metaKey||n.ctrlKey)&&n.key==="k"&&!document.querySelector("dialog[open]")&&(n.preventDefault(),E("home"),F(!1),requestAnimationFrame(()=>as.current?.focus()))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[]),i.useEffect(()=>{if(!D)return;const e=setTimeout(()=>z(""),3500);return()=>clearTimeout(e)},[D]),i.useEffect(()=>{H.current?.scrollTo({top:H.current.scrollHeight,behavior:"smooth"})},[c,is.length]);function g(e){E(e),F(!1),es(!1)}function rs(e,n,l){y(A=>A.map(C=>C.id===e?{...C,status:n,detail:l,time:"刚刚"}:C))}function V(e,n){us(l=>({...l,[e]:[...l[e]??[],n]}))}function P(e,n){j&&(rs(e,n?"running":"done",n?"已允许测试 · 演示运行中":"已拒绝本次测试 · 等待新指令"),V(e,{role:"assistant",text:n?"已记录允许执行。在正式连接中,这一步会交给电脑上的 Agent 继续处理。":"已记录拒绝执行。你可以补充要求,让 Agent 调整下一步计划。"}),z(n?"演示审批已通过":"演示审批已拒绝"))}function os(){if(!r||!j||!L[c]?.trim()&&!$.length)return;const e=[L[c]?.trim(),...$.map(n=>`附件:${n}(未上传)`)].filter(Boolean).join(`
2
2
  `);V(c,{role:"user",text:e}),V(c,{role:"assistant",text:"消息已添加到本地演示会话。接入真实 Host 后,这里会显示 Agent 的实时回复。"}),Z(n=>({...n,[c]:""})),K(n=>({...n,[c]:[]})),ns.current?.focus()}return s.jsxs("div",{className:`app-shell ${ss?"nav-open":""}`,children:[ss&&s.jsx("button",{className:"nav-backdrop","aria-label":"关闭导航",onClick:()=>F(!1)}),s.jsxs("aside",{className:"sidebar",children:[s.jsxs("a",{className:"brand",href:"#",onClick:e=>{e.preventDefault(),p(null),g("home")},children:[s.jsx("img",{className:"brand-symbol",src:Ns,alt:""}),"LinkShell",s.jsx("span",{className:"brand-web",children:"web"})]}),s.jsxs("button",{className:"connection-switch",onClick:()=>x("connect"),children:[s.jsx("span",{className:`source-icon ${t}`,children:s.jsx(a,{name:t==="official"?"globe":"server"})}),s.jsxs("span",{children:[s.jsx("strong",{children:t==="official"?"官方工作空间":"自托管工作空间"}),s.jsx("small",{children:t==="official"?"iTool 账号 · 演示":"设备配对 · 演示"})]}),s.jsx(a,{name:"down",size:15})]}),s.jsxs("button",{className:"button new-task",onClick:()=>x("new"),children:[s.jsx(a,{name:"plus"}),"新建任务",s.jsx("span",{className:"new-task-corner",children:"↗"})]}),s.jsxs("nav",{"aria-label":"主导航",children:[s.jsxs("button",{className:`nav-item ${c==="home"&&!N?"active":""}`,onClick:()=>{p(null),f("all"),g("home")},children:[s.jsx(a,{name:"grid"}),"首页",s.jsx("span",{className:"nav-count",children:u.length})]}),s.jsxs("button",{className:`nav-item ${c==="computers"?"active":""}`,onClick:()=>g("computers"),children:[s.jsx(a,{name:"computer"}),"我的电脑",s.jsx("span",{className:"online-dot"})]})]}),s.jsxs("div",{className:"nav-section-label",children:["项目",s.jsx("span",{children:"2"})]}),["linkshell","itool"].map(e=>s.jsxs("div",{children:[s.jsxs("button",{className:`nav-item project-nav ${N===e&&c==="home"?"active":""}`,onClick:()=>{p(e),f("all"),g("home")},children:[s.jsx(a,{name:"folder"}),e,s.jsx(a,{name:"down",size:13})]}),s.jsx("div",{className:"recent-list",children:u.filter(n=>n.project===e).slice(0,2).map(n=>s.jsxs("button",{className:`recent-task ${c===n.id?"selected":""}`,onClick:()=>g(n.id),children:[s.jsx("span",{className:`tiny-status ${n.status}`}),s.jsx("span",{children:n.title})]},n.id))})]},e)),s.jsxs("div",{className:"sidebar-bottom",children:[s.jsxs("div",{className:"host-presence",children:[s.jsx("span",{className:j?"online-dot":"offline-dot"}),s.jsx("span",{children:"Studio Mac"}),s.jsx("small",{children:j?"演示在线":"连接待恢复"})]}),s.jsxs("button",{className:"profile-button",onClick:()=>x("connect"),children:[s.jsx("span",{className:"avatar",children:t==="official"?"L":s.jsx(a,{name:"server"})}),s.jsxs("span",{children:[s.jsx("strong",{children:t==="official"?"LinkShell 演示账号":"本浏览器"}),s.jsx("small",{children:t==="official"?"官方服务 · Pro":"自托管 · 无需官方订阅"})]}),s.jsx(a,{name:"settings",size:17})]})]})]}),s.jsxs("main",{className:"main",children:[s.jsxs("header",{className:"topbar",children:[s.jsxs("div",{className:"breadcrumbs",children:[s.jsx("button",{className:"icon-button mobile-menu",onClick:()=>F(!0),"aria-label":"打开导航",children:s.jsx(a,{name:"menu"})}),s.jsx("span",{children:"工作空间"}),s.jsx("span",{className:"breadcrumb-slash",children:"/"}),s.jsx("strong",{children:r?r.project:c==="computers"?"我的电脑":N??"概览"}),r&&s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"breadcrumb-slash",children:"/"}),s.jsx("span",{className:"breadcrumb-task",children:"会话"})]})]}),s.jsxs("div",{className:"topbar-right",children:[s.jsx("button",{className:"icon-button theme-switch","aria-label":h==="light"?"切换深色外观":"切换浅色外观",onClick:()=>k(h==="light"?"dark":"light"),children:s.jsx(a,{name:"moon"})}),s.jsxs("span",{className:"demo-tag",children:[s.jsx("span",{}),"交互原型"]}),s.jsx(Y,{label:"预览连接状态",value:b,onValueChange:e=>G(e),options:[{value:"online",label:"正常连接"},{value:"offline",label:"网络中断"},{value:"expired",label:t==="official"?"登录失效":"配对失效"},...t==="official"?[{value:"subscription",label:"Pro 到期"}]:[]]}),s.jsx("button",{className:"icon-button","aria-label":"连接设置",onClick:()=>x("connect"),children:s.jsx(a,{name:"settings"})})]})]}),b!=="online"&&s.jsxs("div",{className:`connection-banner ${b}`,role:"status",children:[s.jsx(a,{name:b==="offline"?"globe":"shield"}),s.jsx("span",{children:b==="offline"?"连接暂时中断,草稿已保留。正式版恢复连接后会自动补齐会话。":b==="subscription"?"演示:电脑的 Pro 订阅已到期,重新接入官方网关需要续订;已有记录仍可查看。":t==="official"?"演示:登录凭证已失效,需要重新登录。":"演示:此浏览器的配对已被撤销,需要重新配对。"}),s.jsx("button",{onClick:()=>b==="offline"?(G("online"),z("已恢复演示连接")):x("connect"),children:b==="offline"?"模拟恢复":"查看连接设置"})]}),!r&&c!=="computers"&&s.jsxs("div",{className:"overview page-enter",children:[s.jsxs("div",{className:"page-heading",children:[s.jsxs("div",{children:[s.jsx("h1",{children:N??"首页"}),s.jsxs("p",{className:"host-summary",children:[s.jsx("span",{className:j?"online-dot":"offline-dot"}),"Studio Mac",cs.length>0&&s.jsxs("span",{className:"waiting-copy",children:["· ",cs.length," 项需要你"]})]})]}),s.jsxs("button",{className:"button primary",onClick:()=>x("new"),children:[s.jsx(a,{name:"plus"}),"新建任务"]})]}),s.jsxs("div",{className:"home-controls",children:[s.jsxs("label",{className:"search-box",children:[s.jsx(a,{name:"search",size:18}),s.jsx("input",{ref:as,"aria-label":"搜索任务",placeholder:"搜索会话、项目或 Agent",value:v,onChange:e=>W(e.target.value)}),s.jsx("kbd",{children:"⌘ K"})]}),s.jsx("div",{className:"filters",role:"group","aria-label":"任务状态筛选",children:["all","running","waiting","done"].map(e=>s.jsx("button",{"aria-pressed":S===e,className:S===e?"selected":"",onClick:()=>f(e),children:e==="all"?"全部":B[e]},e))})]}),["waiting","running","done"].map(e=>{const n=ts.filter(l=>l.status===e);return n.length?s.jsxs("section",{className:"session-group",children:[s.jsxs("div",{className:`section-heading ${e==="waiting"?"waiting-heading":""}`,children:[s.jsxs("h2",{children:[e==="done"?"今天":B[e],s.jsx("span",{children:n.length})]}),e==="running"&&s.jsx("span",{className:"section-note",children:"Agent 正在电脑上工作"})]}),e==="waiting"?n.map(l=>s.jsxs("article",{className:"attention-card",children:[s.jsxs("button",{className:"attention-title",onClick:()=>g(l.id),children:[s.jsx(I,{agent:l.agent}),s.jsxs("span",{children:[s.jsx("strong",{children:l.title}),s.jsxs("small",{children:[l.project," · ",l.agent]})]}),s.jsx("time",{children:l.time}),s.jsx(a,{name:"chevron",size:16})]}),s.jsxs("div",{className:"permission-preview",children:[s.jsxs("div",{children:[s.jsx(a,{name:"shield",size:17}),s.jsx("strong",{children:"需要你的确认"})]}),s.jsx("code",{children:"pnpm --filter @linkshell/client-core test"})]}),s.jsxs("div",{className:"attention-actions",children:[s.jsxs("button",{className:"text-button",onClick:()=>g(l.id),children:["查看会话",s.jsx(a,{name:"chevron",size:13})]}),s.jsx("button",{className:"button secondary",disabled:!j,onClick:()=>P(l.id,!1),children:"拒绝"}),s.jsx("button",{className:"button primary",disabled:!j,onClick:()=>P(l.id,!0),children:"允许本次"})]})]},l.id)):s.jsx("div",{className:"task-list",children:n.map(l=>s.jsxs("button",{className:"task-row",onClick:()=>g(l.id),children:[s.jsxs("span",{className:"row-avatar",children:[s.jsx(I,{agent:l.agent}),s.jsx("span",{className:`tiny-status ${l.status}`})]}),s.jsxs("span",{className:"task-info",children:[s.jsx("strong",{children:l.title}),s.jsxs("span",{children:[s.jsx("span",{className:"project-label",children:l.project}),s.jsx("span",{className:"separator",children:"·"}),s.jsx("span",{className:l.status==="running"?"running-copy":"",children:l.detail})]})]}),s.jsxs("span",{className:"task-meta",children:[s.jsx("small",{children:l.time}),s.jsx("span",{children:l.agent})]}),s.jsx(a,{name:"chevron",size:14})]},l.id))})]},e):null}),!ts.length&&s.jsxs("div",{className:"empty-state",children:[s.jsx(a,{name:"search",size:28}),s.jsx("h3",{children:"没有找到会话"}),s.jsx("p",{children:"试试其他关键词或筛选条件。"}),s.jsx("button",{className:"text-button",onClick:()=>{f("all"),W("")},children:"清除筛选"})]}),s.jsxs("footer",{className:"page-footer",children:[s.jsx(a,{name:"shield",size:13}),s.jsx("span",{children:t==="official"?"官方网关 · 账号连接":"自托管网关 · 设备配对"}),s.jsx("span",{children:"演示数据"})]})]}),c==="computers"&&s.jsxs("div",{className:"overview page-enter",children:[s.jsxs("div",{className:"page-heading",children:[s.jsxs("div",{children:[s.jsx("h1",{children:"我的电脑"}),s.jsx("p",{className:"muted",children:"管理你的电脑与连接方式。"})]}),s.jsxs("button",{className:"button primary",onClick:()=>x("connect"),children:[s.jsx(a,{name:"plus"}),"连接电脑"]})]}),s.jsxs("div",{className:"connection-detail-card",children:[s.jsx("span",{className:"large-source-icon",children:s.jsx(a,{name:t==="official"?"globe":"server",size:28})}),s.jsxs("div",{children:[s.jsx("span",{className:"eyebrow",children:t==="official"?"OFFICIAL GATEWAY":"SELF-HOSTED GATEWAY"}),s.jsx("h2",{children:t==="official"?"LinkShell 官方服务":"你自己的网关"}),s.jsx("code",{children:d||"尚未设置网关"}),s.jsx("p",{className:"muted",children:t==="official"?"通过同一 iTool 账号发现电脑。电脑接入需要有效的 Pro 订阅。":"通过设备配对授权,无需官方账号或订阅。网关与数据由你管理。"})]}),s.jsx("button",{className:"button secondary",onClick:()=>x("connect"),children:"连接设置"})]}),s.jsx("div",{className:"computer-table",children:s.jsxs("div",{children:[s.jsx(a,{name:"computer",size:28}),s.jsxs("span",{children:[s.jsx("strong",{children:"Studio Mac"}),s.jsx("small",{children:"macOS · 演示电脑"})]}),s.jsxs("span",{className:`badge ${j?"running":"waiting"}`,children:[s.jsx("span",{className:"status-dot"}),j?"在线":"待恢复"]}),s.jsx("span",{className:"muted",children:t==="official"?"账号关联":"已配对(演示)"}),s.jsxs("button",{className:"button secondary",onClick:()=>{p(null),g("home")},children:["查看任务",s.jsx(a,{name:"arrow",size:16})]})]})}),s.jsxs("div",{className:"deployment-note",children:[s.jsx(a,{name:"shield"}),s.jsxs("div",{children:[s.jsx("strong",{children:"网页部署位置与网关地址是两个独立设置"}),s.jsx("p",{children:"官方网页可以连接自托管网关。私有部署默认只显示配对入口,并从公开配置读取网关地址;不依赖官方登录服务。正式版不会把官方账号凭证发送给自定义网关。"})]})]})]}),r&&s.jsxs("div",{className:"session-page page-enter",children:[s.jsxs("div",{className:"session-heading",children:[s.jsxs("div",{children:[s.jsxs("div",{className:"session-title",children:[s.jsx("h1",{children:r.title}),s.jsx(ws,{status:r.status})]}),s.jsxs("div",{className:"session-subtitle",children:[s.jsx(I,{agent:r.agent}),s.jsx("span",{children:r.agent}),s.jsx("span",{className:"separator",children:"/"}),s.jsx(a,{name:"computer",size:13}),s.jsx("span",{children:"Studio Mac"}),s.jsx("span",{className:"separator",children:"/"}),s.jsx(a,{name:"branch",size:13}),s.jsx("span",{children:"codex/session-recovery"})]})]}),s.jsxs("div",{className:"session-actions",children:[s.jsx("button",{className:`icon-button ${M?"pressed":""}`,"aria-label":"切换终端","aria-pressed":M,onClick:()=>J(!M),children:s.jsx(a,{name:"terminal"})}),s.jsx("button",{className:`icon-button ${o?"pressed":""}`,"aria-label":"切换文件面板","aria-pressed":!!o,onClick:()=>T(o?null:"changes"),children:s.jsx(a,{name:"panel"})})]})]}),s.jsxs("div",{className:`session-layout ${o?"with-panel":""}`,children:[s.jsxs("div",{className:"conversation-column",children:[s.jsxs("div",{className:"conversation",ref:H,children:[s.jsx("div",{className:"date-divider",children:s.jsx("span",{children:"今天 · 演示会话"})}),s.jsxs("div",{className:"user-message",children:[s.jsxs("span",{className:"message-label",children:["你 ",s.jsx("small",{children:"14:28"})]}),s.jsx("p",{children:r.id==="auth"?"帮我完善登录续期和断线恢复。希望登录一次之后能长期使用,临时网络失败也不要丢掉登录状态。":r.title})]}),s.jsxs("div",{className:"assistant-message",children:[s.jsxs("div",{className:"message-author",children:[s.jsx(I,{agent:r.agent}),s.jsx("strong",{children:r.agent}),s.jsx("span",{children:"14:29"})]}),r.id==="auth"?s.jsxs(s.Fragment,{children:[s.jsx("p",{children:r.id==="auth"?"我检查了当前的连接流程。问题出在刷新失败之后:临时网络错误被当成未登录处理,导致账号下的电脑暂时不可见。":"我会先梳理相关实现,确定改动范围,再逐步完成并验证。以下内容用于展示网页端的工具调用和文件变更布局。"}),s.jsx("p",{children:"这次会把登录状态和连接状态分开处理:"}),s.jsxs("ol",{className:"plan-list",children:[s.jsx("li",{children:"保留本地凭证,区分网络错误与凭证失效。"}),s.jsx("li",{children:"恢复连接时自动续期,重新订阅会话。"}),s.jsx("li",{children:"补齐断线期间的事件,避免消息重复。"})]}),s.jsxs("button",{className:"tool-call",onClick:()=>es(!R),"aria-expanded":R,children:[s.jsx("span",{className:"tool-check",children:s.jsx(a,{name:"check",size:14})}),s.jsx("span",{children:"已检查连接与会话逻辑"}),s.jsx("small",{children:"3 个文件"}),s.jsx(a,{name:R?"down":"chevron",size:14})]}),R&&s.jsxs("div",{className:"tool-output",children:[s.jsxs("code",{children:["read src/auth/session.ts",s.jsx("br",{}),"read src/connection/retry.ts",s.jsx("br",{}),"read test/session.test.ts"]}),s.jsx("p",{children:"演示工具记录,未读取或修改真实文件。"})]}),s.jsxs("div",{className:"change-summary",children:[s.jsx(a,{name:"file",size:16}),s.jsx("button",{onClick:()=>T("changes"),children:"查看 3 个文件变更"}),s.jsx("span",{className:"added",children:"+42"}),s.jsx("span",{className:"removed",children:"−12"})]}),s.jsx("p",{children:"改动已整理好,接下来需要执行测试来验证恢复流程。"}),r.status==="waiting"&&s.jsxs("div",{className:"approval-card",children:[s.jsxs("div",{className:"approval-heading",children:[s.jsx("span",{className:"approval-icon",children:s.jsx(a,{name:"shield",size:19})}),s.jsxs("div",{children:[s.jsx("strong",{children:"允许执行这条命令吗?"}),s.jsx("span",{children:"将在 Studio Mac 的 linkshell 项目中执行"})]}),s.jsx("span",{className:"badge waiting",children:"等待确认"})]}),s.jsx("pre",{children:"pnpm --filter @linkshell/client-core test"}),s.jsxs("div",{className:"approval-footer",children:[s.jsx("span",{children:"仅允许本次操作"}),s.jsx("button",{className:"button secondary",onClick:()=>P(r.id,!1),disabled:!j,children:"拒绝"}),s.jsxs("button",{className:"button primary",onClick:()=>P(r.id,!0),disabled:!j,children:[s.jsx(a,{name:"check",size:15}),"允许执行"]})]})]})]}):s.jsxs("p",{children:["这是一个本地演示会话。你可以在下方补充消息、切换文件面板或展开终端,体验工作区布局。接入 Host 后,这里会显示 ",r.agent," 的真实执行过程。"]})]}),is.map((e,n)=>s.jsxs("div",{className:e.role==="user"?"user-message":"assistant-message reply",children:[s.jsxs("span",{className:"message-label",children:[e.role==="user"?"你":r.agent,s.jsx("small",{children:"刚刚 · 本地演示"})]}),s.jsx("p",{children:e.text})]},`${c}-${n}`))]}),M&&s.jsxs("section",{className:"terminal-panel","aria-label":"演示终端",children:[s.jsxs("div",{className:"terminal-heading",children:[s.jsxs("span",{children:[s.jsx(a,{name:"terminal",size:14}),"终端",s.jsx("span",{className:"terminal-demo",children:"只演示 · 不执行命令"})]}),s.jsx("button",{className:"icon-button","aria-label":"关闭终端",onClick:()=>J(!1),children:s.jsx(a,{name:"close",size:15})})]}),s.jsxs("div",{className:"terminal-output",children:[s.jsxs("p",{children:[s.jsxs("span",{className:"terminal-green",children:["~/projects/",r.project]})," ","on"," ",s.jsx("span",{className:"terminal-blue",children:"codex/session-recovery"})]}),X.map((e,n)=>s.jsx("p",{children:e},n)),s.jsxs("form",{onSubmit:e=>{e.preventDefault(),q.trim()&&(xs([...X,`❯ ${q}`,"原型不执行命令。正式版将连接电脑上的 PTY 终端。"]),Q(""))},children:[s.jsx("span",{children:"❯"}),s.jsx("input",{"aria-label":"演示终端命令",value:q,onChange:e=>Q(e.target.value),spellCheck:!1,placeholder:"试着输入一条命令"})]})]})]}),s.jsxs("div",{className:"composer-wrap",children:[s.jsxs("div",{className:"composer",children:[$.length>0&&s.jsx("div",{className:"attachment-list",children:$.map((e,n)=>s.jsxs("span",{children:[s.jsx(a,{name:"file",size:13}),e,s.jsx("button",{"aria-label":`移除附件 ${e}`,onClick:()=>K(l=>({...l,[c]:$.filter((A,C)=>C!==n)})),children:s.jsx(a,{name:"close",size:12})})]},`${e}-${n}`))}),s.jsx("textarea",{ref:ns,"aria-label":"发送消息",value:L[c]??"",onChange:e=>Z(n=>({...n,[c]:e.target.value})),onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),os())},placeholder:j?"补充你的想法,或告诉 Agent 下一步做什么…":"连接中断也可以继续写,草稿会保留…",rows:2}),s.jsxs("div",{className:"composer-toolbar",children:[s.jsxs("div",{children:[s.jsx("input",{ref:ls,type:"file",multiple:!0,hidden:!0,onChange:e=>{const n=Array.from(e.target.files??[]).map(l=>l.name);K(l=>({...l,[c]:[...l[c]??[],...n]})),e.target.value=""}}),s.jsx("button",{className:"icon-button","aria-label":"添加演示附件",onClick:()=>ls.current?.click(),children:s.jsx(a,{name:"attach",size:17})}),s.jsxs("span",{className:"composer-agent",children:[r.agent,s.jsx("span",{className:"separator",children:"·"}),"默认模型"]})]}),s.jsxs("div",{children:[r.status==="running"&&s.jsx("button",{className:"icon-button","aria-label":"停止演示任务",disabled:!j,onClick:()=>{rs(r.id,"done","已停止 · 演示任务"),z("已停止演示任务")},children:s.jsx(a,{name:"stop",size:16})}),s.jsx("button",{className:"send-button","aria-label":"发送演示消息",disabled:!j||!L[c]?.trim()&&!$.length,onClick:os,children:s.jsx(a,{name:"send",size:19})})]})]})]}),s.jsxs("div",{className:"composer-caption",children:[s.jsx("span",{children:"Enter 发送 · Shift Enter 换行"}),s.jsx("span",{children:"演示消息不会发送到电脑"})]})]})]}),o&&s.jsxs("aside",{className:"file-panel",children:[s.jsxs("div",{className:"panel-tabs",children:[s.jsxs("button",{className:o==="changes"?"selected":"",onClick:()=>T("changes"),children:["变更",s.jsx("span",{children:"3"})]}),s.jsx("button",{className:o==="files"?"selected":"",onClick:()=>T("files"),children:"文件"}),s.jsx("button",{className:"icon-button","aria-label":"关闭文件面板",onClick:()=>T(null),children:s.jsx(a,{name:"close",size:15})})]}),s.jsxs("div",{className:"panel-project",children:[s.jsx(a,{name:"folder",size:15}),r.project,s.jsx("span",{children:"示例文件"})]}),s.jsx("div",{className:"file-list",children:hs.map((e,n)=>s.jsxs("button",{className:O===e?"selected":"",onClick:()=>fs(e),children:[s.jsx(a,{name:"file",size:14}),s.jsx("span",{children:e}),o==="changes"&&s.jsxs("small",{className:"added",children:["+",[18,16,8][n]]})]},e))}),s.jsxs("div",{className:"diff-heading",children:[s.jsx("span",{children:O.split("/").pop()}),s.jsx("span",{children:o==="changes"?"+18 −4":"TypeScript"})]}),s.jsxs("div",{className:"code-preview",children:[s.jsxs("div",{children:[s.jsx("span",{children:"01"}),s.jsx("code",{children:O.includes("test")?"it('retains the session', () => {":"async function reconnect() {"})]}),s.jsxs("div",{children:[s.jsx("span",{children:"02"}),s.jsx("code",{children:" const session = loadSession();"})]}),o==="changes"&&s.jsxs("div",{className:"diff-remove",children:[s.jsx("span",{children:"−"}),s.jsx("code",{children:" if (!token) signOut();"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"03"}),s.jsx("code",{children:" if (!session) return;"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"04"}),s.jsx("code",{children:" try {"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"05"}),s.jsx("code",{children:" await refreshSession();"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"06"}),s.jsx("code",{children:" await resumeConnection();"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"07"}),s.jsx("code",{children:" } catch (error) {"})]}),s.jsxs("div",{className:o==="changes"?"diff-add":"",children:[s.jsx("span",{children:"08"}),s.jsx("code",{children:" scheduleRetry(error);"})]}),s.jsxs("div",{children:[s.jsx("span",{children:"09"}),s.jsx("code",{children:" }"})]}),s.jsxs("div",{children:[s.jsx("span",{children:"10"}),s.jsx("code",{children:"}"})]})]}),s.jsxs("div",{className:"panel-bottom",children:[s.jsx(a,{name:"branch",size:14}),s.jsx("span",{children:"codex/session-recovery"}),s.jsx("span",{className:"added",children:"+42"}),s.jsx("span",{className:"removed",children:"−12"})]})]})]})]})]}),D&&s.jsxs("div",{className:"toast",role:"status",children:[s.jsx(a,{name:"check",size:16}),D]}),_==="connect"&&s.jsx(ys,{source:t,gateway:d,close:()=>x(null),onConnect:(e,n)=>{m(e),w(n),G("online"),x(null),z(e==="official"?"已切换到官方服务演示":"已切换到自托管演示,未发起真实配对")}}),_==="new"&&s.jsx(Ss,{close:()=>x(null),create:(e,n,l)=>{const A=crypto.randomUUID();y(C=>[{id:A,title:e,project:n,agent:l,status:"running",detail:"新建演示任务",time:"刚刚"},...C]),x(null),g(A),z("已创建本地演示任务")}})]})}export{Es as Prototype};