@kenz1117/dsh-engram 0.4.1 → 0.4.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/lib/client.js +1 -1
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
window.__ModuleLoader__.load({id:`@kenz1117/dsh-engram`,factory:e=>{var t={exports:{}},n=t.exports;Object.defineProperty(n,Symbol.toStringTag,{value:`Module`});let r=e("react"),i=e("react/jsx-runtime"),a=`@kenz1117/dsh-engram/panel.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(a)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@kenz1117/dsh-engram`,e.dataset.pluginCss=a,e.textContent=`.bWwFiW_panel{max-width:980px}.bWwFiW_toolbar{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:14px;display:flex}.bWwFiW_scopeTabs{border:1px solid var(--dsw-alias-border-l2);
|
|
1
|
+
window.__ModuleLoader__.load({id:`@kenz1117/dsh-engram`,factory:e=>{var t={exports:{}},n=t.exports;Object.defineProperty(n,Symbol.toStringTag,{value:`Module`});let r=e("react"),i=e("react/jsx-runtime"),a=`@kenz1117/dsh-engram/panel.module.css`;if(typeof document<`u`&&document.querySelector(`style[data-plugin-css=`+JSON.stringify(a)+`]`)===null){let e=document.createElement(`style`);e.dataset.plugin=`@kenz1117/dsh-engram`,e.dataset.pluginCss=a,e.textContent=`.bWwFiW_panel{max-width:980px}.bWwFiW_toolbar{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:14px;display:flex}.bWwFiW_scopeTabs{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:flex-end;gap:18px;margin-right:auto;display:flex}.bWwFiW_scopeOn,.bWwFiW_scopeOff{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;padding:7px 1px 9px;font-size:13px;line-height:20px;position:relative}.bWwFiW_scopeOn,.bWwFiW_scopeOff:hover{color:var(--dsw-alias-label-primary)}.bWwFiW_scopeOn:after{background:var(--dsw-alias-brand-primary);content:"";border-radius:2px 2px 0 0;height:2px;position:absolute;bottom:-1px;left:0;right:0}.bWwFiW_button{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;border-radius:8px;padding:5px 12px;font-size:13px}.bWwFiW_button:hover{border-color:var(--dsw-alias-brand-primary)}.bWwFiW_button:disabled{opacity:.45;cursor:default}.bWwFiW_primary{background:var(--dsw-alias-button-primary-fill);border-color:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-brand-primary-invert)}.bWwFiW_cards{grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:14px;display:grid}.bWwFiW_card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);text-align:left;cursor:pointer;color:var(--dsw-alias-label-primary);font:inherit;border-radius:10px;padding:10px 14px}.bWwFiW_card b{font-size:20px;display:block}.bWwFiW_card span{color:var(--dsw-alias-label-secondary);font-size:12px}.bWwFiW_filters{flex-wrap:wrap;gap:8px;margin-bottom:14px;display:flex}.bWwFiW_input{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px 10px;font-size:13px}.bWwFiW_filters .bWwFiW_input{flex:1;min-width:160px}.bWwFiW_item{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;margin-bottom:10px;padding:12px 14px}.bWwFiW_row1{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:6px;display:flex}.bWwFiW_badge{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-tsp-secondary);border-radius:99px;padding:1px 8px;font-size:11px}.bWwFiW_active{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}.bWwFiW_archived{color:var(--dsw-alias-state-warn-primary);border-color:var(--dsw-alias-state-warn-primary)}.bWwFiW_forgotten{color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}.bWwFiW_content{white-space:pre-wrap;word-break:break-word;color:var(--dsw-alias-label-primary)}.bWwFiW_meta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:14px;margin-top:6px;font-size:12px;display:flex}.bWwFiW_ops{gap:8px;margin-top:8px;display:flex}.bWwFiW_pager{color:var(--dsw-alias-label-secondary);justify-content:center;align-items:center;gap:10px;margin-top:14px;display:flex}.bWwFiW_empty{text-align:center;color:var(--dsw-alias-label-secondary);padding:40px 0}.bWwFiW_backdrop{background:var(--dsw-alias-bg-overlay);z-index:30;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.bWwFiW_dialog{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;width:92vw;max-width:640px;max-height:80vh;padding:18px;overflow:auto}.bWwFiW_dialog h3{margin:0 0 10px;font-size:15px}.bWwFiW_fieldLabel{color:var(--dsw-alias-label-secondary);margin:10px 0 4px;font-size:12px;display:block}.bWwFiW_modalFoot{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}.bWwFiW_review{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);white-space:pre-wrap;max-height:320px;color:var(--dsw-alias-label-primary);border-radius:8px;padding:10px;font-size:12px;overflow:auto}`,document.head.appendChild(e)}var o={ops:`bWwFiW_ops`,modalFoot:`bWwFiW_modalFoot`,review:`bWwFiW_review`,toolbar:`bWwFiW_toolbar`,cards:`bWwFiW_cards`,forgotten:`bWwFiW_forgotten`,meta:`bWwFiW_meta`,card:`bWwFiW_card`,scopeOn:`bWwFiW_scopeOn`,filters:`bWwFiW_filters`,item:`bWwFiW_item`,badge:`bWwFiW_badge`,scopeOff:`bWwFiW_scopeOff`,content:`bWwFiW_content`,row1:`bWwFiW_row1`,empty:`bWwFiW_empty`,input:`bWwFiW_input`,scopeTabs:`bWwFiW_scopeTabs`,dialog:`bWwFiW_dialog`,backdrop:`bWwFiW_backdrop`,active:`bWwFiW_active`,pager:`bWwFiW_pager`,primary:`bWwFiW_primary`,panel:`bWwFiW_panel`,fieldLabel:`bWwFiW_fieldLabel`,button:`bWwFiW_button`,archived:`bWwFiW_archived`};let s=[`fact`,`preference`,`decision`,`episode`,`skill`];async function c(e,t){let n=await fetch(`/api/engram/${e}`,t),r=await n.json();if(!n.ok)throw Error(r.error??`HTTP ${String(n.status)}`);return r}function l(e){return new Date(e).toLocaleString(`zh-CN`,{hour12:!1})}function u({recordId:e,scope:t}){let[n,a]=(0,r.useState)(null);return(0,r.useEffect)(()=>{let n=!1;return c(`review?scope=${t}&id=${encodeURIComponent(e)}`).then(e=>{if(n)return;let t=e.record,r=[`内容: ${t.content}`,`属性: kind=${t.kind}, status=${t.status}, importance=${t.importance}, confidence=${t.confidence}, 访问 ${t.accessCount} 次`,`来源: ${t.sourceSessionId??`显式保存`}${t.sourceRound===null?``:` 第${String(t.sourceRound)}轮`}`];for(let t of[`supersededBy`,`supersedes`,`contradicts`,`related`]){let n=e[t];n!==void 0&&n.length>0&&r.push(`${t}: ${n.join(`, `)}`)}let i=e.operations;i!==void 0&&i.length>0&&(r.push(`最近操作:`),i.forEach(e=>r.push(` ${l(e.at)} ${e.op}${e.detail?` ${e.detail}`:``}`))),a(r.join(`
|
|
2
2
|
`))}).catch(e=>{n||a(`加载失败:${e.message}`)}),()=>{n=!0}},[e,t]),n===null?null:(0,i.jsx)(`pre`,{className:o.review,children:n})}function d({record:e,onClose:t,onSaved:n}){let[a,l]=(0,r.useState)(e.content),[u,d]=(0,r.useState)(e.kind),[f,p]=(0,r.useState)(e.importance);return(0,i.jsx)(`div`,{className:o.backdrop,onClick:t,children:(0,i.jsxs)(`div`,{className:o.dialog,onClick:e=>e.stopPropagation(),children:[(0,i.jsx)(`h3`,{children:`编辑记忆(写入取代链)`}),(0,i.jsx)(`label`,{className:o.fieldLabel,children:`内容`}),(0,i.jsx)(`textarea`,{className:o.input,rows:3,value:a,onChange:e=>l(e.target.value)}),(0,i.jsx)(`label`,{className:o.fieldLabel,children:`种类`}),(0,i.jsx)(`select`,{className:o.input,value:u,onChange:e=>d(e.target.value),children:s.map(e=>(0,i.jsx)(`option`,{value:e,children:e},e))}),(0,i.jsxs)(`label`,{className:o.fieldLabel,children:[`重要性 `,f.toFixed(2)]}),(0,i.jsx)(`input`,{type:`range`,min:0,max:1,step:.05,value:f,onChange:e=>p(Number(e.target.value))}),(0,i.jsxs)(`div`,{className:o.modalFoot,children:[(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:t,children:`取消`}),(0,i.jsx)(`button`,{type:`button`,className:`${o.button} ${o.primary}`,onClick:()=>{c(`update`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:e.id,scope:e.scope,content:a,kind:u,importance:f})}).then(n).catch(e=>{alert(e.message)})},children:`保存(旧条目归档)`})]})]})})}function f(){let[e,t]=(0,r.useState)(`user`),[n,a]=(0,r.useState)(`all`),[f,p]=(0,r.useState)(`all`),[m,h]=(0,r.useState)(``),[g,_]=(0,r.useState)(0),[v,y]=(0,r.useState)(null),[b,x]=(0,r.useState)(null),[S,C]=(0,r.useState)(null),[w,T]=(0,r.useState)(null),[E,D]=(0,r.useState)(null),[O,k]=(0,r.useState)(0),A=(0,r.useCallback)(()=>{k(e=>e+1)},[]);(0,r.useEffect)(()=>{let t=!1,r=new URLSearchParams({scope:e,status:n,kind:f,limit:`20`,offset:String(g)});return m!==``&&r.set(`q`,m),c(`list?${r.toString()}`).then(e=>{t||(y(e),C(null))}).catch(e=>{t||C(e.message)}),c(`stats`).then(e=>{t||x(e.parts)}).catch(()=>{}),()=>{t=!0}},[e,n,f,m,g,O]);let j=(e,t)=>{c(e,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:t.id,scope:t.scope})}).then(A).catch(e=>{alert(e.message)})},M=Math.floor(g/20)+1,N=v===null?1:Math.max(1,Math.ceil(v.total/20));return(0,i.jsxs)(`div`,{className:o.panel,children:[(0,i.jsxs)(`div`,{className:o.toolbar,children:[(0,i.jsx)(`div`,{className:o.scopeTabs,children:[`user`,`project`].map(n=>(0,i.jsx)(`button`,{type:`button`,className:e===n?o.scopeOn:o.scopeOff,onClick:()=>{t(n),_(0)},children:n===`user`?`用户级`:`项目级`},n))}),(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:A,children:`刷新`}),(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{location.href=`/api/engram/export?scope=${e}&format=markdown`},children:`导出 MD`}),(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{location.href=`/api/engram/export?scope=${e}&format=json`},children:`导出 JSON`})]}),(0,i.jsx)(`div`,{className:o.cards,children:(b??[]).map(n=>(0,i.jsxs)(`button`,{type:`button`,className:o.card,style:n.scope===e?{borderColor:`var(--dsw-alias-brand-primary)`}:void 0,onClick:()=>{t(n.scope),_(0)},children:[(0,i.jsx)(`b`,{children:n.stats.total}),(0,i.jsxs)(`span`,{children:[n.scope,` · active `,n.stats.active,` · 信噪比 `,Math.round(n.stats.signalRatio*100),`%`]})]},n.scope))}),(0,i.jsxs)(`div`,{className:o.filters,children:[(0,i.jsxs)(`select`,{className:o.input,value:n,onChange:e=>{a(e.target.value),_(0)},children:[(0,i.jsx)(`option`,{value:`all`,children:`全部状态`}),(0,i.jsx)(`option`,{value:`active`,children:`active`}),(0,i.jsx)(`option`,{value:`archived`,children:`archived`}),(0,i.jsx)(`option`,{value:`forgotten`,children:`forgotten`})]}),(0,i.jsxs)(`select`,{className:o.input,value:f,onChange:e=>{p(e.target.value),_(0)},children:[(0,i.jsx)(`option`,{value:`all`,children:`全部种类`}),s.map(e=>(0,i.jsx)(`option`,{value:e,children:e},e))]}),(0,i.jsx)(`input`,{className:o.input,placeholder:`按内容搜索…`,value:m,onChange:e=>{h(e.target.value.trim()),_(0)}})]}),S!==null&&(0,i.jsx)(`div`,{className:o.empty,children:`加载失败:${S}`}),S===null&&v!==null&&v.records.length===0&&(0,i.jsx)(`div`,{className:o.empty,children:`没有符合条件的记忆`}),(v?.records??[]).map(e=>(0,i.jsxs)(`div`,{className:o.item,children:[(0,i.jsxs)(`div`,{className:o.row1,children:[(0,i.jsx)(`span`,{className:`${o.badge} ${o[e.status]}`,children:e.status}),(0,i.jsx)(`span`,{className:o.badge,children:e.kind}),(0,i.jsx)(`span`,{className:o.badge,children:e.scope})]}),(0,i.jsx)(`div`,{className:o.content,children:e.content}),(0,i.jsxs)(`div`,{className:o.meta,children:[(0,i.jsxs)(`span`,{children:[`重要性 `,e.importance.toFixed(2)]}),(0,i.jsxs)(`span`,{children:[`置信 `,e.confidence.toFixed(2)]}),(0,i.jsxs)(`span`,{children:[`访问 `,e.accessCount,` 次`]}),(0,i.jsx)(`span`,{children:e.sourceSessionId===null?`显式保存`:`来源 ${e.sourceSessionId.slice(0,16)}…${e.sourceRound===null?``:` 第${String(e.sourceRound)}轮`}`}),(0,i.jsx)(`span`,{children:l(e.createdAt)})]}),(0,i.jsxs)(`div`,{className:o.ops,children:[(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{D(e)},children:`详情`}),(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{T(e)},children:`编辑`}),e.status===`active`?(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{j(`forget`,e)},children:`遗忘`}):(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{j(`restore`,e)},children:`恢复`})]})]},e.id)),(0,i.jsxs)(`div`,{className:o.pager,children:[(0,i.jsx)(`button`,{type:`button`,className:o.button,disabled:g===0,onClick:()=>{_(Math.max(0,g-20))},children:`上一页`}),(0,i.jsxs)(`span`,{children:[`第 `,M,` / `,N,` 页 · 共 `,v?.total??0,` 条`]}),(0,i.jsx)(`button`,{type:`button`,className:o.button,disabled:v===null||g+20>=v.total,onClick:()=>{_(g+20)},children:`下一页`})]}),w!==null&&(0,i.jsx)(d,{record:w,onClose:()=>{T(null)},onSaved:()=>{T(null),A()}}),E!==null&&(0,i.jsx)(`div`,{className:o.backdrop,onClick:()=>{D(null)},children:(0,i.jsxs)(`div`,{className:o.dialog,onClick:e=>e.stopPropagation(),children:[(0,i.jsx)(`h3`,{children:`记忆审计`}),(0,i.jsx)(u,{recordId:E.id,scope:E.scope}),(0,i.jsx)(`div`,{className:o.modalFoot,children:(0,i.jsx)(`button`,{type:`button`,className:o.button,onClick:()=>{D(null)},children:`关闭`})})]})})]})}let p=[`slots`];function m(e){e.slots.inject(`settings.section`,()=>e.slots.register({name:`settings.section`,id:`engram`,order:20,label:()=>`记忆库`},f))}return n.apply=m,n.inject=p,t.exports}});
|
|
3
3
|
//# sourceMappingURL=client.js.map
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["useState","styles","useCallback"],"sources":["../src/client/EngramPanel.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 记忆库设置面板:统计卡片、过滤列表、编辑(取代链)、遗忘/恢复、导出。\n * 数据经回环 API(/api/engram/*)读写;内容节点一律 DOM API 构建(防 XSS)。\n * @module @kenz1117/dsh-engram/client/EngramPanel\n */\n\nimport { useCallback, useEffect, useState } from 'react'\nimport styles from './panel.module.css'\n\n/** 列表/详情用的记忆视图(宿主 /api/engram/list 的行结构)。 */\ninterface MemoryRow {\n readonly id: string\n readonly scope: 'user' | 'project'\n readonly kind: string\n readonly content: string\n readonly importance: number\n readonly confidence: number\n readonly status: 'active' | 'archived' | 'forgotten'\n readonly createdAt: number\n readonly accessCount: number\n readonly sourceSessionId: string | null\n readonly sourceRound: number | null\n}\n\ninterface ListResult {\n readonly records: MemoryRow[]\n readonly total: number\n}\n\ninterface StatsPart {\n readonly scope: 'user' | 'project'\n readonly stats: {\n readonly total: number\n readonly active: number\n readonly archived: number\n readonly forgotten: number\n readonly signalRatio: number\n }\n}\n\nconst KINDS = ['fact', 'preference', 'decision', 'episode', 'skill'] as const\nconst PAGE_SIZE = 20\n\nasync function api<T>(path: string, init?: RequestInit): Promise<T> {\n const response = await fetch(`/api/engram/${path}`, init)\n const body = (await response.json()) as T & { error?: string }\n if (!response.ok) throw new Error(body.error ?? `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction fmtTime(ms: number): string {\n return new Date(ms).toLocaleString('zh-CN', { hour12: false })\n}\n\n/** 审计弹层视图。 */\nfunction ReviewBody({ recordId, scope }: { recordId: string; scope: 'user' | 'project' }): React.ReactElement | null {\n const [text, setText] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n api<Record<string, unknown>>(`review?scope=${scope}&id=${encodeURIComponent(recordId)}`)\n .then((view) => {\n if (cancelled) return\n const record = view.record as MemoryRow\n const lines = [\n `内容: ${record.content}`,\n `属性: kind=${record.kind}, status=${record.status}, importance=${record.importance}, confidence=${record.confidence}, 访问 ${record.accessCount} 次`,\n `来源: ${record.sourceSessionId ?? '显式保存'}${record.sourceRound === null ? '' : ` 第${String(record.sourceRound)}轮`}`,\n ]\n for (const key of ['supersededBy', 'supersedes', 'contradicts', 'related'] as const) {\n const ids = view[key] as string[] | undefined\n if (ids !== undefined && ids.length > 0) lines.push(`${key}: ${ids.join(', ')}`)\n }\n const operations = view.operations as { at: number; op: string; detail: string | null }[] | undefined\n if (operations !== undefined && operations.length > 0) {\n lines.push('最近操作:')\n operations.forEach(op => lines.push(` ${fmtTime(op.at)} ${op.op}${op.detail ? ` ${op.detail}` : ''}`))\n }\n setText(lines.join('\\n'))\n })\n .catch((error: Error) => { if (!cancelled) setText(`加载失败:${error.message}`) })\n return () => { cancelled = true }\n }, [recordId, scope])\n if (text === null) return null\n return <pre className={styles.review}>{text}</pre>\n}\n\n/** 编辑弹层:内容/种类/重要性 → POST update(旧条目归档,取代链保留)。 */\nfunction EditDialog({ record, onClose, onSaved }: {\n record: MemoryRow\n onClose: () => void\n onSaved: () => void\n}): React.ReactElement {\n const [content, setContent] = useState(record.content)\n const [kind, setKind] = useState(record.kind)\n const [importance, setImportance] = useState(record.importance)\n const save = (): void => {\n api('update', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: record.id, scope: record.scope, content, kind, importance }),\n })\n .then(onSaved)\n .catch((error: Error) => { alert(error.message) })\n }\n return (\n <div className={styles.backdrop} onClick={onClose}>\n <div className={styles.dialog} onClick={event => event.stopPropagation()}>\n <h3>编辑记忆(写入取代链)</h3>\n <label className={styles.fieldLabel}>内容</label>\n <textarea className={styles.input} rows={3} value={content} onChange={event => setContent(event.target.value)} />\n <label className={styles.fieldLabel}>种类</label>\n <select className={styles.input} value={kind} onChange={event => setKind(event.target.value)}>\n {KINDS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n <label className={styles.fieldLabel}>重要性 {importance.toFixed(2)}</label>\n <input type=\"range\" min={0} max={1} step={0.05} value={importance}\n onChange={event => setImportance(Number(event.target.value))} />\n <div className={styles.modalFoot}>\n <button type=\"button\" className={styles.button} onClick={onClose}>取消</button>\n <button type=\"button\" className={`${styles.button} ${styles.primary}`} onClick={save}>保存(旧条目归档)</button>\n </div>\n </div>\n </div>\n )\n}\n\n/** 设置页「记忆库」section 主组件。 */\nexport function EngramSection(): React.ReactElement {\n const [scope, setScope] = useState<'user' | 'project'>('user')\n const [status, setStatus] = useState('all')\n const [kind, setKind] = useState('all')\n const [q, setQ] = useState('')\n const [offset, setOffset] = useState(0)\n const [list, setList] = useState<ListResult | null>(null)\n const [stats, setStats] = useState<StatsPart[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [editing, setEditing] = useState<MemoryRow | null>(null)\n const [reviewId, setReviewId] = useState<MemoryRow | null>(null)\n const [reloadTick, setReloadTick] = useState(0)\n\n const reload = useCallback((): void => { setReloadTick(tick => tick + 1) }, [])\n\n useEffect(() => {\n let cancelled = false\n const qs = new URLSearchParams({\n scope, status, kind, limit: String(PAGE_SIZE), offset: String(offset),\n })\n if (q !== '') qs.set('q', q)\n api<ListResult>(`list?${qs.toString()}`)\n .then((data) => { if (!cancelled) { setList(data); setError(null) } })\n .catch((loadError: Error) => { if (!cancelled) setError(loadError.message) })\n api<{ parts: StatsPart[] }>('stats')\n .then((data) => { if (!cancelled) setStats(data.parts) })\n .catch(() => { /* 统计失败不影响列表 */ })\n return () => { cancelled = true }\n }, [scope, status, kind, q, offset, reloadTick])\n\n const act = (route: string, record: MemoryRow): void => {\n api(route, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: record.id, scope: record.scope }),\n })\n .then(reload)\n .catch((actError: Error) => { alert(actError.message) })\n }\n\n const page = Math.floor(offset / PAGE_SIZE) + 1\n const pages = list === null ? 1 : Math.max(1, Math.ceil(list.total / PAGE_SIZE))\n\n return (\n <div className={styles.panel}>\n <div className={styles.toolbar}>\n <div className={styles.scopeTabs}>\n {(['user', 'project'] as const).map(option => (\n <button key={option} type=\"button\"\n className={scope === option ? styles.scopeOn : styles.scopeOff}\n onClick={() => { setScope(option); setOffset(0) }}>\n {option === 'user' ? '用户级' : '项目级'}\n </button>\n ))}\n </div>\n <button type=\"button\" className={styles.button} onClick={reload}>刷新</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { location.href = `/api/engram/export?scope=${scope}&format=markdown` }}>导出 MD</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { location.href = `/api/engram/export?scope=${scope}&format=json` }}>导出 JSON</button>\n </div>\n <div className={styles.cards}>\n {(stats ?? []).map(part => (\n <button key={part.scope} type=\"button\" className={styles.card}\n style={part.scope === scope ? { borderColor: 'var(--dsw-alias-brand-primary)' } : undefined}\n onClick={() => { setScope(part.scope); setOffset(0) }}>\n <b>{part.stats.total}</b>\n <span>{part.scope} · active {part.stats.active} · 信噪比 {Math.round(part.stats.signalRatio * 100)}%</span>\n </button>\n ))}\n </div>\n <div className={styles.filters}>\n <select className={styles.input} value={status}\n onChange={event => { setStatus(event.target.value); setOffset(0) }}>\n <option value=\"all\">全部状态</option>\n <option value=\"active\">active</option>\n <option value=\"archived\">archived</option>\n <option value=\"forgotten\">forgotten</option>\n </select>\n <select className={styles.input} value={kind}\n onChange={event => { setKind(event.target.value); setOffset(0) }}>\n <option value=\"all\">全部种类</option>\n {KINDS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n <input className={styles.input} placeholder=\"按内容搜索…\" value={q}\n onChange={event => { setQ(event.target.value.trim()); setOffset(0) }} />\n </div>\n {error !== null && <div className={styles.empty}>{`加载失败:${error}`}</div>}\n {error === null && list !== null && list.records.length === 0 && (\n <div className={styles.empty}>没有符合条件的记忆</div>\n )}\n {(list?.records ?? []).map(record => (\n <div key={record.id} className={styles.item}>\n <div className={styles.row1}>\n <span className={`${styles.badge} ${styles[record.status]}`}>{record.status}</span>\n <span className={styles.badge}>{record.kind}</span>\n <span className={styles.badge}>{record.scope}</span>\n </div>\n <div className={styles.content}>{record.content}</div>\n <div className={styles.meta}>\n <span>重要性 {record.importance.toFixed(2)}</span>\n <span>置信 {record.confidence.toFixed(2)}</span>\n <span>访问 {record.accessCount} 次</span>\n <span>{record.sourceSessionId === null\n ? '显式保存'\n : `来源 ${record.sourceSessionId.slice(0, 16)}…${record.sourceRound === null ? '' : ` 第${String(record.sourceRound)}轮`}`}</span>\n <span>{fmtTime(record.createdAt)}</span>\n </div>\n <div className={styles.ops}>\n <button type=\"button\" className={styles.button}\n onClick={() => { setReviewId(record) }}>详情</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { setEditing(record) }}>编辑</button>\n {record.status === 'active'\n ? <button type=\"button\" className={styles.button}\n onClick={() => { act('forget', record) }}>遗忘</button>\n : <button type=\"button\" className={styles.button}\n onClick={() => { act('restore', record) }}>恢复</button>}\n </div>\n </div>\n ))}\n <div className={styles.pager}>\n <button type=\"button\" className={styles.button} disabled={offset === 0}\n onClick={() => { setOffset(Math.max(0, offset - PAGE_SIZE)) }}>上一页</button>\n <span>第 {page} / {pages} 页 · 共 {list?.total ?? 0} 条</span>\n <button type=\"button\" className={styles.button}\n disabled={list === null || offset + PAGE_SIZE >= list.total}\n onClick={() => { setOffset(offset + PAGE_SIZE) }}>下一页</button>\n </div>\n {editing !== null && (\n <EditDialog record={editing} onClose={() => { setEditing(null) }} onSaved={() => { setEditing(null); reload() }} />\n )}\n {reviewId !== null && (\n <div className={styles.backdrop} onClick={() => { setReviewId(null) }}>\n <div className={styles.dialog} onClick={event => event.stopPropagation()}>\n <h3>记忆审计</h3>\n <ReviewBody recordId={reviewId.id} scope={reviewId.scope} />\n <div className={styles.modalFoot}>\n <button type=\"button\" className={styles.button}\n onClick={() => { setReviewId(null) }}>关闭</button>\n </div>\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * dsh-engram client half: 注册设置页「记忆库」section。\n * 数据经回环 API(/api/engram/*)读取与操作,与 host 半的路由对齐。\n * @module @kenz1117/dsh-engram/client\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only: ctx.slots(renderer 的 SlotMap 渲染接线)。\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\n// Type-only: settings.section 槽位的 SlotMap merge(ui-settings 契约)。\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { EngramSection } from './EngramPanel.tsx'\n\n/** 必需服务:slots 渲染接线。 */\nexport const inject = ['slots']\n\n/**\n * Client plugin body: 设置页注册「记忆库」section(order 20,排在\n * general/models/plugins 之后)。\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'engram',\n order: 20,\n label: () => '记忆库',\n }, EngramSection))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","styles","useCallback"],"sources":["../src/client/EngramPanel.tsx","../src/client/index.ts"],"sourcesContent":["/**\n * 记忆库设置面板:统计卡片、过滤列表、编辑(取代链)、遗忘/恢复、导出。\n * 数据经回环 API(/api/engram/*)读写;内容节点一律 DOM API 构建(防 XSS)。\n * @module @kenz1117/dsh-engram/client/EngramPanel\n */\n\nimport { useCallback, useEffect, useState } from 'react'\nimport styles from './panel.module.css'\n\n/** 列表/详情用的记忆视图(宿主 /api/engram/list 的行结构)。 */\ninterface MemoryRow {\n readonly id: string\n readonly scope: 'user' | 'project'\n readonly kind: string\n readonly content: string\n readonly importance: number\n readonly confidence: number\n readonly status: 'active' | 'archived' | 'forgotten'\n readonly createdAt: number\n readonly accessCount: number\n readonly sourceSessionId: string | null\n readonly sourceRound: number | null\n}\n\ninterface ListResult {\n readonly records: MemoryRow[]\n readonly total: number\n}\n\ninterface StatsPart {\n readonly scope: 'user' | 'project'\n readonly stats: {\n readonly total: number\n readonly active: number\n readonly archived: number\n readonly forgotten: number\n readonly signalRatio: number\n }\n}\n\nconst KINDS = ['fact', 'preference', 'decision', 'episode', 'skill'] as const\nconst PAGE_SIZE = 20\n\nasync function api<T>(path: string, init?: RequestInit): Promise<T> {\n const response = await fetch(`/api/engram/${path}`, init)\n const body = (await response.json()) as T & { error?: string }\n if (!response.ok) throw new Error(body.error ?? `HTTP ${String(response.status)}`)\n return body\n}\n\nfunction fmtTime(ms: number): string {\n return new Date(ms).toLocaleString('zh-CN', { hour12: false })\n}\n\n/** 审计弹层视图。 */\nfunction ReviewBody({ recordId, scope }: { recordId: string; scope: 'user' | 'project' }): React.ReactElement | null {\n const [text, setText] = useState<string | null>(null)\n useEffect(() => {\n let cancelled = false\n api<Record<string, unknown>>(`review?scope=${scope}&id=${encodeURIComponent(recordId)}`)\n .then((view) => {\n if (cancelled) return\n const record = view.record as MemoryRow\n const lines = [\n `内容: ${record.content}`,\n `属性: kind=${record.kind}, status=${record.status}, importance=${record.importance}, confidence=${record.confidence}, 访问 ${record.accessCount} 次`,\n `来源: ${record.sourceSessionId ?? '显式保存'}${record.sourceRound === null ? '' : ` 第${String(record.sourceRound)}轮`}`,\n ]\n for (const key of ['supersededBy', 'supersedes', 'contradicts', 'related'] as const) {\n const ids = view[key] as string[] | undefined\n if (ids !== undefined && ids.length > 0) lines.push(`${key}: ${ids.join(', ')}`)\n }\n const operations = view.operations as { at: number; op: string; detail: string | null }[] | undefined\n if (operations !== undefined && operations.length > 0) {\n lines.push('最近操作:')\n operations.forEach(op => lines.push(` ${fmtTime(op.at)} ${op.op}${op.detail ? ` ${op.detail}` : ''}`))\n }\n setText(lines.join('\\n'))\n })\n .catch((error: Error) => { if (!cancelled) setText(`加载失败:${error.message}`) })\n return () => { cancelled = true }\n }, [recordId, scope])\n if (text === null) return null\n return <pre className={styles.review}>{text}</pre>\n}\n\n/** 编辑弹层:内容/种类/重要性 → POST update(旧条目归档,取代链保留)。 */\nfunction EditDialog({ record, onClose, onSaved }: {\n record: MemoryRow\n onClose: () => void\n onSaved: () => void\n}): React.ReactElement {\n const [content, setContent] = useState(record.content)\n const [kind, setKind] = useState(record.kind)\n const [importance, setImportance] = useState(record.importance)\n const save = (): void => {\n api('update', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: record.id, scope: record.scope, content, kind, importance }),\n })\n .then(onSaved)\n .catch((error: Error) => { alert(error.message) })\n }\n return (\n <div className={styles.backdrop} onClick={onClose}>\n <div className={styles.dialog} onClick={event => event.stopPropagation()}>\n <h3>编辑记忆(写入取代链)</h3>\n <label className={styles.fieldLabel}>内容</label>\n <textarea className={styles.input} rows={3} value={content} onChange={event => setContent(event.target.value)} />\n <label className={styles.fieldLabel}>种类</label>\n <select className={styles.input} value={kind} onChange={event => setKind(event.target.value)}>\n {KINDS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n <label className={styles.fieldLabel}>重要性 {importance.toFixed(2)}</label>\n <input type=\"range\" min={0} max={1} step={0.05} value={importance}\n onChange={event => setImportance(Number(event.target.value))} />\n <div className={styles.modalFoot}>\n <button type=\"button\" className={styles.button} onClick={onClose}>取消</button>\n <button type=\"button\" className={`${styles.button} ${styles.primary}`} onClick={save}>保存(旧条目归档)</button>\n </div>\n </div>\n </div>\n )\n}\n\n/** 设置页「记忆库」section 主组件。 */\nexport function EngramSection(): React.ReactElement {\n const [scope, setScope] = useState<'user' | 'project'>('user')\n const [status, setStatus] = useState('all')\n const [kind, setKind] = useState('all')\n const [q, setQ] = useState('')\n const [offset, setOffset] = useState(0)\n const [list, setList] = useState<ListResult | null>(null)\n const [stats, setStats] = useState<StatsPart[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [editing, setEditing] = useState<MemoryRow | null>(null)\n const [reviewId, setReviewId] = useState<MemoryRow | null>(null)\n const [reloadTick, setReloadTick] = useState(0)\n\n const reload = useCallback((): void => { setReloadTick(tick => tick + 1) }, [])\n\n useEffect(() => {\n let cancelled = false\n const qs = new URLSearchParams({\n scope, status, kind, limit: String(PAGE_SIZE), offset: String(offset),\n })\n if (q !== '') qs.set('q', q)\n api<ListResult>(`list?${qs.toString()}`)\n .then((data) => { if (!cancelled) { setList(data); setError(null) } })\n .catch((loadError: Error) => { if (!cancelled) setError(loadError.message) })\n api<{ parts: StatsPart[] }>('stats')\n .then((data) => { if (!cancelled) setStats(data.parts) })\n .catch(() => { /* 统计失败不影响列表 */ })\n return () => { cancelled = true }\n }, [scope, status, kind, q, offset, reloadTick])\n\n const act = (route: string, record: MemoryRow): void => {\n api(route, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: record.id, scope: record.scope }),\n })\n .then(reload)\n .catch((actError: Error) => { alert(actError.message) })\n }\n\n const page = Math.floor(offset / PAGE_SIZE) + 1\n const pages = list === null ? 1 : Math.max(1, Math.ceil(list.total / PAGE_SIZE))\n\n return (\n <div className={styles.panel}>\n <div className={styles.toolbar}>\n <div className={styles.scopeTabs}>\n {(['user', 'project'] as const).map(option => (\n <button key={option} type=\"button\"\n className={scope === option ? styles.scopeOn : styles.scopeOff}\n onClick={() => { setScope(option); setOffset(0) }}>\n {option === 'user' ? '用户级' : '项目级'}\n </button>\n ))}\n </div>\n <button type=\"button\" className={styles.button} onClick={reload}>刷新</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { location.href = `/api/engram/export?scope=${scope}&format=markdown` }}>导出 MD</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { location.href = `/api/engram/export?scope=${scope}&format=json` }}>导出 JSON</button>\n </div>\n <div className={styles.cards}>\n {(stats ?? []).map(part => (\n <button key={part.scope} type=\"button\" className={styles.card}\n style={part.scope === scope ? { borderColor: 'var(--dsw-alias-brand-primary)' } : undefined}\n onClick={() => { setScope(part.scope); setOffset(0) }}>\n <b>{part.stats.total}</b>\n <span>{part.scope} · active {part.stats.active} · 信噪比 {Math.round(part.stats.signalRatio * 100)}%</span>\n </button>\n ))}\n </div>\n <div className={styles.filters}>\n <select className={styles.input} value={status}\n onChange={event => { setStatus(event.target.value); setOffset(0) }}>\n <option value=\"all\">全部状态</option>\n <option value=\"active\">active</option>\n <option value=\"archived\">archived</option>\n <option value=\"forgotten\">forgotten</option>\n </select>\n <select className={styles.input} value={kind}\n onChange={event => { setKind(event.target.value); setOffset(0) }}>\n <option value=\"all\">全部种类</option>\n {KINDS.map(option => <option key={option} value={option}>{option}</option>)}\n </select>\n <input className={styles.input} placeholder=\"按内容搜索…\" value={q}\n onChange={event => { setQ(event.target.value.trim()); setOffset(0) }} />\n </div>\n {error !== null && <div className={styles.empty}>{`加载失败:${error}`}</div>}\n {error === null && list !== null && list.records.length === 0 && (\n <div className={styles.empty}>没有符合条件的记忆</div>\n )}\n {(list?.records ?? []).map(record => (\n <div key={record.id} className={styles.item}>\n <div className={styles.row1}>\n <span className={`${styles.badge} ${styles[record.status]}`}>{record.status}</span>\n <span className={styles.badge}>{record.kind}</span>\n <span className={styles.badge}>{record.scope}</span>\n </div>\n <div className={styles.content}>{record.content}</div>\n <div className={styles.meta}>\n <span>重要性 {record.importance.toFixed(2)}</span>\n <span>置信 {record.confidence.toFixed(2)}</span>\n <span>访问 {record.accessCount} 次</span>\n <span>{record.sourceSessionId === null\n ? '显式保存'\n : `来源 ${record.sourceSessionId.slice(0, 16)}…${record.sourceRound === null ? '' : ` 第${String(record.sourceRound)}轮`}`}</span>\n <span>{fmtTime(record.createdAt)}</span>\n </div>\n <div className={styles.ops}>\n <button type=\"button\" className={styles.button}\n onClick={() => { setReviewId(record) }}>详情</button>\n <button type=\"button\" className={styles.button}\n onClick={() => { setEditing(record) }}>编辑</button>\n {record.status === 'active'\n ? <button type=\"button\" className={styles.button}\n onClick={() => { act('forget', record) }}>遗忘</button>\n : <button type=\"button\" className={styles.button}\n onClick={() => { act('restore', record) }}>恢复</button>}\n </div>\n </div>\n ))}\n <div className={styles.pager}>\n <button type=\"button\" className={styles.button} disabled={offset === 0}\n onClick={() => { setOffset(Math.max(0, offset - PAGE_SIZE)) }}>上一页</button>\n <span>第 {page} / {pages} 页 · 共 {list?.total ?? 0} 条</span>\n <button type=\"button\" className={styles.button}\n disabled={list === null || offset + PAGE_SIZE >= list.total}\n onClick={() => { setOffset(offset + PAGE_SIZE) }}>下一页</button>\n </div>\n {editing !== null && (\n <EditDialog record={editing} onClose={() => { setEditing(null) }} onSaved={() => { setEditing(null); reload() }} />\n )}\n {reviewId !== null && (\n <div className={styles.backdrop} onClick={() => { setReviewId(null) }}>\n <div className={styles.dialog} onClick={event => event.stopPropagation()}>\n <h3>记忆审计</h3>\n <ReviewBody recordId={reviewId.id} scope={reviewId.scope} />\n <div className={styles.modalFoot}>\n <button type=\"button\" className={styles.button}\n onClick={() => { setReviewId(null) }}>关闭</button>\n </div>\n </div>\n </div>\n )}\n </div>\n )\n}\n","/**\n * dsh-engram client half: 注册设置页「记忆库」section。\n * 数据经回环 API(/api/engram/*)读取与操作,与 host 半的路由对齐。\n * @module @kenz1117/dsh-engram/client\n */\n\nimport type { Context } from '@deepseek-ai/cordis'\n// Type-only: ctx.slots(renderer 的 SlotMap 渲染接线)。\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\n// Type-only: settings.section 槽位的 SlotMap merge(ui-settings 契约)。\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { EngramSection } from './EngramPanel.tsx'\n\n/** 必需服务:slots 渲染接线。 */\nexport const inject = ['slots']\n\n/**\n * Client plugin body: 设置页注册「记忆库」section(order 20,排在\n * general/models/plugins 之后)。\n * @param ctx - client root context.\n */\nexport function apply(ctx: Context): void {\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'engram',\n order: 20,\n label: () => '记忆库',\n }, EngramSection))\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kenz1117/dsh-engram",
|
|
3
3
|
"description": "Cross-session long-term memory for DeepSeek Harness: dual-scope SQLite memory graph, hybrid retrieval, provenance audit, and a knowledge flywheel.",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|