@anvia/studio 0.8.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -19
- package/dist/index.d.ts +37 -60
- package/dist/index.js +1000 -724
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/{ArrowClockwise.es-CSN-gjxO.js → ArrowClockwise.es-DMJj7Hv0.js} +2 -2
- package/dist/ui/assets/{ArrowClockwise.es-CSN-gjxO.js.map → ArrowClockwise.es-DMJj7Hv0.js.map} +1 -1
- package/dist/ui/assets/{agents-page-CkNSbqAj.js → agents-page-CbQpO3Tg.js} +2 -2
- package/dist/ui/assets/agents-page-CbQpO3Tg.js.map +1 -0
- package/dist/ui/assets/{badge-RJJoRC4P.js → badge-BIWy1K8W.js} +1 -1
- package/dist/ui/assets/{badge-RJJoRC4P.js.map → badge-BIWy1K8W.js.map} +1 -1
- package/dist/ui/assets/index-DizotQot.js +119 -0
- package/dist/ui/assets/index-DizotQot.js.map +1 -0
- package/dist/ui/assets/{input-BOUv3rgO.js → input-BTHDDFpv.js} +1 -1
- package/dist/ui/assets/{input-BOUv3rgO.js.map → input-BTHDDFpv.js.map} +1 -1
- package/dist/ui/assets/{knowledge-page-Cot_uYcE.js → knowledge-page-C8zg8uTL.js} +2 -2
- package/dist/ui/assets/{knowledge-page-Cot_uYcE.js.map → knowledge-page-C8zg8uTL.js.map} +1 -1
- package/dist/ui/assets/{mcps-page-BSO6ork4.js → mcps-page-gNYeqSPB.js} +2 -2
- package/dist/ui/assets/{mcps-page-BSO6ork4.js.map → mcps-page-gNYeqSPB.js.map} +1 -1
- package/dist/ui/assets/{memory-page-CG84G--r.js → memory-page-BLrfOqyU.js} +4 -4
- package/dist/ui/assets/memory-page-BLrfOqyU.js.map +1 -0
- package/dist/ui/assets/pipelines-page-hTEhFZGg.js +8 -0
- package/dist/ui/assets/pipelines-page-hTEhFZGg.js.map +1 -0
- package/dist/ui/assets/{renderers-B8gvjR2u.js → renderers-DC_-TD_X.js} +3 -3
- package/dist/ui/assets/{renderers-B8gvjR2u.js.map → renderers-DC_-TD_X.js.map} +1 -1
- package/dist/ui/assets/{sandboxes-page-D910dyFO.js → sandboxes-page-DtPnuza7.js} +2 -2
- package/dist/ui/assets/{sandboxes-page-D910dyFO.js.map → sandboxes-page-DtPnuza7.js.map} +1 -1
- package/dist/ui/assets/{sessions-page-CSN2vSKZ.js → sessions-page-DBzoP7MV.js} +2 -2
- package/dist/ui/assets/{sessions-page-CSN2vSKZ.js.map → sessions-page-DBzoP7MV.js.map} +1 -1
- package/dist/ui/assets/{status-page-CgRNt0wi.js → status-page-Bf1lq444.js} +2 -2
- package/dist/ui/assets/{status-page-CgRNt0wi.js.map → status-page-Bf1lq444.js.map} +1 -1
- package/dist/ui/assets/tool-runner-BbUlfPEO.js +2 -0
- package/dist/ui/assets/{tool-runner-BZN-PZJU.js.map → tool-runner-BbUlfPEO.js.map} +1 -1
- package/dist/ui/assets/{tools-page-DRv7aklU.js → tools-page-BgUz-79v.js} +2 -2
- package/dist/ui/assets/{tools-page-DRv7aklU.js.map → tools-page-BgUz-79v.js.map} +1 -1
- package/dist/ui/assets/trace-browser-qfYPcdR2.js +10 -0
- package/dist/ui/assets/trace-browser-qfYPcdR2.js.map +1 -0
- package/dist/ui/assets/{transcript-item-ZNkQEaCw.js → transcript-item-HFuuqmKM.js} +3 -3
- package/dist/ui/assets/{transcript-item-ZNkQEaCw.js.map → transcript-item-HFuuqmKM.js.map} +1 -1
- package/dist/ui/index.html +1 -2
- package/package.json +12 -11
- package/dist/ui/assets/agents-page-CkNSbqAj.js.map +0 -1
- package/dist/ui/assets/chunk-ADH7NNCS-DM6fsnDI.js +0 -2
- package/dist/ui/assets/chunk-ADH7NNCS-DM6fsnDI.js.map +0 -1
- package/dist/ui/assets/index-Bh7RLPBw.js +0 -56
- package/dist/ui/assets/index-Bh7RLPBw.js.map +0 -1
- package/dist/ui/assets/memory-page-CG84G--r.js.map +0 -1
- package/dist/ui/assets/pipelines-page-Hbf5ffUH.js +0 -8
- package/dist/ui/assets/pipelines-page-Hbf5ffUH.js.map +0 -1
- package/dist/ui/assets/tool-runner-BZN-PZJU.js +0 -2
- package/dist/ui/assets/trace-browser-B07coNNE.js +0 -10
- package/dist/ui/assets/trace-browser-B07coNNE.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e,r as t,s as n}from"./utils-C9GMruoG.js";import{
|
|
2
|
-
`).trim();if(t.length>0)return T(t);let n=e.content.flatMap(e=>e.type===`
|
|
3
|
-
`).trim();if(r.length>0)return T(r);let i=e.content.filter(e=>e.type===`image`).length;return i>0?`${i} generated image${i===1?``:`s`}`:`Assistant response`}function T(e){let t=e.replace(/\s+/g,` `).trim();return t.length>220?`${t.slice(0,217)}...`:t}function E(e){let[t,n]=(0,v.useState)([]),[r,a]=(0,v.useState)(``),[g,_]=(0,v.useState)([]),[b,x]=(0,v.useState)([]),[S,C]=(0,v.useState)(``),[w,T]=(0,v.useState)(``),[E,O]=(0,v.useState)(),[A,N]=(0,v.useState)(),[P,F]=(0,v.useState)(!1),[B,V]=(0,v.useState)(!1),[H,U]=(0,v.useState)(!1),[W,G]=(0,v.useState)(``),K=(0,v.useRef)(0),q=t.find(e=>e.ref===r),J=(0,v.useCallback)(async()=>{if(!e.enabled){n([]),a(``);return}F(!0),G(``);try{let e=await fetch(`/memory/sources`);if(!e.ok)throw Error(`Memory sources failed with HTTP ${e.status}`);let t=await e.json();n(t.sources),a(e=>t.sources.some(t=>t.ref===e)?e:z(t.sources))}catch(e){G(e instanceof Error?e.message:String(e))}finally{F(!1)}},[e.enabled]);(0,v.useEffect)(()=>{J()},[J]);let Y=(0,v.useCallback)(async()=>{let t=K.current+1;if(K.current=t,!e.enabled||q===void 0||!q.available){_([]),x([]),O(void 0),N(void 0),V(!1);return}V(!0),G(``);try{let e=`/memory/sources/${encodeURIComponent(q.ref)}`,[n,r]=await Promise.all([fetch(`${e}/users?limit=50`),fetch(`${e}/conversations?limit=100`)]);if(!n.ok)throw Error(`Memory users failed with HTTP ${n.status}`);if(!r.ok)throw Error(`Memory conversations failed with HTTP ${r.status}`);let i=await n.json(),a=await r.json();if(K.current!==t)return;_(i.users),x(a.conversations),T(e=>a.conversations.find(t=>t.ref===e)?.ref??a.conversations[0]?.ref??``)}catch(e){K.current===t&&G(e instanceof Error?e.message:String(e))}finally{K.current===t&&V(!1)}},[e.enabled,q]);(0,v.useEffect)(()=>{C(``),T(``),_([]),x([]),O(void 0),N(void 0),Y()},[Y]),(0,v.useEffect)(()=>{if(!e.enabled||q===void 0||!q.available||w.length===0){O(void 0),N(void 0);return}let t=q.ref,n=!1;async function r(){U(!0),G(``);try{let e=`/memory/sources/${encodeURIComponent(t)}/conversations/${encodeURIComponent(w)}`,[r,i]=await Promise.all([fetch(`${e}/messages`),fetch(`${e}/steps`)]);if(!r.ok)throw Error(`Conversation messages failed with HTTP ${r.status}`);if(!i.ok)throw Error(`Conversation steps failed with HTTP ${i.status}`);n||(O(await r.json()),N(await i.json()))}catch(e){n||(G(e instanceof Error?e.message:String(e)),O(void 0),N(void 0))}finally{n||U(!1)}}return r(),()=>{n=!0}},[e.enabled,w,q]);let X=(0,v.useMemo)(()=>S.length===0?b:b.filter(e=>e.userId===S),[b,S]),Z=(0,v.useMemo)(()=>R(g,b),[b,g]),Q=X.find(e=>e.ref===w)??X[0];return(0,v.useEffect)(()=>{if(X.length===0){T(``);return}X.some(e=>e.ref===w)||T(X[0]?.ref??``)},[w,X]),(0,y.jsxs)(f,{className:`grid-rows-[auto_minmax(0,1fr)]`,"aria-label":`Memory`,children:[(0,y.jsx)(o,{title:`Memory`,description:`Inspect persisted agent conversations directly. Studio sessions appear only as a fallback for agents without configured memory.`,action:(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start`,children:[t.length===0?null:(0,y.jsxs)(h,{value:r,onValueChange:a,children:[(0,y.jsx)(p,{className:`h-8 min-h-8 w-60 rounded-md border-border text-xs max-sm:w-full`,children:(0,y.jsx)(u,{placeholder:`Memory source`})}),(0,y.jsx)(s,{align:`end`,children:t.map(e=>(0,y.jsxs)(c,{value:e.ref,children:[e.label,e.available?``:` (unavailable)`]},e.ref))})]}),(0,y.jsx)(m,{label:`users`,value:Z.userCount}),(0,y.jsx)(m,{label:`conversations`,value:Z.conversationCount}),(0,y.jsx)(m,{label:`messages`,value:Z.messageCount}),(0,y.jsx)(i,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,type:`button`,variant:`secondary`,disabled:P||B,onClick:()=>void J(),children:`Refresh`})]})}),(0,y.jsx)(l,{className:`overflow-hidden`,children:e.enabled?P&&t.length===0?(0,y.jsx)(d,{title:`Loading memory`,text:`Discovering configured memory sources.`}):W.length>0&&t.length===0?(0,y.jsx)(d,{title:`Memory error`,text:W}):q===void 0?(0,y.jsx)(d,{title:`No memory sources`,text:`No registered agent exposes memory.`}):q.available?B&&b.length===0?(0,y.jsx)(d,{title:`Loading memory`,text:`Reading ${q.label}.`}):W.length>0&&b.length===0?(0,y.jsx)(d,{title:`Memory error`,text:W}):b.length===0?(0,y.jsx)(I,{source:q,userCount:g.length,onRefresh:()=>void Y()}):(0,y.jsxs)(`div`,{className:[`grid h-full min-h-0 overflow-hidden`,W.length===0?`grid-rows-[minmax(0,1fr)]`:`grid-rows-[auto_minmax(0,1fr)]`].join(` `),children:[W.length===0?null:(0,y.jsx)(L,{message:W}),(0,y.jsxs)(`div`,{className:`grid min-h-0 grid-cols-[260px_minmax(320px,0.78fr)_minmax(0,1.22fr)] overflow-hidden border-t border-border/80 max-xl:grid-cols-[240px_minmax(0,1fr)] max-xl:grid-rows-[minmax(240px,0.42fr)_minmax(0,1fr)] max-md:grid-cols-1 max-md:grid-rows-[auto_minmax(240px,0.38fr)_minmax(0,1fr)]`,children:[(0,y.jsx)(D,{users:g,selectedUserId:S,totalConversations:b.length,onSelect:C}),(0,y.jsx)(k,{agents:e.agents,conversations:X,selectedConversationRef:Q?.ref??``,source:q,onSelect:T}),(0,y.jsx)(j,{agents:e.agents,conversation:Q,detailLoading:H,messages:E,source:q,steps:A})]})]}):(0,y.jsx)(M,{source:q}):(0,y.jsx)(d,{title:`Memory unavailable`,text:`No agent memory or Studio session store is configured.`})})]})}function D(e){return(0,y.jsx)(`aside`,{className:`min-h-0 overflow-auto border-r border-border/80 pr-3 max-md:border-b max-md:border-r-0 max-md:pr-0`,children:(0,y.jsxs)(`div`,{className:`grid gap-3 py-4 pr-3 max-md:pr-0`,children:[(0,y.jsx)(P,{label:`Users`,value:e.users.length}),(0,y.jsx)(O,{active:e.selectedUserId.length===0,title:`All users`,detail:`${e.totalConversations} conversations`,onClick:()=>e.onSelect(``)}),(0,y.jsx)(`div`,{className:`grid gap-1`,children:e.users.map(t=>(0,y.jsx)(O,{active:e.selectedUserId===t.userId,title:t.userId,detail:`${t.conversationCount} conversations / ${a(t.lastInteractionAt)}`,onClick:()=>e.onSelect(t.userId)},t.userId))})]})})}function O(e){return(0,y.jsxs)(`button`,{className:[`grid min-w-0 gap-1 rounded-lg border border-transparent px-3 py-2.5 text-left transition duration-200 hover:border-border/80 hover:bg-muted/25 focus-visible:border-ring focus-visible:outline-none`,e.active?`border-border/80 bg-muted/35`:``].join(` `),type:`button`,onClick:e.onClick,children:[(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.title}),(0,y.jsx)(`span`,{className:`min-w-0 truncate text-xs leading-5 text-muted-foreground`,children:e.detail})]})}function k(e){return(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto border-r border-border/80 px-4 max-xl:border-r-0 max-xl:pr-0 max-md:border-b max-md:px-0`,children:(0,y.jsxs)(`div`,{className:`grid gap-3 py-4`,children:[(0,y.jsx)(P,{label:`Conversations`,value:e.conversations.length}),e.conversations.length===0?(0,y.jsx)(`div`,{className:`border-y border-dashed border-border/80 px-3 py-8 text-center text-sm text-muted-foreground`,children:`No conversations for this user.`}):(0,y.jsx)(`div`,{className:`grid border-y border-border/80`,children:e.conversations.map(t=>(0,y.jsx)(A,{active:t.ref===e.selectedConversationRef,agentName:V(e.agents,e.source,t.agentIds),conversation:t,onSelect:()=>e.onSelect(t.ref)},t.ref))})]})})}function A(e){return(0,y.jsxs)(`button`,{className:[`grid min-w-0 gap-2 border-b border-border/70 px-3 py-3 text-left transition duration-200 last:border-b-0 hover:bg-muted/20 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,e.active?`bg-muted/35`:``].join(` `),type:`button`,onClick:e.onSelect,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-3`,children:[(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-1`,children:[(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.conversation.title??e.conversation.sessionId}),(0,y.jsxs)(`span`,{className:`min-w-0 truncate text-xs text-muted-foreground`,children:[e.agentName,` / `,e.conversation.userId]})]}),(0,y.jsx)(`span`,{className:`shrink-0 text-xs tabular-nums text-muted-foreground`,children:e.conversation.messageCount})]}),(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground`,children:[(0,y.jsx)(`span`,{children:a(e.conversation.updatedAt)}),(0,y.jsx)(`span`,{className:`min-w-0 truncate`,children:e.conversation.sessionId})]})]})}function j(e){return e.conversation===void 0?(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1`,children:(0,y.jsx)(d,{title:`No conversation selected`,text:`Choose a conversation to inspect.`})}):(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1`,children:(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-5`,children:[(0,y.jsxs)(`header`,{className:`grid gap-4 border-b border-border/80 pb-5`,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-4 max-md:grid`,children:[(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-2`,children:[(0,y.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:`Persisted conversation`}),(0,y.jsx)(`h2`,{className:`m-0 min-w-0 truncate text-2xl font-semibold leading-none text-foreground`,children:e.conversation.title??e.conversation.sessionId}),(0,y.jsx)(`span`,{className:`min-w-0 break-all font-mono text-xs text-muted-foreground`,children:e.conversation.ref})]}),(0,y.jsxs)(`div`,{className:`flex flex-wrap justify-end gap-2 max-md:justify-start`,children:[(0,y.jsx)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:e.source.storeKind??e.source.kind}),(0,y.jsx)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:V(e.agents,e.source,e.conversation.agentIds)})]})]}),(0,y.jsxs)(`div`,{className:`grid border-y border-border/80 sm:grid-cols-4 sm:divide-x sm:divide-border/80`,children:[(0,y.jsx)(F,{label:`user`,value:e.conversation.userId}),(0,y.jsx)(F,{label:`messages`,value:e.conversation.messageCount}),(0,y.jsx)(F,{label:`created`,value:a(e.conversation.createdAt)}),(0,y.jsx)(F,{label:`updated`,value:a(e.conversation.updatedAt)})]})]}),e.detailLoading?(0,y.jsx)(d,{title:`Loading detail`,text:`Reading persisted messages.`}):(0,y.jsxs)(`div`,{className:`grid gap-4`,children:[e.conversation.metadata===void 0?null:(0,y.jsx)(N,{title:`metadata`,value:e.conversation.metadata}),(0,y.jsx)(x,{records:e.messages?.records??[]}),(0,y.jsx)(N,{title:`messages`,value:e.messages?.messages??[]}),(0,y.jsx)(N,{title:`message records`,value:e.messages?.records??[]}),(0,y.jsx)(N,{title:`derived transcript`,value:e.steps?.steps??[]})]})]})})}function M(e){return(0,y.jsx)(d,{className:`h-full`,title:`${e.source.label} is not inspectable`,text:e.source.reason??`This memory store does not expose read-only discovery.`})}function N(e){let t=Array.isArray(e.value)?e.value.length:void 0;return(0,y.jsxs)(`details`,{className:`group grid min-w-0 overflow-hidden border-y border-border/80`,open:!0,children:[(0,y.jsxs)(`summary`,{className:`flex min-h-11 cursor-pointer list-none items-center justify-between gap-3 bg-muted/10 px-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden`,children:[(0,y.jsx)(`span`,{children:e.title}),(0,y.jsx)(`span`,{className:`font-medium normal-case tracking-normal`,children:t===void 0?`JSON`:`${t} items`})]}),(0,y.jsx)(`div`,{className:`min-w-0 overflow-x-auto border-t border-border/70`,children:(0,y.jsx)(`pre`,{className:`m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground`,children:(0,y.jsx)(`code`,{children:(0,y.jsx)(_,{text:B(e.value)})})})})]})}function P(e){return(0,y.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,y.jsx)(`h2`,{className:`m-0 text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground`,children:e.label}),(0,y.jsx)(`span`,{className:`text-xs font-semibold tabular-nums text-muted-foreground`,children:e.value})]})}function F(e){return(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-1 px-3 py-3 first:pl-0 last:pr-0`,children:[(0,y.jsx)(`span`,{className:`text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:e.label}),(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm text-foreground`,title:String(e.value),children:e.value})]})}function I(e){return(0,y.jsx)(d,{className:`h-full`,title:`No saved conversations yet`,text:`Conversations will appear here after the connected agent writes to ${e.source.label}. ${e.userCount} users are currently available.`,action:(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center justify-center gap-3`,children:[(0,y.jsx)(i,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,type:`button`,variant:`secondary`,onClick:e.onRefresh,children:`Refresh`}),(0,y.jsx)(`span`,{className:`text-xs leading-5 text-muted-foreground`,children:`Existing database conversations are discovered automatically.`})]})})}function L(e){return(0,y.jsx)(`div`,{className:`mb-3 border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs leading-5 text-destructive`,children:e.message})}function R(e,t){return{userCount:e.length,conversationCount:t.length,messageCount:t.reduce((e,t)=>e+t.messageCount,0)}}function z(e){return e.find(e=>e.kind===`agent`&&e.available)?.ref??e.find(e=>e.available)?.ref??e[0]?.ref??``}function B(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function V(e,t,n){if(n.length===1){let t=n[0]??`agent`;return e.find(e=>e.id===t)?.name??t}return t.label}export{E as MemoryPage};
|
|
4
|
-
//# sourceMappingURL=memory-page-
|
|
1
|
+
import{i as e,r as t,s as n}from"./utils-C9GMruoG.js";import{$ as r,F as i,a,d as o,f as s,i as c,m as l,n as u,o as d,p as f,q as p,r as m,u as h}from"./index-DizotQot.js";import{t as g}from"./badge-BIWy1K8W.js";import{t as _}from"./renderers-DC_-TD_X.js";var v=n(e(),1),y=t();function b(e){return e.flatMap(e=>e.message.role===`assistant`?[{position:e.position,runId:e.runId,turn:e.turn,createdAt:e.createdAt,preview:w(e.message),generation:p(e.message)}]:[])}function x(e){let t=b(e.records);return(0,y.jsxs)(`section`,{className:`grid min-w-0 overflow-hidden border-y border-border/80`,children:[(0,y.jsxs)(`header`,{className:`flex min-h-11 items-center justify-between gap-3 bg-muted/10 px-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:[(0,y.jsx)(`span`,{children:`Assistant responses`}),(0,y.jsxs)(`span`,{className:`font-medium normal-case tracking-normal`,children:[t.length,` responses`]})]}),t.length===0?(0,y.jsx)(`div`,{className:`border-t border-border/70 px-4 py-8 text-center text-sm text-muted-foreground`,children:`No persisted assistant responses.`}):(0,y.jsx)(`div`,{className:`grid divide-y divide-border/70 border-t border-border/70`,children:t.map(e=>(0,y.jsx)(S,{row:e},`${e.position}:${e.runId}`))})]})}function S(e){let t=e.row.generation;return(0,y.jsxs)(`article`,{className:`grid min-w-0 gap-3 px-3 py-4`,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center justify-between gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2`,children:[(0,y.jsxs)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:[`Turn `,e.row.turn]}),t===void 0?(0,y.jsx)(g,{className:`border-border/80 bg-background/40 text-muted-foreground`,children:`Usage unavailable`}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:t.provider}),(0,y.jsx)(g,{className:`max-w-full truncate border-border/80 bg-muted/45 text-foreground`,children:t.modelId})]})]}),(0,y.jsx)(`span`,{className:`shrink-0 text-xs text-muted-foreground`,children:r(e.row.createdAt)})]}),(0,y.jsx)(`p`,{className:`m-0 whitespace-pre-wrap break-words text-sm leading-6 text-foreground`,children:e.row.preview}),t===void 0?null:(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground`,children:[(0,y.jsx)(C,{label:`total`,value:t.usage.totalTokens,suffix:` tokens`}),(0,y.jsx)(C,{label:`input`,value:t.usage.inputTokens}),(0,y.jsx)(C,{label:`output`,value:t.usage.outputTokens}),(0,y.jsx)(C,{label:`cached`,value:t.usage.cachedInputTokens}),(0,y.jsx)(C,{label:`cache create`,value:t.usage.cacheCreationInputTokens})]})]})}function C(e){return(0,y.jsxs)(`span`,{children:[e.label,` `,e.value.toLocaleString(),e.suffix]})}function w(e){if(typeof e.content==`string`)return e.content.trim().length>0?T(e.content):`Assistant response`;let t=e.content.flatMap(e=>e.type===`text`?[e.text]:[]).join(`
|
|
2
|
+
`).trim();if(t.length>0)return T(t);let n=e.content.flatMap(e=>e.type===`tool-call`?[e.toolName]:[]);if(n.length>0)return`Tool call${n.length===1?``:`s`}: ${n.join(`, `)}`;let r=e.content.flatMap(e=>e.type===`reasoning`?[e.text]:[]).join(`
|
|
3
|
+
`).trim();if(r.length>0)return T(r);let i=e.content.filter(e=>e.type===`image`).length;return i>0?`${i} generated image${i===1?``:`s`}`:`Assistant response`}function T(e){let t=e.replace(/\s+/g,` `).trim();return t.length>220?`${t.slice(0,217)}...`:t}function E(e){let[t,n]=(0,v.useState)([]),[r,p]=(0,v.useState)(``),[g,_]=(0,v.useState)([]),[b,x]=(0,v.useState)([]),[S,C]=(0,v.useState)(``),[w,T]=(0,v.useState)(``),[E,O]=(0,v.useState)(),[A,N]=(0,v.useState)(),[P,F]=(0,v.useState)(!1),[B,V]=(0,v.useState)(!1),[H,U]=(0,v.useState)(!1),[W,G]=(0,v.useState)(``),K=(0,v.useRef)(0),q=t.find(e=>e.ref===r),J=(0,v.useCallback)(async()=>{if(!e.enabled){n([]),p(``);return}F(!0),G(``);try{let e=await fetch(`/memory/sources`);if(!e.ok)throw Error(`Memory sources failed with HTTP ${e.status}`);let t=await e.json();n(t.sources),p(e=>t.sources.some(t=>t.ref===e)?e:z(t.sources))}catch(e){G(e instanceof Error?e.message:String(e))}finally{F(!1)}},[e.enabled]);(0,v.useEffect)(()=>{J()},[J]);let Y=(0,v.useCallback)(async()=>{let t=K.current+1;if(K.current=t,!e.enabled||q===void 0||!q.available){_([]),x([]),O(void 0),N(void 0),V(!1);return}V(!0),G(``);try{let e=`/memory/sources/${encodeURIComponent(q.ref)}`,[n,r]=await Promise.all([fetch(`${e}/users?limit=50`),fetch(`${e}/conversations?limit=100`)]);if(!n.ok)throw Error(`Memory users failed with HTTP ${n.status}`);if(!r.ok)throw Error(`Memory conversations failed with HTTP ${r.status}`);let i=await n.json(),a=await r.json();if(K.current!==t)return;_(i.users),x(a.conversations),T(e=>a.conversations.find(t=>t.ref===e)?.ref??a.conversations[0]?.ref??``)}catch(e){K.current===t&&G(e instanceof Error?e.message:String(e))}finally{K.current===t&&V(!1)}},[e.enabled,q]);(0,v.useEffect)(()=>{C(``),T(``),_([]),x([]),O(void 0),N(void 0),Y()},[Y]),(0,v.useEffect)(()=>{if(!e.enabled||q===void 0||!q.available||w.length===0){O(void 0),N(void 0);return}let t=q.ref,n=!1;async function r(){U(!0),G(``);try{let e=`/memory/sources/${encodeURIComponent(t)}/conversations/${encodeURIComponent(w)}`,[r,i]=await Promise.all([fetch(`${e}/messages`),fetch(`${e}/steps`)]);if(!r.ok)throw Error(`Conversation messages failed with HTTP ${r.status}`);if(!i.ok)throw Error(`Conversation steps failed with HTTP ${i.status}`);n||(O(await r.json()),N(await i.json()))}catch(e){n||(G(e instanceof Error?e.message:String(e)),O(void 0),N(void 0))}finally{n||U(!1)}}return r(),()=>{n=!0}},[e.enabled,w,q]);let X=(0,v.useMemo)(()=>S.length===0?b:b.filter(e=>e.userId===S),[b,S]),Z=(0,v.useMemo)(()=>R(g,b),[b,g]),Q=X.find(e=>e.ref===w)??X[0];return(0,v.useEffect)(()=>{if(X.length===0){T(``);return}X.some(e=>e.ref===w)||T(X[0]?.ref??``)},[w,X]),(0,y.jsxs)(d,{className:`grid-rows-[auto_minmax(0,1fr)]`,"aria-label":`Memory`,children:[(0,y.jsx)(a,{title:`Memory`,description:`Inspect persisted agent conversations directly. Studio sessions appear only as a fallback for agents without configured memory.`,action:(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start`,children:[t.length===0?null:(0,y.jsxs)(h,{value:r,onValueChange:p,children:[(0,y.jsx)(f,{className:`h-8 min-h-8 w-60 rounded-md border-border text-xs max-sm:w-full`,children:(0,y.jsx)(l,{placeholder:`Memory source`})}),(0,y.jsx)(o,{align:`end`,children:t.map(e=>(0,y.jsxs)(s,{value:e.ref,children:[e.label,e.available?``:` (unavailable)`]},e.ref))})]}),(0,y.jsx)(m,{label:`users`,value:Z.userCount}),(0,y.jsx)(m,{label:`conversations`,value:Z.conversationCount}),(0,y.jsx)(m,{label:`messages`,value:Z.messageCount}),(0,y.jsx)(i,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,type:`button`,variant:`secondary`,disabled:P||B,onClick:()=>void J(),children:`Refresh`})]})}),(0,y.jsx)(c,{className:`overflow-hidden`,children:e.enabled?P&&t.length===0?(0,y.jsx)(u,{title:`Loading memory`,text:`Discovering configured memory sources.`}):W.length>0&&t.length===0?(0,y.jsx)(u,{title:`Memory error`,text:W}):q===void 0?(0,y.jsx)(u,{title:`No memory sources`,text:`No registered agent exposes memory.`}):q.available?B&&b.length===0?(0,y.jsx)(u,{title:`Loading memory`,text:`Reading ${q.label}.`}):W.length>0&&b.length===0?(0,y.jsx)(u,{title:`Memory error`,text:W}):b.length===0?(0,y.jsx)(I,{source:q,userCount:g.length,onRefresh:()=>void Y()}):(0,y.jsxs)(`div`,{className:[`grid h-full min-h-0 overflow-hidden`,W.length===0?`grid-rows-[minmax(0,1fr)]`:`grid-rows-[auto_minmax(0,1fr)]`].join(` `),children:[W.length===0?null:(0,y.jsx)(L,{message:W}),(0,y.jsxs)(`div`,{className:`grid min-h-0 grid-cols-[260px_minmax(320px,0.78fr)_minmax(0,1.22fr)] overflow-hidden border-t border-border/80 max-xl:grid-cols-[240px_minmax(0,1fr)] max-xl:grid-rows-[minmax(240px,0.42fr)_minmax(0,1fr)] max-md:grid-cols-1 max-md:grid-rows-[auto_minmax(240px,0.38fr)_minmax(0,1fr)]`,children:[(0,y.jsx)(D,{users:g,selectedUserId:S,totalConversations:b.length,onSelect:C}),(0,y.jsx)(k,{agents:e.agents,conversations:X,selectedConversationRef:Q?.ref??``,source:q,onSelect:T}),(0,y.jsx)(j,{agents:e.agents,conversation:Q,detailLoading:H,messages:E,source:q,steps:A})]})]}):(0,y.jsx)(M,{source:q}):(0,y.jsx)(u,{title:`Memory unavailable`,text:`No agent memory or Studio session store is configured.`})})]})}function D(e){return(0,y.jsx)(`aside`,{className:`min-h-0 overflow-auto border-r border-border/80 pr-3 max-md:border-b max-md:border-r-0 max-md:pr-0`,children:(0,y.jsxs)(`div`,{className:`grid gap-3 py-4 pr-3 max-md:pr-0`,children:[(0,y.jsx)(P,{label:`Users`,value:e.users.length}),(0,y.jsx)(O,{active:e.selectedUserId.length===0,title:`All users`,detail:`${e.totalConversations} conversations`,onClick:()=>e.onSelect(``)}),(0,y.jsx)(`div`,{className:`grid gap-1`,children:e.users.map(t=>(0,y.jsx)(O,{active:e.selectedUserId===t.userId,title:t.userId,detail:`${t.conversationCount} conversations / ${r(t.lastInteractionAt)}`,onClick:()=>e.onSelect(t.userId)},t.userId))})]})})}function O(e){return(0,y.jsxs)(`button`,{className:[`grid min-w-0 gap-1 rounded-lg border border-transparent px-3 py-2.5 text-left transition duration-200 hover:border-border/80 hover:bg-muted/25 focus-visible:border-ring focus-visible:outline-none`,e.active?`border-border/80 bg-muted/35`:``].join(` `),type:`button`,onClick:e.onClick,children:[(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.title}),(0,y.jsx)(`span`,{className:`min-w-0 truncate text-xs leading-5 text-muted-foreground`,children:e.detail})]})}function k(e){return(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto border-r border-border/80 px-4 max-xl:border-r-0 max-xl:pr-0 max-md:border-b max-md:px-0`,children:(0,y.jsxs)(`div`,{className:`grid gap-3 py-4`,children:[(0,y.jsx)(P,{label:`Conversations`,value:e.conversations.length}),e.conversations.length===0?(0,y.jsx)(`div`,{className:`border-y border-dashed border-border/80 px-3 py-8 text-center text-sm text-muted-foreground`,children:`No conversations for this user.`}):(0,y.jsx)(`div`,{className:`grid border-y border-border/80`,children:e.conversations.map(t=>(0,y.jsx)(A,{active:t.ref===e.selectedConversationRef,agentName:V(e.agents,e.source,t.agentIds),conversation:t,onSelect:()=>e.onSelect(t.ref)},t.ref))})]})})}function A(e){return(0,y.jsxs)(`button`,{className:[`grid min-w-0 gap-2 border-b border-border/70 px-3 py-3 text-left transition duration-200 last:border-b-0 hover:bg-muted/20 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring`,e.active?`bg-muted/35`:``].join(` `),type:`button`,onClick:e.onSelect,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-3`,children:[(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-1`,children:[(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.conversation.title??e.conversation.sessionId}),(0,y.jsxs)(`span`,{className:`min-w-0 truncate text-xs text-muted-foreground`,children:[e.agentName,` / `,e.conversation.userId]})]}),(0,y.jsx)(`span`,{className:`shrink-0 text-xs tabular-nums text-muted-foreground`,children:e.conversation.messageCount})]}),(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground`,children:[(0,y.jsx)(`span`,{children:r(e.conversation.updatedAt)}),(0,y.jsx)(`span`,{className:`min-w-0 truncate`,children:e.conversation.sessionId})]})]})}function j(e){return e.conversation===void 0?(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1`,children:(0,y.jsx)(u,{title:`No conversation selected`,text:`Choose a conversation to inspect.`})}):(0,y.jsx)(`section`,{className:`min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1`,children:(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-5`,children:[(0,y.jsxs)(`header`,{className:`grid gap-4 border-b border-border/80 pb-5`,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-4 max-md:grid`,children:[(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-2`,children:[(0,y.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:`Persisted conversation`}),(0,y.jsx)(`h2`,{className:`m-0 min-w-0 truncate text-2xl font-semibold leading-none text-foreground`,children:e.conversation.title??e.conversation.sessionId}),(0,y.jsx)(`span`,{className:`min-w-0 break-all font-mono text-xs text-muted-foreground`,children:e.conversation.ref})]}),(0,y.jsxs)(`div`,{className:`flex flex-wrap justify-end gap-2 max-md:justify-start`,children:[(0,y.jsx)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:e.source.storeKind??e.source.kind}),(0,y.jsx)(g,{className:`border-border/80 bg-muted/45 text-foreground`,children:V(e.agents,e.source,e.conversation.agentIds)})]})]}),(0,y.jsxs)(`div`,{className:`grid border-y border-border/80 sm:grid-cols-4 sm:divide-x sm:divide-border/80`,children:[(0,y.jsx)(F,{label:`user`,value:e.conversation.userId}),(0,y.jsx)(F,{label:`messages`,value:e.conversation.messageCount}),(0,y.jsx)(F,{label:`created`,value:r(e.conversation.createdAt)}),(0,y.jsx)(F,{label:`updated`,value:r(e.conversation.updatedAt)})]})]}),e.detailLoading?(0,y.jsx)(u,{title:`Loading detail`,text:`Reading persisted messages.`}):(0,y.jsxs)(`div`,{className:`grid gap-4`,children:[e.conversation.metadata===void 0?null:(0,y.jsx)(N,{title:`metadata`,value:e.conversation.metadata}),(0,y.jsx)(x,{records:e.messages?.records??[]}),(0,y.jsx)(N,{title:`messages`,value:e.messages?.messages??[]}),(0,y.jsx)(N,{title:`message records`,value:e.messages?.records??[]}),(0,y.jsx)(N,{title:`derived transcript`,value:e.steps?.steps??[]})]})]})})}function M(e){return(0,y.jsx)(u,{className:`h-full`,title:`${e.source.label} is not inspectable`,text:e.source.reason??`This memory store does not expose read-only discovery.`})}function N(e){let t=Array.isArray(e.value)?e.value.length:void 0;return(0,y.jsxs)(`details`,{className:`group grid min-w-0 overflow-hidden border-y border-border/80`,open:!0,children:[(0,y.jsxs)(`summary`,{className:`flex min-h-11 cursor-pointer list-none items-center justify-between gap-3 bg-muted/10 px-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden`,children:[(0,y.jsx)(`span`,{children:e.title}),(0,y.jsx)(`span`,{className:`font-medium normal-case tracking-normal`,children:t===void 0?`JSON`:`${t} items`})]}),(0,y.jsx)(`div`,{className:`min-w-0 overflow-x-auto border-t border-border/70`,children:(0,y.jsx)(`pre`,{className:`m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground`,children:(0,y.jsx)(`code`,{children:(0,y.jsx)(_,{text:B(e.value)})})})})]})}function P(e){return(0,y.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,y.jsx)(`h2`,{className:`m-0 text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground`,children:e.label}),(0,y.jsx)(`span`,{className:`text-xs font-semibold tabular-nums text-muted-foreground`,children:e.value})]})}function F(e){return(0,y.jsxs)(`div`,{className:`grid min-w-0 gap-1 px-3 py-3 first:pl-0 last:pr-0`,children:[(0,y.jsx)(`span`,{className:`text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:e.label}),(0,y.jsx)(`span`,{className:`min-w-0 truncate text-sm text-foreground`,title:String(e.value),children:e.value})]})}function I(e){return(0,y.jsx)(u,{className:`h-full`,title:`No saved conversations yet`,text:`Conversations will appear here after the connected agent writes to ${e.source.label}. ${e.userCount} users are currently available.`,action:(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center justify-center gap-3`,children:[(0,y.jsx)(i,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,type:`button`,variant:`secondary`,onClick:e.onRefresh,children:`Refresh`}),(0,y.jsx)(`span`,{className:`text-xs leading-5 text-muted-foreground`,children:`Existing database conversations are discovered automatically.`})]})})}function L(e){return(0,y.jsx)(`div`,{className:`mb-3 border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs leading-5 text-destructive`,children:e.message})}function R(e,t){return{userCount:e.length,conversationCount:t.length,messageCount:t.reduce((e,t)=>e+t.messageCount,0)}}function z(e){return e.find(e=>e.kind===`agent`&&e.available)?.ref??e.find(e=>e.available)?.ref??e[0]?.ref??``}function B(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function V(e,t,n){if(n.length===1){let t=n[0]??`agent`;return e.find(e=>e.id===t)?.name??t}return t.label}export{E as MemoryPage};
|
|
4
|
+
//# sourceMappingURL=memory-page-BLrfOqyU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-page-BLrfOqyU.js","names":[],"sources":["../../../src/ui/app/modules/memory/memory-generation-ledger.tsx","../../../src/ui/app/modules/memory/memory-page.tsx"],"sourcesContent":["import { getAssistantGenerationMetadata, type Message } from \"@anvia/core/completion\";\nimport type { StudioMemoryMessageRecord } from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { formatRelativeTime } from \"../shared/format\";\n\ntype AssistantMessage = Extract<Message, { role: \"assistant\" }>;\n\nexport type MemoryGenerationRow = {\n position: number;\n runId: string;\n turn: number;\n createdAt: string;\n preview: string;\n generation: ReturnType<typeof getAssistantGenerationMetadata>;\n};\n\nexport function memoryGenerationRows(records: StudioMemoryMessageRecord[]): MemoryGenerationRow[] {\n return records.flatMap((record) => {\n if (record.message.role !== \"assistant\") {\n return [];\n }\n return [\n {\n position: record.position,\n runId: record.runId,\n turn: record.turn,\n createdAt: record.createdAt,\n preview: assistantPreview(record.message),\n generation: getAssistantGenerationMetadata(record.message),\n },\n ];\n });\n}\n\nexport function MemoryGenerationLedger(props: { records: StudioMemoryMessageRecord[] }) {\n const rows = memoryGenerationRows(props.records);\n return (\n <section className=\"grid min-w-0 overflow-hidden border-y border-border/80\">\n <header className=\"flex min-h-11 items-center justify-between gap-3 bg-muted/10 px-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground\">\n <span>Assistant responses</span>\n <span className=\"font-medium normal-case tracking-normal\">{rows.length} responses</span>\n </header>\n {rows.length === 0 ? (\n <div className=\"border-t border-border/70 px-4 py-8 text-center text-sm text-muted-foreground\">\n No persisted assistant responses.\n </div>\n ) : (\n <div className=\"grid divide-y divide-border/70 border-t border-border/70\">\n {rows.map((row) => (\n <GenerationRow row={row} key={`${row.position}:${row.runId}`} />\n ))}\n </div>\n )}\n </section>\n );\n}\n\nfunction GenerationRow(props: { row: MemoryGenerationRow }) {\n const generation = props.row.generation;\n return (\n <article className=\"grid min-w-0 gap-3 px-3 py-4\">\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-2\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n <Badge className=\"border-border/80 bg-muted/45 text-foreground\">\n Turn {props.row.turn}\n </Badge>\n {generation === undefined ? (\n <Badge className=\"border-border/80 bg-background/40 text-muted-foreground\">\n Usage unavailable\n </Badge>\n ) : (\n <>\n <Badge className=\"border-border/80 bg-muted/45 text-foreground\">\n {generation.provider}\n </Badge>\n <Badge className=\"max-w-full truncate border-border/80 bg-muted/45 text-foreground\">\n {generation.modelId}\n </Badge>\n </>\n )}\n </div>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {formatRelativeTime(props.row.createdAt)}\n </span>\n </div>\n <p className=\"m-0 whitespace-pre-wrap break-words text-sm leading-6 text-foreground\">\n {props.row.preview}\n </p>\n {generation === undefined ? null : (\n <div className=\"flex min-w-0 flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground\">\n <UsageMetric label=\"total\" value={generation.usage.totalTokens} suffix=\" tokens\" />\n <UsageMetric label=\"input\" value={generation.usage.inputTokens} />\n <UsageMetric label=\"output\" value={generation.usage.outputTokens} />\n <UsageMetric label=\"cached\" value={generation.usage.cachedInputTokens} />\n <UsageMetric label=\"cache create\" value={generation.usage.cacheCreationInputTokens} />\n </div>\n )}\n </article>\n );\n}\n\nfunction UsageMetric(props: { label: string; value: number; suffix?: string | undefined }) {\n return (\n <span>\n {props.label} {props.value.toLocaleString()}\n {props.suffix}\n </span>\n );\n}\n\nfunction assistantPreview(message: AssistantMessage): string {\n if (typeof message.content === \"string\") {\n return message.content.trim().length > 0\n ? truncatePreview(message.content)\n : \"Assistant response\";\n }\n const text = message.content\n .flatMap((content) => (content.type === \"text\" ? [content.text] : []))\n .join(\"\\n\")\n .trim();\n if (text.length > 0) {\n return truncatePreview(text);\n }\n\n const toolNames = message.content.flatMap((content) =>\n content.type === \"tool-call\" ? [content.toolName] : [],\n );\n if (toolNames.length > 0) {\n return `Tool call${toolNames.length === 1 ? \"\" : \"s\"}: ${toolNames.join(\", \")}`;\n }\n\n const reasoning = message.content\n .flatMap((content) => (content.type === \"reasoning\" ? [content.text] : []))\n .join(\"\\n\")\n .trim();\n if (reasoning.length > 0) {\n return truncatePreview(reasoning);\n }\n\n const imageCount = message.content.filter((content) => content.type === \"image\").length;\n return imageCount > 0\n ? `${imageCount} generated image${imageCount === 1 ? \"\" : \"s\"}`\n : \"Assistant response\";\n}\n\nfunction truncatePreview(value: string): string {\n const compact = value.replace(/\\s+/g, \" \").trim();\n return compact.length > 220 ? `${compact.slice(0, 217)}...` : compact;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n StudioConfig,\n StudioMemorySourceConversationMessages,\n StudioMemorySourceConversationSteps,\n StudioMemorySourceConversationSummary,\n StudioMemorySourceConversationsPage,\n StudioMemorySourceSummary,\n StudioMemorySourcesPage,\n StudioMemorySourceUsersPage,\n} from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport {\n StudioEmptyState,\n StudioHeaderMetric,\n StudioPageContent,\n StudioPageHeader,\n StudioPageShell,\n} from \"../../components/ui/studio\";\nimport { formatRelativeTime } from \"../shared/format\";\nimport { JsonSyntax } from \"../shared/renderers\";\nimport { MemoryGenerationLedger } from \"./memory-generation-ledger\";\n\nexport function MemoryPage(props: { agents: StudioConfig[\"agents\"]; enabled: boolean }) {\n const [sources, setSources] = useState<StudioMemorySourceSummary[]>([]);\n const [selectedSourceRef, setSelectedSourceRef] = useState(\"\");\n const [users, setUsers] = useState<StudioMemorySourceUsersPage[\"users\"]>([]);\n const [conversations, setConversations] = useState<StudioMemorySourceConversationSummary[]>([]);\n const [selectedUserId, setSelectedUserId] = useState(\"\");\n const [selectedConversationRef, setSelectedConversationRef] = useState(\"\");\n const [messages, setMessages] = useState<StudioMemorySourceConversationMessages | undefined>();\n const [steps, setSteps] = useState<StudioMemorySourceConversationSteps | undefined>();\n const [sourcesLoading, setSourcesLoading] = useState(false);\n const [loading, setLoading] = useState(false);\n const [detailLoading, setDetailLoading] = useState(false);\n const [error, setError] = useState(\"\");\n const memoryRequest = useRef(0);\n\n const selectedSource = sources.find((source) => source.ref === selectedSourceRef);\n\n const loadSources = useCallback(async () => {\n if (!props.enabled) {\n setSources([]);\n setSelectedSourceRef(\"\");\n return;\n }\n setSourcesLoading(true);\n setError(\"\");\n try {\n const response = await fetch(\"/memory/sources\");\n if (!response.ok) throw new Error(`Memory sources failed with HTTP ${response.status}`);\n const body = (await response.json()) as StudioMemorySourcesPage;\n setSources(body.sources);\n setSelectedSourceRef((current) =>\n body.sources.some((source) => source.ref === current)\n ? current\n : defaultSourceRef(body.sources),\n );\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : String(loadError));\n } finally {\n setSourcesLoading(false);\n }\n }, [props.enabled]);\n\n useEffect(() => {\n void loadSources();\n }, [loadSources]);\n\n const loadMemory = useCallback(async () => {\n const requestId = memoryRequest.current + 1;\n memoryRequest.current = requestId;\n if (!props.enabled || selectedSource === undefined || !selectedSource.available) {\n setUsers([]);\n setConversations([]);\n setMessages(undefined);\n setSteps(undefined);\n setLoading(false);\n return;\n }\n setLoading(true);\n setError(\"\");\n try {\n const sourcePath = `/memory/sources/${encodeURIComponent(selectedSource.ref)}`;\n const [usersResponse, conversationsResponse] = await Promise.all([\n fetch(`${sourcePath}/users?limit=50`),\n fetch(`${sourcePath}/conversations?limit=100`),\n ]);\n if (!usersResponse.ok) {\n throw new Error(`Memory users failed with HTTP ${usersResponse.status}`);\n }\n if (!conversationsResponse.ok) {\n throw new Error(`Memory conversations failed with HTTP ${conversationsResponse.status}`);\n }\n const usersBody = (await usersResponse.json()) as StudioMemorySourceUsersPage;\n const conversationsBody =\n (await conversationsResponse.json()) as StudioMemorySourceConversationsPage;\n if (memoryRequest.current !== requestId) return;\n setUsers(usersBody.users);\n setConversations(conversationsBody.conversations);\n setSelectedConversationRef(\n (current) =>\n conversationsBody.conversations.find((conversation) => conversation.ref === current)\n ?.ref ??\n conversationsBody.conversations[0]?.ref ??\n \"\",\n );\n } catch (loadError) {\n if (memoryRequest.current === requestId) {\n setError(loadError instanceof Error ? loadError.message : String(loadError));\n }\n } finally {\n if (memoryRequest.current === requestId) setLoading(false);\n }\n }, [props.enabled, selectedSource]);\n\n useEffect(() => {\n setSelectedUserId(\"\");\n setSelectedConversationRef(\"\");\n setUsers([]);\n setConversations([]);\n setMessages(undefined);\n setSteps(undefined);\n void loadMemory();\n }, [loadMemory]);\n\n useEffect(() => {\n if (\n !props.enabled ||\n selectedSource === undefined ||\n !selectedSource.available ||\n selectedConversationRef.length === 0\n ) {\n setMessages(undefined);\n setSteps(undefined);\n return;\n }\n const sourceRef = selectedSource.ref;\n let cancelled = false;\n async function loadDetail() {\n setDetailLoading(true);\n setError(\"\");\n try {\n const conversationPath = `/memory/sources/${encodeURIComponent(\n sourceRef,\n )}/conversations/${encodeURIComponent(selectedConversationRef)}`;\n const [messagesResponse, stepsResponse] = await Promise.all([\n fetch(`${conversationPath}/messages`),\n fetch(`${conversationPath}/steps`),\n ]);\n if (!messagesResponse.ok) {\n throw new Error(`Conversation messages failed with HTTP ${messagesResponse.status}`);\n }\n if (!stepsResponse.ok) {\n throw new Error(`Conversation steps failed with HTTP ${stepsResponse.status}`);\n }\n if (!cancelled) {\n setMessages((await messagesResponse.json()) as StudioMemorySourceConversationMessages);\n setSteps((await stepsResponse.json()) as StudioMemorySourceConversationSteps);\n }\n } catch (loadError) {\n if (!cancelled) {\n setError(loadError instanceof Error ? loadError.message : String(loadError));\n setMessages(undefined);\n setSteps(undefined);\n }\n } finally {\n if (!cancelled) setDetailLoading(false);\n }\n }\n void loadDetail();\n return () => {\n cancelled = true;\n };\n }, [props.enabled, selectedConversationRef, selectedSource]);\n\n const visibleConversations = useMemo(\n () =>\n selectedUserId.length === 0\n ? conversations\n : conversations.filter((conversation) => conversation.userId === selectedUserId),\n [conversations, selectedUserId],\n );\n const totals = useMemo(() => memoryTotals(users, conversations), [conversations, users]);\n const selectedConversation =\n visibleConversations.find((conversation) => conversation.ref === selectedConversationRef) ??\n visibleConversations[0];\n\n useEffect(() => {\n if (visibleConversations.length === 0) {\n setSelectedConversationRef(\"\");\n return;\n }\n if (\n !visibleConversations.some((conversation) => conversation.ref === selectedConversationRef)\n ) {\n setSelectedConversationRef(visibleConversations[0]?.ref ?? \"\");\n }\n }, [selectedConversationRef, visibleConversations]);\n\n return (\n <StudioPageShell className=\"grid-rows-[auto_minmax(0,1fr)]\" aria-label=\"Memory\">\n <StudioPageHeader\n title=\"Memory\"\n description=\"Inspect persisted agent conversations directly. Studio sessions appear only as a fallback for agents without configured memory.\"\n action={\n <div className=\"flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start\">\n {sources.length === 0 ? null : (\n <Select value={selectedSourceRef} onValueChange={setSelectedSourceRef}>\n <SelectTrigger className=\"h-8 min-h-8 w-60 rounded-md border-border text-xs max-sm:w-full\">\n <SelectValue placeholder=\"Memory source\" />\n </SelectTrigger>\n <SelectContent align=\"end\">\n {sources.map((source) => (\n <SelectItem value={source.ref} key={source.ref}>\n {source.label}\n {source.available ? \"\" : \" (unavailable)\"}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n <StudioHeaderMetric label=\"users\" value={totals.userCount} />\n <StudioHeaderMetric label=\"conversations\" value={totals.conversationCount} />\n <StudioHeaderMetric label=\"messages\" value={totals.messageCount} />\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n type=\"button\"\n variant=\"secondary\"\n disabled={sourcesLoading || loading}\n onClick={() => void loadSources()}\n >\n Refresh\n </Button>\n </div>\n }\n />\n\n <StudioPageContent className=\"overflow-hidden\">\n {!props.enabled ? (\n <StudioEmptyState\n title=\"Memory unavailable\"\n text=\"No agent memory or Studio session store is configured.\"\n />\n ) : sourcesLoading && sources.length === 0 ? (\n <StudioEmptyState title=\"Loading memory\" text=\"Discovering configured memory sources.\" />\n ) : error.length > 0 && sources.length === 0 ? (\n <StudioEmptyState title=\"Memory error\" text={error} />\n ) : selectedSource === undefined ? (\n <StudioEmptyState title=\"No memory sources\" text=\"No registered agent exposes memory.\" />\n ) : !selectedSource.available ? (\n <UnavailableSource source={selectedSource} />\n ) : loading && conversations.length === 0 ? (\n <StudioEmptyState title=\"Loading memory\" text={`Reading ${selectedSource.label}.`} />\n ) : error.length > 0 && conversations.length === 0 ? (\n <StudioEmptyState title=\"Memory error\" text={error} />\n ) : conversations.length === 0 ? (\n <MemoryEmptyDashboard\n source={selectedSource}\n userCount={users.length}\n onRefresh={() => void loadMemory()}\n />\n ) : (\n <div\n className={[\n \"grid h-full min-h-0 overflow-hidden\",\n error.length === 0 ? \"grid-rows-[minmax(0,1fr)]\" : \"grid-rows-[auto_minmax(0,1fr)]\",\n ].join(\" \")}\n >\n {error.length === 0 ? null : <InlineError message={error} />}\n <div className=\"grid min-h-0 grid-cols-[260px_minmax(320px,0.78fr)_minmax(0,1.22fr)] overflow-hidden border-t border-border/80 max-xl:grid-cols-[240px_minmax(0,1fr)] max-xl:grid-rows-[minmax(240px,0.42fr)_minmax(0,1fr)] max-md:grid-cols-1 max-md:grid-rows-[auto_minmax(240px,0.38fr)_minmax(0,1fr)]\">\n <MemoryUserRail\n users={users}\n selectedUserId={selectedUserId}\n totalConversations={conversations.length}\n onSelect={setSelectedUserId}\n />\n <ConversationLedger\n agents={props.agents}\n conversations={visibleConversations}\n selectedConversationRef={selectedConversation?.ref ?? \"\"}\n source={selectedSource}\n onSelect={setSelectedConversationRef}\n />\n <ConversationDetail\n agents={props.agents}\n conversation={selectedConversation}\n detailLoading={detailLoading}\n messages={messages}\n source={selectedSource}\n steps={steps}\n />\n </div>\n </div>\n )}\n </StudioPageContent>\n </StudioPageShell>\n );\n}\n\nfunction MemoryUserRail(props: {\n users: StudioMemorySourceUsersPage[\"users\"];\n selectedUserId: string;\n totalConversations: number;\n onSelect: (userId: string) => void;\n}) {\n return (\n <aside className=\"min-h-0 overflow-auto border-r border-border/80 pr-3 max-md:border-b max-md:border-r-0 max-md:pr-0\">\n <div className=\"grid gap-3 py-4 pr-3 max-md:pr-0\">\n <SectionLabel label=\"Users\" value={props.users.length} />\n <UserFilterButton\n active={props.selectedUserId.length === 0}\n title=\"All users\"\n detail={`${props.totalConversations} conversations`}\n onClick={() => props.onSelect(\"\")}\n />\n <div className=\"grid gap-1\">\n {props.users.map((user) => (\n <UserFilterButton\n active={props.selectedUserId === user.userId}\n title={user.userId}\n detail={`${user.conversationCount} conversations / ${formatRelativeTime(\n user.lastInteractionAt,\n )}`}\n key={user.userId}\n onClick={() => props.onSelect(user.userId)}\n />\n ))}\n </div>\n </div>\n </aside>\n );\n}\n\nfunction UserFilterButton(props: {\n active: boolean;\n title: string;\n detail: string;\n onClick: () => void;\n}) {\n return (\n <button\n className={[\n \"grid min-w-0 gap-1 rounded-lg border border-transparent px-3 py-2.5 text-left transition duration-200 hover:border-border/80 hover:bg-muted/25 focus-visible:border-ring focus-visible:outline-none\",\n props.active ? \"border-border/80 bg-muted/35\" : \"\",\n ].join(\" \")}\n type=\"button\"\n onClick={props.onClick}\n >\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">{props.title}</span>\n <span className=\"min-w-0 truncate text-xs leading-5 text-muted-foreground\">\n {props.detail}\n </span>\n </button>\n );\n}\n\nfunction ConversationLedger(props: {\n agents: StudioConfig[\"agents\"];\n conversations: StudioMemorySourceConversationSummary[];\n selectedConversationRef: string;\n source: StudioMemorySourceSummary;\n onSelect: (conversationRef: string) => void;\n}) {\n return (\n <section className=\"min-h-0 overflow-auto border-r border-border/80 px-4 max-xl:border-r-0 max-xl:pr-0 max-md:border-b max-md:px-0\">\n <div className=\"grid gap-3 py-4\">\n <SectionLabel label=\"Conversations\" value={props.conversations.length} />\n {props.conversations.length === 0 ? (\n <div className=\"border-y border-dashed border-border/80 px-3 py-8 text-center text-sm text-muted-foreground\">\n No conversations for this user.\n </div>\n ) : (\n <div className=\"grid border-y border-border/80\">\n {props.conversations.map((conversation) => (\n <ConversationRow\n active={conversation.ref === props.selectedConversationRef}\n agentName={sourceAgentLabel(props.agents, props.source, conversation.agentIds)}\n conversation={conversation}\n key={conversation.ref}\n onSelect={() => props.onSelect(conversation.ref)}\n />\n ))}\n </div>\n )}\n </div>\n </section>\n );\n}\n\nfunction ConversationRow(props: {\n conversation: StudioMemorySourceConversationSummary;\n agentName: string;\n active: boolean;\n onSelect: () => void;\n}) {\n return (\n <button\n className={[\n \"grid min-w-0 gap-2 border-b border-border/70 px-3 py-3 text-left transition duration-200 last:border-b-0 hover:bg-muted/20 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\",\n props.active ? \"bg-muted/35\" : \"\",\n ].join(\" \")}\n type=\"button\"\n onClick={props.onSelect}\n >\n <div className=\"flex min-w-0 items-start justify-between gap-3\">\n <div className=\"grid min-w-0 gap-1\">\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {props.conversation.title ?? props.conversation.sessionId}\n </span>\n <span className=\"min-w-0 truncate text-xs text-muted-foreground\">\n {props.agentName} / {props.conversation.userId}\n </span>\n </div>\n <span className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {props.conversation.messageCount}\n </span>\n </div>\n <div className=\"flex min-w-0 flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground\">\n <span>{formatRelativeTime(props.conversation.updatedAt)}</span>\n <span className=\"min-w-0 truncate\">{props.conversation.sessionId}</span>\n </div>\n </button>\n );\n}\n\nfunction ConversationDetail(props: {\n agents: StudioConfig[\"agents\"];\n conversation: StudioMemorySourceConversationSummary | undefined;\n detailLoading: boolean;\n messages: StudioMemorySourceConversationMessages | undefined;\n source: StudioMemorySourceSummary;\n steps: StudioMemorySourceConversationSteps | undefined;\n}) {\n if (props.conversation === undefined) {\n return (\n <section className=\"min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1\">\n <StudioEmptyState\n title=\"No conversation selected\"\n text=\"Choose a conversation to inspect.\"\n />\n </section>\n );\n }\n\n return (\n <section className=\"min-h-0 overflow-auto py-4 pl-5 max-xl:col-span-2 max-xl:pl-0 max-md:col-span-1\">\n <div className=\"grid min-w-0 gap-5\">\n <header className=\"grid gap-4 border-b border-border/80 pb-5\">\n <div className=\"flex min-w-0 items-start justify-between gap-4 max-md:grid\">\n <div className=\"grid min-w-0 gap-2\">\n <div className=\"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground\">\n Persisted conversation\n </div>\n <h2 className=\"m-0 min-w-0 truncate text-2xl font-semibold leading-none text-foreground\">\n {props.conversation.title ?? props.conversation.sessionId}\n </h2>\n <span className=\"min-w-0 break-all font-mono text-xs text-muted-foreground\">\n {props.conversation.ref}\n </span>\n </div>\n <div className=\"flex flex-wrap justify-end gap-2 max-md:justify-start\">\n <Badge className=\"border-border/80 bg-muted/45 text-foreground\">\n {props.source.storeKind ?? props.source.kind}\n </Badge>\n <Badge className=\"border-border/80 bg-muted/45 text-foreground\">\n {sourceAgentLabel(props.agents, props.source, props.conversation.agentIds)}\n </Badge>\n </div>\n </div>\n <div className=\"grid border-y border-border/80 sm:grid-cols-4 sm:divide-x sm:divide-border/80\">\n <Fact label=\"user\" value={props.conversation.userId} />\n <Fact label=\"messages\" value={props.conversation.messageCount} />\n <Fact label=\"created\" value={formatRelativeTime(props.conversation.createdAt)} />\n <Fact label=\"updated\" value={formatRelativeTime(props.conversation.updatedAt)} />\n </div>\n </header>\n\n {props.detailLoading ? (\n <StudioEmptyState title=\"Loading detail\" text=\"Reading persisted messages.\" />\n ) : (\n <div className=\"grid gap-4\">\n {props.conversation.metadata === undefined ? null : (\n <JsonPanel title=\"metadata\" value={props.conversation.metadata} />\n )}\n <MemoryGenerationLedger records={props.messages?.records ?? []} />\n <JsonPanel title=\"messages\" value={props.messages?.messages ?? []} />\n <JsonPanel title=\"message records\" value={props.messages?.records ?? []} />\n <JsonPanel title=\"derived transcript\" value={props.steps?.steps ?? []} />\n </div>\n )}\n </div>\n </section>\n );\n}\n\nfunction UnavailableSource(props: { source: StudioMemorySourceSummary }) {\n return (\n <StudioEmptyState\n className=\"h-full\"\n title={`${props.source.label} is not inspectable`}\n text={props.source.reason ?? \"This memory store does not expose read-only discovery.\"}\n />\n );\n}\n\nfunction JsonPanel(props: { title: string; value: unknown }) {\n const count = Array.isArray(props.value) ? props.value.length : undefined;\n return (\n <details className=\"group grid min-w-0 overflow-hidden border-y border-border/80\" open>\n <summary className=\"flex min-h-11 cursor-pointer list-none items-center justify-between gap-3 bg-muted/10 px-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden\">\n <span>{props.title}</span>\n <span className=\"font-medium normal-case tracking-normal\">\n {count === undefined ? \"JSON\" : `${count} items`}\n </span>\n </summary>\n <div className=\"min-w-0 overflow-x-auto border-t border-border/70\">\n <pre className=\"m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground\">\n <code>\n <JsonSyntax text={formatJson(props.value)} />\n </code>\n </pre>\n </div>\n </details>\n );\n}\n\nfunction SectionLabel(props: { label: string; value: number }) {\n return (\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <h2 className=\"m-0 text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground\">\n {props.label}\n </h2>\n <span className=\"text-xs font-semibold tabular-nums text-muted-foreground\">\n {props.value}\n </span>\n </div>\n );\n}\n\nfunction Fact(props: { label: string; value: string | number }) {\n return (\n <div className=\"grid min-w-0 gap-1 px-3 py-3 first:pl-0 last:pr-0\">\n <span className=\"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground\">\n {props.label}\n </span>\n <span className=\"min-w-0 truncate text-sm text-foreground\" title={String(props.value)}>\n {props.value}\n </span>\n </div>\n );\n}\n\nfunction MemoryEmptyDashboard(props: {\n source: StudioMemorySourceSummary;\n userCount: number;\n onRefresh: () => void;\n}) {\n return (\n <StudioEmptyState\n className=\"h-full\"\n title=\"No saved conversations yet\"\n text={`Conversations will appear here after the connected agent writes to ${props.source.label}. ${props.userCount} users are currently available.`}\n action={\n <div className=\"flex min-w-0 flex-wrap items-center justify-center gap-3\">\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n type=\"button\"\n variant=\"secondary\"\n onClick={props.onRefresh}\n >\n Refresh\n </Button>\n <span className=\"text-xs leading-5 text-muted-foreground\">\n Existing database conversations are discovered automatically.\n </span>\n </div>\n }\n />\n );\n}\n\nfunction InlineError(props: { message: string }) {\n return (\n <div className=\"mb-3 border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs leading-5 text-destructive\">\n {props.message}\n </div>\n );\n}\n\nfunction memoryTotals(\n users: StudioMemorySourceUsersPage[\"users\"],\n conversations: StudioMemorySourceConversationSummary[],\n): { userCount: number; conversationCount: number; messageCount: number } {\n return {\n userCount: users.length,\n conversationCount: conversations.length,\n messageCount: conversations.reduce(\n (total, conversation) => total + conversation.messageCount,\n 0,\n ),\n };\n}\n\nfunction defaultSourceRef(sources: StudioMemorySourceSummary[]): string {\n return (\n sources.find((source) => source.kind === \"agent\" && source.available)?.ref ??\n sources.find((source) => source.available)?.ref ??\n sources[0]?.ref ??\n \"\"\n );\n}\n\nfunction formatJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction sourceAgentLabel(\n agents: StudioConfig[\"agents\"],\n source: StudioMemorySourceSummary,\n agentIds: string[],\n): string {\n if (agentIds.length === 1) {\n const agentId = agentIds[0] ?? \"agent\";\n return agents.find((agent) => agent.id === agentId)?.name ?? agentId;\n }\n return source.label;\n}\n"],"mappings":"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"}
|