@teammy/server 0.1.12 → 0.1.13

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.
@@ -0,0 +1 @@
1
+ function e(e,t,n){return`/projects/${encodeURIComponent(e)}/files?${new URLSearchParams({owner:t,path:n})}`}function t(e,t,n,r={}){let i=new URLSearchParams({owner:t,sessionKey:n});return r.revision!==void 0&&i.set(`revision`,String(r.revision)),r.source===`handoff`?i.set(`source`,`handoff`):r.messageId&&i.set(`messageId`,r.messageId),`/projects/${encodeURIComponent(e)}/sessions?${i}`}export{t as n,e as t};
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-BW6ule39.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-BTcnf4jy.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-A_XSN_Cz.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.12",
3
+ "version": "0.1.13",
4
4
  "description": "The centralized Teammy collaboration hub server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- import{$ as e,A as t,C as n,D as r,E as i,M as a,O as o,S as s,T as c,_ as l,et as u,h as d,m as f,p,u as m,v as h,x as g,y as _}from"./index-BW6ule39.js";import{t as v}from"./project-links-XbF78Bal.js";import"./file-links-BHeuStKI.js";var y=e(),b=t(),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:a}=m(),c=(0,y.useCallback)(e=>i(`tasks`,p,{signal:e}),[i]),l=r(c,3e3,o(a,`tasks`)),[u,f]=(0,y.useState)(),h=l.data,g=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)(s,{error:!0,children:l.error}),(0,b.jsx)(`section`,{className:`task-board-lanes`,"aria-label":`任务进度`,"data-testid":`progress-board`,children:x.filter(e=>e.status!==null||h?.tasks.some(e=>e.status===null)).map(e=>{let t=h?.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)(d,{children:h?t.length:`—`})]}),(0,b.jsx)(`div`,{className:`task-lane-content`,children:t.length?t.map(e=>(0,b.jsx)(C,{task:e,names:g,onEdit:()=>f(e),onSaved:()=>void l.reload()},e.id)):(0,b.jsx)(`p`,{className:`task-lane-empty`,children:l.error&&!h?`读取失败`:h?`暂无任务`:`读取中…`})})]},e.label)})}),u&&(0,b.jsx)(T,{task:u,onClose:()=>f(void 0),onSaved:()=>{f(void 0),l.reload()}},u.id)]})}function C({task:e,names:t,onEdit:n,onSaved:r}){let{projectId:o,request:l}=m(),d=i(),[p,g]=(0,y.useState)(!1),[x,S]=(0,y.useState)(``);async function C(){if(!p){g(!0),S(``);try{await l(`tasks/${e.id}/correction`,f,{method:`PATCH`,signal:d,body:{needsConfirmation:!1,expectedRevision:e.revision}}),d.aborted||r()}catch(e){d.aborted||S(a(e))}finally{g(!1)}}}return(0,b.jsxs)(`details`,{className:`task-card`,"data-testid":`task-card`,"data-task-id":e.id,"data-owner":e.owner,"data-status":e.status??`unknown`,children:[(0,b.jsxs)(`summary`,{className:`task-card-heading`,"data-testid":`task-toggle`,children:[(0,b.jsx)(`h3`,{children:e.title}),(0,b.jsxs)(`span`,{className:`task-card-meta`,children:[(0,b.jsx)(`small`,{children:t.get(e.owner)??e.owner}),e.needsConfirmation&&(0,b.jsxs)(`span`,{className:`task-confirmation`,"data-testid":`task-confirmation`,children:[(0,b.jsx)(h,{name:`attention`,size:`small`}),`需要确认`]})]})]}),(0,b.jsx)(_,{icon:`edit`,className:`task-card-edit`,label:`纠正任务:${e.title}`,"data-testid":`task-correct`,disabled:p,onClick:n}),(0,b.jsxs)(`div`,{className:`task-card-details`,children:[e.corrected&&!e.needsConfirmation&&(0,b.jsx)(`small`,{children:`已确认`}),e.needsReview&&(0,b.jsx)(`p`,{children:`本次整理未能明确对应,请核对来源。`}),(0,b.jsx)(`h4`,{children:`目标`}),(0,b.jsx)(`p`,{children:e.goal?(0,b.jsx)(w,{value:e.goal,names:t}):`目标未明确`}),(0,b.jsx)(`h4`,{children:`当前进展`}),(0,b.jsx)(`p`,{className:`task-progress`,children:(0,b.jsx)(w,{value:e.progress,names:t})}),(0,b.jsx)(`div`,{className:`task-card-sources`,children:e.sources.map(t=>(0,b.jsxs)(`a`,{"data-testid":`task-source`,href:u(t.kind===`material`?`/projects/${o}/materials?id=${t.materialId}&revision=${t.revision}`:v(o,e.owner,t.path)),children:[(0,b.jsx)(h,{name:`file`,size:`small`}),(0,b.jsx)(`span`,{children:t.path})]},t.path))}),e.syncedAt&&(0,b.jsxs)(`small`,{children:[`资料同步于 `,(0,b.jsx)(c,{value:e.syncedAt})]}),e.needsConfirmation&&(0,b.jsxs)(`div`,{className:`task-card-confirm`,children:[(0,b.jsx)(s,{error:!0,children:x}),(0,b.jsx)(`button`,{className:`primary`,"data-testid":`task-confirm-save`,disabled:p,onClick:()=>void C(),children:p?`正在保存…`:`保存`})]})]})]})}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:e,onClose:t,onSaved:n}){let{request:r}=m(),o=i(),[c,u]=(0,y.useState)(e.title),[d,p]=(0,y.useState)(e.status??``),[h,_]=(0,y.useState)(e.goal??``),[v,S]=(0,y.useState)(e.progress),[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)(``),D={...c===e.title?{}:{title:c},...d===(e.status??``)?{}:{status:d||null},...h===(e.goal??``)?{}:{goal:h||null},...v===e.progress?{}:{progress:v},...e.needsConfirmation?{needsConfirmation:!1}:{}};async function O(t=!1){if(!(C||!t&&!Object.keys(D).length)){w(!0),E(``);try{await r(`tasks/${e.id}/correction`,f,{method:t?`DELETE`:`PATCH`,signal:o,...t?{}:{body:{...D,expectedRevision:e.revision}}}),o.aborted||n()}catch(e){o.aborted||E(a(e))}finally{w(!1)}}}return(0,b.jsx)(g,{id:`task-correction`,title:`纠正任务`,onClose:t,children:(0,b.jsxs)(`form`,{className:`stack`,"aria-busy":C,onSubmit:e=>{e.preventDefault(),O()},children:[(0,b.jsx)(l,{id:`task-title`,label:`标题`,children:(0,b.jsx)(`input`,{value:c,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:()=>p(e.status)}),(0,b.jsx)(`span`,{children:e.label})]},e.status))})]}),(0,b.jsx)(l,{id:`task-goal`,label:`目标`,children:(0,b.jsx)(`textarea`,{value:h,onChange:e=>_(e.target.value)})}),(0,b.jsx)(l,{id:`task-progress`,label:`当前进展`,children:(0,b.jsx)(`textarea`,{value:v,onChange:e=>S(e.target.value)})}),(0,b.jsx)(s,{error:!0,children:T}),(0,b.jsxs)(`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:`保存`}),e.corrected&&e.jobId&&(0,b.jsx)(`button`,{type:`button`,disabled:C,"data-testid":`task-correction-reset`,onClick:()=>void O(!0),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{$ as e,A as t,B as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,M as d,O as f,P as p,R as m,S as h,T as g,U as _,W as v,Y as y,Z as b,d as x,et as S,g as C,j as w,l as T,q as E,u as D,v as O,y as k,z as A}from"./index-BW6ule39.js";import{n as j,r as M,t as N}from"./Markdown-SFOHcUZw.js";import{n as P}from"./project-links-XbF78Bal.js";import{i as F,r as I}from"./WorkspaceTree-B7mZepdd.js";var L=e(),R=s([`overview`,`handoff`]),z=E({title:l().trim().min(1),summary:l().trim().min(1)}).strict(),B=E({markdown:l().trim().min(1)}).strict(),V=z.extend({sourceRevision:A,sourceHash:m,generatedAt:l(),stale:v()}),H=E({kind:R,status:s([`absent`,`queued`,`running`,`succeeded`,`failed`]),available:v(),currentRevision:A,sourceRevision:A.nullable(),stale:v(),result:y([z,B]).nullable(),generatedAt:l().nullable(),error:l().nullable()}),U=s([`claude-code`,`codex`,`cursor`,`pi`,`dsh`]),W=E({formatVersion:o(1),adapterVersion:o(1),agent:U,nativeId:l().min(1).max(512),cwd:l().min(1).max(4096),messages:_(E({id:l().min(1).max(1024),role:s([`user`,`assistant`]),text:l().min(1),source:l().min(1).max(1024)}).strict())}).strict().refine(e=>new Set(e.messages.map(e=>e.id)).size===e.messages.length,`Duplicate message IDs.`);E({operationId:b(),sessionKey:m,parentRevision:A,blob:c}).strict(),E({revision:A,hash:m.nullable(),cleared:v()});var G=E({owner:n,sessionKey:m,agent:U,nativeId:l(),cwd:l(),title:l(),revision:A,updatedAt:l(),messageCount:u().int().nonnegative(),blob:c,overview:V.optional()}),K=E({sessions:_(G),nextCursor:A.nullable()}),q=E({totalSessions:u().int().nonnegative(),totalMessages:u().int().nonnegative(),memberCount:u().int().nonnegative(),updatedAt:l().nullable()});E({owner:n.optional(),sessionKey:m.optional()}).strict().refine(e=>!e.sessionKey||!!e.owner,`A session scope requires an owner.`);var J=E({matches:_(E({owner:n,sessionKey:m,revision:A,messageId:l(),role:s([`user`,`assistant`]),snippet:l(),title:l()})),nextCursor:A.nullable()}),Y=E({owner:n,key:m,revision:A.refine(e=>e>0).optional(),messageId:l().min(1).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`)}:{}});return n.success?{target:n.data}:{error:`对话链接不完整或已损坏。`}}var Z=t();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)(O,{name:`chevron`,size:`small`})}),children:[(0,Z.jsx)(O,{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:i,onFocus:a}){let{request:o,projectId:s}=D(),c=(0,L.useCallback)(t=>o(`sessions?${new URLSearchParams({owner:e,limit:`50`,order:`updated`})}`,K,{signal:t}),[e,o]),l=r(c,15e3,f(s,`session-tree`,e)),[u,m]=(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=u?u.nextCursor:l.data?.nextCursor;return(0,Z.jsxs)(`div`,{role:`group`,"aria-busy":l.loading||g,children:[(0,Z.jsx)(h,{error:!0,children:l.error||v}),l.error&&(0,Z.jsx)(`button`,{onClick:()=>void l.reload(),children:`重试`}),l.loading&&!l.data&&(0,Z.jsx)(`span`,{className:`tree-status`,role:`status`,children:`正在加载…`}),[...new Map([...u?.sessions??[],...l.data?.sessions??[]].map(e=>[e.sessionKey,e])).values()].sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt)||e.sessionKey.localeCompare(t.sessionKey)).map(r=>(0,Z.jsxs)(x,{type:`button`,role:`treeitem`,"aria-level":2,"aria-selected":t?.owner===e&&t.key===r.sessionKey,className:`tree-item`,style:{"--tree-level":2},tabIndex:i===`${e}/${r.sessionKey}`?0:-1,"data-testid":`session-row`,"data-owner-id":e,"data-session-key":r.sessionKey,title:p(r.title||r.nativeId),onFocus:()=>a(`${e}/${r.sessionKey}`),onClick:()=>n({owner:e,key:r.sessionKey,title:r.title||r.nativeId}),leading:(0,Z.jsx)(`span`,{className:`tree-chevron`}),children:[(0,Z.jsx)(O,{name:`sessions`}),(0,Z.jsx)(`span`,{className:`tree-name`,children:p(r.title||r.nativeId)})]},r.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});m(e=>({sessions:[...e?.sessions??[],...n.sessions],nextCursor:n.nextCursor}))}catch(e){t.signal.aborted||y(d(e))}finally{t.signal.aborted||_(!1)}},children:`加载更多`})]})}function ee({info:e}){let[t,n]=(0,L.useState)(!1);return(0,Z.jsxs)(`details`,{className:`session-handoff`,onToggle:e=>n(e.currentTarget.open),children:[(0,Z.jsx)(`summary`,{children:`交接说明`}),t&&(0,Z.jsx)(te,{info:e})]})}function te({info:e}){let{request:t}=D(),n=`sessions/${encodeURIComponent(e.owner)}/${e.sessionKey}`,a=(0,L.useCallback)(e=>t(`${n}/analysis/handoff`,H,{signal:e}),[t,n]),o=r(a,5e3),s=i(),[c,l]=(0,L.useState)(!1),[u,f]=(0,L.useState)(``),p=o.data,m=c||p?.status===`queued`||p?.status===`running`,_=p?.result&&`markdown`in p.result?p.result.markdown:void 0;return(0,Z.jsxs)(`div`,{className:`stack`,"data-testid":`session-handoff`,children:[(0,Z.jsx)(h,{error:!0,children:u||o.error}),p&&(0,Z.jsxs)(`div`,{className:`inline-actions`,children:[(!_||p.stale)&&(0,Z.jsx)(`button`,{"data-testid":`session-handoff-generate`,disabled:m||!p.available,onClick:async()=>{l(!0),f(``);try{await t(`${n}/handoff`,H,{method:`POST`,signal:s}),await o.reload()}catch(e){s.aborted||f(d(e))}finally{s.aborted||l(!1)}},children:m?`正在整理…`:p.status===`failed`?`重新生成`:_?`更新交接说明`:`生成交接说明`}),!p.available&&(0,Z.jsx)(`small`,{children:`请先配置项目模型接入点`}),p.status===`failed`&&(0,Z.jsx)(`small`,{children:`整理未完成,可重试`}),p.stale&&(0,Z.jsx)(`small`,{children:`对话已有新内容`}),p.currentRevision!==e.revision&&(0,Z.jsx)(`small`,{children:`交接说明使用最新对话;当前阅读的是历史原文`})]}),_&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsxs)(`small`,{children:[`基于版本 `,p.sourceRevision,` · `,(0,Z.jsx)(g,{value:p.generatedAt})]}),(0,Z.jsx)(`div`,{className:`markdown`,"data-testid":`session-handoff-body`,children:(0,Z.jsx)(N,{children:_})})]})]})}function ne({members:e}){let{request:t,projectId:n,api:i}=D(),o=(0,L.useCallback)(async e=>{let[n,r]=await Promise.all([t(`sessions/stats`,q,{signal:e}),i.members(e)]);return{...n,members:r.members}},[t,i]),s=r(o,!0,f(n,`session-stats`)),[c,l]=(0,L.useState)(``),[u,d]=(0,L.useState)(``),[m,g]=(0,L.useState)(0),[_]=(0,L.useState)(()=>X(location.search)),[v,y]=(0,L.useState)(_.target),[b,x]=(0,L.useState)(_.target),[w,E]=(0,L.useState)(_.error??``),[O,A]=(0,L.useState)(``),j=(0,L.useRef)(null),M=v?.key?v.title?`搜索对话:${p(v.title)}`:`搜索当前对话`:v?`搜索:${v.owner} 的对话内容`:``,N=()=>{y(void 0),A(``),F(),j.current?.focus()};function F(){if(!b?.messageId)return;let{messageId:e,...t}=b;x(t),history.replaceState(null,``,S(P(n,t.owner,t.key,t)))}let I=(0,L.useCallback)(e=>{y(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),y(e.target),E(e.error??``),d(``),l(``),A(``)};return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]);let R=(e,t=``)=>{x(e),y(e),d(``),A(t),E(``),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)(T,{title:a.sessions,icon:`sessions`,count:(0,Z.jsx)(`span`,{"data-testid":`session-total`,children:s.data?.totalSessions??`—`}),children:(0,Z.jsx)(k,{icon:`refresh`,label:`刷新${a.sessions}`,"data-testid":`sessions-refresh`,disabled:s.loading,onClick:()=>{s.reload(),g(e=>e+1)}})}),(0,Z.jsx)(h,{error:!0,children:s.error}),(0,Z.jsx)(Q,{members:(s.data?.members??e).filter(e=>e.hasSessions),refresh:m,selected:v,onOwner:e=>{y({owner:e}),x(void 0),d(``),A(``),E(``),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)(h,{error:!0,children:w}):u?(0,Z.jsx)(re,{query:u,refresh:m,scope:{...v?{owner:v.owner}:{},...v?.key?{sessionKey:v.key}:{}},onSelect:e=>R(e,u)},`${u}/${v?.owner??``}/${v?.key??``}`):b?(0,Z.jsx)(ie,{selection:b,highlight:O,onLoaded:I,onLatest:()=>R({owner:b.owner,key:b.key})},`${b.owner}/${b.key}/${b.revision}/${m}`):(0,Z.jsx)(C,{mascot:!0,title:`选择对话开始阅读`,description:`也可以在下方搜索会话库内容。`})}),(0,Z.jsxs)(`form`,{className:`session-search-dock`,"data-testid":`session-search-form`,onSubmit:e=>{e.preventDefault(),d(c.trim()),A(``),E(``),g(e=>e+1)},children:[v&&(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&&v&&(e.preventDefault(),N())}}),(u||c||O)&&(0,Z.jsx)(k,{icon:`close`,label:`清空搜索`,"data-testid":`session-search-clear`,onClick:()=>{l(``),d(``),A(``),F(),j.current?.focus()}}),(0,Z.jsx)(k,{icon:`search`,type:`submit`,label:`搜索`,"data-testid":`session-search`,disabled:!c.trim()})]})]})]})]})}function re({query:e,refresh:t,scope:n,onSelect:i}){let{request:a}=D(),[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=r(c);return(0,Z.jsxs)(`section`,{className:`session-results stack`,"aria-label":`搜索结果`,"aria-busy":l.loading,children:[(0,Z.jsx)(h,{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:()=>i({owner:t.owner,key:t.sessionKey,revision:t.revision,messageId:t.messageId,title:t.title}),children:[(0,Z.jsx)(`strong`,{children:p(t.title)}),(0,Z.jsxs)(`small`,{children:[t.owner,` · `,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.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:i}){let{request:a}=D(),o=(0,L.useCallback)(async t=>{try{return await a(`sessions/${encodeURIComponent(e.owner)}/${e.key}${e.revision===void 0?``:`?revision=${e.revision}`}`,G,{signal:t})}catch(e){throw e instanceof w&&e.code===`SESSION_NOT_FOUND`?Error(`找不到这条对话或引用的版本,原链接可能已失效。`):e}},[a,e.owner,e.key,e.revision]),s=r(o,5e3);return(0,L.useEffect)(()=>{s.data&&n(s.data)},[s.data,n]),(0,Z.jsxs)(`section`,{className:`session-conversation stack`,"data-testid":`session-detail`,children:[(0,Z.jsx)(h,{error:!0,children:s.error}),s.error&&(0,Z.jsx)(`button`,{onClick:()=>void s.reload(),children:`重试`}),s.loading&&!s.data&&(0,Z.jsx)(`p`,{role:`status`,children:`正在读取对话…`}),s.data&&(0,Z.jsx)(ae,{info:s.data,messageId:e.messageId,highlight:t,pinned:e.revision!==void 0,onLatest:i},s.data.blob.sha256)]})}function ae({info:e,messageId:t,highlight:n,pinned:i,onLatest:a}){let{readTextBlob:o,projectId:s}=D(),c=(0,L.useCallback)(async t=>W.parse(JSON.parse(await o(e.blob,t))),[e.blob.sha256,e.blob.size]),l=r(c),u=(0,L.useRef)(null);return(0,L.useEffect)(()=>{l.data&&t&&u.current?.scrollIntoView({block:`center`})},[l.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)(g,{value:e.updatedAt}),i&&(0,Z.jsxs)(Z.Fragment,{children:[` `,`· 引用版本 `,e.revision,` ·`,` `,(0,Z.jsx)(`a`,{href:S(P(s,e.owner,e.sessionKey)),onClick:e=>{e.preventDefault(),a()},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}),(0,Z.jsx)(h,{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.data&&(0,Z.jsxs)(Z.Fragment,{children:[t&&!l.data.messages.some(e=>e.id===t)&&(0,Z.jsx)(h,{children:`该版本中找不到引用的消息,已打开对话原文。`}),(0,Z.jsx)(`div`,{className:`session-messages`,children:l.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?u: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:n,children:e.text})})]},e.id))})]})]})}export{ne as Sessions};
@@ -1 +0,0 @@
1
- function e(e,t,n){return`/projects/${encodeURIComponent(e)}/files?${new URLSearchParams({owner:t,path:n})}`}function t(e,t,n,r={}){let i=new URLSearchParams({owner:t,sessionKey:n});return r.revision!==void 0&&i.set(`revision`,String(r.revision)),r.messageId!==void 0&&i.set(`messageId`,r.messageId),`/projects/${encodeURIComponent(e)}/sessions?${i}`}export{t as n,e as t};