@teammy/server 0.1.19 → 0.1.20

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.
Binary file
@@ -6,7 +6,7 @@
6
6
  <meta name="theme-color" content="#161615" />
7
7
  <title>Teammy 工作台</title>
8
8
  <link rel="icon" type="image/png" href="./assets/teammy-favicon-BiDvlPj2.png" />
9
- <script type="module" crossorigin src="./assets/index-BRdnk3k3.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-CfWIg76q.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-Swfty9kO.css">
11
11
  </head>
12
12
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teammy/server",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "The centralized Teammy collaboration hub server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- import{C as e,E as t,F as n,I as r,J as i,M as a,N as o,P as s,Q as c,S as l,Z as u,a as d,g as f,i as p,it as ee,j as m,m as te,n as h,o as g,r as ne,rt as _,t as re,w as ie}from"./index-BRdnk3k3.js";import{t as v}from"./Markdown-2LnVpzw0.js";var y=_(),b=s(),x=e=>new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}),S=e=>e.replace(/[#*_`>]/g,``).replace(/\s+/g,` `).trim();function ae({mine:e=!1,author:t,time:n,children:r}){return(0,b.jsx)(`div`,{className:`assistant-bubble-row ${e?`mine`:``}`,children:(0,b.jsxs)(`div`,{className:`assistant-bubble`,children:[(0,b.jsxs)(`div`,{className:`assistant-bubble-meta`,children:[(0,b.jsx)(`span`,{children:t}),(0,b.jsx)(`time`,{dateTime:n,children:x(n)})]}),r]})})}function C({me:s}){let{projectId:_,request:C}=te(),w=o(),se=a(_,s,`assistant-selection`),T=a(_,s,`assistant-drafts`),ce=(0,y.useCallback)(e=>C(`agents/outbox`,d,{signal:e}),[C]),E=m(ce,3e3,a(_,s,`outbox`)),le=(0,y.useCallback)(e=>C(`agents/chats`,re,{signal:e}),[C]),D=m(le,3e3,a(_,s,`chats`)),[O,ue]=(0,y.useState)(()=>{let e=new URLSearchParams(location.search),t=e.get(`chat`);return t?`chat:${t}`:e.get(`message`)??w?.get(se)??``}),k=O.startsWith(`chat:`)?O.slice(5):``,A=!O||!!k,[j,M]=(0,y.useState)(()=>w?.get(a(_,s,`chat`,k))),N=j?.id===k?j:w?.get(a(_,s,`chat`,k)),de=D.data?.chats.find(e=>e.id===k),[fe,P]=(0,y.useState)(),[F,I]=(0,y.useState)(()=>w?.get(T)??{}),L=F[O]??``,R=e=>I(t=>({...t,[O]:e})),[z,B]=(0,y.useState)(!1),[V,H]=(0,y.useState)(!1),[pe,U]=(0,y.useState)(``),[W,G]=(0,y.useState)(``),K=(0,y.useRef)(new Map),me=(0,y.useRef)(null),q=(0,y.useRef)(!0),J=(0,y.useRef)(O);J.current=O,(0,y.useEffect)(()=>{j&&w?.set(a(_,s,`chat`,j.id),j)},[w,_,s,j]),(0,y.useEffect)(()=>{w?.set(T,F)},[w,T,F]);function Y(e){J.current=e,ue(e),w?.set(se,e);let t=new URL(location.href);e.startsWith(`chat:`)?t.searchParams.set(`chat`,e.slice(5)):t.searchParams.delete(`chat`),e&&!e.startsWith(`chat:`)&&e!==`debug`?t.searchParams.set(`message`,e):t.searchParams.delete(`message`),history.replaceState(history.state,``,t)}(0,y.useEffect)(()=>{!O&&D.data?.chats.length&&Y(`chat:${D.data.chats[0].id}`)},[O,D.data]);let X=(E.data?.messages??[]).filter(e=>e.box===`debug`).reverse(),Z=E.data?.messages.find(e=>e.id===(O===`debug`?fe:O));(0,y.useEffect)(()=>{O!==`debug`&&Z?.conversationId&&Y(`chat:${Z.conversationId}`)},[O,Z?.conversationId]);let Q=X.filter(e=>!e.readAt).map(e=>e.id).join(`,`);(0,y.useEffect)(()=>{Z&&!Z.readAt&&O!==`debug`&&C(`agents/outbox/${Z.id}/read`,g,{method:`POST`}).then(()=>{window.dispatchEvent(new Event(`teammy:outbox`)),E.reload()}).catch(e=>U(r(e)))},[Z?.id,Z?.readAt,O,C,E.reload]),(0,y.useEffect)(()=>{O===`debug`&&Q&&Promise.all(Q.split(`,`).map(e=>C(`agents/outbox/${e}/read`,g,{method:`POST`}))).then(()=>{window.dispatchEvent(new Event(`teammy:outbox`)),E.reload()}).catch(e=>U(r(e)))},[O,Q,C,E.reload]),(0,y.useEffect)(()=>{if(G(``),!k)return;let e=!0,t=-1,i=!1,o=new AbortController,l=n=>{!e||n.id!==k||n.cursor<t||(t=n.cursor,i=!0,n.redirect?Y(`chat:${n.redirect}`):(M(n),G(``)))};C(`agents/chats/${k}`,h,{signal:o.signal}).then(l).catch(t=>{e&&!o.signal.aborted&&(t instanceof n&&[401,403,404].includes(t.status)&&(w?.delete(a(_,s,`chat`,k)),M(e=>e?.id===k?void 0:e)),i||G(r(t)))});let d=n=>{let r=Number(n.lastEventId);return!e||!Number.isSafeInteger(r)||r<=t?!1:(t=r,!0)},f=new EventSource(ee(`/api/v1/projects/${encodeURIComponent(_)}/agents/chats/${encodeURIComponent(k)}/events`));f.addEventListener(`snapshot`,t=>{if(e)try{l(h.parse(JSON.parse(t.data)))}catch(e){G(r(e))}}),f.onerror=()=>{e&&G(`对话连接中断,正在重新连接…`)},f.addEventListener(`context`,e=>{if(!d(e))return;let n=h.pick({kind:!0,title:!0,status:!0,visibility:!0,participants:!0,pending:!0,hold:!0,redirect:!0}).parse(JSON.parse(e.data));n.redirect?Y(`chat:${n.redirect}`):M(e=>e?.id===k?{...e,...n,cursor:t}:e)}),f.addEventListener(`message`,e=>{if(!d(e))return;let t=ne.parse(JSON.parse(e.data));M(n=>n?.id===k?{...n,readCursor:Math.max(n.readCursor,t.seq),cursor:Math.max(n.cursor,Number(e.lastEventId)||0),messages:[...n.messages.filter(e=>e.id!==t.id),t].sort((e,t)=>e.seq-t.seq)}:n)}),f.addEventListener(`message_removed`,e=>{if(!d(e))return;let{id:n}=u({id:c()}).parse(JSON.parse(e.data));M(e=>e?.id===k?{...e,cursor:t,messages:e.messages.filter(e=>e.id!==n)}:e)}),f.addEventListener(`run`,e=>{if(!d(e))return;let t=p.parse(JSON.parse(e.data));M(n=>n?.id===k?{...n,cursor:Math.max(n.cursor,Number(e.lastEventId)||0),runs:n.runs.some(e=>e.id===t.id)?n.runs:[...n.runs,t]}:n)});for(let e of[`delta`,`reset`,`state`])f.addEventListener(e,t=>{if(!d(t))return;let n=JSON.parse(t.data);M(r=>r?.id===k?{...r,cursor:Math.max(r.cursor,Number(t.lastEventId)||0),messages:r.messages.map(t=>t.runId!==n.id||t.role!==`assistant`?t:{...t,body:e===`delta`?t.body+(n.text??``):e===`reset`?``:n.answer??t.body,state:n.state??t.state}),runs:r.runs.map(t=>t.id===n.id?{...t,answer:e===`delta`?t.answer+(n.text??``):e===`reset`?``:n.answer??t.answer,state:n.state??t.state,error:n.error===void 0?t.error:n.error}:t)}:r)});return()=>{e=!1,o.abort(),f.close()}},[_,k,s,C,w]),(0,y.useEffect)(()=>{if(!N?.kind||N.id!==k)return;let e=()=>{document.visibilityState===`visible`&&C(`agents/chats/${k}/read`,u({ok:i()}),{method:`POST`,body:{cursor:N.readCursor}}).then(()=>{D.reload(),window.dispatchEvent(new Event(`teammy:outbox`))}).catch(e=>U(r(e)))},t=setTimeout(e,300);return document.addEventListener(`visibilitychange`,e),()=>{clearTimeout(t),document.removeEventListener(`visibilitychange`,e)}},[k,N?.readCursor,N?.kind,C]),(0,y.useEffect)(()=>{q.current&&me.current?.scrollIntoView({block:`end`})},[O,j?.messages,Z?.recipients,X.length]);function he(){window.dispatchEvent(new Event(`teammy:outbox`)),E.reload()}async function $(e){if(q.current=!0,Y(e),U(``),P(void 0),e.startsWith(`chat:`)||e===`debug`)return;let t=E.data?.messages.find(t=>t.id===e)?.conversationId;if(t)Y(`chat:${t}`);else try{await C(`agents/outbox/${e}/read`,g,{method:`POST`}),he()}catch(e){U(r(e))}}async function ge(){if(!V){H(!0),U(``);try{let e=await C(`agents/chats`,h,{method:`POST`});M(e),await $(`chat:${e.id}`),D.reload()}catch(e){U(r(e))}finally{H(!1)}}}async function _e(e){e.preventDefault();let t=L.trim();if(!t||z||V)return;B(!0),U(``);let n=K.current.get(O);n&&n.text===t||(n={text:t,id:crypto.randomUUID()},K.current.set(O,n));try{if(A){let e=n.target??k;if(!e){let r=await C(`agents/chats`,h,{method:`POST`});e=r.id,n.target=e,K.current.set(`chat:${e}`,n),I(n=>({...n,[`chat:${e}`]:t})),J.current===O&&(M(r),Y(`chat:${e}`))}let r=await C(`agents/chats/${e}`,p.extend({conversationId:c().optional()}),{method:`POST`,body:{text:t,requestId:n.id}});r.conversationId&&r.conversationId!==e&&(J.current===O||J.current===`chat:${e}`)&&Y(`chat:${r.conversationId}`),M(t=>t?.id===e?{...t,runs:t.runs.some(e=>e.id===r.id)?t.runs:[...t.runs,r]}:t),D.reload()}else{let e=await C(`agents/outbox/${Z.id}/reply`,u({conversationId:c()}),{method:`POST`,body:{body:t,requestId:n.id}});he(),J.current===O&&Y(`chat:${e.conversationId}`),D.reload(),P(void 0)}K.current.delete(O),n.target&&K.current.delete(`chat:${n.target}`),I(e=>({...e,[O]:``,...n.target?{[`chat:${n.target}`]:``}:{}}))}catch(e){U(r(e))}finally{B(!1)}}let ve=A||!!Z&&!Z.archivedAt,ye=A&&!N&&(!!k||!D.data);return(0,b.jsxs)(`div`,{className:`split-layout assistant-layout`,"data-testid":`assistant-page`,children:[(0,b.jsxs)(`aside`,{className:`assistant-list`,"aria-label":`消息列表`,children:[(0,b.jsxs)(`header`,{className:`assistant-list-heading`,children:[(0,b.jsx)(`h1`,{children:`消息`}),(0,b.jsx)(e,{className:`assistant-new-chat`,icon:`plus`,label:`新建对话`,disabled:V,onClick:()=>void ge(),"data-testid":`assistant-launcher`})]}),(0,b.jsxs)(`div`,{className:`assistant-message-scroll`,children:[D.loading&&!D.data&&(0,b.jsx)(`p`,{className:`assistant-list-status`,role:`status`,children:`加载中…`}),D.data?.chats.map(e=>(0,b.jsxs)(`button`,{type:`button`,"data-testid":`assistant-chat-${e.id}`,className:`assistant-message-item assistant-chat-item ${k===e.id?`selected`:``}`,"aria-pressed":k===e.id,onClick:()=>void $(`chat:${e.id}`),children:[(0,b.jsx)(`span`,{className:`assistant-message-dot ${e.unread||e.state===`running`||e.state===`queued`?`unread`:``}`}),(0,b.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,b.jsx)(f,{selected:k===e.id,children:(0,b.jsx)(`strong`,{children:e.title})}),(0,b.jsxs)(`time`,{dateTime:e.updatedAt,children:[new Date(e.updatedAt).toLocaleDateString([],{month:`numeric`,day:`numeric`}),` `,x(e.updatedAt)]})]})]},e.id)),!!X.length&&(0,b.jsxs)(`button`,{type:`button`,"data-testid":`debug-outbox`,className:`assistant-message-item ${O===`debug`?`selected`:``}`,onClick:()=>void $(`debug`),children:[(0,b.jsx)(`span`,{className:`assistant-message-dot ${Q?`unread`:``}`}),(0,b.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,b.jsx)(f,{selected:O===`debug`,children:(0,b.jsx)(`strong`,{children:`运行提醒`})}),(0,b.jsx)(`span`,{children:S(X.at(-1).body)})]})]}),E.data?.messages.filter(e=>e.box!==`debug`&&!e.conversationId).sort((e,t)=>Number(!!e.archivedAt)-Number(!!t.archivedAt)).map(e=>(0,b.jsxs)(`button`,{type:`button`,"data-testid":`outbox-${e.id}`,className:`assistant-message-item ${e.archivedAt?`archived`:``} ${O===e.id?`selected`:``}`,onClick:()=>void $(e.id),children:[(0,b.jsx)(`span`,{className:`assistant-message-dot ${e.readAt?``:`unread`}`}),(0,b.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,b.jsx)(f,{selected:O===e.id,children:(0,b.jsx)(`strong`,{children:S(e.body)})}),(0,b.jsxs)(`time`,{dateTime:e.createdAt,children:[new Date(e.createdAt).toLocaleDateString([],{month:`numeric`,day:`numeric`}),` `,x(e.createdAt)]})]})]},e.id))]}),(0,b.jsx)(t,{error:!0,children:E.error||D.error})]}),(0,b.jsxs)(`section`,{className:`assistant-thread`,"aria-label":A?`Tim对话`:`消息内容`,children:[(0,b.jsxs)(`header`,{className:`assistant-thread-heading`,children:[(0,b.jsx)(`h2`,{children:A?de?.title??N?.title??(k?`无标题`:`Tim`):O===`debug`?`运行提醒`:`项目消息`}),N?.kind===`matter`&&(0,b.jsxs)(`span`,{className:`assistant-participants`,title:N.participants?.join(`、`),children:[N.visibility===`project`?`项目共享 · `:``,N.participants?.join(`、`)]})]}),N?.kind===`matter`&&(N.hold||N.pending||N.status===`completed`)&&(0,b.jsx)(`div`,{className:`assistant-matter-state`,role:`status`,children:N.hold?`${N.hold.scope===`all`?`已暂停`:`暂缓修改`} · ${N.hold.reason}`:N.pending?`待确认 · ${N.pending.members.join(`、`)}:${N.pending.question}`:`已完成`}),(0,b.jsxs)(`div`,{className:`assistant-transcript`,role:`log`,"aria-live":`polite`,"data-testid":`assistant-transcript`,onScroll:e=>{let t=e.currentTarget;q.current=t.scrollHeight-t.scrollTop-t.clientHeight<100},children:[A?ye?(0,b.jsxs)(`div`,{className:`assistant-empty`,"data-testid":`assistant-loading`,children:[(0,b.jsx)(ie,{}),(0,b.jsx)(`p`,{role:`status`,children:W||D.error?`暂时无法加载对话`:`加载中…`})]}):N?.messages.length?N.messages.filter(e=>e.body||[`queued`,`running`,`failed`].includes(e.state)).map(e=>(0,b.jsx)(`div`,{className:`assistant-turn`,children:(0,b.jsxs)(ae,{mine:e.role===`user`&&e.author===s,author:`${e.role===`assistant`?`Tim`:e.author}${e.source===`wecom`?` · 企业微信`:``}`,time:e.createdAt,children:[e.body&&(0,b.jsx)(`div`,{className:`markdown`,children:(0,b.jsx)(v,{children:e.body})}),e.role===`assistant`&&[`queued`,`running`].includes(e.state)&&(0,b.jsxs)(`span`,{className:`assistant-typing`,"aria-label":`正在回答`,children:[(0,b.jsx)(`i`,{}),(0,b.jsx)(`i`,{}),(0,b.jsx)(`i`,{})]}),e.state===`failed`&&(0,b.jsx)(t,{error:!0,children:N.runs.find(t=>t.id===e.runId)?.error||`本次回答未完成。`})]})},e.id)):(0,b.jsxs)(`div`,{className:`assistant-empty`,children:[(0,b.jsx)(ie,{}),(0,b.jsx)(`p`,{children:`有什么项目问题想聊聊?`})]}):!E.data&&E.loading?(0,b.jsx)(`div`,{className:`assistant-empty`,children:(0,b.jsx)(`p`,{role:`status`,children:`加载中…`})}):O===`debug`?X.map(e=>(0,b.jsx)(oe,{item:e,onReply:e.archivedAt?void 0:()=>{P(e.id),R(``),U(``)}},e.id)):Z&&(0,b.jsx)(oe,{item:Z}),(0,b.jsx)(`div`,{ref:me})]}),(0,b.jsx)(t,{error:!0,children:pe||(A?W:``)}),ve?(0,b.jsxs)(`form`,{className:`assistant-composer`,onSubmit:e=>void _e(e),children:[(0,b.jsx)(`textarea`,{value:L,disabled:V,onChange:e=>R(e.target.value),"aria-label":A?`向Tim提问`:`回复消息`,placeholder:A?`问问Tim…`:`回复…`,rows:2,onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),e.currentTarget.form?.requestSubmit())}}),(0,b.jsx)(`button`,{className:`primary assistant-send`,type:`submit`,disabled:z||V||ye||!L.trim(),"aria-label":`发送`,children:(0,b.jsx)(l,{name:`send`})})]}):O!==`debug`&&Z&&(0,b.jsxs)(`div`,{className:`assistant-archived`,children:[(0,b.jsx)(l,{name:`archive`}),`已归档`]})]})]})}function oe({item:e,onReply:t}){return(0,b.jsx)(`div`,{"data-testid":`outbox-thread-${e.id}`,children:(0,b.jsxs)(ae,{author:e.box===`debug`?`运行提醒`:`Tim`,time:e.createdAt,children:[(0,b.jsx)(`div`,{className:`markdown`,children:(0,b.jsx)(v,{children:e.body})}),t&&(0,b.jsx)(`button`,{type:`button`,className:`assistant-debug-reply`,onClick:t,children:`回复`})]})})}export{C as Assistant};
@@ -1 +0,0 @@
1
- import{A as e,C as t,D as n,E as r,I as i,M as a,P as o,S as s,T as c,_ as l,it as u,j as d,k as f,m as p,rt as m,v as h,x as g,y as _}from"./index-BRdnk3k3.js";import{t as v}from"./project-links-Dy6-B89_.js";import"./file-links-DhXbS2mn.js";var y=m(),b=o(),x=[{status:`planned`,label:`计划`},{status:`in_progress`,label:`进行中`},{status:`in_review`,label:`待验收`},{status:`completed`,label:`已完成`},{status:null,label:`未明确`}];function S({members:e,project:t}){let{request:i,projectId:o}=p(),s=(0,y.useCallback)(e=>i(`tasks`,l,{signal:e}),[i]),c=d(s,3e3,a(o,`tasks`)),[u,f]=(0,y.useState)(),m=c.data,h=new Map(e.map(e=>[e.id,e.displayName||e.id]));return(0,b.jsxs)(`div`,{className:`task-board`,children:[(0,b.jsx)(n,{title:t?.projectName.trim()?`${t.projectName.trim()}|工作看板`:`工作看板`,description:t?.description.trim()||``}),(0,b.jsx)(r,{error:!0,children:c.error}),(0,b.jsx)(`section`,{className:`task-board-lanes`,"aria-label":`任务进度`,"data-testid":`progress-board`,children:x.filter(e=>e.status!==null||m?.tasks.some(e=>e.status===null)).map(e=>{let t=m?.tasks.filter(t=>t.status===e.status)??[];return(0,b.jsxs)(`section`,{className:`task-lane`,"aria-label":e.label,"data-stage":e.status??`unknown`,children:[(0,b.jsxs)(`h2`,{children:[(0,b.jsx)(`span`,{className:`lane-dot`}),e.label,(0,b.jsx)(_,{children:m?t.length:`—`})]}),(0,b.jsx)(`div`,{className:`task-lane-content`,children:t.length?t.map(e=>(0,b.jsx)(C,{task:e,names:h,onEdit:()=>f(e),onSaved:()=>void c.reload()},e.id)):(0,b.jsx)(`p`,{className:`task-lane-empty`,children:c.error&&!m?`读取失败`:m?`暂无任务`:`读取中…`})})]},e.label)})}),u&&(0,b.jsx)(T,{task:u,onClose:()=>f(void 0),onSaved:()=>{f(void 0),c.reload()}},u.id)]})}function C({task:n,names:a,onEdit:o,onSaved:c}){let{projectId:l,request:d}=p(),m=e(),[g,_]=(0,y.useState)(!1),[x,S]=(0,y.useState)(``);async function C(){if(!g){_(!0),S(``);try{await d(`tasks/${n.id}/correction`,h,{method:`PATCH`,signal:m,body:{needsConfirmation:!1,expectedRevision:n.revision}}),m.aborted||c()}catch(e){m.aborted||S(i(e))}finally{_(!1)}}}return(0,b.jsxs)(`details`,{className:`task-card`,"data-testid":`task-card`,"data-task-id":n.id,"data-owner":n.owner,"data-status":n.status??`unknown`,children:[(0,b.jsxs)(`summary`,{className:`task-card-heading`,"data-testid":`task-toggle`,children:[(0,b.jsx)(`h3`,{children:n.title}),(0,b.jsxs)(`span`,{className:`task-card-meta`,children:[(0,b.jsx)(`small`,{children:a.get(n.owner)??n.owner}),n.needsConfirmation&&(0,b.jsxs)(`span`,{className:`task-confirmation`,"data-testid":`task-confirmation`,children:[(0,b.jsx)(s,{name:`attention`,size:`small`}),`需要确认`]})]})]}),(0,b.jsx)(t,{icon:`edit`,className:`task-card-edit`,label:`纠正任务:${n.title}`,"data-testid":`task-correct`,disabled:g,onClick:o}),(0,b.jsxs)(`div`,{className:`task-card-details`,children:[(0,b.jsx)(`h4`,{children:`目标`}),(0,b.jsx)(`p`,{children:n.goal?(0,b.jsx)(w,{value:n.goal,names:a}):`目标未明确`}),(0,b.jsx)(`h4`,{children:`当前进展`}),(0,b.jsx)(`p`,{className:`task-progress`,children:(0,b.jsx)(w,{value:n.progress,names:a})}),(0,b.jsx)(`div`,{className:`task-card-sources`,children:n.sources.map(e=>(0,b.jsxs)(`a`,{"data-testid":`task-source`,href:u(e.kind===`material`?`/projects/${l}/materials?id=${e.materialId}&revision=${e.revision}`:v(l,n.owner,e.path)),children:[(0,b.jsx)(s,{name:`file`,size:`small`}),(0,b.jsx)(`span`,{children:e.path})]},e.path))}),n.syncedAt&&(0,b.jsxs)(`small`,{children:[`资料同步于 `,(0,b.jsx)(f,{value:n.syncedAt})]}),n.needsConfirmation&&(0,b.jsxs)(`div`,{className:`task-card-confirm`,children:[(0,b.jsx)(r,{error:!0,children:x}),(0,b.jsx)(`button`,{className:`primary`,"data-testid":`task-confirm-save`,disabled:g,onClick:()=>void C(),children:g?`正在保存…`:`保存`})]})]})]})}function w({value:e,names:t}){return e.split(/(@[a-z][a-z0-9_-]*)/gi).map((e,n)=>e.startsWith(`@`)&&t.has(e.slice(1))?(0,b.jsx)(`mark`,{className:`task-mention`,children:e},n):e)}function T({task:t,onClose:n,onSaved:a}){let{request:o}=p(),s=e(),[l,u]=(0,y.useState)(t.title),[d,f]=(0,y.useState)(t.status??``),[m,_]=(0,y.useState)(t.goal??``),[v,S]=(0,y.useState)(t.progress),[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)(``),D={...l===t.title?{}:{title:l},...d===(t.status??``)?{}:{status:d||null},...m===(t.goal??``)?{}:{goal:m||null},...v===t.progress?{}:{progress:v},...t.needsConfirmation?{needsConfirmation:!1}:{}};async function O(){if(!C&&Object.keys(D).length){w(!0),E(``);try{await o(`tasks/${t.id}/correction`,h,{method:`PATCH`,signal:s,body:{...D,expectedRevision:t.revision}}),s.aborted||a()}catch(e){s.aborted||E(i(e))}finally{w(!1)}}}return(0,b.jsx)(c,{id:`task-correction`,title:`纠正任务`,onClose:n,children:(0,b.jsxs)(`form`,{className:`stack`,"aria-busy":C,onSubmit:e=>{e.preventDefault(),O()},children:[(0,b.jsx)(g,{id:`task-title`,label:`标题`,children:(0,b.jsx)(`input`,{value:l,required:!0,onChange:e=>u(e.target.value)})}),(0,b.jsxs)(`fieldset`,{className:`task-status-field`,disabled:C,children:[(0,b.jsx)(`legend`,{children:`状态`}),(0,b.jsx)(`div`,{className:`task-status-options`,"data-testid":`task-status`,children:x.filter(e=>e.status!==null).map(e=>(0,b.jsxs)(`label`,{className:`task-status-choice`,children:[(0,b.jsx)(`input`,{type:`radio`,name:`task-status`,value:e.status,checked:d===e.status,onChange:()=>f(e.status)}),(0,b.jsx)(`span`,{children:e.label})]},e.status))}),(0,b.jsx)(`small`,{children:`待验收:任务成果已提交,等待验收或最终确认。`})]}),(0,b.jsx)(g,{id:`task-goal`,label:`目标`,children:(0,b.jsx)(`textarea`,{value:m,onChange:e=>_(e.target.value)})}),(0,b.jsx)(g,{id:`task-progress`,label:`当前进展`,children:(0,b.jsx)(`textarea`,{value:v,onChange:e=>S(e.target.value)})}),(0,b.jsx)(r,{error:!0,children:T}),(0,b.jsx)(`div`,{className:`row wrap`,children:(0,b.jsx)(`button`,{type:`submit`,className:`primary`,disabled:C||!Object.keys(D).length,"data-testid":`task-correction-save`,children:`保存`})})]})})}function E({members:e,config:t}){return(0,b.jsx)(S,{members:e,project:t})}export{E as Dashboard};
@@ -1 +0,0 @@
1
- import{C as e,D as t,E as n,F as r,I as i,J as a,K as o,L as s,M as c,O as l,P as u,Q as d,S as f,V as p,X as m,Z as h,b as g,c as _,d as v,f as y,it as b,j as x,l as S,m as C,p as w,q as T,rt as E,tt as D,u as O,z as k}from"./index-BRdnk3k3.js";import{t as A}from"./Markdown-2LnVpzw0.js";import{t as j}from"./project-links-Dy6-B89_.js";import{t as M}from"./file-links-DhXbS2mn.js";import{n as N,t as P}from"./WorkspaceTree-CU784GTC.js";import{t as F}from"./HtmlPreview-C4jbdvbl.js";var I=E(),L=d().trim().min(1).max(120).refine(e=>!/[\r\n]/.test(e),`请使用一句简短的项目记忆。`),R=h({id:D(),text:L,state:o([`draft`,`kept`]),revision:m().int().positive(),createdAt:d(),updatedAt:d()}),z=h({cards:T(R)});h({id:D(),text:L}).strict(),h({expectedRevision:m().int().positive(),text:L.optional(),action:o([`keep`,`discard`,`delete`]).optional()}).strict().refine(e=>e.text!==void 0||e.action!==void 0,`没有需要保存的修改。`),h({text:L}).strict();var B=u();function V(){let{request:r,projectId:i}=C(),a=(0,I.useCallback)(e=>r(`memory`,z,{signal:e}),[r]),o=x(a,5e3,c(i,`memory`)),[l,u]=(0,I.useState)(null),[d,f]=(0,I.useState)({}),p=(0,I.useRef)(null),m=[...o.data?.cards??[]];for(let e of Object.values(d))m.some(t=>t.id===e.id)||m.push(e);if(o.data&&!p.current&&(p.current=[...m].sort((e,t)=>Number(t.state===`kept`)-Number(e.state===`kept`)).map(e=>e.id)),p.current){let e=new Map(p.current.map((e,t)=>[e,t]));for(let t of m)e.has(t.id)||(e.set(t.id,p.current.length),p.current.push(t.id));m.sort((t,n)=>e.get(t.id)-e.get(n.id))}return(0,B.jsxs)(`section`,{className:`memory-page`,children:[(0,B.jsx)(t,{title:`记忆`,children:(0,B.jsx)(e,{icon:`plus`,label:`新增记忆`,disabled:!!l,onClick:()=>u(s())})}),(0,B.jsx)(n,{error:!0,children:o.error}),!o.data&&o.loading&&(0,B.jsx)(`p`,{role:`status`,children:`加载中…`}),(0,B.jsxs)(`div`,{className:`memory-cards`,children:[l&&(0,B.jsx)(H,{id:l,onDone:()=>u(null),reload:o.reload},l),m.map(e=>(0,B.jsx)(H,{id:e.id,card:e,reload:o.reload,onEditing:t=>f(n=>{let r={...n};return t?r[e.id]=e:delete r[e.id],r})},e.id))]}),o.data&&m.length===0&&!l&&(0,B.jsx)(`p`,{className:`memory-empty`,children:`暂无记忆`})]})}function H({id:t,card:r,reload:o,onDone:s,onEditing:c}){let{request:l}=C(),[u,d]=(0,I.useState)(!r),[p,m]=(0,I.useState)(r?.text??``),[g,_]=(0,I.useState)(r?.revision),[v,y]=(0,I.useState)(!1),[b,x]=(0,I.useState)(``),S=(0,I.useRef)(!1),w=(0,I.useRef)(!1);function T(){w.current=!1,c?.(!0),m(r?.text??``),_(r?.revision),x(``),d(!0)}function E(){w.current=!0,d(!1),x(``),c?.(!1),s?.()}async function D(e){if(!S.current){if(!e&&r&&p===r.text)d(!1),c?.(!1);else if((!e||e===`keep`)&&!L.safeParse(u?p:r?.text).success)x(`请填写一句记忆,最多 120 个字符。`);else{S.current=!0,y(!0),x(``);try{r?await l(`memory/${t}`,h({saved:a()}),{method:`PATCH`,body:{expectedRevision:u?g:r.revision,...e?{action:e}:{},...u&&e!==`discard`&&e!==`delete`?{text:p}:{}}}):await l(`memory`,R,{method:`POST`,body:{id:t,text:p}}),d(!1),await o(),c?.(!1),s?.()}catch(e){x(i(e)),await o()}finally{S.current=!1,y(!1)}}}}return(0,B.jsxs)(`article`,{className:`memory-card`,"data-testid":`memory-card`,"data-memory-id":t,children:[(0,B.jsx)(`span`,{className:`memory-status ${r?.state===`kept`?`is-kept`:``}`,role:`img`,"aria-label":r?.state===`kept`?`已保留`:`待确认`,children:(0,B.jsx)(f,{name:r?.state===`kept`?`check`:`question`})}),(0,B.jsxs)(`div`,{className:`memory-content`,children:[u?(0,B.jsx)(`textarea`,{autoFocus:!0,"aria-label":`记忆内容`,value:p,maxLength:120,rows:2,disabled:v,onChange:e=>m(e.target.value.replace(/[\r\n]+/g,` `)),onBlur:e=>{w.current?w.current=!1:e.relatedTarget instanceof Element&&e.relatedTarget.closest(`.memory-actions`)||b||D()},onKeyDown:e=>{e.nativeEvent.isComposing||(e.key===`Escape`&&(e.preventDefault(),E()),e.key===`Enter`&&(e.preventDefault(),D()))}}):(0,B.jsx)(`button`,{type:`button`,className:`memory-text`,"aria-label":`编辑记忆:${r?.text??``}`,onClick:T,children:r?.text}),(0,B.jsx)(n,{error:!0,children:b})]}),(0,B.jsxs)(`div`,{className:`memory-actions`,onMouseDown:e=>{u&&e.preventDefault()},children:[(!r||r.state===`draft`)&&(0,B.jsx)(e,{icon:`check`,label:r?`保留记忆`:`保存记忆`,disabled:v,onClick:()=>void D(r?`keep`:void 0)}),u&&r?.state===`kept`&&(0,B.jsx)(e,{icon:`check`,label:`保存记忆`,disabled:v,onClick:()=>void D()}),(0,B.jsx)(e,{icon:`close`,label:r?r.state===`draft`?`舍弃记忆`:`删除记忆`:`取消新增`,disabled:v,onClick:()=>{r?D(r.state===`draft`?`discard`:`delete`):E()}})]})]})}function U(e,t){let n=t.split(`/`).slice(0,-1);return n.map((t,r)=>N(e,n.slice(0,r+1).join(`/`))).concat(N(e,``))}function W({members:t,me:i,onRefresh:a}){let{api:o,projectId:s}=C(),[c,l]=(0,I.useState)(()=>{let e=new URLSearchParams(location.search),n=e.get(`owner`),r=p.safeParse(e.get(`path`));return n&&(y(n)||t.some(e=>e.id===n))&&r.success&&!v(r.data)?{owner:n,path:r.data}:void 0}),[u,d]=(0,I.useState)(()=>new Set(c?U(c.owner,c.path):[N(i,``)])),[f,m]=(0,I.useState)(()=>c?{...c,kind:`file`}:void 0),[h,T]=(0,I.useState)(0),[E,D]=(0,I.useState)(()=>{let e=new URLSearchParams(location.search);return!c&&(e.has(`owner`)||e.has(`path`))?`文件链接不完整或目标已不可用。`:``}),A=(0,I.useCallback)(async e=>{if(c)try{return{owner:c.owner,...await o.file(c.owner,c.path,void 0,e)}}catch(e){throw e instanceof r&&e.code===`FILE_NOT_FOUND`?Error(`找不到这个文件,可能已被删除或移动。`):e}},[c?.owner,c?.path,h]),F=x(A),L=F.data?.owner===c?.owner&&F.data?.file.path===c?.path?F.data:void 0;function R(e,t){let n=t.split(`/`).filter(Boolean);d(t=>{let r=new Set(t);for(let t=0;t<=n.length;t++)r.add(N(e,n.slice(0,t).join(`/`)));return r})}function z(e,t){D(``),R(e,t.split(`/`).slice(0,-1).join(`/`)),l({owner:e,path:t}),m({owner:e,path:t,kind:`file`}),history.replaceState(null,``,b(j(s,e,t)))}function H(e){if(!c)return!1;let n=M(y(c.owner)?c.path:`${c.owner}/${c.path}`,e);if(!n)return!/^[a-z][a-z0-9+.-]*:/i.test(e)&&!e.startsWith(`//`)&&(D(`该链接超出工作区,请在原仓库查看。`),!0);if(v(n.path))return D(`配置文件不在文件浏览中显示。`),!0;let[r,...i]=n.path.split(`/`),a=t.some(e=>e.id===r),o=a?r:O(n.path)?S:_,s=a?i.join(`/`):n.path;return D(``),n.directory?(R(o,s),m({owner:o,path:s,kind:`directory`})):o===c.owner&&s===c.path?n.anchor&&[...document.querySelectorAll(`.markdown h1,.markdown h2,.markdown h3,.markdown h4`)].find(e=>e.textContent?.trim().toLowerCase().replace(/\s+/g,`-`)===n.anchor.toLowerCase())?.scrollIntoView({block:`center`}):z(o,s),!0}return(0,B.jsxs)(`div`,{className:`split-layout file-explorer`,"data-testid":`file-browser`,children:[(0,B.jsxs)(`aside`,{className:`file-tree-pane`,"aria-label":`文件资源管理器`,children:[(0,B.jsx)(w,{title:`工作区`,icon:`files`,children:(0,B.jsx)(e,{icon:`refresh`,label:`刷新文件`,"data-testid":`files-refresh`,onClick:()=>{D(``),T(e=>e+1),a()}})}),(0,B.jsx)(P,{members:t,expanded:u,selected:f,revealed:!F.loading&&!F.error&&L?{owner:L.owner,path:L.file.path,file:L.file}:void 0,onSelect:z,onToggle:(e,t)=>{m({owner:e,path:t,kind:`directory`}),d(n=>{let r=new Set(n),i=N(e,t);return r.has(i)?r.delete(i):r.add(i),r})}},h)]}),(0,B.jsx)(`section`,{className:`file-detail`,"data-testid":`file-preview`,"data-owner-id":c?.owner,"data-file-path":c?.path,"aria-label":k.filePreview,children:c?.owner===`_resources`&&c.path===`_memory/MEMORY.md`?(0,B.jsx)(V,{}):c?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(n,{error:!0,children:E||!F.loading&&F.error}),F.error&&(0,B.jsx)(`button`,{className:`file-entry-retry`,"data-testid":`files-retry`,onClick:()=>void F.reload(),children:k.retry}),F.loading?(0,B.jsx)(`p`,{className:`preview-body`,role:`status`,children:k.loading}):!F.error&&L&&(0,B.jsx)(G,{owner:L.owner,file:L.file,onLink:H},`${L.owner}:${L.file.path}:${L.file.sha256}`)]}):E?(0,B.jsx)(n,{error:!0,children:E}):(0,B.jsx)(g,{mascot:!0,title:`查看工作区文件`,description:k.pickFile})})]})}function G({owner:t,file:r,onLink:i}){let{readTextBlob:a,blobUrl:o,projectId:s}=C(),[u,d]=(0,I.useState)(!1),p=r.size>524288,m=/\.(md|markdown)$/i.test(r.path),h=/\.html?$/i.test(r.path),g=(0,I.useCallback)(e=>p?Promise.resolve(void 0):a(r,e),[r.sha256,r.size,p]),_=x(g,!1,c(s,`file-body`,r.sha256));return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`header`,{className:`file-detail-header`,children:[(0,B.jsxs)(`span`,{className:`file-detail-path`,title:`${y(t)?`workspaces`:t}/${r.path}`,children:[(0,B.jsxs)(`span`,{children:[y(t)?`workspaces`:t,` / `]}),r.path]}),(0,B.jsxs)(l,{label:`文件操作`,children:[(m||h)&&(0,B.jsx)(e,{icon:u?`preview`:`code`,label:u?`切换为预览`:`切换为原文`,"data-testid":`file-toggle-raw`,"aria-pressed":u,onClick:()=>d(!u)}),(0,B.jsx)(`a`,{className:`icon-button`,"data-testid":`file-download`,"aria-label":k.download,title:k.download,href:o(r.sha256),download:r.path.split(`/`).at(-1),children:(0,B.jsx)(f,{name:`download`})})]})]}),p?(0,B.jsx)(`div`,{className:`empty`,children:(0,B.jsx)(`p`,{children:k.previewLarge})}):_.error?(0,B.jsxs)(`div`,{className:`preview-body`,children:[(0,B.jsx)(n,{error:!0,children:_.error}),(0,B.jsx)(`button`,{"data-testid":`file-preview-retry`,onClick:()=>void _.reload(),children:k.retry})]}):_.loading?(0,B.jsx)(`p`,{className:`preview-body`,role:`status`,children:k.loading}):(0,B.jsx)(`div`,{className:`preview-body${h&&!u?` preview-body-html`:``}`,children:h&&!u?(0,B.jsx)(F,{url:o(r.sha256),name:r.path.split(`/`).at(-1)}):m&&!u?(0,B.jsx)(`article`,{className:`markdown`,"data-testid":`file-content`,"data-format":`markdown`,children:(0,B.jsx)(A,{onLink:i,children:_.data??``})}):(0,B.jsx)(`pre`,{className:`raw`,"data-testid":`file-content`,"data-format":`text`,children:_.data})})]})}export{W as Files};
@@ -1,6 +0,0 @@
1
- import{C as e,E as t,G as n,H as r,I as i,K as a,L as o,M as s,P as c,Q as l,S as u,T as d,U as f,X as p,Z as m,b as h,et as g,h as _,it as v,j as y,m as b,nt as x,p as S,q as C,rt as w,tt as T,x as E}from"./index-BRdnk3k3.js";import{n as D,r as O,t as k}from"./Markdown-2LnVpzw0.js";import{i as A,r as ee}from"./WorkspaceTree-CU784GTC.js";import{t as j}from"./HtmlPreview-C4jbdvbl.js";function M(e){return x(n,e)}var N=w(),P=l().regex(/^R\d{6,}$/),F=m({name:l().min(1),sha256:r,size:p().int().nonnegative()}),I=g().refine(e=>/^https?:\/\//i.test(e),`Use an HTTP or HTTPS URL.`);m({operationId:T(),title:l().trim().default(``),text:l().optional(),url:I.optional(),originals:C(F).default([])}).strict().refine(e=>!!e.text?.trim()||!!e.url||e.originals.length>0,`Provide text, a link or a file.`),m({expectedRevision:f,title:l().trim().min(1).optional(),url:I.nullable().optional(),content:l().optional(),summary:l().optional(),sourceVersion:l().optional(),contentDate:l().optional(),originals:C(F).optional()}).strict();var L=m({id:P,projectId:l(),title:l(),submittedBy:l(),createdAt:l(),revision:f,source:m({kind:a([`web`,`chat`,`group`]),url:l().nullable(),groupId:l().optional(),messageId:l().optional(),sourceVersion:l().optional(),contentDate:l().optional()}),originals:C(F),content:l().nullable(),summary:l().nullable(),state:a([`waiting`,`running`,`ready`,`failed`]),error:l().nullable(),url:l()}),R=m({materials:C(L),nextCursor:p().nullable()});m({query:l().trim().min(1),scope:a([`all`,`workspace`,`materials`]).default(`all`),materialId:P.optional(),originalHash:r.optional(),after:l().default(``),limit:M().int().min(1).max(200).default(30)}).strict();var z=m({items:C(m({key:l(),kind:a([`workspace`,`materials`]),title:l(),snippet:l(),url:l(),path:l()})),nextCursor:l().nullable()}),B=c();function te(e){let t=(e.content??``).trimStart().split(`
2
- `);return t[0]?.replace(/^#\s+/,``).trim()===e.title.trim()&&t[0].startsWith(`# `)&&t.shift(),t.join(`
3
- `).trimStart()}function V(){let e=new URLSearchParams(location.search),t=e.get(`id`);return t?{id:t,...e.get(`original`)?{original:e.get(`original`)}:{},...e.get(`revision`)?{revision:e.get(`revision`)}:{}}:void 0}function H(){let{request:n,projectId:r}=b(),[a,o]=(0,N.useState)(V),[c,l]=(0,N.useState)(a),[d,f]=(0,N.useState)(()=>new Set(a?[a.id]:[])),[p,m]=(0,N.useState)(!1),[g,x]=(0,N.useState)(``),[C,w]=(0,N.useState)(``),[T,E]=(0,N.useState)(``),[D,O]=(0,N.useState)([]),[j,M]=(0,N.useState)(),[P,F]=(0,N.useState)(!1),[I,z]=(0,N.useState)(``),H=(0,N.useRef)(null),U=(0,N.useCallback)(e=>n(`materials`,R,{signal:e}),[n]),W=y(U,5e3,s(r,`materials`)),G=(0,N.useCallback)(e=>a?n(`materials/${encodeURIComponent(a.id)}${a.revision?`?revision=${encodeURIComponent(a.revision)}`:``}`,L,{signal:e}):Promise.resolve(null),[n,a?.id,a?.revision]),K=y(G,5e3),q=K.data?.id===a?.id?K.data:null,J=[...new Map([...D,...W.data?.materials??[],...q?[q]:[]].map(e=>[e.id,e])).values()].sort((e,t)=>t.createdAt.localeCompare(e.createdAt)||t.id.localeCompare(e.id)),Y=j===void 0?W.data?.nextCursor:j;function X(e,t=``){o(e),l(e),w(``),E(t),m(!1),f(t=>new Set([...t,e.id])),history.replaceState(null,``,v(`/projects/${r}/materials?${new URLSearchParams({...e})}`))}(0,N.useEffect)(()=>{let e=()=>{let e=V();o(e),l(e),w(``),x(``),E(``),m(!1),e&&f(t=>new Set([...t,e.id]))};return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]);async function ae(){if(Y&&!P){F(!0),z(``);try{let e=await n(`materials?before=${Y}`,R);O(t=>[...t,...e.materials]),M(e.nextCursor)}catch(e){z(i(e))}finally{F(!1)}}}let Z=J.find(e=>e.id===c?.id),Q=Z?.originals.find(e=>e.sha256===c?.original)?.name??Z?.title??`当前资料`;function $(){l(void 0),E(``),H.current?.focus()}return(0,B.jsxs)(`div`,{className:`split-layout file-explorer session-explorer`,"data-testid":`materials-page`,children:[(0,B.jsxs)(`aside`,{className:`file-tree-pane`,"aria-label":`资料目录`,children:[(0,B.jsx)(S,{title:`资料`,icon:`materials`,children:(0,B.jsx)(e,{icon:`plus`,label:`新增资料`,onClick:()=>{m(!0),z(``)}})}),(0,B.jsx)(t,{error:!0,children:W.error||I}),W.data?J.length===0?(0,B.jsx)(`p`,{className:`tree-status`,children:`暂无资料`}):(0,B.jsx)(`div`,{role:`tree`,"aria-label":`项目资料`,onKeyDown:ee,children:J.map(e=>(0,B.jsxs)(`div`,{role:`none`,children:[(0,B.jsxs)(_,{role:`treeitem`,"aria-level":1,"aria-expanded":d.has(e.id),"aria-selected":!p&&a?.id===e.id&&!a.original,className:`tree-item tree-folder`,style:{"--tree-level":1},"data-testid":`material-folder`,title:e.title,onClick:()=>{let t=d.has(e.id);X({id:e.id}),t&&f(t=>{let n=new Set(t);return n.delete(e.id),n})},leading:(0,B.jsx)(`span`,{className:`tree-chevron ${d.has(e.id)?`expanded`:``}`,children:(0,B.jsx)(u,{name:`chevron`,size:`small`})}),children:[(0,B.jsx)(u,{name:`files`}),(0,B.jsx)(`span`,{className:`tree-name`,children:e.title})]}),d.has(e.id)&&(0,B.jsx)(`div`,{role:`group`,children:[...e.originals].sort((e,t)=>A(e.name,t.name)).map((t,n)=>(0,B.jsxs)(_,{role:`treeitem`,"aria-level":2,"aria-selected":!p&&a?.id===e.id&&a.original===t.sha256,className:`tree-item`,style:{"--tree-level":2},"data-testid":`material-original`,title:t.name,onClick:()=>X({id:e.id,original:t.sha256,...e.id===a?.id&&a.revision?{revision:a.revision}:{}}),leading:(0,B.jsx)(`span`,{className:`tree-chevron`}),children:[(0,B.jsx)(u,{name:`file`}),(0,B.jsx)(`span`,{className:`tree-name`,children:t.name})]},`${t.sha256}:${n}`))})]},e.id))}):(0,B.jsx)(`p`,{className:`tree-status`,children:`加载中…`}),Y&&(0,B.jsx)(`button`,{className:`tree-action`,disabled:P,onClick:()=>void ae(),children:P?`加载中…`:`加载更多`})]}),(0,B.jsxs)(`section`,{className:`session-reader`,"aria-label":`资料内容与搜索`,children:[(0,B.jsx)(`div`,{className:`session-reader-content`,children:p?(0,B.jsx)(ie,{onCancel:()=>m(!1),onSaved:e=>{X({id:e}),W.reload()}}):C?(0,B.jsx)(ne,{query:C,scope:c,onSelect:e=>X(e,C)},`${C}/${c?.id}/${c?.original}`):a?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(t,{error:!0,children:K.error}),q?a.original?(0,B.jsx)(re,{material:q,hash:a.original,highlight:T},`${q.id}:${a.original}`):(0,B.jsxs)(`article`,{className:`material-body`,children:[(0,B.jsx)(`h1`,{children:q.title}),a.revision&&(0,B.jsx)(`button`,{className:`material-link`,onClick:()=>X({id:a.id}),children:`查看最新内容`}),!a.revision&&(q.state===`waiting`||q.state===`running`)?(0,B.jsx)(`p`,{className:`muted`,role:`status`,children:`正在整理…`}):null,(0,B.jsx)(t,{error:!0,children:q.error??``}),!a.revision&&q.state===`failed`&&(0,B.jsx)(`button`,{onClick:()=>void n(`materials/${a.id}/retry`,L,{method:`POST`}).then(()=>K.reload()).catch(e=>z(i(e))),children:`重试整理`}),q.content?(0,B.jsx)(`div`,{className:`markdown`,children:(0,B.jsx)(k,{highlight:T,children:te(q)})}):(0,B.jsx)(`p`,{className:`muted`,children:`正文尚未整理,可以先查看左侧原件。`})]}):(0,B.jsx)(`p`,{role:`status`,children:`加载中…`})]}):(0,B.jsx)(h,{mascot:!0,title:`选择资料开始阅读`,description:`也可以在下方搜索资料内容。`})}),!p&&(0,B.jsxs)(`form`,{className:`session-search-dock`,"data-testid":`material-search-form`,onSubmit:e=>{e.preventDefault(),w(g.trim()),E(``)},children:[c&&(0,B.jsxs)(`button`,{type:`button`,className:`search-scope-chip`,title:`清除搜索范围`,"aria-label":`清除范围:${Q}`,onClick:$,children:[(0,B.jsxs)(`span`,{className:`scope-label`,children:[`搜索:`,Q]}),(0,B.jsx)(`span`,{"aria-hidden":`true`,children:`×`})]}),(0,B.jsxs)(`div`,{className:`session-search-input-row`,children:[(0,B.jsx)(`input`,{ref:H,"aria-label":`搜索资料`,placeholder:`搜索资料内容`,value:g,onChange:e=>x(e.target.value),onKeyDown:e=>{e.key===`Backspace`&&!g&&c&&(e.preventDefault(),$())}}),(C||g||T)&&(0,B.jsx)(e,{icon:`close`,label:`清空搜索`,onClick:()=>{x(``),w(``),E(``),H.current?.focus()}}),(0,B.jsx)(e,{icon:`search`,type:`submit`,label:`搜索`,disabled:!g.trim()})]})]})]})]})}function ne({query:e,scope:n,onSelect:r}){let{request:i}=b(),[a,o]=(0,N.useState)(``),s=(0,N.useCallback)(t=>i(`resources/search?${new URLSearchParams({query:e,scope:`materials`,after:a,...n?{materialId:n.id}:{},...n?.original?{originalHash:n.original}:{}})}`,z,{signal:t}),[i,e,n?.id,n?.original,a]),c=y(s);return(0,B.jsxs)(`section`,{className:`session-results stack`,"aria-label":`搜索结果`,children:[(0,B.jsx)(t,{error:!0,children:c.error}),c.loading?(0,B.jsx)(`p`,{role:`status`,children:`正在搜索…`}):c.data?.items.length===0?(0,B.jsx)(`p`,{className:`empty`,children:`没有找到匹配的资料`}):c.data?.items.map(t=>(0,B.jsxs)(`button`,{className:`session-item`,"data-testid":`material-match`,onClick:()=>{let e=new URL(t.url,location.origin).searchParams;r({id:e.get(`id`),...e.get(`original`)?{original:e.get(`original`)}:{},...e.get(`revision`)?{revision:e.get(`revision`)}:{}})},children:[(0,B.jsx)(`strong`,{children:t.title.replace(/^R\d+ · /,``)}),(0,B.jsx)(`span`,{className:`session-excerpt`,children:(0,B.jsx)(D,{value:O(t.snippet,e),query:e})})]},t.key)),c.data?.nextCursor&&(0,B.jsx)(`button`,{disabled:c.loading,onClick:()=>o(c.data.nextCursor),children:`下一页`})]})}function re({material:n,hash:r,highlight:i}){let{projectId:a}=b(),o=n.originals.find(e=>e.sha256===r),c=v(`/api/v1/projects/${a}/materials/${n.id}/originals/${r}?revision=${n.revision}`),[l,d]=(0,N.useState)(!1),f=(0,N.useCallback)(async e=>{let t=await fetch(c,{signal:e});if(!t.ok)throw Error(`原件暂时无法读取。`);let n=await t.arrayBuffer();try{let e=new TextDecoder(`utf8`,{fatal:!0}).decode(n);return e.includes(`\0`)?null:e}catch{return null}},[c]),p=y(f,!1,s(a,`material-original`,r));if(!o)return(0,B.jsx)(t,{error:!0,children:`找不到此原件。`});let m=/\.(md|markdown)$/i.test(o.name),h=/\.html?$/i.test(o.name);return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`header`,{className:`file-detail-header`,children:[(0,B.jsx)(`span`,{className:`file-detail-path`,children:o.name}),(0,B.jsxs)(`div`,{className:`toolbar-actions`,children:[(m||h)&&(0,B.jsx)(e,{icon:l?`preview`:`code`,label:l?`切换为预览`:`切换为原文`,"aria-pressed":l,onClick:()=>d(!l)}),(0,B.jsx)(`a`,{className:`icon-button`,"aria-label":`下载原件`,title:`下载原件`,href:c,download:o.name,children:(0,B.jsx)(u,{name:`download`})})]})]}),(0,B.jsx)(t,{error:!0,children:p.error}),p.loading?(0,B.jsx)(`p`,{role:`status`,children:`加载中…`}):p.data===null?(0,B.jsx)(`p`,{className:`muted`,children:`此格式请下载后查看。`}):p.data!==void 0&&(0,B.jsx)(`div`,{className:`preview-body${h&&!l?` preview-body-html`:``}`,"data-testid":`material-original-content`,children:h&&!l?(0,B.jsx)(j,{url:c,name:o.name}):m&&!l?(0,B.jsx)(`article`,{className:`markdown`,children:(0,B.jsx)(k,{highlight:i,children:p.data})}):(0,B.jsx)(`pre`,{className:`raw`,children:(0,B.jsx)(D,{value:p.data,query:i})})})]})}function U(e){if(e.kind===`text`){try{if([`http:`,`https:`].includes(new URL(e.text.trim()).protocol))return`link`}catch{}return`text`}let{name:t,type:n}=e.file;return n.startsWith(`image/`)||/\.(png|jpe?g|gif|webp|svg|heic|avif)$/i.test(t)?`imageFile`:/\.(csv|tsv|xlsx?|ods)$/i.test(t)?`spreadsheetFile`:/\.(json|ya?ml|xml|html?|css|[cm]?[jt]sx?|py|go|rs|sh|sql)$/i.test(t)?`codeFile`:n.startsWith(`text/`)||/\.(pdf|docx?|odt|rtf|md|txt)$/i.test(t)?`file`:`attachment`}function W(e){try{return new URL(e.trim()).hostname}catch{return e.trim().split(`
4
- `)[0]?.slice(0,80)||`文本`}}function G(e){try{return new URL(e.trim()).href}catch{return e.trim().split(`
5
- `).slice(1).join(`
6
- `)}}function ie({onSaved:n,onCancel:r}){let{request:a,projectId:s}=b(),[c,l]=(0,N.useState)([]),[f,p]=(0,N.useState)(),[m,h]=(0,N.useState)(!1),[g,_]=(0,N.useState)(``),y=(0,N.useRef)(null),x=(0,N.useRef)(o()),S=(0,N.useRef)(new Map);function C(e){l(e),x.current=o(),_(``)}async function w(){h(!0),_(``);try{let e=[];for(let[t,n]of c.entries()){let r=S.current.get(n.id);if(!r){let e=n.kind===`file`?n.file.name:`${W(n.text)}.txt`,i=await fetch(v(`/api/v1/projects/${s}/materials/uploads`),{method:`POST`,headers:{"content-type":`application/octet-stream`,"x-teammy-web":`1`},body:n.kind===`file`?n.file:new Blob([n.text],{type:`text/plain`})}),a=await i.json();if(!i.ok)throw Error(a.error?.message??`第 ${t+1} 项上传失败。`);r={name:e,sha256:a.sha256,size:a.size},S.current.set(n.id,r)}e.push(r)}let t=c.length===1&&c[0]?.kind===`text`?c[0].text.trim():``,r;try{let e=new URL(t);[`http:`,`https:`].includes(e.protocol)&&(r=e.href)}catch{}n((await a(`materials`,L,{method:`POST`,body:{operationId:x.current,originals:e,...r?{url:r}:{}}})).id)}catch(e){_(i(e))}finally{h(!1)}}return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`form`,{className:`material-form`,onSubmit:e=>{e.preventDefault(),w()},children:[(0,B.jsx)(`h1`,{children:`新增资料`}),(0,B.jsx)(`p`,{className:`muted`,children:`上传附件到项目,以便于Tim进行理解`}),(0,B.jsx)(t,{error:!0,children:g}),(0,B.jsxs)(`fieldset`,{disabled:m,children:[(0,B.jsxs)(`div`,{className:`attachment-grid`,children:[c.map(t=>(0,B.jsxs)(`article`,{className:`attachment-card`,"data-testid":`attachment-card`,children:[t.kind===`text`?(0,B.jsxs)(`button`,{type:`button`,className:`attachment-content`,"aria-label":`编辑:${W(t.text)}`,onClick:()=>p({id:t.id,text:t.text}),children:[(0,B.jsx)(u,{name:U(t)}),(0,B.jsx)(`span`,{className:`attachment-name`,children:W(t.text)}),G(t.text)&&(0,B.jsx)(`span`,{className:`attachment-excerpt`,children:G(t.text)})]}):(0,B.jsxs)(`div`,{className:`attachment-content`,children:[(0,B.jsx)(u,{name:U(t)}),(0,B.jsx)(`span`,{className:`attachment-name`,children:t.file.name})]}),(0,B.jsx)(e,{className:`attachment-remove`,icon:`close`,label:`移除:${t.kind===`file`?t.file.name:W(t.text)}`,onClick:()=>{S.current.delete(t.id),C(c.filter(e=>e.id!==t.id))}})]},t.id)),(0,B.jsxs)(`button`,{type:`button`,className:`attachment-add`,onClick:()=>p({text:``}),children:[(0,B.jsx)(u,{name:`addText`}),(0,B.jsx)(`span`,{children:`添加文本/链接`})]}),(0,B.jsxs)(`button`,{type:`button`,className:`attachment-add`,onClick:()=>y.current?.click(),children:[(0,B.jsx)(u,{name:`addFile`}),(0,B.jsx)(`span`,{children:`添加文件`})]})]}),(0,B.jsx)(`input`,{ref:y,type:`file`,multiple:!0,hidden:!0,"aria-label":`原始文件`,onChange:e=>{C([...c,...[...e.target.files??[]].map(e=>({id:o(),kind:`file`,file:e}))]),e.target.value=``}}),(0,B.jsxs)(`div`,{className:`actions attachment-actions`,children:[(0,B.jsx)(`button`,{type:`button`,onClick:r,children:`取消`}),(0,B.jsx)(`button`,{type:`submit`,className:`primary`,disabled:!c.length,children:m?`上传中…`:`提交资料`})]})]})]}),f&&(0,B.jsx)(d,{id:`material-text-editor`,title:`添加文本/链接`,onClose:()=>p(void 0),children:(0,B.jsxs)(`form`,{className:`stack`,onSubmit:e=>{if(e.preventDefault(),!f.text.trim())return;let t={id:f.id??o(),kind:`text`,text:f.text};S.current.delete(t.id),C(f.id?c.map(e=>e.id===f.id?t:e):[...c,t]),p(void 0)},children:[(0,B.jsx)(E,{id:`material-attachment-text`,label:`文本或链接`,children:(0,B.jsx)(`textarea`,{autoFocus:!0,rows:8,value:f.text,onChange:e=>p({...f,text:e.target.value}),placeholder:`粘贴文本或网页链接`})}),(0,B.jsx)(`div`,{className:`actions`,children:(0,B.jsx)(`button`,{type:`submit`,className:`primary`,disabled:!f.text.trim(),children:f.id?`保存`:`添加`})})]})})]})}export{H as Materials};
@@ -1 +0,0 @@
1
- import{$ as e,A as t,B as n,C as r,E as i,F as a,H as o,I as s,J as c,K as l,M as u,P as d,Q as f,R as p,S as m,U as h,W as g,X as _,Y as v,Z as y,b,h as x,it as S,j as C,k as w,m as T,p as E,q as D,rt as O,tt as k,z as A}from"./index-BRdnk3k3.js";import{n as j,r as M,t as N}from"./Markdown-2LnVpzw0.js";import{n as P}from"./project-links-Dy6-B89_.js";import{i as F,r as I}from"./WorkspaceTree-CU784GTC.js";var L=O(),R=l([`overview`,`handoff`]),z=y({title:f().trim().min(1),summary:f().trim().min(1)}).strict(),B=y({markdown:f().trim().min(1)}).strict(),V=z.extend({sourceRevision:h,sourceHash:o,generatedAt:f(),stale:c()}),H=y({kind:R,status:l([`absent`,`queued`,`running`,`succeeded`,`failed`]),available:c(),currentRevision:h,sourceRevision:h.nullable(),stale:c(),result:e([z,B]).nullable(),generatedAt:f().nullable(),error:f().nullable()}),U=l([`claude-code`,`codex`,`cursor`,`pi`,`dsh`]),W=y({formatVersion:v(1),adapterVersion:v(1),agent:U,nativeId:f().min(1).max(512),cwd:f().min(1).max(4096),messages:D(y({id:f().min(1).max(1024),role:l([`user`,`assistant`]),text:f().min(1),source:f().min(1).max(1024)}).strict())}).strict().refine(e=>new Set(e.messages.map(e=>e.id)).size===e.messages.length,`Duplicate message IDs.`);y({operationId:k(),sessionKey:o,parentRevision:h,blob:n}).strict(),y({revision:h,hash:o.nullable(),cleared:c()});var G=y({owner:g,sessionKey:o,agent:U,nativeId:f(),cwd:f(),title:f(),revision:h,updatedAt:f(),messageCount:_().int().nonnegative(),blob:n,overview:V.optional()}),K=y({sessions:D(G),nextCursor:h.nullable()}),q=y({totalSessions:_().int().nonnegative(),totalMessages:_().int().nonnegative(),memberCount:_().int().nonnegative(),updatedAt:f().nullable()});y({owner:g.optional(),sessionKey:o.optional()}).strict().refine(e=>!e.sessionKey||!!e.owner,`A session scope requires an owner.`);var J=y({matches:D(y({owner:g,sessionKey:o,revision:h,messageId:f(),source:l([`message`,`handoff`]).default(`message`),role:l([`user`,`assistant`]),snippet:f(),title:f()})),nextCursor:h.nullable()}),Y=y({owner:g,key:o,revision:h.refine(e=>e>0).optional(),messageId:f().min(1).optional(),source:l([`message`,`handoff`]).optional()});function X(e){let t=new URLSearchParams(e);if(![`owner`,`sessionKey`,`revision`,`messageId`].some(e=>t.has(e)))return{};let n=Y.safeParse({owner:t.get(`owner`),key:t.get(`sessionKey`),...t.has(`revision`)?{revision:Number(t.get(`revision`))}:{},...t.has(`messageId`)?{messageId:t.get(`messageId`)}:{},...t.has(`source`)?{source:t.get(`source`)}:{}});return n.success?{target:n.data}:{error:`对话链接不完整或已损坏。`}}var Z=d();function Q({members:e,refresh:t,selected:n,onOwner:r,onSession:i}){let[a,o]=(0,L.useState)(()=>new Set(n?.key?[n.owner]:[])),[s,c]=(0,L.useState)(e[0]?.id??``);return(0,Z.jsx)(`div`,{role:`tree`,"aria-label":`成员对话`,"data-testid":`session-tree`,onKeyDown:I,children:[...e].sort((e,t)=>F(e.id,t.id)).map(e=>(0,Z.jsxs)(`div`,{role:`none`,children:[(0,Z.jsxs)(x,{type:`button`,role:`treeitem`,"aria-level":1,"aria-expanded":a.has(e.id),"aria-selected":n?.owner===e.id&&!n.key,className:`tree-item tree-folder`,style:{"--tree-level":1},tabIndex:s===e.id?0:-1,"data-testid":`session-owner`,"data-owner-id":e.id,onFocus:()=>c(e.id),onClick:()=>{o(t=>{let n=new Set(t);return n.has(e.id)?n.delete(e.id):n.add(e.id),n}),r(e.id)},leading:(0,Z.jsx)(`span`,{className:`tree-chevron ${a.has(e.id)?`expanded`:``}`,children:(0,Z.jsx)(m,{name:`chevron`,size:`small`})}),children:[(0,Z.jsx)(m,{name:`files`}),(0,Z.jsx)(`span`,{className:`tree-name`,title:e.id,children:e.id})]}),a.has(e.id)&&(0,Z.jsx)($,{owner:e.id,selected:n,onSession:i,focused:s,onFocus:c},`${e.id}/${t}`)]},e.id))})}function $({owner:e,selected:t,onSession:n,focused:r,onFocus:a}){let{request:o,projectId:c}=T(),l=(0,L.useCallback)(t=>o(`sessions?${new URLSearchParams({owner:e,limit:`50`,order:`updated`})}`,K,{signal:t}),[e,o]),d=C(l,15e3,u(c,`session-tree`,e)),[f,h]=(0,L.useState)(),[g,_]=(0,L.useState)(!1),[v,y]=(0,L.useState)(``),b=(0,L.useRef)(null);(0,L.useEffect)(()=>()=>b.current?.abort(),[]);let S=f?f.nextCursor:d.data?.nextCursor;return(0,Z.jsxs)(`div`,{role:`group`,"aria-busy":d.loading||g,children:[(0,Z.jsx)(i,{error:!0,children:d.error||v}),d.error&&(0,Z.jsx)(`button`,{onClick:()=>void d.reload(),children:`重试`}),d.loading&&!d.data&&(0,Z.jsx)(`span`,{className:`tree-status`,role:`status`,children:`正在加载…`}),[...new Map([...f?.sessions??[],...d.data?.sessions??[]].map(e=>[e.sessionKey,e])).values()].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)||e.sessionKey.localeCompare(t.sessionKey)).map(i=>(0,Z.jsxs)(x,{type:`button`,role:`treeitem`,"aria-level":2,"aria-selected":t?.owner===e&&t.key===i.sessionKey,className:`tree-item`,style:{"--tree-level":2},tabIndex:r===`${e}/${i.sessionKey}`?0:-1,"data-testid":`session-row`,"data-owner-id":e,"data-session-key":i.sessionKey,title:p(i.title||i.nativeId),onFocus:()=>a(`${e}/${i.sessionKey}`),onClick:()=>n({owner:e,key:i.sessionKey,title:i.title||i.nativeId}),leading:(0,Z.jsx)(`span`,{className:`tree-chevron`}),children:[(0,Z.jsx)(m,{name:`sessions`}),(0,Z.jsx)(`span`,{className:`tree-name`,children:p(i.title||i.nativeId)})]},i.sessionKey)),S!=null&&(0,Z.jsx)(`button`,{className:`tree-action`,"data-testid":`session-tree-more`,disabled:g,onClick:async()=>{_(!0),y(``);let t=new AbortController;b.current=t;try{let n=await o(`sessions?${new URLSearchParams({owner:e,after:String(S),limit:`50`,order:`updated`})}`,K,{signal:t.signal});h(e=>({sessions:[...e?.sessions??[],...n.sessions],nextCursor:n.nextCursor}))}catch(e){t.signal.aborted||y(s(e))}finally{t.signal.aborted||_(!1)}},children:`加载更多`})]})}function ee({info:e,targeted:t=!1,highlight:n=``}){let[r,i]=(0,L.useState)(t),a=(0,L.useRef)(null);return(0,L.useEffect)(()=>{t&&a.current?.scrollIntoView({block:`center`})},[t]),(0,Z.jsxs)(`details`,{ref:a,open:r,className:`session-handoff`,onToggle:e=>i(e.currentTarget.open),children:[(0,Z.jsx)(`summary`,{children:`交接说明`}),r&&(0,Z.jsx)(te,{info:e,revision:t?e.revision:void 0,highlight:n})]})}function te({info:e,revision:n,highlight:r}){let{request:a}=T(),o=`sessions/${encodeURIComponent(e.owner)}/${e.sessionKey}`,c=(0,L.useCallback)(e=>a(`${o}/analysis/handoff${n===void 0?``:`?revision=${n}`}`,H,{signal:e}),[a,o,n]),l=C(c,5e3),u=t(),[d,f]=(0,L.useState)(!1),[p,m]=(0,L.useState)(``),h=l.data,g=d||h?.status===`queued`||h?.status===`running`,_=h?.result&&`markdown`in h.result?h.result.markdown:void 0;return(0,Z.jsxs)(`div`,{className:`stack`,"data-testid":`session-handoff`,children:[(0,Z.jsx)(i,{error:!0,children:p||l.error}),l.loading&&!h&&(0,Z.jsx)(`small`,{role:`status`,children:`正在加载…`}),h&&(0,Z.jsxs)(`div`,{className:`inline-actions`,children:[h.status===`failed`&&n===void 0&&(0,Z.jsx)(`button`,{"data-testid":`session-handoff-generate`,disabled:g||!h.available,onClick:async()=>{f(!0),m(``);try{await a(`${o}/handoff`,H,{method:`POST`,signal:u}),await l.reload()}catch(e){u.aborted||m(s(e))}finally{u.aborted||f(!1)}},children:g?`正在整理…`:`重试`}),!h.available&&(0,Z.jsx)(`small`,{children:`请先配置项目模型接入点`}),h.status===`failed`&&(0,Z.jsx)(`small`,{children:`整理未完成,可重试`}),h.available&&h.status!==`failed`&&(!_||h.stale||g)&&(0,Z.jsx)(`small`,{role:`status`,children:h.status===`running`||d?`正在整理…`:_?`对话已有新内容,等待自动更新…`:`等待自动整理…`}),h.currentRevision!==e.revision&&(0,Z.jsx)(`small`,{children:`交接说明使用最新对话;当前阅读的是历史原文`})]}),_&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`small`,{children:[`基于版本 `,h.sourceRevision,` · `,(0,Z.jsx)(w,{value:h.generatedAt})]}),(0,Z.jsx)(`div`,{className:`markdown`,"data-testid":`session-handoff-body`,children:(0,Z.jsx)(N,{highlight:r,children:_})})]})]})}function ne({members:e}){let{request:t,projectId:n,api:a}=T(),o=(0,L.useCallback)(async e=>{let[n,r]=await Promise.all([t(`sessions/stats`,q,{signal:e}),a.members(e)]);return{...n,members:r.members}},[t,a]),s=C(o,!0,u(n,`session-stats`)),[c,l]=(0,L.useState)(``),[d,f]=(0,L.useState)(``),[m,h]=(0,L.useState)(0),[g]=(0,L.useState)(()=>X(location.search)),[_,v]=(0,L.useState)(g.target),[y,x]=(0,L.useState)(g.target),[w,D]=(0,L.useState)(g.error??``),[O,k]=(0,L.useState)(``),j=(0,L.useRef)(null),M=_?.key?_.title?`搜索对话:${p(_.title)}`:`搜索当前对话`:_?`搜索:${_.owner} 的对话内容`:``,N=()=>{v(void 0),k(``),F(),j.current?.focus()};function F(){if(!y?.messageId)return;let{messageId:e,...t}=y;x(t),history.replaceState(null,``,S(P(n,t.owner,t.key,t)))}let I=(0,L.useCallback)(e=>{v(t=>t?.owner===e.owner&&t.key===e.sessionKey&&t.title!==e.title?{...t,title:e.title}:t)},[]);(0,L.useEffect)(()=>{let e=()=>{let e=X(location.search);x(e.target),v(e.target),D(e.error??``),f(``),l(``),k(``)};return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]);let R=(e,t=``)=>{x(e),v(e),f(``),k(t),D(``),history.replaceState(null,``,S(P(n,e.owner,e.key,e)))};return(0,Z.jsxs)(`div`,{className:`split-layout file-explorer session-explorer`,children:[(0,Z.jsxs)(`section`,{className:`file-tree-pane`,"aria-label":`${A.sessions}目录`,children:[(0,Z.jsx)(E,{title:A.sessions,icon:`sessions`,count:(0,Z.jsx)(`span`,{"data-testid":`session-total`,children:s.data?.totalSessions??`—`}),children:(0,Z.jsx)(r,{icon:`refresh`,label:`刷新${A.sessions}`,"data-testid":`sessions-refresh`,disabled:s.loading,onClick:()=>{s.reload(),h(e=>e+1)}})}),(0,Z.jsx)(i,{error:!0,children:s.error}),(0,Z.jsx)(Q,{members:(s.data?.members??e).filter(e=>e.hasSessions),refresh:m,selected:_,onOwner:e=>{v({owner:e}),x(void 0),f(``),k(``),D(``),history.replaceState(null,``,S(`/projects/${encodeURIComponent(n)}/sessions`))},onSession:R})]}),(0,Z.jsxs)(`section`,{className:`session-reader`,"aria-label":`对话内容与搜索`,children:[(0,Z.jsx)(`div`,{className:`session-reader-content`,children:w?(0,Z.jsx)(i,{error:!0,children:w}):d?(0,Z.jsx)(re,{query:d,refresh:m,scope:{..._?{owner:_.owner}:{},..._?.key?{sessionKey:_.key}:{}},onSelect:e=>R(e,d)},`${d}/${_?.owner??``}/${_?.key??``}`):y?(0,Z.jsx)(ie,{selection:y,highlight:O,onLoaded:I,onLatest:()=>R({owner:y.owner,key:y.key})},`${y.owner}/${y.key}/${y.revision}/${y.source}/${m}`):(0,Z.jsx)(b,{mascot:!0,title:`选择对话开始阅读`,description:`也可以在下方搜索会话库内容。`})}),(0,Z.jsxs)(`form`,{className:`session-search-dock`,"data-testid":`session-search-form`,onSubmit:e=>{e.preventDefault(),f(c.trim()),k(``),D(``),h(e=>e+1)},children:[_&&(0,Z.jsxs)(`button`,{type:`button`,className:`search-scope-chip`,"data-testid":`session-search-scope`,title:`清除搜索范围`,"aria-label":`清除范围:${M}`,onClick:N,children:[(0,Z.jsx)(`span`,{className:`scope-label`,children:M}),(0,Z.jsx)(`span`,{"aria-hidden":`true`,children:`×`})]}),(0,Z.jsxs)(`div`,{className:`session-search-input-row`,children:[(0,Z.jsx)(`input`,{ref:j,"aria-label":`搜索对话`,"data-testid":`session-query`,value:c,maxLength:500,placeholder:`搜索会话库内容`,onChange:e=>l(e.target.value),onKeyDown:e=>{e.key===`Backspace`&&!c&&_&&(e.preventDefault(),N())}}),(d||c||O)&&(0,Z.jsx)(r,{icon:`close`,label:`清空搜索`,"data-testid":`session-search-clear`,onClick:()=>{l(``),f(``),k(``),F(),j.current?.focus()}}),(0,Z.jsx)(r,{icon:`search`,type:`submit`,label:`搜索`,"data-testid":`session-search`,disabled:!c.trim()})]})]})]})]})}function re({query:e,refresh:t,scope:n,onSelect:r}){let{request:a}=T(),[o,s]=(0,L.useState)(0),c=(0,L.useCallback)(t=>a(`sessions/search?${new URLSearchParams({q:e,after:String(o),limit:`30`,order:`updated`,...n.owner?{owner:n.owner}:{},...n.sessionKey?{sessionKey:n.sessionKey}:{}})}`,J,{signal:t}),[a,e,o,t,n.owner,n.sessionKey]),l=C(c);return(0,Z.jsxs)(`section`,{className:`session-results stack`,"aria-label":`搜索结果`,"aria-busy":l.loading,children:[(0,Z.jsx)(i,{error:!0,children:l.error}),l.error&&(0,Z.jsx)(`button`,{onClick:()=>void l.reload(),children:`重试`}),l.loading&&(0,Z.jsx)(`p`,{role:`status`,children:`正在搜索…`}),!l.loading&&l.data?.matches.map(t=>(0,Z.jsxs)(`button`,{className:`session-item`,"data-testid":`session-match`,"data-message-id":t.messageId,onClick:()=>r({owner:t.owner,key:t.sessionKey,revision:t.revision,messageId:t.messageId||void 0,source:t.source,title:t.title}),children:[(0,Z.jsx)(`strong`,{children:p(t.title)}),(0,Z.jsxs)(`small`,{children:[t.owner,` ·`,` `,t.source===`handoff`?`交接说明`:t.role===`user`?`用户`:`助手`]}),(0,Z.jsx)(`span`,{className:`session-excerpt`,children:(0,Z.jsx)(j,{value:M(t.snippet,e),query:e})})]},`${t.owner}:${t.sessionKey}:${t.revision}:${t.source}:${t.messageId}`)),!l.loading&&l.data?.matches.length===0&&(0,Z.jsx)(`p`,{className:`empty`,children:`没有找到匹配的对话`}),l.data?.nextCursor!=null&&(0,Z.jsx)(`button`,{"data-testid":`sessions-next`,disabled:l.loading,onClick:()=>s(l.data.nextCursor),children:`下一页`}),o>0&&(0,Z.jsx)(`button`,{disabled:l.loading,onClick:()=>s(0),children:`返回第一页`})]})}function ie({selection:e,highlight:t,onLoaded:n,onLatest:r}){let{request:o}=T(),s=(0,L.useCallback)(async t=>{try{return await o(`sessions/${encodeURIComponent(e.owner)}/${e.key}${e.revision===void 0?``:`?revision=${e.revision}`}`,G,{signal:t})}catch(e){throw e instanceof a&&e.code===`SESSION_NOT_FOUND`?Error(`找不到这条对话或引用的版本,原链接可能已失效。`):e}},[o,e.owner,e.key,e.revision]),c=C(s,5e3);return(0,L.useEffect)(()=>{c.data&&n(c.data)},[c.data,n]),(0,Z.jsxs)(`section`,{className:`session-conversation stack`,"data-testid":`session-detail`,children:[(0,Z.jsx)(i,{error:!0,children:c.error}),c.error&&(0,Z.jsx)(`button`,{onClick:()=>void c.reload(),children:`重试`}),c.loading&&!c.data&&(0,Z.jsx)(`p`,{role:`status`,children:`正在读取对话…`}),c.data&&(0,Z.jsx)(ae,{info:c.data,messageId:e.messageId,handoff:e.source===`handoff`,highlight:t,pinned:e.revision!==void 0,onLatest:r},c.data.blob.sha256)]})}function ae({info:e,messageId:t,handoff:n,highlight:r,pinned:a,onLatest:o}){let{readTextBlob:s,projectId:c}=T(),l=(0,L.useCallback)(async t=>W.parse(JSON.parse(await s(e.blob,t))),[e.blob.sha256,e.blob.size]),u=C(l),d=(0,L.useRef)(null);return(0,L.useEffect)(()=>{u.data&&t&&d.current?.scrollIntoView({block:`center`})},[u.data,t]),(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`header`,{className:`conversation-header`,children:[(0,Z.jsx)(`h2`,{className:`session-title`,children:p(e.title||e.nativeId)}),(0,Z.jsxs)(`p`,{children:[e.owner,` · `,e.agent,` · `,e.messageCount,` 条消息`]}),(0,Z.jsxs)(`small`,{children:[(0,Z.jsx)(w,{value:e.updatedAt}),a&&(0,Z.jsxs)(Z.Fragment,{children:[` `,`· 引用版本 `,e.revision,` ·`,` `,(0,Z.jsx)(`a`,{href:S(P(c,e.owner,e.sessionKey)),onClick:e=>{e.preventDefault(),o()},children:`查看最新`})]})]}),e.overview&&(0,Z.jsx)(`p`,{"data-testid":`session-summary`,children:e.overview.summary}),e.overview?.stale&&(0,Z.jsx)(`small`,{children:`摘要待更新`})]}),(0,Z.jsx)(ee,{info:e,targeted:n,highlight:n?r:``}),(0,Z.jsx)(i,{error:!0,children:u.error}),u.error&&(0,Z.jsx)(`button`,{onClick:()=>void u.reload(),children:`重新读取`}),u.loading&&(0,Z.jsx)(`p`,{role:`status`,children:`正在读取对话…`}),u.data&&(0,Z.jsxs)(Z.Fragment,{children:[t&&!u.data.messages.some(e=>e.id===t)&&(0,Z.jsx)(i,{children:`该版本中找不到引用的消息,已打开对话原文。`}),(0,Z.jsx)(`div`,{className:`session-messages`,children:u.data.messages.map(e=>(0,Z.jsxs)(`article`,{className:`session-message ${e.role} ${e.id===t?`matched`:``}`,"data-testid":`session-message`,"data-message-id":e.id,ref:e.id===t?d:void 0,children:[(0,Z.jsx)(`div`,{className:`message-role`,children:e.role===`user`?`用户`:`助手`}),(0,Z.jsx)(`div`,{className:`markdown`,children:(0,Z.jsx)(N,{highlight:r,children:e.text})})]},e.id))})]})]})}export{ne as Sessions};
@@ -1 +0,0 @@
1
- import{E as e,I as t,M as n,P as r,S as i,c as a,d as o,f as s,h as c,j as l,l as u,m as d,rt as f,u as p}from"./index-BRdnk3k3.js";var m=f(),h=new Intl.Collator(`zh-CN`,{numeric:!0,sensitivity:`base`});function g(e,t){return h.compare(e,t)||(e<t?-1:+(e>t))}var _=r();function v(e){let t=e.target.closest(`[role="treeitem"]`);if(!t)return;let n=[...e.currentTarget.querySelectorAll(`[role="treeitem"]`)],r=n.indexOf(t),i=Number(t.getAttribute(`aria-level`)),a;switch(e.key){case`ArrowDown`:a=n[r+1];break;case`ArrowUp`:a=n[r-1];break;case`Home`:a=n[0];break;case`End`:a=n.at(-1);break;case`ArrowRight`:t.getAttribute(`aria-expanded`)===`false`?t.click():Number(n[r+1]?.getAttribute(`aria-level`))>i&&(a=n[r+1]);break;case`ArrowLeft`:t.getAttribute(`aria-expanded`)===`true`?t.click():a=n.slice(0,r).reverse().find(e=>Number(e.getAttribute(`aria-level`))<i);break;default:return}e.preventDefault(),a?.focus()}var y=(e,t)=>`${e}/${t}`,b=e=>({"--tree-level":e});function x({members:e,...t}){let[n,r]=(0,m.useState)(()=>{let t=e.find(e=>e.hasFiles);return`folder:${y(t?.id??`_resources`,t?``:`_memory`)}`});return(0,_.jsx)(`div`,{role:`tree`,"aria-label":`工作区文件`,"data-testid":`workspace-tree`,onKeyDown:v,children:(0,_.jsx)(C,{owner:a,path:``,level:1,members:e.filter(e=>e.hasFiles),context:{...t,focused:n,onFocus:r}})})}function S({owner:e,path:t,level:n,context:r}){let a=r.expanded.has(y(e,t)),o=`folder:${y(e,t)}`;return(0,_.jsxs)(`div`,{role:`none`,children:[(0,_.jsxs)(c,{type:`button`,role:`treeitem`,className:`tree-item tree-folder`,style:b(n),"aria-label":t||e,"aria-level":n,"aria-expanded":a,"aria-selected":r.selected?.kind===`directory`&&r.selected.owner===e&&r.selected.path===t,tabIndex:r.focused===o?0:-1,"data-testid":`directory-row`,"data-owner-id":e,"data-directory-path":t,onFocus:()=>r.onFocus(o),onClick:()=>r.onToggle(e,t),leading:(0,_.jsx)(`span`,{className:`tree-chevron ${a?`expanded`:``}`,children:(0,_.jsx)(i,{name:`chevron`,size:`small`})}),children:[(0,_.jsx)(i,{name:`files`}),(0,_.jsx)(`span`,{className:`tree-name`,children:t.split(`/`).at(-1)||e})]}),a&&(0,_.jsx)(C,{owner:e,path:t,level:n+1,context:r})]})}function C({owner:r,path:a,level:f,context:h,members:v=[]}){let{api:x,projectId:C}=d(),w=(0,m.useCallback)(e=>x.tree(r,a,void 0,``,e),[r,a]),T=l(w,!1,n(C,`file-tree`,r,a)),[E,D]=(0,m.useState)(),[O,k]=(0,m.useState)(!1),[A,j]=(0,m.useState)(``),M=(0,m.useRef)(null);(0,m.useEffect)(()=>()=>M.current?.abort(),[]);let N=E?.revision===T.data?.revision?E:void 0,P=N?N.nextCursor:T.data?.nextCursor;async function F(){if(!P||!T.data||O)return;k(!0),j(``);let e=new AbortController;M.current=e;try{let t=await x.tree(r,a,T.data.revision,P,e.signal);e.signal.aborted||D({...t,entries:[...N?.entries??[],...t.entries]})}catch(n){e.signal.aborted||j(t(n))}finally{e.signal.aborted||k(!1)}}let I=[...(T.data?.entries??[]).filter(e=>!o(e.path)),...(N?.entries??[]).filter(e=>!o(e.path))],L=h.revealed;if(L?.owner===r&&!o(L.path)&&(!a||L.path.startsWith(a+`/`))){let e=a?L.path.slice(a.length+1):L.path,t=e.indexOf(`/`),n=t<0?L.path:[a,e.slice(0,t)].filter(Boolean).join(`/`);I.some(e=>e.path===n)||I.push(t<0?{...L.file,kind:`file`}:{kind:`directory`,path:n})}let R=[...I.filter(e=>r!==`_project`||!p(e.path)).map(e=>({...e,owner:r})),...r===`_project`&&!a?[{kind:`directory`,path:`_memory`,owner:u}]:[],...v.map(e=>({kind:`directory`,path:``,owner:e.id}))].sort((e,t)=>e.kind===t.kind?g(e.path.split(`/`).at(-1)||e.owner,t.path.split(`/`).at(-1)||t.owner):e.kind===`directory`?-1:1);return(0,_.jsxs)(`div`,{role:`group`,"aria-label":y(s(r)?`workspaces`:r,a),"aria-busy":T.loading||O,children:[T.loading&&(0,_.jsx)(`p`,{className:`tree-status`,role:`status`,children:`正在加载…`}),(0,_.jsx)(e,{error:!0,children:T.error||A}),T.error&&(0,_.jsx)(`button`,{className:`tree-action`,onClick:()=>void T.reload(),children:`重试`}),R.map(e=>e.kind===`directory`?(0,_.jsx)(S,{owner:e.owner,path:e.path,level:f,context:h},y(e.owner,e.path)):(0,_.jsxs)(c,{type:`button`,role:`treeitem`,className:`tree-item`,style:b(f),"aria-label":e.path,"aria-level":f,"aria-selected":h.selected?.kind===`file`&&h.selected.owner===r&&h.selected.path===e.path,tabIndex:h.focused===`file:${y(r,e.path)}`?0:-1,"data-testid":`file-row`,"data-owner-id":r,"data-file-path":e.path,onFocus:()=>h.onFocus(`file:${y(r,e.path)}`),onClick:()=>h.onSelect(r,e.path),leading:(0,_.jsx)(`span`,{className:`tree-chevron`}),children:[(0,_.jsx)(i,{name:`file`}),(0,_.jsx)(`span`,{className:`tree-name`,children:e.path.split(`/`).at(-1)})]},e.path)),P&&(0,_.jsx)(`button`,{className:`tree-action`,"data-testid":`files-load-more`,disabled:O,onClick:()=>void F(),children:O?`正在加载…`:`加载更多`})]})}export{g as i,y as n,v as r,x as t};