@teammy/server 0.1.7 → 0.1.9

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": "@teammy/server",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
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,D as n,J as r,M as i,O as a,S as o,W as ee,a as te,b as s,et as ne,f as c,i as l,k as re,n as u,o as d,q as f,r as ie,t as ae,u as oe,v as p,y as se}from"./index-DQsx-e5d.js";import{t as m}from"./Markdown-BRPMsc7D.js";var h=e(),g=t(),_=e=>new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}),v=e=>e.replace(/[#*_`>]/g,``).replace(/\s+/g,` `).trim();function y({mine:e=!1,author:t,time:n,children:r}){return(0,g.jsx)(`div`,{className:`assistant-bubble-row ${e?`mine`:``}`,children:(0,g.jsxs)(`div`,{className:`assistant-bubble`,children:[(0,g.jsxs)(`div`,{className:`assistant-bubble-meta`,children:[(0,g.jsx)(`span`,{children:t}),(0,g.jsx)(`time`,{dateTime:n,children:_(n)})]}),r]})})}function b({me:e}){let{projectId:t,request:b}=oe(),S=re(),C=a(t,e,`assistant-selection`),w=a(t,e,`assistant-drafts`),ce=(0,h.useCallback)(e=>b(`agents/outbox`,te,{signal:e}),[b]),T=n(ce,3e3,a(t,e,`outbox`)),le=(0,h.useCallback)(e=>b(`agents/chats`,ae,{signal:e}),[b]),E=n(le,3e3,a(t,e,`chats`)),[D,ue]=(0,h.useState)(()=>{let e=new URLSearchParams(location.search),t=e.get(`chat`);return t?`chat:${t}`:e.get(`message`)??S?.get(C)??``}),O=D.startsWith(`chat:`)?D.slice(5):``,k=!D||!!O,[A,j]=(0,h.useState)(()=>S?.get(a(t,e,`chat`,O))),M=A?.id===O?A:S?.get(a(t,e,`chat`,O)),de=E.data?.chats.find(e=>e.id===O),[fe,N]=(0,h.useState)(),[P,F]=(0,h.useState)(()=>S?.get(w)??{}),I=P[D]??``,L=e=>F(t=>({...t,[D]:e})),[R,z]=(0,h.useState)(!1),[B,V]=(0,h.useState)(!1),[pe,H]=(0,h.useState)(``),[U,W]=(0,h.useState)(``),G=(0,h.useRef)(new Map),K=(0,h.useRef)(null),q=(0,h.useRef)(!0),J=(0,h.useRef)(D);J.current=D,(0,h.useEffect)(()=>{A&&S?.set(a(t,e,`chat`,A.id),A)},[S,t,e,A]),(0,h.useEffect)(()=>{S?.set(w,P)},[S,w,P]);function Y(e){J.current=e,ue(e),S?.set(C,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,h.useEffect)(()=>{!D&&E.data?.chats.length&&Y(`chat:${E.data.chats[0].id}`)},[D,E.data]);let X=(T.data?.messages??[]).filter(e=>e.box===`debug`).reverse(),Z=T.data?.messages.find(e=>e.id===(D===`debug`?fe:D));(0,h.useEffect)(()=>{D!==`debug`&&Z?.conversationId&&Y(`chat:${Z.conversationId}`)},[D,Z?.conversationId]);let Q=X.filter(e=>!e.readAt).map(e=>e.id).join(`,`);(0,h.useEffect)(()=>{Z&&!Z.readAt&&D!==`debug`&&b(`agents/outbox/${Z.id}/read`,d,{method:`POST`}).then(()=>{window.dispatchEvent(new Event(`teammy:outbox`)),T.reload()}).catch(e=>H(i(e)))},[Z?.id,Z?.readAt,D,b,T.reload]),(0,h.useEffect)(()=>{D===`debug`&&Q&&Promise.all(Q.split(`,`).map(e=>b(`agents/outbox/${e}/read`,d,{method:`POST`}))).then(()=>{window.dispatchEvent(new Event(`teammy:outbox`)),T.reload()}).catch(e=>H(i(e)))},[D,Q,b,T.reload]),(0,h.useEffect)(()=>{if(W(``),!O)return;let e=!0,n=new EventSource(ne(`/api/v1/projects/${encodeURIComponent(t)}/agents/chats/${encodeURIComponent(O)}/events`));n.addEventListener(`snapshot`,t=>{if(e)try{let e=u.parse(JSON.parse(t.data));if(e.redirect){Y(`chat:${e.redirect}`);return}j(e),W(``)}catch(e){W(i(e))}}),n.onerror=()=>{e&&W(`对话连接中断,正在重新连接…`)},n.addEventListener(`context`,t=>{if(!e)return;let n=u.pick({kind:!0,title:!0,status:!0,visibility:!0,participants:!0,pending:!0,hold:!0,redirect:!0}).parse(JSON.parse(t.data));n.redirect?Y(`chat:${n.redirect}`):j(e=>e?.id===O?{...e,...n}:e)}),n.addEventListener(`message`,t=>{if(!e)return;let n=ie.parse(JSON.parse(t.data));j(e=>e&&{...e,readCursor:Math.max(e.readCursor,n.seq),cursor:Math.max(e.cursor,Number(t.lastEventId)||0),messages:[...e.messages.filter(e=>e.id!==n.id),n].sort((e,t)=>e.seq-t.seq)})}),n.addEventListener(`message_removed`,t=>{if(!e)return;let{id:n}=f({id:r()}).parse(JSON.parse(t.data));j(e=>e?.id===O?{...e,messages:e.messages.filter(e=>e.id!==n)}:e)}),n.addEventListener(`run`,t=>{if(!e)return;let n=l.parse(JSON.parse(t.data));j(e=>e&&{...e,cursor:Math.max(e.cursor,Number(t.lastEventId)||0),runs:e.runs.some(e=>e.id===n.id)?e.runs:[...e.runs,n]})});for(let t of[`delta`,`reset`,`state`])n.addEventListener(t,n=>{if(!e)return;let r=JSON.parse(n.data);j(e=>e&&{...e,cursor:Math.max(e.cursor,Number(n.lastEventId)||0),messages:e.messages.map(e=>e.runId!==r.id||e.role!==`assistant`?e:{...e,body:t===`delta`?e.body+(r.text??``):t===`reset`?``:r.answer??e.body,state:r.state??e.state}),runs:e.runs.map(e=>e.id===r.id?{...e,answer:t===`delta`?e.answer+(r.text??``):t===`reset`?``:r.answer??e.answer,state:r.state??e.state,error:r.error===void 0?e.error:r.error}:e)})});return()=>{e=!1,n.close()}},[t,O]),(0,h.useEffect)(()=>{if(!M?.kind||M.id!==O)return;let e=()=>{document.visibilityState===`visible`&&b(`agents/chats/${O}/read`,f({ok:ee()}),{method:`POST`,body:{cursor:M.readCursor}}).then(()=>{E.reload(),window.dispatchEvent(new Event(`teammy:outbox`))}).catch(e=>H(i(e)))},t=setTimeout(e,300);return document.addEventListener(`visibilitychange`,e),()=>{clearTimeout(t),document.removeEventListener(`visibilitychange`,e)}},[O,M?.readCursor,M?.kind,b]),(0,h.useEffect)(()=>{q.current&&K.current?.scrollIntoView({block:`end`})},[D,A?.messages,Z?.recipients,X.length]);function me(){window.dispatchEvent(new Event(`teammy:outbox`)),T.reload()}async function $(e){if(q.current=!0,Y(e),H(``),N(void 0),e.startsWith(`chat:`)||e===`debug`)return;let t=T.data?.messages.find(t=>t.id===e)?.conversationId;if(t)Y(`chat:${t}`);else try{await b(`agents/outbox/${e}/read`,d,{method:`POST`}),me()}catch(e){H(i(e))}}async function he(){if(!B){V(!0),H(``);try{let e=await b(`agents/chats`,u,{method:`POST`});j(e),await $(`chat:${e.id}`),E.reload()}catch(e){H(i(e))}finally{V(!1)}}}async function ge(e){e.preventDefault();let t=I.trim();if(!t||R||B)return;z(!0),H(``);let n=G.current.get(D);n&&n.text===t||(n={text:t,id:crypto.randomUUID()},G.current.set(D,n));try{if(k){let e=n.target??O;if(!e){let r=await b(`agents/chats`,u,{method:`POST`});e=r.id,n.target=e,G.current.set(`chat:${e}`,n),F(n=>({...n,[`chat:${e}`]:t})),J.current===D&&(j(r),Y(`chat:${e}`))}let i=await b(`agents/chats/${e}`,l.extend({conversationId:r().optional()}),{method:`POST`,body:{text:t,requestId:n.id}});i.conversationId&&i.conversationId!==e&&(J.current===D||J.current===`chat:${e}`)&&Y(`chat:${i.conversationId}`),j(t=>t?.id===e?{...t,runs:t.runs.some(e=>e.id===i.id)?t.runs:[...t.runs,i]}:t),E.reload()}else{let e=await b(`agents/outbox/${Z.id}/reply`,f({conversationId:r()}),{method:`POST`,body:{body:t,requestId:n.id}});me(),J.current===D&&Y(`chat:${e.conversationId}`),E.reload(),N(void 0)}G.current.delete(D),n.target&&G.current.delete(`chat:${n.target}`),F(e=>({...e,[D]:``,...n.target?{[`chat:${n.target}`]:``}:{}}))}catch(e){H(i(e))}finally{z(!1)}}let _e=k||!!Z&&!Z.archivedAt,ve=k&&!M&&(!!O||!E.data);return(0,g.jsxs)(`div`,{className:`split-layout assistant-layout`,"data-testid":`assistant-page`,children:[(0,g.jsxs)(`aside`,{className:`assistant-list`,"aria-label":`消息列表`,children:[(0,g.jsxs)(`header`,{className:`assistant-list-heading`,children:[(0,g.jsx)(`h1`,{children:`消息`}),(0,g.jsx)(se,{className:`assistant-new-chat`,icon:`plus`,label:`新建对话`,disabled:B,onClick:()=>void he(),"data-testid":`assistant-launcher`})]}),(0,g.jsxs)(`div`,{className:`assistant-message-scroll`,children:[E.loading&&!E.data&&(0,g.jsx)(`p`,{className:`assistant-list-status`,role:`status`,children:`加载中…`}),E.data?.chats.map(e=>(0,g.jsxs)(`button`,{type:`button`,"data-testid":`assistant-chat-${e.id}`,className:`assistant-message-item assistant-chat-item ${O===e.id?`selected`:``}`,"aria-pressed":O===e.id,onClick:()=>void $(`chat:${e.id}`),children:[(0,g.jsx)(`span`,{className:`assistant-message-dot ${e.unread||e.state===`running`||e.state===`queued`?`unread`:``}`}),(0,g.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,g.jsx)(c,{selected:O===e.id,children:(0,g.jsx)(`strong`,{children:e.title})}),(0,g.jsxs)(`time`,{dateTime:e.updatedAt,children:[new Date(e.updatedAt).toLocaleDateString([],{month:`numeric`,day:`numeric`}),` `,_(e.updatedAt)]})]})]},e.id)),!!X.length&&(0,g.jsxs)(`button`,{type:`button`,"data-testid":`debug-outbox`,className:`assistant-message-item ${D===`debug`?`selected`:``}`,onClick:()=>void $(`debug`),children:[(0,g.jsx)(`span`,{className:`assistant-message-dot ${Q?`unread`:``}`}),(0,g.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,g.jsx)(c,{selected:D===`debug`,children:(0,g.jsx)(`strong`,{children:`运行提醒`})}),(0,g.jsx)(`span`,{children:v(X.at(-1).body)})]})]}),T.data?.messages.filter(e=>e.box!==`debug`&&!e.conversationId).sort((e,t)=>Number(!!e.archivedAt)-Number(!!t.archivedAt)).map(e=>(0,g.jsxs)(`button`,{type:`button`,"data-testid":`outbox-${e.id}`,className:`assistant-message-item ${e.archivedAt?`archived`:``} ${D===e.id?`selected`:``}`,onClick:()=>void $(e.id),children:[(0,g.jsx)(`span`,{className:`assistant-message-dot ${e.readAt?``:`unread`}`}),(0,g.jsxs)(`span`,{className:`assistant-message-copy`,children:[(0,g.jsx)(c,{selected:D===e.id,children:(0,g.jsx)(`strong`,{children:v(e.body)})}),(0,g.jsxs)(`time`,{dateTime:e.createdAt,children:[new Date(e.createdAt).toLocaleDateString([],{month:`numeric`,day:`numeric`}),` `,_(e.createdAt)]})]})]},e.id))]}),(0,g.jsx)(o,{error:!0,children:T.error||E.error})]}),(0,g.jsxs)(`section`,{className:`assistant-thread`,"aria-label":k?`Tim对话`:`消息内容`,children:[(0,g.jsxs)(`header`,{className:`assistant-thread-heading`,children:[(0,g.jsx)(`h2`,{children:k?de?.title??M?.title??(O?`无标题`:`Tim`):D===`debug`?`运行提醒`:`项目消息`}),M?.kind===`matter`&&(0,g.jsxs)(`span`,{className:`assistant-participants`,title:M.participants?.join(`、`),children:[M.visibility===`project`?`项目共享 · `:``,M.participants?.join(`、`)]})]}),M?.kind===`matter`&&(M.hold||M.pending||M.status===`completed`)&&(0,g.jsx)(`div`,{className:`assistant-matter-state`,role:`status`,children:M.hold?`${M.hold.scope===`all`?`已暂停`:`暂缓修改`} · ${M.hold.reason}`:M.pending?`待确认 · ${M.pending.members.join(`、`)}:${M.pending.question}`:`已完成`}),(0,g.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:[k?ve?(0,g.jsxs)(`div`,{className:`assistant-empty`,"data-testid":`assistant-loading`,children:[(0,g.jsx)(s,{}),(0,g.jsx)(`p`,{role:`status`,children:U||E.error?`暂时无法加载对话`:`加载中…`})]}):M?.messages.length?M.messages.filter(e=>e.body||[`queued`,`running`,`failed`].includes(e.state)).map(t=>(0,g.jsx)(`div`,{className:`assistant-turn`,children:(0,g.jsxs)(y,{mine:t.role===`user`&&t.author===e,author:`${t.role===`assistant`?`Tim`:t.author}${t.source===`wecom`?` · 企业微信`:``}`,time:t.createdAt,children:[t.body&&(0,g.jsx)(`div`,{className:`markdown`,children:(0,g.jsx)(m,{children:t.body})}),t.role===`assistant`&&[`queued`,`running`].includes(t.state)&&(0,g.jsxs)(`span`,{className:`assistant-typing`,"aria-label":`正在回答`,children:[(0,g.jsx)(`i`,{}),(0,g.jsx)(`i`,{}),(0,g.jsx)(`i`,{})]}),t.state===`failed`&&(0,g.jsx)(o,{error:!0,children:M.runs.find(e=>e.id===t.runId)?.error||`本次回答未完成。`})]})},t.id)):(0,g.jsxs)(`div`,{className:`assistant-empty`,children:[(0,g.jsx)(s,{}),(0,g.jsx)(`p`,{children:`有什么项目问题想聊聊?`})]}):!T.data&&T.loading?(0,g.jsx)(`div`,{className:`assistant-empty`,children:(0,g.jsx)(`p`,{role:`status`,children:`加载中…`})}):D===`debug`?X.map(e=>(0,g.jsx)(x,{item:e,onReply:e.archivedAt?void 0:()=>{N(e.id),L(``),H(``)}},e.id)):Z&&(0,g.jsx)(x,{item:Z}),(0,g.jsx)(`div`,{ref:K})]}),(0,g.jsx)(o,{error:!0,children:pe||(k?U:``)}),_e?(0,g.jsxs)(`form`,{className:`assistant-composer`,onSubmit:e=>void ge(e),children:[(0,g.jsx)(`textarea`,{value:I,disabled:B,onChange:e=>L(e.target.value),"aria-label":k?`向Tim提问`:`回复消息`,placeholder:k?`问问Tim…`:`回复…`,rows:2,onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),e.currentTarget.form?.requestSubmit())}}),(0,g.jsx)(`button`,{className:`primary assistant-send`,type:`submit`,disabled:R||B||ve||!I.trim(),"aria-label":`发送`,children:(0,g.jsx)(p,{name:`send`})})]}):D!==`debug`&&Z&&(0,g.jsxs)(`div`,{className:`assistant-archived`,children:[(0,g.jsx)(p,{name:`archive`}),`已归档`]})]})]})}function x({item:e,onReply:t}){return(0,g.jsx)(`div`,{"data-testid":`outbox-thread-${e.id}`,children:(0,g.jsxs)(y,{author:e.box===`debug`?`运行提醒`:`Tim`,time:e.createdAt,children:[(0,g.jsx)(`div`,{className:`markdown`,children:(0,g.jsx)(m,{children:e.body})}),t&&(0,g.jsx)(`button`,{type:`button`,className:`assistant-debug-reply`,onClick:t,children:`回复`})]})})}export{b as Assistant};