dsh-memory-eternal 0.2.8 → 0.3.0

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 CHANGED
@@ -126,7 +126,7 @@ Vault 目录结构:
126
126
  - **统计概览**:总卡数、近 7 天新增、标签数、知识卡数
127
127
  - **检索**:中文片段即时搜索(280ms 防抖)
128
128
  - **知识卡网格**:kind 筛选(全部/项目/知识/内容/提示词/业务/工具/教训),点击卡片阅读全文(frontmatter 一并展示)
129
- - **知识图谱(增强版)**:力导向有机布局(大规模自动切**径向布局** + 节点/连线上限 + 标签节流,**几千节点不卡**);节点 = 知识卡(按 kind 渐变+发光着色、按连接数自动放大);连线 = `[[wikilink]]` 或共享标签(曲线渐变 + 流动动画);**滚轮缩放、按住左键拖动画布**、**左键凸显关联节点并淡化无关节点**、**右键打开卡片**、悬停高亮
129
+ - **知识图谱(增强版)**:**多环径向 / 力导向**混合布局(按 kind 分扇区、枢纽在内圈、环间距不重叠,数量大也不乱);节点 = 知识卡(按 kind 渐变+发光着色、按连接数自动放大);连线 = `[[wikilink]]` 或共享标签(曲线渐变 + 流动动画,只保留**高影响力主干边**避免毛球);**默认只显示枢纽标签**、放大后全量显示;**几千节点不卡**(节点/连线上限 + 标签节流 + O(n) 布局);**滚轮缩放、按住左键拖动画布**、**左键凸显关联节点并淡化无关节点**、**右键打开卡片**、悬停高亮
130
130
 
131
131
  ## 🔧 设置
132
132
 
@@ -176,6 +176,9 @@ dsh-memory-eternal/
176
176
 
177
177
  ## 📦 发布记录
178
178
 
179
+ - **v0.3.0**:知识图谱**科学布局**升级——多环径向/力导向混合布局(按 kind 分扇区、枢纽在内圈、环间距不重叠,数量大也不乱);只保留**高影响力主干边**(避免毛球);默认只显示**枢纽标签**、放大后全量;大图关闭节点发光提升性能。
180
+ - **v0.2.9**:修复 **GitHub 源安装无法启动**——提交 `lib/client.js`(此前被忽略未入库,GitHub 拉取的包缺客户端 bundle,导致 DSH 启动失败)。
181
+ - **v0.2.8**:安装说明去掉 `npx` 前缀,只保留跨平台 `dsh plugin --profile web add`。
179
182
  - **v0.2.7**:安装说明跨平台化——主推 `dsh plugin --profile web add`(无需 cd/平台路径),注明官方 registry(避免 npmmirror 滞后)与 pnpm 备选。
180
183
  - **v0.2.6**:安装/更新说明补充——DSH profile 为 pnpm workspace,用 `pnpm add dsh-memory-eternal@latest`(勿用 `npm install`,会因 `link:` 报 `EUNSUPPORTEDPROTOCOL`)。
181
184
  - **v0.2.5**:安装方式统一为 `dsh plugin --profile web add`(README 标注 npx 备选写法)。
package/lib/client.js CHANGED
@@ -3,7 +3,7 @@ window.__ModuleLoader__.load({
3
3
  factory: (require) => {
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
- var te=Object.create;var q=Object.defineProperty;var ae=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ne=Object.getPrototypeOf,oe=Object.prototype.hasOwnProperty;var se=(t,r)=>{for(var n in r)q(t,n,{get:r[n],enumerable:!0})},V=(t,r,n,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let d of re(r))!oe.call(t,d)&&d!==n&&q(t,d,{get:()=>r[d],enumerable:!(o=ae(r,d))||o.enumerable});return t};var ie=(t,r,n)=>(n=t!=null?te(ne(t)):{},V(r||!t||!t.__esModule?q(n,"default",{value:t,enumerable:!0}):n,t)),le=t=>V(q({},"__esModule",{value:!0}),t);var ze={};se(ze,{apply:()=>ge,inject:()=>ce});module.exports=le(ze);var c=ie(require("react"),1),e=require("react/jsx-runtime"),H="memory-eternal",U="/memory-eternal/api",ce=["settingsScope","slots","locale","connection","remote"],de={nav:"\u8BB0\u5FC6",loading:"\u52A0\u8F7D\u4E2D\u2026",refresh:"\u5237\u65B0",overview:"\u8BB0\u5FC6\u5E93\u6982\u89C8",total:"\u77E5\u8BC6\u5361",recent:"\u8FD1 7 \u5929\u65B0\u589E",tags:"\u6807\u7B7E",searchPlaceholder:"\u641C\u7D22\u8BB0\u5FC6\uFF08\u652F\u6301\u4E2D\u6587\u7247\u6BB5\uFF09\u2026",search:"\u641C\u7D22",all:"\u5168\u90E8",kindProject:"\u9879\u76EE",kindKnowledge:"\u77E5\u8BC6",kindContent:"\u5185\u5BB9",kindPrompt:"\u63D0\u793A\u8BCD",kindBusiness:"\u4E1A\u52A1",kindTool:"\u5DE5\u5177",kindMistake:"\u6559\u8BAD",cardsTab:"\u77E5\u8BC6\u5361",graphTab:"\u77E5\u8BC6\u56FE\u8C31",graph:"\u77E5\u8BC6\u56FE\u8C31",graphHint:"\u8282\u70B9=\u77E5\u8BC6\u5361\uFF1B\u8FDE\u7EBF=[[\u94FE\u63A5]] \u6216\u5171\u4EAB\u6807\u7B7E\u3002\u70B9\u51FB\u8282\u70B9\u9605\u8BFB\u5361\u7247\u3002",graphTip:"\u5DE6\u952E\u51F8\u663E\u5173\u8054\u8282\u70B9 \xB7 \u53F3\u952E\u6253\u5F00\u5361\u7247 \xB7 \u6EDA\u8F6E\u7F29\u653E \xB7 \u6309\u4F4F\u5DE6\u952E\u62D6\u52A8\u753B\u5E03",capped:"\u5DF2\u5C55\u793A\u6700\u6838\u5FC3\u7684",clearFocus:"\u53D6\u6D88\u9AD8\u4EAE",empty:"\u8BB0\u5FC6\u5E93\u8FD8\u662F\u7A7A\u7684\u3002\u591A\u804A\u51E0\u8F6E\u540E\uFF0C\u503C\u5F97\u4FDD\u5B58\u7684\u5185\u5BB9\u4F1A\u81EA\u52A8\u6C89\u6DC0\u6210\u77E5\u8BC6\u5361\u3002",emptyGraph:"\u56FE\u8C31\u6682\u65E0\u6570\u636E\u3002",open:"\u9605\u8BFB",updated:"\u66F4\u65B0\u4E8E",created:"\u521B\u5EFA\u4E8E",source:"\u6765\u6E90",close:"\u5173\u95ED",vaultDir:"\u8BB0\u5FC6\u5E93\u76EE\u5F55",capture:"\u81EA\u52A8\u6C89\u6DC0",recall:"\u81EA\u52A8\u53EC\u56DE",enabled:"\u5DF2\u542F\u7528",disabled:"\u5DF2\u7981\u7528",error:"\u52A0\u8F7D\u5931\u8D25",back:"\u8FD4\u56DE\u5217\u8868",cardCount:"\u5F20\u5361",nodes:"\u8282\u70B9",edges:"\u8FDE\u7EBF",memoryTitle:"\u8BB0\u5FC6\u5E93",memoryHint:"\u4F60\u7684\u672C\u5730\u7B2C\u4E8C\u5927\u8111",zoomIn:"\u653E\u5927",zoomOut:"\u7F29\u5C0F",fit:"\u9002\u5E94"},pe={nav:"Memory",loading:"Loading\u2026",refresh:"Refresh",overview:"Memory Overview",total:"Cards",recent:"Added (7d)",tags:"Tags",searchPlaceholder:"Search memory\u2026",search:"Search",all:"All",kindProject:"Projects",kindKnowledge:"Knowledge",kindContent:"Content",kindPrompt:"Prompts",kindBusiness:"Business",kindTool:"Tools",kindMistake:"Mistakes",cardsTab:"Cards",graphTab:"Graph",graph:"Knowledge Graph",graphHint:"Nodes = cards; edges = [[links]] or shared tags. Click a node to read.",graphTip:"Left-click focuses neighbors \xB7 right-click opens card \xB7 scroll to zoom \xB7 hold left to pan",capped:"Showing the",clearFocus:"Clear highlight",empty:"Memory is empty. After a few conversations, valuable content is auto-captured.",emptyGraph:"No graph data yet.",open:"Read",updated:"Updated",created:"Created",source:"Source",close:"Close",vaultDir:"Vault directory",capture:"Auto capture",recall:"Auto recall",enabled:"on",disabled:"off",error:"Load failed",back:"Back to list",cardCount:"cards",nodes:"nodes",edges:"edges",memoryTitle:"Memory Library",memoryHint:"Your local second brain",zoomIn:"Zoom in",zoomOut:"Zoom out",fit:"Fit"},me=["all","project","knowledge","content","prompt","business","tool","mistake"],I={project:"#3b82f6",knowledge:"#22c55e",content:"#f43f5e",prompt:"#06b6d4",business:"#eab308",tool:"#f97316",mistake:"#a855f7",other:"#64748b"},_={project:"kindProject",knowledge:"kindKnowledge",content:"kindContent",prompt:"kindPrompt",business:"kindBusiness",tool:"kindTool",mistake:"kindMistake",other:"kindKnowledge"},Y=`
6
+ var ae=Object.create;var q=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,se=Object.prototype.hasOwnProperty;var ie=(e,r)=>{for(var n in r)q(e,n,{get:r[n],enumerable:!0})},V=(e,r,n,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let g of ne(r))!se.call(e,g)&&g!==n&&q(e,g,{get:()=>r[g],enumerable:!(o=re(r,g))||o.enumerable});return e};var le=(e,r,n)=>(n=e!=null?ae(oe(e)):{},V(r||!e||!e.__esModule?q(n,"default",{value:e,enumerable:!0}):n,e)),ce=e=>V(q({},"__esModule",{value:!0}),e);var je={};ie(je,{apply:()=>ue,inject:()=>de});module.exports=ce(je);var p=le(require("react"),1),t=require("react/jsx-runtime"),H="memory-eternal",U="/memory-eternal/api",de=["settingsScope","slots","locale","connection","remote"],pe={nav:"\u8BB0\u5FC6",loading:"\u52A0\u8F7D\u4E2D\u2026",refresh:"\u5237\u65B0",overview:"\u8BB0\u5FC6\u5E93\u6982\u89C8",total:"\u77E5\u8BC6\u5361",recent:"\u8FD1 7 \u5929\u65B0\u589E",tags:"\u6807\u7B7E",searchPlaceholder:"\u641C\u7D22\u8BB0\u5FC6\uFF08\u652F\u6301\u4E2D\u6587\u7247\u6BB5\uFF09\u2026",search:"\u641C\u7D22",all:"\u5168\u90E8",kindProject:"\u9879\u76EE",kindKnowledge:"\u77E5\u8BC6",kindContent:"\u5185\u5BB9",kindPrompt:"\u63D0\u793A\u8BCD",kindBusiness:"\u4E1A\u52A1",kindTool:"\u5DE5\u5177",kindMistake:"\u6559\u8BAD",cardsTab:"\u77E5\u8BC6\u5361",graphTab:"\u77E5\u8BC6\u56FE\u8C31",graph:"\u77E5\u8BC6\u56FE\u8C31",graphHint:"\u8282\u70B9=\u77E5\u8BC6\u5361\uFF1B\u8FDE\u7EBF=[[\u94FE\u63A5]] \u6216\u5171\u4EAB\u6807\u7B7E\u3002\u70B9\u51FB\u8282\u70B9\u9605\u8BFB\u5361\u7247\u3002",graphTip:"\u5DE6\u952E\u51F8\u663E\u5173\u8054\u8282\u70B9 \xB7 \u53F3\u952E\u6253\u5F00\u5361\u7247 \xB7 \u6EDA\u8F6E\u7F29\u653E \xB7 \u6309\u4F4F\u5DE6\u952E\u62D6\u52A8\u753B\u5E03",capped:"\u5DF2\u5C55\u793A\u6700\u6838\u5FC3\u7684",clearFocus:"\u53D6\u6D88\u9AD8\u4EAE",empty:"\u8BB0\u5FC6\u5E93\u8FD8\u662F\u7A7A\u7684\u3002\u591A\u804A\u51E0\u8F6E\u540E\uFF0C\u503C\u5F97\u4FDD\u5B58\u7684\u5185\u5BB9\u4F1A\u81EA\u52A8\u6C89\u6DC0\u6210\u77E5\u8BC6\u5361\u3002",emptyGraph:"\u56FE\u8C31\u6682\u65E0\u6570\u636E\u3002",open:"\u9605\u8BFB",updated:"\u66F4\u65B0\u4E8E",created:"\u521B\u5EFA\u4E8E",source:"\u6765\u6E90",close:"\u5173\u95ED",vaultDir:"\u8BB0\u5FC6\u5E93\u76EE\u5F55",capture:"\u81EA\u52A8\u6C89\u6DC0",recall:"\u81EA\u52A8\u53EC\u56DE",enabled:"\u5DF2\u542F\u7528",disabled:"\u5DF2\u7981\u7528",error:"\u52A0\u8F7D\u5931\u8D25",back:"\u8FD4\u56DE\u5217\u8868",cardCount:"\u5F20\u5361",nodes:"\u8282\u70B9",edges:"\u8FDE\u7EBF",memoryTitle:"\u8BB0\u5FC6\u5E93",memoryHint:"\u4F60\u7684\u672C\u5730\u7B2C\u4E8C\u5927\u8111",zoomIn:"\u653E\u5927",zoomOut:"\u7F29\u5C0F",fit:"\u9002\u5E94"},me={nav:"Memory",loading:"Loading\u2026",refresh:"Refresh",overview:"Memory Overview",total:"Cards",recent:"Added (7d)",tags:"Tags",searchPlaceholder:"Search memory\u2026",search:"Search",all:"All",kindProject:"Projects",kindKnowledge:"Knowledge",kindContent:"Content",kindPrompt:"Prompts",kindBusiness:"Business",kindTool:"Tools",kindMistake:"Mistakes",cardsTab:"Cards",graphTab:"Graph",graph:"Knowledge Graph",graphHint:"Nodes = cards; edges = [[links]] or shared tags. Click a node to read.",graphTip:"Left-click focuses neighbors \xB7 right-click opens card \xB7 scroll to zoom \xB7 hold left to pan",capped:"Showing the",clearFocus:"Clear highlight",empty:"Memory is empty. After a few conversations, valuable content is auto-captured.",emptyGraph:"No graph data yet.",open:"Read",updated:"Updated",created:"Created",source:"Source",close:"Close",vaultDir:"Vault directory",capture:"Auto capture",recall:"Auto recall",enabled:"on",disabled:"off",error:"Load failed",back:"Back to list",cardCount:"cards",nodes:"nodes",edges:"edges",memoryTitle:"Memory Library",memoryHint:"Your local second brain",zoomIn:"Zoom in",zoomOut:"Zoom out",fit:"Fit"},ge=["all","project","knowledge","content","prompt","business","tool","mistake"],L={project:"#3b82f6",knowledge:"#22c55e",content:"#f43f5e",prompt:"#06b6d4",business:"#eab308",tool:"#f97316",mistake:"#a855f7",other:"#64748b"},_={project:"kindProject",knowledge:"kindKnowledge",content:"kindContent",prompt:"kindPrompt",business:"kindBusiness",tool:"kindTool",mistake:"kindMistake",other:"kindKnowledge"},Y=`
7
7
  .memory-eternal-root { font-family: inherit; color: var(--dsw-alias-label-primary, #1f2937); }
8
8
  .mc-card { background: var(--dsw-alias-bg-layer-1, #fff); border: 1px solid var(--dsw-alias-border-l1, #e5e7eb); border-radius: 12px; padding: 14px 16px; }
9
9
  .mc-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin-bottom: 14px; }
@@ -69,7 +69,7 @@ var te=Object.create;var q=Object.defineProperty;var ae=Object.getOwnPropertyDes
69
69
  .me-graph-canvas.dragging { cursor: grabbing; }
70
70
  .me-graph-tip { font-size: 11px; opacity: 0.6; }
71
71
  .me-graph-canvas svg { width: 100%; height: 100%; display: block; }
72
- .me-graph-edge { fill: none; stroke: var(--dsw-alias-border-l2, #cbd5e1); stroke-width: 1.6; opacity: 0.75; stroke-dasharray: 4 5; animation: me-dash 1.6s linear infinite; }
72
+ .me-graph-edge { fill: none; stroke: var(--dsw-alias-border-l2, #cbd5e1); stroke-width: 1.3; opacity: 0.5; stroke-dasharray: 4 5; animation: me-dash 1.6s linear infinite; }
73
73
  @keyframes me-dash { to { stroke-dashoffset: -16; } }
74
74
  .me-graph-node { cursor: pointer; }
75
75
  .me-graph-node circle.inner { transition: r 0.18s; }
@@ -88,7 +88,7 @@ var te=Object.create;var q=Object.defineProperty;var ae=Object.getOwnPropertyDes
88
88
  .me-graph-legend { display: flex; gap: 12px; flex-wrap: wrap; padding: 2px 2px 0; font-size: 11px; opacity: 0.85; }
89
89
  .me-graph-legend .lg { display: inline-flex; align-items: center; gap: 5px; }
90
90
  .me-graph-hint { font-size: 11px; opacity: 0.6; margin-left: auto; }
91
- `;function ge(t){t.effect(()=>t.locale.register(H,{zh:de,en:pe}),"memory-eternal: locale");let r=t.locale.bind(H);t.effect(()=>t.slots.inject("settings.section",()=>t.slots.register({name:"settings.section",id:H,order:25,label:()=>r("nav"),locale:H,inject:()=>({})},()=>c.default.createElement(W,{t:r,inModal:!1}))),"memory-eternal: settings section"),t.effect(()=>t.slots.inject("sidebar.footer.action",()=>t.slots.register({name:"sidebar.footer.action",id:`${H}:footer`,order:100,label:()=>r("nav"),locale:H,inject:()=>({})},n=>c.default.createElement(fe,{t:r,wide:!(n&&n.wide===!1)}))),"memory-eternal: sidebar footer action")}function fe({t,wide:r}){let[n,o]=(0,c.useState)(!1);return(0,e.jsxs)("div",{className:`me-footer${r?"":" rail"}`,children:[(0,e.jsx)("style",{children:Y}),(0,e.jsxs)("button",{type:"button",className:"me-footer-btn",onClick:()=>o(!0),"aria-label":t("nav"),title:t("nav"),children:[(0,e.jsx)("span",{className:"me-footer-ico","aria-hidden":"true",children:(0,e.jsx)(Z,{})}),(0,e.jsx)("span",{className:"me-footer-label",children:t("nav")})]}),n&&(0,e.jsx)(ue,{t,onClose:()=>o(!1)})]})}function Z(){return(0,e.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[(0,e.jsx)("ellipse",{cx:"12",cy:"5.5",rx:"8",ry:"3"}),(0,e.jsx)("path",{d:"M4 5.5v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"}),(0,e.jsx)("path",{d:"M4 11.5v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"})]})}function ue({t,onClose:r}){return(0,c.useEffect)(()=>{let n=o=>{o.key==="Escape"&&r()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[r]),(0,e.jsxs)("div",{className:"me-overlay-top",onClick:r,children:[(0,e.jsx)("style",{children:Y}),(0,e.jsx)("div",{className:"me-modal",onClick:n=>n.stopPropagation(),children:(0,e.jsx)(W,{t,inModal:!0,onClose:r})})]})}function W({t,inModal:r,onClose:n}){let[o,d]=(0,c.useState)(null),[N,g]=(0,c.useState)([]),[l,z]=(0,c.useState)(!0),[D,j]=(0,c.useState)(""),[k,C]=(0,c.useState)("all"),[y,u]=(0,c.useState)(""),[M,f]=(0,c.useState)("cards"),[P,A]=(0,c.useState)(null),L=(0,c.useRef)(null),E=(0,c.useCallback)(async(p=k,$=y)=>{try{z(!0),j("");let v=new URLSearchParams;p&&p!=="all"&&v.set("kind",p),$.trim()&&v.set("q",$.trim());let a=await(await fetch(`${U}/cards?${v.toString()}`)).json();a.ok&&g(a.cards||[])}catch(v){j(String(v&&v.message?v.message:v))}finally{z(!1)}},[k,y]),h=(0,c.useCallback)(async()=>{try{let[p,$]=await Promise.all([fetch(`${U}/overview`).then(v=>v.json()),fetch(`${U}/cards`).then(v=>v.json())]);p.ok&&d(p),$.ok&&g($.cards||[])}catch(p){j(String(p&&p.message?p.message:p))}finally{z(!1)}},[]);(0,c.useEffect)(()=>(h(),()=>{L.current&&clearTimeout(L.current)}),[h]);let i=p=>{u(p),L.current&&clearTimeout(L.current),L.current=setTimeout(()=>E(k,p),280)},x=p=>{C(p),E(p,y)},T=async p=>{try{let v=await(await fetch(`${U}/card?path=${encodeURIComponent(p.path||p.id)}`)).json();v.ok&&A({path:v.path,title:p.title,text:v.text})}catch($){j(String($&&$.message?$.message:$))}};return(0,e.jsxs)("div",{className:"memory-eternal-root",style:{height:"100%",display:"flex",flexDirection:"column"},children:[(0,e.jsx)("style",{children:Y}),r&&(0,e.jsxs)("div",{className:"me-modal-head",children:[(0,e.jsxs)("div",{className:"me-modal-title",children:[(0,e.jsx)(Z,{}),(0,e.jsx)("h2",{children:t("memoryTitle")}),(0,e.jsx)("span",{children:t("memoryHint")})]}),(0,e.jsx)("div",{className:"spacer"}),(0,e.jsx)("button",{type:"button",className:"me-modal-close",onClick:n,"aria-label":t("close"),children:"\u2715"})]}),(0,e.jsxs)("div",{className:"me-modal-body",children:[(0,e.jsxs)("div",{className:"mc-stats",children:[(0,e.jsx)(X,{label:t("total"),value:o?o.total:"\u2014"}),(0,e.jsx)(X,{label:t("recent"),value:o?o.recent:"\u2014"}),(0,e.jsx)(X,{label:t("tags"),value:o?o.tags:"\u2014"}),(0,e.jsx)(X,{label:t("cardCount"),value:o?o.byKind?.knowledge??0:"\u2014"})]}),(0,e.jsxs)("div",{className:"mc-toolbar",children:[(0,e.jsx)("input",{type:"text",placeholder:t("searchPlaceholder"),value:y,onChange:p=>i(p.target.value)}),(0,e.jsxs)("div",{className:"mc-tabs",children:[(0,e.jsx)("button",{type:"button",className:`mc-tab${M==="cards"?" active":""}`,onClick:()=>f("cards"),children:t("cardsTab")}),(0,e.jsx)("button",{type:"button",className:`mc-tab${M==="graph"?" active":""}`,onClick:()=>f("graph"),children:t("graphTab")})]}),(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>h(),children:t("refresh")})]}),M==="cards"&&(0,e.jsx)("div",{className:"mc-chips",children:me.map(p=>(0,e.jsx)("button",{type:"button",className:`mc-chip${k===p?" active":""}`,onClick:()=>x(p),children:t(p==="all"?"all":_[p])},p))}),D&&(0,e.jsxs)("div",{className:"mc-empty",children:[t("error"),"\uFF1A",D]}),M==="cards"?l&&!N.length?(0,e.jsx)("div",{className:"mc-empty",children:t("loading")}):N.length===0?(0,e.jsx)("div",{className:"mc-empty",children:t("empty")}):(0,e.jsx)("div",{className:"mc-grid",children:N.map(p=>(0,e.jsx)(he,{card:p,t,onOpen:T},p.path))}):(0,e.jsx)(ye,{t,onOpen:T}),P&&(0,e.jsx)(be,{t,card:P,onClose:()=>A(null)})]})]})}var X=({label:t,value:r})=>(0,e.jsxs)("div",{className:"mc-stat mc-card",children:[(0,e.jsx)("b",{children:r}),(0,e.jsx)("span",{children:t})]}),he=({card:t,t:r,onOpen:n})=>(0,e.jsxs)("article",{className:"mc-cardrow mc-card",onClick:()=>n(t),children:[(0,e.jsxs)("h4",{children:[(0,e.jsx)("span",{className:"mc-kind",style:{background:I[t.kind]||I.other}}),t.title]}),(0,e.jsx)("p",{children:t.summary||""}),t.tags.length>0&&(0,e.jsx)("div",{className:"mc-tags",children:t.tags.slice(0,4).map(o=>(0,e.jsx)("span",{className:"mc-tag",children:o},o))}),(0,e.jsxs)("footer",{children:[(0,e.jsx)("span",{children:r(_[t.kind])}),(0,e.jsx)("span",{children:Ce(t.updated)})]})]});function be({t,card:r,onClose:n}){return(0,c.useEffect)(()=>{let o=d=>{d.key==="Escape"&&n()};return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[n]),(0,e.jsxs)("div",{className:"me-overlay",onClick:n,children:[(0,e.jsx)("style",{children:Y}),(0,e.jsxs)("div",{className:"me-dialog",onClick:o=>o.stopPropagation(),children:[(0,e.jsxs)("div",{className:"me-dialog-head",children:[(0,e.jsx)("h3",{children:r.title}),(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:n,children:t("close")})]}),(0,e.jsx)("div",{className:"me-dialog-body",children:r.text})]})]})}function ye({t,onOpen:r}){let[n,o]=(0,c.useState)(null),[d,N]=(0,c.useState)("");return(0,c.useEffect)(()=>{let g=!0;return fetch(`${U}/graph`).then(l=>l.json()).then(l=>{g&&o(l.ok?l:null)}).catch(l=>{g&&N(String(l&&l.message?l.message:l))}),()=>{g=!1}},[]),(0,e.jsxs)("div",{className:"me-graph",children:[(0,e.jsx)("style",{children:Y}),d&&(0,e.jsxs)("div",{className:"mc-empty",children:[t("error"),"\uFF1A",d]}),!n&&!d&&(0,e.jsx)("div",{className:"mc-empty",children:t("loading")}),n&&n.nodes.length===0&&(0,e.jsx)("div",{className:"mc-empty",children:t("emptyGraph")}),n&&n.nodes.length>0&&(0,e.jsx)(ve,{nodes:n.nodes,edges:n.edges,onOpen:r,t,countLabel:`${n.nodes.length} ${t("nodes")} \xB7 ${xe(n.edges)} ${t("edges")}`})]})}function xe(t){let r=new Set;for(let n of t||[])r.add([n.source,n.target].sort().join("|"));return r.size}function ve({nodes:t,edges:r,onOpen:n,t:o,countLabel:d}){let l=(0,c.useRef)(null),z=(0,c.useRef)(null),D=(0,c.useRef)(null),j=(0,c.useRef)(null),k=(0,c.useRef)({x:0,y:0,k:1}),C=(0,c.useRef)(null),y=(0,c.useRef)(!1),[u,M]=(0,c.useState)(null),f=(0,c.useMemo)(()=>{let a={};r.forEach(w=>{a[w.source]=(a[w.source]||0)+1,a[w.target]=(a[w.target]||0)+1});let s=420,m=900,b=t,S=!1;t.length>s&&(b=[...t].sort((w,K)=>(a[K.id]||0)-(a[w.id]||0)).slice(0,s),S=!0);let R=new Set(b.map(w=>w.id)),B=new Set,O=[];r.forEach(w=>{if(!R.has(w.source)||!R.has(w.target))return;let K=[w.source,w.target].sort().join("|");B.has(K)||(B.add(K),O.push(w))}),O.sort((w,K)=>(a[w.source]||0)+(a[w.target]||0)-((a[K.source]||0)+(a[K.target]||0)));let F=Math.min(b.length,28),J=b.map(w=>a[w.id]||0).sort((w,K)=>K-w),ee=F>0?J[F-1]:1/0;return{list:b,es:O.slice(0,m),capped:S,maxDeg:Math.max(1,...Object.values(a)),deg:a,hubMin:ee}},[t,r]),P=(0,c.useMemo)(()=>we(f.list,f.es,980,620),[f.list,f.es,980,620]),A=(0,c.useMemo)(()=>f.list.reduce((a,s,m)=>(a[s.id]=m,a),{}),[f.list]),L=(0,c.useMemo)(()=>{let a={};return f.list.forEach(s=>{a[s.id]=new Set}),f.es.forEach(s=>{a[s.source]&&a[s.source].add(s.target),a[s.target]&&a[s.target].add(s.source)}),a},[f.list,f.es]),E=(0,c.useCallback)(()=>{let a=D.current;if(!a)return;let{x:s,y:m,k:b}=k.current;a.setAttribute("transform",`translate(${s} ${m}) scale(${b})`),j.current&&j.current.classList.toggle("all",b>=1.4)},[]);(0,c.useEffect)(()=>{E()},[E,P]);let h=(0,c.useCallback)((a,s)=>{let m=z.current;if(!m||typeof m.getScreenCTM!="function")return{x:a,y:s};let b=m.getScreenCTM();if(!b)return{x:a,y:s};let S=new DOMPoint(a,s).matrixTransform(b.inverse());return{x:S.x,y:S.y}},[]),i=(0,c.useCallback)((a,s)=>{let m=k.current,b=Math.min(5,Math.max(.25,m.k*s));k.current={k:b,x:a.x-b/m.k*(a.x-m.x),y:a.y-b/m.k*(a.y-m.y)},E()},[E]);(0,c.useEffect)(()=>{let a=l.current;if(!a)return;let s=m=>{m.preventDefault(),i(h(m.clientX,m.clientY),m.deltaY<0?1.12:1/1.12)};return a.addEventListener("wheel",s,{passive:!1}),()=>a.removeEventListener("wheel",s)},[h,i]);let x=a=>{if(a.button!==0)return;let s=h(a.clientX,a.clientY);C.current={px:s.x,py:s.y,tx:k.current.x,ty:k.current.y,started:!1,id:a.pointerId},y.current=!1},T=a=>{let s=C.current;if(!s)return;let m=h(a.clientX,a.clientY);Math.abs(m.x-s.px)+Math.abs(m.y-s.py)>1.5&&(y.current=!0,!s.started&&l.current&&l.current.setPointerCapture&&(l.current.setPointerCapture(a.pointerId),s.started=!0),l.current&&l.current.classList.add("dragging"),k.current={...k.current,x:s.tx+(m.x-s.px),y:s.ty+(m.y-s.py)},E())},p=()=>{C.current=null,l.current&&l.current.classList.remove("dragging")},$=a=>{n({path:a.id,title:a.title})},v=a=>{y.current||M(a.id)},G=a=>7+Math.min(9,(f.deg[a.id]||0)/f.maxDeg*9);return(0,e.jsxs)("div",{className:"me-graph",children:[(0,e.jsxs)("div",{className:"me-graph-toolbar",children:[(0,e.jsx)("span",{className:"me-graph-count",children:d}),u&&(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>M(null),children:o("clearFocus")}),(0,e.jsx)("span",{className:"spacer",style:{flex:1}}),(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>i({x:980/2,y:620/2},1/1.25),"aria-label":o("zoomOut"),children:"\u2212"}),(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>{k.current={x:0,y:0,k:1},E()},"aria-label":o("fit"),children:o("fit")}),(0,e.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>i({x:980/2,y:620/2},1.25),"aria-label":o("zoomIn"),children:"+"})]}),(0,e.jsxs)("div",{className:"me-graph-canvas",ref:l,onPointerDown:x,onPointerMove:T,onPointerUp:p,onPointerLeave:p,onContextMenu:a=>{a.preventDefault(),M(null)},onClick:a=>{y.current||M(null)},children:[(0,e.jsxs)("svg",{ref:z,viewBox:"0 0 980 620",role:"img",children:[(0,e.jsxs)("defs",{children:[Object.keys(I).map(a=>(0,e.jsxs)("radialGradient",{id:`me-grad-${a}`,cx:"35%",cy:"30%",r:"75%",children:[(0,e.jsx)("stop",{offset:"0%",stopColor:Me(I[a],.55)}),(0,e.jsx)("stop",{offset:"60%",stopColor:I[a]}),(0,e.jsx)("stop",{offset:"100%",stopColor:$e(I[a],.25)})]},a)),Object.keys(I).map(a=>(0,e.jsxs)("linearGradient",{id:`me-edge-${a}`,gradientUnits:"userSpaceOnUse",children:[(0,e.jsx)("stop",{offset:"0%",stopColor:I[a],stopOpacity:"0.4"}),(0,e.jsx)("stop",{offset:"100%",stopColor:I[a],stopOpacity:"0.85"})]},`e-${a}`)),(0,e.jsxs)("filter",{id:"me-glow",x:"-60%",y:"-60%",width:"220%",height:"220%",children:[(0,e.jsx)("feGaussianBlur",{stdDeviation:"3.2",result:"b"}),(0,e.jsxs)("feMerge",{children:[(0,e.jsx)("feMergeNode",{in:"b"}),(0,e.jsx)("feMergeNode",{in:"SourceGraphic"})]})]})]}),(0,e.jsxs)("g",{ref:D,transform:"translate(0 0) scale(1)",children:[f.es.map((a,s)=>{let m=A[a.source],b=A[a.target];if(m===void 0||b===void 0)return null;let S=P[m],R=P[b];if(!S||!R)return null;let B=f.list[m].kind||"other",O=u&&a.source!==u&&a.target!==u,F=u&&(a.source===u||a.target===u);return(0,e.jsx)("path",{d:Ne(S,R),className:`me-graph-edge${O?" dim":""}${F?" focus":""}`,style:{stroke:`url(#me-edge-${B})`,animationDelay:`${s%8*.12}s`}},`e${s}`)}),f.list.map((a,s)=>{let m=P[s];if(!m)return null;let b=a.kind||"other",S=G(a),R=u&&a.id!==u&&!L[a.id].has(u),B=u&&(a.id===u||L[a.id].has(u));return(0,e.jsxs)("g",{className:`me-graph-node in${B?" focus":""}${R?" dim":""}`,style:{animationDelay:`${s*.02}s`},transform:`translate(${m.x} ${m.y})`,onClick:O=>{O.stopPropagation(),v(a)},onContextMenu:O=>{O.preventDefault(),O.stopPropagation(),$(a)},children:[(0,e.jsx)("circle",{className:"inner",r:S,fill:`url(#me-grad-${b})`,stroke:I[b],strokeOpacity:"0.9",filter:"url(#me-glow)"}),(0,e.jsx)("circle",{r:Math.max(2.4,S*.2),fill:"rgba(255,255,255,0.85)"})]},a.id)}),(0,e.jsx)("g",{ref:j,className:"me-labels",children:f.list.map((a,s)=>{let m=P[s];if(!m)return null;let b=G(a),S=(f.deg[a.id]||0)>=f.hubMin,R=u&&a.id!==u&&!L[a.id].has(u);return(0,e.jsx)("text",{className:`${S?"me-nodelabel":"me-nodelabel minor"}${R?" dim":""}`,x:m.x+b+7,y:m.y+4,children:String(a.title||"").slice(0,16)},`l${a.id}`)})})]})]}),(0,e.jsxs)("div",{className:"me-graph-legend",children:[Object.keys(I).map(a=>(0,e.jsxs)("span",{className:"lg",children:[(0,e.jsx)("span",{className:"mc-kind",style:{background:I[a]}}),o(_[a])]},a)),(0,e.jsx)("span",{className:"me-graph-hint",children:o("graphHint")})]})]}),(0,e.jsxs)("div",{className:"me-graph-tip",children:[f.capped?`${o("capped")} ${f.list.length} / ${t.length} ${o("nodes")} \xB7 `:"",o("graphTip")]})]})}function we(t,r,n,o){let d=t.length;if(d===0)return[];if(d>160)return ke(t,n,o);let N=d<60?260:d<120?180:120,g=t.map((h,i)=>{let x=i/d*Math.PI*2-Math.PI/2;return{x:Math.cos(x),y:Math.sin(x)}}),l=g.map(()=>({x:0,y:0})),z=t.map(()=>[]);r.forEach(h=>{let i=t.findIndex(T=>T.id===h.source),x=t.findIndex(T=>T.id===h.target);i>=0&&x>=0&&i!==x&&(z[i].push(x),z[x].push(i))});let D=1.35,j=.035,k=.03,C=.84;for(let h=0;h<N;h++){for(let i=0;i<d;i++)for(let x=i+1;x<d;x++){let T=g[i].x-g[x].x,p=g[i].y-g[x].y,$=T*T+p*p||.01,v=Math.sqrt($),G=D/$,a=T/v*G,s=p/v*G;l[i].x+=a,l[i].y+=s,l[x].x-=a,l[x].y-=s}for(let i=0;i<d;i++)for(let x of z[i])l[i].x+=(g[x].x-g[i].x)*j,l[i].y+=(g[x].y-g[i].y)*j;for(let i=0;i<d;i++)l[i].x-=g[i].x*k,l[i].y-=g[i].y*k;for(let i=0;i<d;i++)l[i].x=Math.max(-.5,Math.min(.5,l[i].x*C)),l[i].y=Math.max(-.5,Math.min(.5,l[i].y*C)),g[i].x+=l[i].x,g[i].y+=l[i].y}let y=1/0,u=-1/0,M=1/0,f=-1/0;g.forEach(h=>{y=Math.min(y,h.x),u=Math.max(u,h.x),M=Math.min(M,h.y),f=Math.max(f,h.y)});let P=70,A=Math.min((n-2*P)/(u-y||1),(o-2*P)/(f-M||1)),L=(y+u)/2,E=(M+f)/2;return g.map(h=>({x:n/2+(h.x-L)*A,y:o/2+(h.y-E)*A}))}function ke(t,r,n){let o=t.length,d=r/2,N=n/2,g=Math.min(r,n)/2-80,l={};t.forEach((k,C)=>{let y=k.kind||"other";(l[y]=l[y]||[]).push(C)});let z=Object.keys(l),D=new Array(o),j=-Math.PI/2;for(let k of z){let C=l[k],y=C.length/o*Math.PI*2,u=j;C.forEach((M,f)=>{let P=C.length===1?u+y/2:u+y*(f+.5)/C.length;D[M]={x:d+g*Math.cos(P),y:N+g*Math.sin(P)}}),j+=y}return D}function Ne(t,r){let n=(t.x+r.x)/2,o=(t.y+r.y)/2,d=r.x-t.x,N=r.y-t.y,g=Math.sqrt(d*d+N*N)||1,l=Math.min(38,g*.18),z=n-N/g*l,D=o+d/g*l;return`M ${t.x} ${t.y} Q ${z} ${D} ${r.x} ${r.y}`}function Q(t){let r=t.replace("#",""),n=r.length===3?r.split("").map(o=>o+o).join(""):r;return[parseInt(n.slice(0,2),16),parseInt(n.slice(2,4),16),parseInt(n.slice(4,6),16)]}function Me(t,r){let[n,o,d]=Q(t);return`rgb(${Math.round(n+(255-n)*r)}, ${Math.round(o+(255-o)*r)}, ${Math.round(d+(255-d)*r)})`}function $e(t,r){let[n,o,d]=Q(t);return`rgb(${Math.round(n*(1-r))}, ${Math.round(o*(1-r))}, ${Math.round(d*(1-r))})`}function Ce(t){if(!t)return"";let r=new Date(t);if(Number.isNaN(r.getTime()))return"";let n=new Date,o=r.toDateString()===n.toDateString(),d=g=>String(g).padStart(2,"0"),N=`${d(r.getHours())}:${d(r.getMinutes())}`;return o?N:`${r.getMonth()+1}-${r.getDate()} ${N}`}
91
+ `;function ue(e){e.effect(()=>e.locale.register(H,{zh:pe,en:me}),"memory-eternal: locale");let r=e.locale.bind(H);e.effect(()=>e.slots.inject("settings.section",()=>e.slots.register({name:"settings.section",id:H,order:25,label:()=>r("nav"),locale:H,inject:()=>({})},()=>p.default.createElement(W,{t:r,inModal:!1}))),"memory-eternal: settings section"),e.effect(()=>e.slots.inject("sidebar.footer.action",()=>e.slots.register({name:"sidebar.footer.action",id:`${H}:footer`,order:100,label:()=>r("nav"),locale:H,inject:()=>({})},n=>p.default.createElement(fe,{t:r,wide:!(n&&n.wide===!1)}))),"memory-eternal: sidebar footer action")}function fe({t:e,wide:r}){let[n,o]=(0,p.useState)(!1);return(0,t.jsxs)("div",{className:`me-footer${r?"":" rail"}`,children:[(0,t.jsx)("style",{children:Y}),(0,t.jsxs)("button",{type:"button",className:"me-footer-btn",onClick:()=>o(!0),"aria-label":e("nav"),title:e("nav"),children:[(0,t.jsx)("span",{className:"me-footer-ico","aria-hidden":"true",children:(0,t.jsx)(Z,{})}),(0,t.jsx)("span",{className:"me-footer-label",children:e("nav")})]}),n&&(0,t.jsx)(he,{t:e,onClose:()=>o(!1)})]})}function Z(){return(0,t.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[(0,t.jsx)("ellipse",{cx:"12",cy:"5.5",rx:"8",ry:"3"}),(0,t.jsx)("path",{d:"M4 5.5v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"}),(0,t.jsx)("path",{d:"M4 11.5v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"})]})}function he({t:e,onClose:r}){return(0,p.useEffect)(()=>{let n=o=>{o.key==="Escape"&&r()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[r]),(0,t.jsxs)("div",{className:"me-overlay-top",onClick:r,children:[(0,t.jsx)("style",{children:Y}),(0,t.jsx)("div",{className:"me-modal",onClick:n=>n.stopPropagation(),children:(0,t.jsx)(W,{t:e,inModal:!0,onClose:r})})]})}function W({t:e,inModal:r,onClose:n}){let[o,g]=(0,p.useState)(null),[z,C]=(0,p.useState)([]),[d,u]=(0,p.useState)(!0),[j,T]=(0,p.useState)(""),[N,E]=(0,p.useState)("all"),[S,h]=(0,p.useState)(""),[x,m]=(0,p.useState)("cards"),[k,O]=(0,p.useState)(null),v=(0,p.useRef)(null),P=(0,p.useCallback)(async(c=N,w=S)=>{try{u(!0),T("");let y=new URLSearchParams;c&&c!=="all"&&y.set("kind",c),w.trim()&&y.set("q",w.trim());let a=await(await fetch(`${U}/cards?${y.toString()}`)).json();a.ok&&C(a.cards||[])}catch(y){T(String(y&&y.message?y.message:y))}finally{u(!1)}},[N,S]),D=(0,p.useCallback)(async()=>{try{let[c,w]=await Promise.all([fetch(`${U}/overview`).then(y=>y.json()),fetch(`${U}/cards`).then(y=>y.json())]);c.ok&&g(c),w.ok&&C(w.cards||[])}catch(c){T(String(c&&c.message?c.message:c))}finally{u(!1)}},[]);(0,p.useEffect)(()=>(D(),()=>{v.current&&clearTimeout(v.current)}),[D]);let f=c=>{h(c),v.current&&clearTimeout(v.current),v.current=setTimeout(()=>P(N,c),280)},i=c=>{E(c),P(c,S)},b=async c=>{try{let y=await(await fetch(`${U}/card?path=${encodeURIComponent(c.path||c.id)}`)).json();y.ok&&O({path:y.path,title:c.title,text:y.text})}catch(w){T(String(w&&w.message?w.message:w))}};return(0,t.jsxs)("div",{className:"memory-eternal-root",style:{height:"100%",display:"flex",flexDirection:"column"},children:[(0,t.jsx)("style",{children:Y}),r&&(0,t.jsxs)("div",{className:"me-modal-head",children:[(0,t.jsxs)("div",{className:"me-modal-title",children:[(0,t.jsx)(Z,{}),(0,t.jsx)("h2",{children:e("memoryTitle")}),(0,t.jsx)("span",{children:e("memoryHint")})]}),(0,t.jsx)("div",{className:"spacer"}),(0,t.jsx)("button",{type:"button",className:"me-modal-close",onClick:n,"aria-label":e("close"),children:"\u2715"})]}),(0,t.jsxs)("div",{className:"me-modal-body",children:[(0,t.jsxs)("div",{className:"mc-stats",children:[(0,t.jsx)(X,{label:e("total"),value:o?o.total:"\u2014"}),(0,t.jsx)(X,{label:e("recent"),value:o?o.recent:"\u2014"}),(0,t.jsx)(X,{label:e("tags"),value:o?o.tags:"\u2014"}),(0,t.jsx)(X,{label:e("cardCount"),value:o?o.byKind?.knowledge??0:"\u2014"})]}),(0,t.jsxs)("div",{className:"mc-toolbar",children:[(0,t.jsx)("input",{type:"text",placeholder:e("searchPlaceholder"),value:S,onChange:c=>f(c.target.value)}),(0,t.jsxs)("div",{className:"mc-tabs",children:[(0,t.jsx)("button",{type:"button",className:`mc-tab${x==="cards"?" active":""}`,onClick:()=>m("cards"),children:e("cardsTab")}),(0,t.jsx)("button",{type:"button",className:`mc-tab${x==="graph"?" active":""}`,onClick:()=>m("graph"),children:e("graphTab")})]}),(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>D(),children:e("refresh")})]}),x==="cards"&&(0,t.jsx)("div",{className:"mc-chips",children:ge.map(c=>(0,t.jsx)("button",{type:"button",className:`mc-chip${N===c?" active":""}`,onClick:()=>i(c),children:e(c==="all"?"all":_[c])},c))}),j&&(0,t.jsxs)("div",{className:"mc-empty",children:[e("error"),"\uFF1A",j]}),x==="cards"?d&&!z.length?(0,t.jsx)("div",{className:"mc-empty",children:e("loading")}):z.length===0?(0,t.jsx)("div",{className:"mc-empty",children:e("empty")}):(0,t.jsx)("div",{className:"mc-grid",children:z.map(c=>(0,t.jsx)(be,{card:c,t:e,onOpen:b},c.path))}):(0,t.jsx)(xe,{t:e,onOpen:b}),k&&(0,t.jsx)(ye,{t:e,card:k,onClose:()=>O(null)})]})]})}var X=({label:e,value:r})=>(0,t.jsxs)("div",{className:"mc-stat mc-card",children:[(0,t.jsx)("b",{children:r}),(0,t.jsx)("span",{children:e})]}),be=({card:e,t:r,onOpen:n})=>(0,t.jsxs)("article",{className:"mc-cardrow mc-card",onClick:()=>n(e),children:[(0,t.jsxs)("h4",{children:[(0,t.jsx)("span",{className:"mc-kind",style:{background:L[e.kind]||L.other}}),e.title]}),(0,t.jsx)("p",{children:e.summary||""}),e.tags.length>0&&(0,t.jsx)("div",{className:"mc-tags",children:e.tags.slice(0,4).map(o=>(0,t.jsx)("span",{className:"mc-tag",children:o},o))}),(0,t.jsxs)("footer",{children:[(0,t.jsx)("span",{children:r(_[e.kind])}),(0,t.jsx)("span",{children:ze(e.updated)})]})]});function ye({t:e,card:r,onClose:n}){return(0,p.useEffect)(()=>{let o=g=>{g.key==="Escape"&&n()};return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[n]),(0,t.jsxs)("div",{className:"me-overlay",onClick:n,children:[(0,t.jsx)("style",{children:Y}),(0,t.jsxs)("div",{className:"me-dialog",onClick:o=>o.stopPropagation(),children:[(0,t.jsxs)("div",{className:"me-dialog-head",children:[(0,t.jsx)("h3",{children:r.title}),(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:n,children:e("close")})]}),(0,t.jsx)("div",{className:"me-dialog-body",children:r.text})]})]})}function xe({t:e,onOpen:r}){let[n,o]=(0,p.useState)(null),[g,z]=(0,p.useState)("");return(0,p.useEffect)(()=>{let C=!0;return fetch(`${U}/graph`).then(d=>d.json()).then(d=>{C&&o(d.ok?d:null)}).catch(d=>{C&&z(String(d&&d.message?d.message:d))}),()=>{C=!1}},[]),(0,t.jsxs)("div",{className:"me-graph",children:[(0,t.jsx)("style",{children:Y}),g&&(0,t.jsxs)("div",{className:"mc-empty",children:[e("error"),"\uFF1A",g]}),!n&&!g&&(0,t.jsx)("div",{className:"mc-empty",children:e("loading")}),n&&n.nodes.length===0&&(0,t.jsx)("div",{className:"mc-empty",children:e("emptyGraph")}),n&&n.nodes.length>0&&(0,t.jsx)(we,{nodes:n.nodes,edges:n.edges,onOpen:r,t:e,countLabel:`${n.nodes.length} ${e("nodes")} \xB7 ${ve(n.edges)} ${e("edges")}`})]})}function ve(e){let r=new Set;for(let n of e||[])r.add([n.source,n.target].sort().join("|"));return r.size}function we({nodes:e,edges:r,onOpen:n,t:o,countLabel:g}){let d=(0,p.useRef)(null),u=(0,p.useRef)(null),j=(0,p.useRef)(null),T=(0,p.useRef)(null),N=(0,p.useRef)({x:0,y:0,k:1}),E=(0,p.useRef)(null),S=(0,p.useRef)(!1),[h,x]=(0,p.useState)(null),m=(0,p.useMemo)(()=>{let a={};r.forEach(M=>{a[M.source]=(a[M.source]||0)+1,a[M.target]=(a[M.target]||0)+1});let l=420,s=e,$=!1;e.length>l&&(s=[...e].sort((M,G)=>(a[G.id]||0)-(a[M.id]||0)).slice(0,l),$=!0);let I=new Set(s.map(M=>M.id)),R=new Set,K=[];r.forEach(M=>{if(!I.has(M.source)||!I.has(M.target))return;let G=[M.source,M.target].sort().join("|");R.has(G)||(R.add(G),K.push(M))}),K.sort((M,G)=>{let te=(a[M.source]||0)+(a[M.target]||0);return(a[G.source]||0)+(a[G.target]||0)-te});let A=Math.min(K.length,s.length<=40?Math.round(s.length*3):Math.max(80,Math.round(s.length*2.2))),F=s.length<=16?s.length:Math.max(8,Math.min(16,Math.round(s.length*.22))),J=s.map(M=>a[M.id]||0).sort((M,G)=>G-M),ee=F>0?J[F-1]:1/0;return{list:s,es:K.slice(0,A),capped:$,maxDeg:Math.max(1,...Object.values(a)),deg:a,hubMin:ee}},[e,r]),k=(0,p.useMemo)(()=>ke(m.list,m.es,980,620),[m.list,m.es,980,620]),O=(0,p.useMemo)(()=>m.list.reduce((a,l,s)=>(a[l.id]=s,a),{}),[m.list]),v=(0,p.useMemo)(()=>{let a={};return m.list.forEach(l=>{a[l.id]=new Set}),m.es.forEach(l=>{a[l.source]&&a[l.source].add(l.target),a[l.target]&&a[l.target].add(l.source)}),a},[m.list,m.es]),P=(0,p.useCallback)(()=>{let a=j.current;if(!a)return;let{x:l,y:s,k:$}=N.current;a.setAttribute("transform",`translate(${l} ${s}) scale(${$})`),T.current&&T.current.classList.toggle("all",$>=1.4)},[]);(0,p.useEffect)(()=>{P()},[P,k]);let D=(0,p.useCallback)((a,l)=>{let s=u.current;if(!s||typeof s.getScreenCTM!="function")return{x:a,y:l};let $=s.getScreenCTM();if(!$)return{x:a,y:l};let I=new DOMPoint(a,l).matrixTransform($.inverse());return{x:I.x,y:I.y}},[]),f=(0,p.useCallback)((a,l)=>{let s=N.current,$=Math.min(5,Math.max(.25,s.k*l));N.current={k:$,x:a.x-$/s.k*(a.x-s.x),y:a.y-$/s.k*(a.y-s.y)},P()},[P]);(0,p.useEffect)(()=>{let a=d.current;if(!a)return;let l=s=>{s.preventDefault(),f(D(s.clientX,s.clientY),s.deltaY<0?1.12:1/1.12)};return a.addEventListener("wheel",l,{passive:!1}),()=>a.removeEventListener("wheel",l)},[D,f]);let i=a=>{if(a.button!==0)return;let l=D(a.clientX,a.clientY);E.current={px:l.x,py:l.y,tx:N.current.x,ty:N.current.y,started:!1,id:a.pointerId},S.current=!1},b=a=>{let l=E.current;if(!l)return;let s=D(a.clientX,a.clientY);Math.abs(s.x-l.px)+Math.abs(s.y-l.py)>1.5&&(S.current=!0,!l.started&&d.current&&d.current.setPointerCapture&&(d.current.setPointerCapture(a.pointerId),l.started=!0),d.current&&d.current.classList.add("dragging"),N.current={...N.current,x:l.tx+(s.x-l.px),y:l.ty+(s.y-l.py)},P())},c=()=>{E.current=null,d.current&&d.current.classList.remove("dragging")},w=a=>{n({path:a.id,title:a.title})},y=a=>{S.current||x(a.id)},B=a=>7+Math.min(9,(m.deg[a.id]||0)/m.maxDeg*9);return(0,t.jsxs)("div",{className:"me-graph",children:[(0,t.jsxs)("div",{className:"me-graph-toolbar",children:[(0,t.jsx)("span",{className:"me-graph-count",children:g}),h&&(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>x(null),children:o("clearFocus")}),(0,t.jsx)("span",{className:"spacer",style:{flex:1}}),(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>f({x:980/2,y:620/2},1/1.25),"aria-label":o("zoomOut"),children:"\u2212"}),(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>{N.current={x:0,y:0,k:1},P()},"aria-label":o("fit"),children:o("fit")}),(0,t.jsx)("button",{type:"button",className:"mc-btn",onClick:()=>f({x:980/2,y:620/2},1.25),"aria-label":o("zoomIn"),children:"+"})]}),(0,t.jsxs)("div",{className:"me-graph-canvas",ref:d,onPointerDown:i,onPointerMove:b,onPointerUp:c,onPointerLeave:c,onContextMenu:a=>{a.preventDefault(),x(null)},onClick:a=>{S.current||x(null)},children:[(0,t.jsxs)("svg",{ref:u,viewBox:"0 0 980 620",role:"img",children:[(0,t.jsxs)("defs",{children:[Object.keys(L).map(a=>(0,t.jsxs)("radialGradient",{id:`me-grad-${a}`,cx:"35%",cy:"30%",r:"75%",children:[(0,t.jsx)("stop",{offset:"0%",stopColor:$e(L[a],.55)}),(0,t.jsx)("stop",{offset:"60%",stopColor:L[a]}),(0,t.jsx)("stop",{offset:"100%",stopColor:Ce(L[a],.25)})]},a)),Object.keys(L).map(a=>(0,t.jsxs)("linearGradient",{id:`me-edge-${a}`,gradientUnits:"userSpaceOnUse",children:[(0,t.jsx)("stop",{offset:"0%",stopColor:L[a],stopOpacity:"0.4"}),(0,t.jsx)("stop",{offset:"100%",stopColor:L[a],stopOpacity:"0.85"})]},`e-${a}`)),(0,t.jsxs)("filter",{id:"me-glow",x:"-60%",y:"-60%",width:"220%",height:"220%",children:[(0,t.jsx)("feGaussianBlur",{stdDeviation:"3.2",result:"b"}),(0,t.jsxs)("feMerge",{children:[(0,t.jsx)("feMergeNode",{in:"b"}),(0,t.jsx)("feMergeNode",{in:"SourceGraphic"})]})]})]}),(0,t.jsxs)("g",{ref:j,transform:"translate(0 0) scale(1)",children:[m.es.map((a,l)=>{let s=O[a.source],$=O[a.target];if(s===void 0||$===void 0)return null;let I=k[s],R=k[$];if(!I||!R)return null;let K=m.list[s].kind||"other",A=h&&a.source!==h&&a.target!==h,F=h&&(a.source===h||a.target===h);return(0,t.jsx)("path",{d:Ne(I,R),className:`me-graph-edge${A?" dim":""}${F?" focus":""}`,style:{stroke:`url(#me-edge-${K})`,animationDelay:`${l%8*.12}s`}},`e${l}`)}),m.list.map((a,l)=>{let s=k[l];if(!s)return null;let $=a.kind||"other",I=B(a),R=h&&a.id!==h&&!v[a.id].has(h),K=h&&(a.id===h||v[a.id].has(h));return(0,t.jsxs)("g",{className:`me-graph-node in${K?" focus":""}${R?" dim":""}`,style:{animationDelay:`${l*.02}s`},transform:`translate(${s.x} ${s.y})`,onClick:A=>{A.stopPropagation(),y(a)},onContextMenu:A=>{A.preventDefault(),A.stopPropagation(),w(a)},children:[(0,t.jsx)("circle",{className:"inner",r:I,fill:`url(#me-grad-${$})`,stroke:L[$],strokeOpacity:"0.9",filter:m.list.length<=120?"url(#me-glow)":void 0}),(0,t.jsx)("circle",{r:Math.max(2.4,I*.2),fill:"rgba(255,255,255,0.85)"})]},a.id)}),(0,t.jsx)("g",{ref:T,className:"me-labels",children:m.list.map((a,l)=>{let s=k[l];if(!s)return null;let $=B(a),I=(m.deg[a.id]||0)>=m.hubMin,R=h&&a.id!==h&&!v[a.id].has(h);return(0,t.jsx)("text",{className:`${I?"me-nodelabel":"me-nodelabel minor"}${R?" dim":""}`,x:s.x+$+7,y:s.y+4,children:String(a.title||"").slice(0,16)},`l${a.id}`)})})]})]}),(0,t.jsxs)("div",{className:"me-graph-legend",children:[Object.keys(L).map(a=>(0,t.jsxs)("span",{className:"lg",children:[(0,t.jsx)("span",{className:"mc-kind",style:{background:L[a]}}),o(_[a])]},a)),(0,t.jsx)("span",{className:"me-graph-hint",children:o("graphHint")})]})]}),(0,t.jsxs)("div",{className:"me-graph-tip",children:[m.capped?`${o("capped")} ${m.list.length} / ${e.length} ${o("nodes")} \xB7 `:"",o("graphTip")]})]})}function ke(e,r,n,o){let g=e.length;if(g===0)return[];if(g>24)return Me(e,r,n,o);let z=320,C=Math.max(3,Math.sqrt(g)*2.4),d=e.map((f,i)=>{let b=i/g*Math.PI*2-Math.PI/2;return{x:C*Math.cos(b),y:C*Math.sin(b)}}),u=d.map(()=>({x:0,y:0})),j=e.map(()=>[]);r.forEach(f=>{let i=e.findIndex(c=>c.id===f.source),b=e.findIndex(c=>c.id===f.target);i>=0&&b>=0&&i!==b&&(j[i].push(b),j[b].push(i))});let T=2.8,N=.02,E=.006,S=.85;for(let f=0;f<z;f++){for(let i=0;i<g;i++)for(let b=i+1;b<g;b++){let c=d[i].x-d[b].x,w=d[i].y-d[b].y,y=c*c+w*w||.01,B=Math.sqrt(y),a=T/y,l=c/B*a,s=w/B*a;u[i].x+=l,u[i].y+=s,u[b].x-=l,u[b].y-=s}for(let i=0;i<g;i++)for(let b of j[i])u[i].x+=(d[b].x-d[i].x)*N,u[i].y+=(d[b].y-d[i].y)*N;for(let i=0;i<g;i++)u[i].x-=d[i].x*E,u[i].y-=d[i].y*E;for(let i=0;i<g;i++)u[i].x=Math.max(-.35,Math.min(.35,u[i].x*S)),u[i].y=Math.max(-.35,Math.min(.35,u[i].y*S)),d[i].x+=u[i].x,d[i].y+=u[i].y}let h=1/0,x=-1/0,m=1/0,k=-1/0;d.forEach(f=>{h=Math.min(h,f.x),x=Math.max(x,f.x),m=Math.min(m,f.y),k=Math.max(k,f.y)});let O=60,v=Math.min((n-2*O)/(x-h||1),(o-2*O)/(k-m||1)),P=(h+x)/2,D=(m+k)/2;return d.map(f=>({x:n/2+(f.x-P)*v,y:o/2+(f.y-D)*v}))}function Me(e,r,n,o){let g=e.length,z=n/2,C=o/2,d=Math.min(n,o)/2-56,u={};r.forEach(x=>{u[x.source]=(u[x.source]||0)+1,u[x.target]=(u[x.target]||0)+1});let j={};e.forEach((x,m)=>{let k=x.kind||"other";(j[k]=j[k]||[]).push(m)});let T=Object.keys(j),N=new Array(g),E=-Math.PI/2,S=46,h=56;for(let x of T){let m=j[x].sort((f,i)=>(u[e[i].id]||0)-(u[e[f].id]||0)),k=m.length/g*Math.PI*2,O=E,v=0,P=0;for(;v<m.length&&P<60;){let f=Math.min(64+P*h,d),i=f*k,b=Math.max(1,Math.floor(i/S)),c=Math.min(b,m.length-v);for(let w=0;w<c;w++){let y=O+k*(v+w+.5)/m.length;N[m[v+w]]={x:z+f*Math.cos(y),y:C+f*Math.sin(y)}}v+=c,P++}let D=0;for(;v<m.length&&D<m.length;){let f=O+k*(v+.5)/m.length;N[m[v]]={x:z+d*Math.cos(f),y:C+d*Math.sin(f)},v++,D++}E+=k}return N}function Ne(e,r){let n=(e.x+r.x)/2,o=(e.y+r.y)/2,g=r.x-e.x,z=r.y-e.y,C=Math.sqrt(g*g+z*z)||1,d=Math.min(38,C*.18),u=n-z/C*d,j=o+g/C*d;return`M ${e.x} ${e.y} Q ${u} ${j} ${r.x} ${r.y}`}function Q(e){let r=e.replace("#",""),n=r.length===3?r.split("").map(o=>o+o).join(""):r;return[parseInt(n.slice(0,2),16),parseInt(n.slice(2,4),16),parseInt(n.slice(4,6),16)]}function $e(e,r){let[n,o,g]=Q(e);return`rgb(${Math.round(n+(255-n)*r)}, ${Math.round(o+(255-o)*r)}, ${Math.round(g+(255-g)*r)})`}function Ce(e,r){let[n,o,g]=Q(e);return`rgb(${Math.round(n*(1-r))}, ${Math.round(o*(1-r))}, ${Math.round(g*(1-r))})`}function ze(e){if(!e)return"";let r=new Date(e);if(Number.isNaN(r.getTime()))return"";let n=new Date,o=r.toDateString()===n.toDateString(),g=C=>String(C).padStart(2,"0"),z=`${g(r.getHours())}:${g(r.getMinutes())}`;return o?z:`${r.getMonth()+1}-${r.getDate()} ${z}`}
92
92
 
93
93
  return module.exports;
94
94
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-memory-eternal",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "记忆核心(Memory Eternal):自研的 DeepSeek Harness 记忆插件,不移植任何既有记忆框架——对话结束后自动沉淀知识卡到本地 Markdown Vault(自研去重、自研 CJK 检索、可 git 管理),设置页提供图形化知识库(统计 / 搜索 / 知识图谱 + 侧边栏一键弹窗),Agent 通过 memory_recall 工具按需召回历史上下文。零人工干预。",
5
5
  "license": "MIT",
6
6
  "repository": {