@tobycaimf/dsh-archived-sessions 1.0.0 → 1.0.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.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/client/index.jsx"],
4
- "sourcesContent": ["/**\n * dsh-archived-sessions \u2014 browser half: renders the \"\u5F52\u6863\u4F1A\u8BDD\" Settings\n * section (settings.section list slot). It talks to the host half's\n * /archived-sessions/* JSON routes (list / restore / delete) by fetch,\n * showing title, session date, and a workspace tag (handles deleted\n * workspaces). All DOM/runtime wiring failures are logged, never thrown \u2014 a\n * thrown plugin apply takes down the whole web-shell boot.\n *\n * @module dsh-archived-sessions/client\n */\n\nimport React, { useEffect, useRef, useState } from 'react'\n\nexport const inject = ['slots']\n\nconst CSS = `\n.archv{display:flex;flex-direction:column;gap:4px;max-width:800px;padding:8px 2px 28px}\n.archv-head{display:flex;align-items:center;gap:10px;margin:0 0 2px}\n.archv-title{font-size:16px;font-weight:650;color:var(--dsw-alias-label-primary);letter-spacing:-0.01em;margin:0}\n.archv-count{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:1px 8px;flex:none}\n.archv-sub{font-size:12px;line-height:1.55;color:var(--dsw-alias-label-tertiary);margin:0 0 12px;max-width:64ch}\n.archv-err{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);border-radius:10px;color:var(--dsw-alias-state-error-primary);font-size:12px;margin-bottom:10px}\n.archv-errretry{appearance:none;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:transparent;color:inherit;border-radius:8px;padding:4px 10px;font-size:11px;cursor:pointer;flex:none}\n.archv-errretry:focus-visible,.archv-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}\n.archv-list{display:flex;flex-direction:column;gap:8px}\n.archv-card{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-fill-elevated);transition:border-color .15s ease,background-color .15s ease}\n.archv-card:hover{border-color:var(--dsw-alias-border-l4)}\n.archv-main{min-width:0;display:flex;flex-direction:column;gap:4px}\n.archv-name{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.archv-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}\n.archv-wtag{display:inline-flex;align-items:center;gap:4px;max-width:100%;font-size:11px;font-weight:500;line-height:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:3px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.archv-wgone{border-style:dashed;color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}\n.archv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}\n.archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}\n.archv-dot{color:var(--dsw-alias-border-l3);flex:none}\n.archv-actions{display:flex;gap:8px;flex:none}\n.archv-btn{appearance:none;min-height:32px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:9px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:background-color .15s ease,border-color .15s ease,color .15s ease}\n.archv-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.archv-btn:disabled{opacity:.5;cursor:default}\n.archv-restore{min-width:62px;justify-content:center}\n.archv-del{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent)}\n.archv-del:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}\n.archv-empty{display:flex;align-items:center;gap:10px;padding:20px 14px;border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.archv-skel{display:flex;flex-direction:column;gap:8px}\n.archv-skel-card{height:58px;border-radius:12px;background:var(--dsw-alias-fill-subtle);position:relative;overflow:hidden}\n.archv-skel-card::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--dsw-alias-fill-elevated) 75%,transparent),transparent);animation:archv-shimmer 1.4s infinite}\n.archv-status{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:60;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);padding:9px 16px;border-radius:999px;font-size:12px;box-shadow:0 8px 24px rgb(0 0 0/.18);display:flex;align-items:center;gap:8px;animation:archv-pop .18s ease-out;max-width:min(90vw,420px)}\n.archv-spin{width:12px;height:12px;border:2px solid color-mix(in srgb,var(--dsw-alias-label-secondary) 35%,transparent);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;animation:archv-rot .8s linear infinite;flex:none}\n@keyframes archv-shimmer{100%{transform:translateX(100%)}}\n@keyframes archv-rot{to{transform:rotate(360deg)}}\n@keyframes archv-pop{from{opacity:0;transform:translateX(-50%) translateY(10px)}}\n@media (prefers-reduced-motion:reduce){.archv-skel-card::after{animation:none}.archv-card,.archv-btn{transition:none}.archv-status,.archv-spin{animation:none}}\n@media (max-width:560px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}}\n`\n\nfunction fmtDate(iso) {\n if (!iso) return null\n const d = new Date(iso)\n if (isNaN(d.getTime())) return null\n try {\n return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }).format(d)\n } catch {\n return String(iso)\n }\n}\n\nfunction pathName(p) {\n if (!p) return null\n const parts = String(p).replace(/\\\\+$/, '').split(/[/\\\\]/)\n return parts[parts.length - 1] || p\n}\n\nasync function postJSON(path, body) {\n const res = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify(body || {}),\n })\n const data = await res.json().catch(() => null)\n if (!res.ok || !data) throw new Error((data && (data.error || data.message)) || `request failed (${res.status})`)\n return data\n}\n\nfunction ArchivedPanel() {\n const [items, setItems] = useState(null)\n const [busy, setBusy] = useState(null)\n const [confirmId, setConfirmId] = useState(null)\n const [error, setError] = useState(null)\n const [toast, setToast] = useState(null)\n const timer = useRef(null)\n\n const showToast = (msg) => {\n if (timer.current) clearTimeout(timer.current)\n setToast(msg)\n timer.current = setTimeout(() => setToast(null), 2400)\n }\n\n const refresh = () => {\n setError(null)\n postJSON('/archived-sessions/list', {})\n .then((r) => setItems(r.items || []))\n .catch((e) => setError(String((e && e.message) || e)))\n }\n\n useEffect(() => {\n refresh()\n return () => { if (timer.current) clearTimeout(timer.current) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const act = (action, it) => {\n if (busy) return\n if (action === 'delete') {\n if (confirmId !== it.sessionId) { setConfirmId(it.sessionId); return }\n setConfirmId(null)\n } else { setConfirmId(null); setError(null) }\n setBusy(it.sessionId)\n postJSON('/archived-sessions/' + action, { sessionId: it.sessionId })\n .then(() => {\n setBusy(null)\n showToast(action === 'restore' ? `\u5DF2\u6062\u590D\u300C${it.title || it.sessionId}\u300D` : `\u5DF2\u5220\u9664 ${it.title || it.sessionId}`)\n refresh()\n })\n .catch((e) => { setBusy(null); setConfirmId(null); setError(String((e && e.message) || e)) })\n }\n\n const workspaceTag = (it) => {\n if (it.hasWorkspace && it.workspaceGone) {\n return (\n <span className=\"archv-wtag archv-wgone\" title={(it.workspacePath || '') + '\uFF08\u539F\u5DE5\u4F5C\u533A\u5DF2\u5220\u9664\uFF09'}>\n \u5DE5\u4F5C\u533A\u5DF2\u5220 \u00B7 {pathName(it.workspacePath) || '?'}\n </span>\n )\n }\n const wName = it.workspaceTitle || pathName(it.workspacePath)\n if (wName) return <span className=\"archv-wtag\" title={it.workspacePath || ''}>{wName}</span>\n return null\n }\n\n return (\n <div className=\"archv\" role=\"region\" aria-label=\"\u5F52\u6863\u4F1A\u8BDD\">\n <style>{CSS}</style>\n <div className=\"archv-head\">\n <h2 className=\"archv-title\">\u5F52\u6863\u4F1A\u8BDD</h2>\n {items !== null && <span className=\"archv-count\" aria-label={`${items.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD`}>{items.length}</span>}\n </div>\n <p className=\"archv-sub\">\n \u88AB\u5F52\u6863\uFF08\u4ECE\u4FA7\u680F\u9690\u85CF\uFF09\u7684\u4F1A\u8BDD\u90FD\u5728\u8FD9\u91CC\u3002\u6062\u590D\u4F1A\u628A\u4F1A\u8BDD\u653E\u56DE\u539F\u5206\u7EC4\uFF1B\u5220\u9664\u4F1A\u5F7B\u5E95\u79FB\u9664\u65E5\u5FD7\u6587\u4EF6\uFF0C\u4E0D\u53EF\u6062\u590D\u3002\n </p>\n {error && (\n <div className=\"archv-err\" role=\"alert\">\n <span>{error}</span>\n <button type=\"button\" className=\"archv-errretry\" onClick={refresh}>\u91CD\u8BD5</button>\n </div>\n )}\n {items === null ? (\n <div className=\"archv-skel\" aria-label=\"\u52A0\u8F7D\u4E2D\">\n {[0, 1, 2].map((i) => <div key={i} className=\"archv-skel-card\" />)}\n </div>\n ) : items.length === 0 ? (\n <div className=\"archv-empty\">\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u4FA7\u680F\u4EFB\u4E00\u4F1A\u8BDD\u7684\u83DC\u5355\u91CC\u9009\u62E9\u300C\u5F52\u6863\u300D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002</div>\n ) : (\n <div className=\"archv-list\" role=\"list\">\n {items.map((it) => {\n const isConfirm = confirmId === it.sessionId\n const date = fmtDate(it.createdAt)\n const wtag = workspaceTag(it)\n return (\n <div key={it.sessionId} className=\"archv-card\" role=\"listitem\">\n <div className=\"archv-main\">\n <div className=\"archv-name\" title={it.title || ''}>{it.title || '(\u65E0\u6807\u9898)'}</div>\n <div className=\"archv-meta\">\n {date && <span className=\"archv-date\">{date}</span>}\n {date && wtag && <span className=\"archv-dot\">\u00B7</span>}\n {wtag}\n <span className=\"archv-id\">{it.sessionId}</span>\n </div>\n </div>\n <div className=\"archv-actions\">\n <button type=\"button\" className=\"archv-btn archv-restore\" disabled={busy !== null} aria-label={'\u6062\u590D ' + (it.title || it.sessionId)} onClick={() => act('restore', it)}>\n {busy === it.sessionId && <span className=\"archv-spin\" aria-hidden=\"true\" />}\u6062\u590D\n </button>\n <button type=\"button\" className=\"archv-btn archv-del\" disabled={busy !== null} aria-label={(isConfirm ? '\u786E\u8BA4\u5220\u9664 ' : '\u5220\u9664 ') + (it.title || it.sessionId)} onClick={() => act('delete', it)}>\n {isConfirm ? '\u786E\u8BA4\u5220\u9664?' : '\u5220\u9664'}\n </button>\n </div>\n </div>\n )\n })}\n </div>\n )}\n {toast && <div className=\"archv-status\" role=\"status\">{toast}</div>}\n </div>\n )\n}\n\nexport function apply(ctx) {\n ctx.slots.inject('settings.section', () =>\n ctx.slots.register(\n { name: 'settings.section', id: 'archived-sessions', order: 90, label: '\u5F52\u6863\u4F1A\u8BDD' },\n (props) => <ArchivedPanel {...props} />,\n ),\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * dsh-archived-sessions \u2014 browser half: renders a single \"\u4F1A\u8BDD\u7BA1\u7406\" settings\n * section (settings.section list slot) that unifies archived-session\n * management and cross-workspace moving. It talks to the host half's\n * /archived-sessions/* JSON routes by fetch, showing every conversation with\n * its archive state and offering archive / restore / delete / move (and batch)\n * actions. All DOM/runtime wiring failures are logged, never thrown \u2014 a thrown\n * plugin apply takes down the whole web-shell boot.\n *\n * @module dsh-archived-sessions/client\n */\n\nimport React, { useEffect, useRef, useState } from 'react'\n\nexport const inject = ['slots']\n\nconst CSS = `\n.archv{display:flex;flex-direction:column;gap:4px;max-width:800px;padding:8px 2px 28px}\n.archv-head{display:flex;align-items:center;gap:10px;margin:0 0 2px}\n.archv-title{font-size:16px;font-weight:650;color:var(--dsw-alias-label-primary);letter-spacing:-0.01em;margin:0}\n.archv-count{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:1px 8px;flex:none}\n.archv-sub{font-size:12px;line-height:1.55;color:var(--dsw-alias-label-tertiary);margin:0 0 12px;max-width:64ch}\n.archv-err{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 12px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);border-radius:10px;color:var(--dsw-alias-state-error-primary);font-size:12px;margin-bottom:10px}\n.archv-errretry{appearance:none;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:transparent;color:inherit;border-radius:8px;padding:4px 10px;font-size:11px;cursor:pointer;flex:none}\n.sess-filter{display:flex;align-items:center;gap:6px;margin:0 0 12px}\n.sess-fbtn{appearance:none;min-height:30px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:999px;font-size:12px;font-weight:500;cursor:pointer}\n.sess-fbtn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.sess-fbtn-on{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3)}\n.sess-batch{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 2px 4px;margin-bottom:4px}\n.sess-btntext{font-size:12px;color:var(--dsw-alias-label-tertiary);flex:none}\n.archv-list{display:flex;flex-direction:column;gap:8px}\n.archv-card{display:flex;flex-direction:column;align-items:stretch;gap:0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-fill-elevated);transition:border-color .15s ease,background-color .15s ease}\n.archv-card:hover{border-color:var(--dsw-alias-border-l4)}\n.archv-card-exp{border-color:var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-1)}\n.archv-row{display:flex;align-items:center;gap:14px;width:100%;min-width:0}\n.archv-main{min-width:0;display:flex;flex-direction:column;gap:4px}\n.archv-name{font-size:13px;font-weight:550;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.archv-meta{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}\n.archv-wtag{display:inline-flex;align-items:center;gap:4px;max-width:100%;font-size:11px;font-weight:500;line-height:1;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-fill-subtle);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:3px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.archv-wgone{border-style:dashed;color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 7%,transparent)}\n.archv-active{color:var(--dsw-alias-state-success-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent)}\n.archv-date{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:none}\n.archv-id{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10.5px;color:var(--dsw-alias-label-tertiary);flex:none}\n.archv-dot{color:var(--dsw-alias-border-l3);flex:none}\n.archv-check{width:15px;height:15px;accent-color:var(--dsw-alias-state-business-primary);flex:none;cursor:pointer}\n.archv-body{flex:1;min-width:0;display:flex;align-items:center;gap:12px}\n.archv-actions{display:flex;gap:8px;flex:none;flex-wrap:wrap;justify-content:flex-end}\n.archv-btn{appearance:none;min-height:32px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-fill-subtle);color:var(--dsw-alias-label-secondary);border-radius:9px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:background-color .15s ease,border-color .15s ease,color .15s ease}\n.archv-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.archv-btn:disabled{opacity:.5;cursor:default}\n.archv-del{color:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent)}\n.archv-del:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}\n.archv-go{color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 45%,transparent)}\n.archv-go:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent);color:var(--dsw-alias-state-business-primary)}\n.archv-empty{display:flex;align-items:center;gap:10px;padding:20px 14px;border:1px dashed var(--dsw-alias-border-l3);border-radius:12px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.archv-skel{display:flex;flex-direction:column;gap:8px}\n.archv-skel-card{height:58px;border-radius:12px;background:var(--dsw-alias-fill-subtle);position:relative;overflow:hidden}\n.archv-skel-card::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--dsw-alias-fill-elevated) 75%,transparent),transparent);animation:archv-shimmer 1.4s infinite}\n.archv-status{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:60;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);padding:9px 16px;border-radius:999px;font-size:12px;box-shadow:0 8px 24px rgb(0 0 0/.18);display:flex;align-items:center;gap:8px;animation:archv-pop .18s ease-out;max-width:min(90vw,420px)}\n.archv-spin{width:12px;height:12px;border:2px solid color-mix(in srgb,var(--dsw-alias-label-secondary) 35%,transparent);border-top-color:var(--dsw-alias-label-secondary);border-radius:50%;animation:archv-rot .8s linear infinite;flex:none}\n@keyframes archv-shimmer{100%{transform:translateX(100%)}}\n@keyframes archv-rot{to{transform:rotate(360deg)}}\n@keyframes archv-pop{from{opacity:0;transform:translateX(-50%) translateY(10px)}}\n@media (prefers-reduced-motion:reduce){.archv-skel-card::after{animation:none}.archv-card,.archv-btn{transition:none}.archv-status,.archv-spin{animation:none}}\n@media (max-width:640px){.archv-card{flex-direction:column;align-items:stretch;gap:10px}.archv-actions{justify-content:flex-end}}\n.mv-sheet{width:100%;box-sizing:border-box;display:flex;flex-direction:column;gap:12px;margin-top:12px;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-left:3px solid var(--dsw-alias-state-business-primary);border-radius:10px;background:var(--dsw-alias-fill-subtle)}\n.mv-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:10px}\n.mv-sheet-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);margin:0}\n.mv-sheet-close{appearance:none;width:26px;height:26px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:7px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1}\n.mv-sheet-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.mv-seg{display:flex;gap:2px;padding:2px;background:var(--dsw-alias-fill-elevated);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;width:100%}\n.mv-segbtn{appearance:none;flex:1;min-height:30px;padding:0 12px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px}\n.mv-segbtn:hover:not(:disabled){color:var(--dsw-alias-label-primary)}\n.mv-segbtn-on{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);box-shadow:0 1px 2px rgb(0 0 0/.08)}\n.mv-field{display:flex;flex-direction:column;gap:6px}\n.mv-field label.mv-field-label{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}\n.mv-field select,.mv-field input[type=text]{box-sizing:border-box;appearance:none;width:100%;min-height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-fill-elevated);color:var(--dsw-alias-label-primary);font-size:12px;font-family:inherit}\n.mv-field select:focus-visible,.mv-field input[type=text]:focus-visible,.mv-sheet-close:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}\n.mv-browse-row{display:flex;align-items:center;gap:8px}\n.mv-browse-row input[type=text]{flex:1;min-width:0}\n.mv-foot{display:flex;justify-content:flex-end;align-items:center;gap:8px;margin-top:2px}\n@media (max-width:640px){.archv-row{flex-wrap:wrap}.mv-sheet{padding:12px}}\n`\n\nfunction fmtDate(iso) {\n if (!iso) return null\n const d = new Date(iso)\n if (isNaN(d.getTime())) return null\n try {\n return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }).format(d)\n } catch {\n return String(iso)\n }\n}\n\nfunction pathName(p) {\n if (!p) return null\n const parts = String(p).replace(/\\\\+$/, '').split(/[/\\\\]/)\n return parts[parts.length - 1] || p\n}\n\nasync function postJSON(path, body) {\n const res = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'application/json' },\n body: JSON.stringify(body || {}),\n })\n const data = await res.json().catch(() => null)\n if (!res.ok || !data) throw new Error((data && (data.error || data.message)) || `request failed (${res.status})`)\n return data\n}\n\n// Left-nav icon swap: DSH's settings shell renders a shared fallback gear for\n// every custom section and settings.section has no per-section icon field.\n// Like dsh-better-sidebar, we mark our own row by matching its visible label\n// text, then CSS swaps the gear for an archive-box glyph. The marker owns no\n// shell structure and is removed on fiber disposal (HMR-safe, ships with the\n// plugin).\nconst NAV_CSS = `\n[data-dsh-nav-sessions] > svg:first-child { display: none; }\n[data-dsh-nav-sessions]::before {\n content: ''; flex: none; width: 16px; height: 16px; background: currentColor;\n -webkit-mask: url(\"data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E\") center / contain no-repeat;\n mask: url(\"data:image/svg+xml,%3Csvg%20xmlns%3D'http://www.w3.org/2000/svg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'none'%20stroke%3D'black'%20stroke-width%3D'2'%20stroke-linecap%3D'round'%20stroke-linejoin%3D'round'%3E%3Cpath%20d%3D'M21%208v13H3V8'/%3E%3Cpath%20d%3D'M1%203h22v5H1z'/%3E%3Cpath%20d%3D'M10%2012h4'/%3E%3C/svg%3E\") center / contain no-repeat;\n}\n`\n\nfunction markSettingsNav() {\n const LABEL = '\u4F1A\u8BDD\u7BA1\u7406'\n let disposed = false\n const sync = () => {\n if (disposed) return\n const buttons = document.querySelectorAll('[role=\"dialog\"] nav button')\n for (const b of buttons) {\n const t = (b.textContent || '').trim()\n if (t === LABEL) b.setAttribute('data-dsh-nav-sessions', '')\n else b.removeAttribute('data-dsh-nav-sessions')\n }\n }\n sync()\n const obs = new MutationObserver(sync)\n obs.observe(document.body, { childList: true, subtree: true, characterData: true })\n return () => {\n disposed = true\n obs.disconnect()\n document.querySelectorAll('[data-dsh-nav-sessions]').forEach((e) => e.removeAttribute('data-dsh-nav-sessions'))\n }\n}\n\nfunction installSettingsNavIcons(ctx) {\n const styleEl = document.createElement('style')\n styleEl.textContent = NAV_CSS\n document.head.appendChild(styleEl)\n const dispose = markSettingsNav()\n ctx.effect(() => () => {\n dispose()\n if (styleEl.parentNode) styleEl.parentNode.removeChild(styleEl)\n })\n}\n\nfunction SessionPanel({ workspacesSvc }) {\n const [sessions, setSessions] = useState(null)\n const [workspaces, setWorkspaces] = useState([])\n const [filter, setFilter] = useState('all') // 'all' | 'archived'\n const [selected, setSelected] = useState({})\n const [confirmDel, setConfirmDel] = useState(null)\n const [confirmBatch, setConfirmBatch] = useState(false)\n const [busy, setBusy] = useState(null)\n const [openMove, setOpenMove] = useState(null)\n const [moveMode, setMoveMode] = useState('existing')\n const [targetWs, setTargetWs] = useState('')\n const [newPath, setNewPath] = useState('')\n const [error, setError] = useState(null)\n const [toast, setToast] = useState(null)\n const [picking, setPicking] = useState(false)\n const timer = useRef(null)\n\n const showToast = (msg) => {\n if (timer.current) clearTimeout(timer.current)\n setToast(msg)\n timer.current = setTimeout(() => setToast(null), 2400)\n }\n\n const refresh = () => {\n setError(null)\n Promise.all([\n postJSON('/archived-sessions/sessions', {}),\n postJSON('/archived-sessions/workspaces', {}),\n ])\n .then(([s, works]) => {\n setSessions(s.items || [])\n setWorkspaces(works.items || [])\n setSelected({})\n setConfirmDel(null)\n setConfirmBatch(false)\n if (!targetWs && works.items && works.items.length) setTargetWs(works.items[0].workspaceId)\n })\n .catch((e) => setError(String((e && e.message) || e)))\n }\n\n useEffect(() => {\n refresh()\n return () => { if (timer.current) clearTimeout(timer.current) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const wsPath = (id) => {\n const w = workspaces.find((x) => x.workspaceId === id)\n return w ? w.path : ''\n }\n\n const archivedList = sessions ? sessions.filter((x) => x.archived) : []\n const activeList = sessions ? sessions.filter((x) => !x.archived) : []\n const list = filter === 'archived' ? archivedList : sessions || []\n const selIds = Object.keys(selected).filter((k) => selected[k])\n\n const toggle = (id) => setSelected((s) => ({ ...s, [id]: !s[id] }))\n const clearSel = () => setSelected({})\n const selectAll = () => {\n const o = {}\n list.forEach((x) => { o[x.sessionId] = true })\n setSelected(o)\n }\n\n const act = (action, it) => {\n if (busy) return\n if (action === 'delete') {\n if (confirmDel !== it.sessionId) { setConfirmDel(it.sessionId); return }\n setConfirmDel(null)\n }\n setBusy(it.sessionId)\n postJSON('/archived-sessions/' + action, { sessionId: it.sessionId })\n .then(() => {\n setBusy(null)\n const n = it.title || it.sessionId\n showToast(action === 'archive' ? `\u5DF2\u5F52\u6863\u300C${n}\u300D` : action === 'restore' ? `\u5DF2\u6062\u590D\u300C${n}\u300D` : `\u5DF2\u5220\u9664 ${n}`)\n refresh()\n })\n .catch((e) => { setBusy(null); setConfirmDel(null); setError(String((e && e.message) || e)) })\n }\n\n const doMove = (it) => {\n const targetPath = moveMode === 'new' ? newPath.trim() : wsPath(targetWs)\n if (!targetPath) { setError('\u8BF7\u9009\u62E9\u5DF2\u6709\u5DE5\u4F5C\u533A\u6216\u8F93\u5165\u65B0\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84'); return }\n setBusy(it.sessionId)\n setError(null)\n postJSON('/archived-sessions/move', { sessionId: it.sessionId, targetPath })\n .then((r) => {\n setBusy(null)\n setOpenMove(null)\n setMoveMode('existing')\n setNewPath('')\n showToast(`\u5DF2\u628A\u300C${it.title || it.sessionId}\u300D\u79FB\u5230 ${r.workspaceTitle || targetPath}`)\n refresh()\n })\n .catch((e) => { setBusy(null); setError(String((e && e.message) || e)) })\n }\n\n const doBatch = (action) => {\n if (!selIds.length || busy) return\n if (action === 'delete-many') {\n if (!confirmBatch) { setConfirmBatch(true); return }\n setConfirmBatch(false)\n }\n setBusy('__batch__')\n postJSON('/archived-sessions/' + action, { sessionIds: selIds })\n .then((r) => {\n setBusy(null)\n const n = (r && (r.archived || r.restored || r.deleted)) || selIds.length\n showToast(`\u5DF2\u5904\u7406 ${n} \u4E2A\u4F1A\u8BDD`)\n refresh()\n })\n .catch((e) => { setBusy(null); setConfirmBatch(false); setError(String((e && e.message) || e)) })\n }\n\n const openMoveFor = (it) => {\n if (openMove === it.sessionId) { setOpenMove(null); return }\n setTargetWs(workspaces.length ? (targetWs || workspaces[0].workspaceId) : '')\n setMoveMode('existing')\n setNewPath('')\n setOpenMove(it.sessionId)\n }\n\n const pickDirectory = async () => {\n if (!workspacesSvc || picking) return\n setPicking(true)\n try {\n const p = await workspacesSvc.pickDirectory()\n if (p) { setNewPath(p); setMoveMode('new') }\n } catch (e) {\n setError(String((e && e.message) || e))\n } finally {\n setPicking(false)\n }\n }\n\n const workspaceTag = (it) => {\n if (it.hasWorkspace && it.workspaceGone) {\n return <span className=\"archv-wtag archv-wgone\" title={(it.workspacePath || '') + '\uFF08\u539F\u5DE5\u4F5C\u533A\u5DF2\u5220\u9664\uFF09'}>\u5DE5\u4F5C\u533A\u5DF2\u5220 \u00B7 {pathName(it.workspacePath) || '?'}</span>\n }\n const wName = it.workspaceTitle || pathName(it.workspacePath)\n if (wName) return <span className=\"archv-wtag\" title={it.workspacePath || ''}>{wName}</span>\n return <span className=\"archv-wtag\">\u672A\u5206\u7EC4</span>\n }\n\n const rowActions = (it) => {\n if (it.archived) {\n return (\n <div className=\"archv-actions\">\n <button type=\"button\" className=\"archv-btn archv-go\" disabled={busy !== null} onClick={() => act('restore', it)}>\u6062\u590D</button>\n <button type=\"button\" className=\"archv-btn archv-go\" disabled={busy !== null} onClick={() => openMoveFor(it)}>{openMove === it.sessionId ? '\u6536\u8D77' : '\u79FB\u52A8\u2026'}</button>\n <button type=\"button\" className=\"archv-btn archv-del\" disabled={busy !== null} onClick={() => act('delete', it)}>{confirmDel === it.sessionId ? '\u786E\u8BA4\u5220\u9664?' : '\u5220\u9664'}</button>\n </div>\n )\n }\n return (\n <div className=\"archv-actions\">\n <button type=\"button\" className=\"archv-btn\" disabled={busy !== null} onClick={() => act('archive', it)}>\u5F52\u6863</button>\n <button type=\"button\" className=\"archv-btn archv-go\" disabled={busy !== null} onClick={() => openMoveFor(it)}>{openMove === it.sessionId ? '\u6536\u8D77' : '\u79FB\u52A8\u2026'}</button>\n </div>\n )\n }\n\n return (\n <div className=\"archv\" role=\"region\" aria-label=\"\u4F1A\u8BDD\u7BA1\u7406\">\n <style>{CSS}</style>\n <div className=\"archv-head\">\n <h2 className=\"archv-title\">\u4F1A\u8BDD\u7BA1\u7406</h2>\n {sessions !== null && <span className=\"archv-count\" aria-label={`${sessions.length} \u4E2A\u4F1A\u8BDD`}>{sessions.length}</span>}\n </div>\n <p className=\"archv-sub\">\n \u7EDF\u4E00\u7BA1\u7406\u5168\u90E8\u4F1A\u8BDD\uFF1A\u5F52\u6863 / \u6062\u590D / \u5F7B\u5E95\u5220\u9664 / \u79FB\u52A8\u5230\u5176\u4ED6\u5DE5\u4F5C\u533A\uFF0C\u652F\u6301\u6279\u91CF\u3002\u5F52\u6863\u4F1A\u4ECE\u4FA7\u680F\u9690\u85CF\uFF1B\u5220\u9664\u4F1A\u5F7B\u5E95\u79FB\u9664\u65E5\u5FD7\uFF0C\u4E0D\u53EF\u6062\u590D\u3002\n </p>\n {error && (\n <div className=\"archv-err\" role=\"alert\">\n <span>{error}</span>\n <button type=\"button\" className=\"archv-errretry\" onClick={refresh}>\u91CD\u8BD5</button>\n </div>\n )}\n {sessions === null ? (\n <div className=\"archv-skel\" aria-label=\"\u52A0\u8F7D\u4E2D\">\n {[0, 1, 2].map((i) => <div key={i} className=\"archv-skel-card\" />)}\n </div>\n ) : (\n <>\n <div className=\"sess-filter\" role=\"tablist\" aria-label=\"\u4F1A\u8BDD\u7B5B\u9009\">\n <button type=\"button\" className={'sess-fbtn' + (filter === 'all' ? ' sess-fbtn-on' : '')} onClick={() => { setFilter('all'); clearSel(); setConfirmBatch(false) }}>\u5168\u90E8 ({sessions.length})</button>\n <button type=\"button\" className={'sess-fbtn' + (filter === 'archived' ? ' sess-fbtn-on' : '')} onClick={() => { setFilter('archived'); clearSel(); setConfirmBatch(false) }}>\u5DF2\u5F52\u6863 ({archivedList.length})</button>\n </div>\n\n {list.length > 0 && (\n <div className=\"sess-batch\">\n <span className=\"sess-btntext\">{selIds.length ? `\u5DF2\u9009 ${selIds.length} \u9879` : (filter === 'archived' ? `\u5171 ${archivedList.length} \u4E2A\u5F52\u6863\u4F1A\u8BDD` : `\u5171 ${sessions.length} \u4E2A\u4F1A\u8BDD\uFF08\u6D3B\u52A8 ${activeList.length} / \u5DF2\u5F52\u6863 ${archivedList.length}\uFF09`)}</span>\n <button type=\"button\" className=\"archv-btn\" disabled={list.length === 0} onClick={selectAll}>\u5168\u9009</button>\n {selIds.length > 0 && (\n <>\n {filter === 'archived' && (\n <>\n <button type=\"button\" className=\"archv-btn\" disabled={busy !== null} onClick={() => doBatch('restore-many')}>\u6062\u590D\u6240\u9009</button>\n <button type=\"button\" className=\"archv-btn archv-del\" disabled={busy !== null} onClick={() => doBatch('delete-many')}>{confirmBatch ? '\u786E\u8BA4\u5220\u9664\u6240\u9009?' : '\u5220\u9664\u6240\u9009'}</button>\n </>\n )}\n {filter === 'all' && (\n <button type=\"button\" className=\"archv-btn\" disabled={busy !== null} onClick={() => doBatch('archive-many')}>\u5F52\u6863\u6240\u9009</button>\n )}\n <button type=\"button\" className=\"archv-btn\" onClick={clearSel}>\u53D6\u6D88\u9009\u62E9</button>\n </>\n )}\n </div>\n )}\n\n {list.length === 0 ? (\n <div className=\"archv-empty\">{filter === 'archived' ? '\u76EE\u524D\u6CA1\u6709\u5F52\u6863\u4F1A\u8BDD\u3002\u5728\u201C\u5168\u90E8\u201D\u91CC\u9009\u4E2D\u4F1A\u8BDD\u70B9\u201C\u5F52\u6863\u201D\u5373\u53EF\u6536\u7EB3\u8FDB\u6765\u3002' : '\u6682\u65E0\u53EF\u7BA1\u7406\u7684\u4F1A\u8BDD\u3002'}</div>\n ) : (\n <div className=\"archv-list\" role=\"list\">\n {list.map((it) => {\n const date = fmtDate(it.createdAt)\n const expanded = openMove === it.sessionId\n return (\n <div key={it.sessionId} className={'archv-card' + (expanded ? ' archv-card-exp' : '')} role=\"listitem\">\n <div className=\"archv-row\">\n <input\n type=\"checkbox\"\n className=\"archv-check\"\n checked={!!selected[it.sessionId]}\n onChange={() => toggle(it.sessionId)}\n aria-label={'\u9009\u62E9 ' + (it.title || it.sessionId)}\n />\n <div className=\"archv-body\">\n <div className=\"archv-main\">\n <div className=\"archv-name\" title={it.title || ''}>{it.title || '(\u65E0\u6807\u9898)'}</div>\n <div className=\"archv-meta\">\n {it.archived ? <span className=\"archv-wtag archv-wgone\">\u5DF2\u5F52\u6863</span> : <span className=\"archv-wtag archv-active\">\u6D3B\u52A8</span>}\n {workspaceTag(it)}\n {date && <><span className=\"archv-dot\">\u00B7</span><span className=\"archv-date\">{date}</span></>}\n <span className=\"archv-id\">{it.sessionId}</span>\n </div>\n </div>\n {rowActions(it)}\n </div>\n </div>\n {expanded && (\n <div className=\"mv-sheet\" role=\"region\" aria-label=\"\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A\">\n <div className=\"mv-sheet-head\">\n <h3 className=\"mv-sheet-title\">\u79FB\u52A8\u5230\u5DE5\u4F5C\u533A</h3>\n <button type=\"button\" className=\"mv-sheet-close\" aria-label=\"\u5173\u95ED\" onClick={() => setOpenMove(null)}>\u00D7</button>\n </div>\n <div className=\"mv-seg\" role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={moveMode === 'existing'} className={'mv-segbtn' + (moveMode === 'existing' ? ' mv-segbtn-on' : '')} onClick={() => setMoveMode('existing')}>\u5DF2\u6709\u5DE5\u4F5C\u533A</button>\n <button type=\"button\" role=\"tab\" aria-selected={moveMode === 'new'} className={'mv-segbtn' + (moveMode === 'new' ? ' mv-segbtn-on' : '')} onClick={() => setMoveMode('new')}>\u65B0\u5EFA\u76EE\u5F55</button>\n </div>\n {moveMode === 'existing' ? (\n <div className=\"mv-field\">\n <label className=\"mv-field-label\" htmlFor=\"mv-target-ws\">\u76EE\u6807\u5DE5\u4F5C\u533A</label>\n <select id=\"mv-target-ws\" value={targetWs} onChange={(e) => setTargetWs(e.target.value)}>\n {workspaces.length === 0 && <option value=\"\">\uFF08\u6682\u65E0\u5DE5\u4F5C\u533A\uFF09</option>}\n {workspaces.map((w) => (\n <option key={w.workspaceId} value={w.workspaceId}>{w.title} \u00B7 {w.path}</option>\n ))}\n </select>\n </div>\n ) : (\n <div className=\"mv-field\">\n <label className=\"mv-field-label\" htmlFor=\"mv-new-path\">\u65B0\u5DE5\u4F5C\u533A\u76EE\u5F55\u8DEF\u5F84</label>\n <div className=\"mv-browse-row\">\n <input\n id=\"mv-new-path\"\n type=\"text\"\n value={newPath}\n onChange={(e) => setNewPath(e.target.value)}\n placeholder=\"\u4F8B\u5982 /Users/you/Projects/demo \u6216 ~/demo\"\n />\n <button\n type=\"button\"\n className=\"archv-btn\"\n onClick={pickDirectory}\n disabled={busy !== null || picking || !workspacesSvc}\n title={!workspacesSvc ? '\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9' : '\u6253\u5F00\u7CFB\u7EDF\u76EE\u5F55\u9009\u62E9\u7A97\u53E3'}\n >\n {picking ? '\u9009\u62E9\u4E2D\u2026' : '\u6D4F\u89C8\u2026'}\n </button>\n </div>\n </div>\n )}\n <div className=\"mv-foot\">\n <button type=\"button\" className=\"archv-btn\" onClick={() => setOpenMove(null)}>\u53D6\u6D88</button>\n <button type=\"button\" className=\"archv-btn archv-go\" disabled={busy !== null} onClick={() => doMove(it)}>\n {busy === it.sessionId && <span className=\"archv-spin\" aria-hidden=\"true\" />}\u786E\u8BA4\u79FB\u52A8\n </button>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n </>\n )}\n {toast && <div className=\"archv-status\" role=\"status\">{toast}</div>}\n </div>\n )\n}\n\nexport function apply(ctx) {\n installSettingsNavIcons(ctx)\n const workspacesSvc = ctx.get('workspaces')\n ctx.slots.inject('settings.section', () =>\n ctx.slots.register(\n { name: 'settings.section', id: 'session-manager', order: 90, label: '\u4F1A\u8BDD\u7BA1\u7406' },\n (props) => <SessionPanel {...props} workspacesSvc={workspacesSvc} />,\n ),\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/lib/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // src/index.js
2
- import { unlink } from "node:fs/promises";
2
+ import { mkdir, realpath, rename, unlink } from "node:fs/promises";
3
+ import { basename, isAbsolute, join } from "node:path";
4
+ import { homedir } from "node:os";
3
5
  var name = "dsh-archived-sessions";
4
6
  var inject = ["webServer", "workspaceRegistry", "sessionPersistence", "sessionQuery", "storageDomain"];
5
7
  var MAX_TITLE = 80;
@@ -160,6 +162,160 @@ function apply(ctx) {
160
162
  }
161
163
  return { ok: true, deleted: true, removedPath };
162
164
  }
165
+ async function moveTargetWorkspace(rawPath) {
166
+ if (typeof rawPath !== "string" || !rawPath.trim()) throw new Error("\u7F3A\u5C11\u76EE\u6807\u5DE5\u4F5C\u533A\u8DEF\u5F84");
167
+ let p = String(rawPath).trim();
168
+ if (p.startsWith("~/")) p = join(homedir(), p.slice(2));
169
+ if (!isAbsolute(p)) p = join(homedir(), p);
170
+ let canonical = null;
171
+ try {
172
+ canonical = await realpath(p);
173
+ } catch (e) {
174
+ canonical = null;
175
+ }
176
+ if (canonical === null) {
177
+ await mkdir(p, { recursive: true });
178
+ canonical = await realpath(p);
179
+ }
180
+ return { canonical, entity: await w.create(canonical, basename(canonical) || "workspace") };
181
+ }
182
+ async function moveOne(sid, targetPath) {
183
+ const sessions = ctx.get("sessions");
184
+ if (sessions && sessions.get(sid)) {
185
+ throw new Error("\u8BE5\u4F1A\u8BDD\u5F53\u524D\u5904\u4E8E\u6253\u5F00\u72B6\u6001\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u522B\u7684\u4F1A\u8BDD\u518D\u79FB\u52A8\u3002");
186
+ }
187
+ const r = await sp.readFrom(sid, 0);
188
+ if (!r || !r.meta) throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u8BE5\u4F1A\u8BDD\u7684\u65E5\u5FD7");
189
+ const meta = r.meta;
190
+ const events = r.events;
191
+ const oldCwd = meta.cwd || null;
192
+ const { canonical, entity: target } = await moveTargetWorkspace(targetPath);
193
+ if (oldCwd) {
194
+ let oldCanon = null;
195
+ try {
196
+ oldCanon = await realpath(oldCwd);
197
+ } catch (e) {
198
+ oldCanon = null;
199
+ }
200
+ if (oldCanon === canonical) {
201
+ return { ok: true, already: true, workspaceId: target.id, workspaceTitle: target.title };
202
+ }
203
+ }
204
+ const newHeader = Object.assign({}, meta, { cwd: canonical });
205
+ let oldPath = null;
206
+ let backupPath = null;
207
+ try {
208
+ const loc = sp.locate(meta);
209
+ if (loc && typeof loc.path === "string" && loc.path) oldPath = loc.path;
210
+ } catch (e) {
211
+ oldPath = null;
212
+ }
213
+ if (oldPath) {
214
+ backupPath = `${oldPath}.move-backup-${Date.now()}`;
215
+ try {
216
+ await rename(oldPath, backupPath);
217
+ } catch (e) {
218
+ if (e && e.code !== "ENOENT") throw new Error("\u79FB\u52A8\u5931\u8D25\uFF1A\u65E0\u6CD5\u5907\u4EFD\u65E7\u7684\u4F1A\u8BDD\u65E5\u5FD7");
219
+ backupPath = null;
220
+ }
221
+ }
222
+ const restore = async () => {
223
+ if (backupPath && oldPath) {
224
+ try {
225
+ await rename(backupPath, oldPath);
226
+ } catch (e) {
227
+ }
228
+ }
229
+ };
230
+ if (typeof sp.create !== "function" || typeof sp.append !== "function") {
231
+ await restore();
232
+ throw new Error("\u5F53\u524D\u4F1A\u8BDD\u5B58\u50A8\u540E\u7AEF\u4E0D\u652F\u6301\u5B89\u5168\u79FB\u52A8\uFF0C\u5DF2\u4E2D\u6B62\u3002");
233
+ }
234
+ try {
235
+ await sp.create(newHeader);
236
+ await sp.append(sid, events);
237
+ const check = await sp.readFrom(sid, 0);
238
+ if (!check || !check.meta || check.meta.cwd !== canonical) {
239
+ throw new Error("\u79FB\u52A8\u540E\u6821\u9A8C\u5931\u8D25\uFF1A\u4F1A\u8BDD\u5DE5\u4F5C\u76EE\u5F55\u672A\u6B63\u786E\u66F4\u65B0");
240
+ }
241
+ } catch (e) {
242
+ await restore();
243
+ throw new Error("\u79FB\u52A8\u4F1A\u8BDD\u65E5\u5FD7\u5931\u8D25\uFF1A" + String(e && e.message || e));
244
+ }
245
+ if (backupPath) {
246
+ try {
247
+ await unlink(backupPath);
248
+ } catch (e) {
249
+ }
250
+ }
251
+ for (const ent of w.list()) {
252
+ try {
253
+ await ent.detachSession(sid);
254
+ } catch (e) {
255
+ }
256
+ }
257
+ if (w.headers && typeof w.headers.set === "function") w.headers.set(sid, newHeader);
258
+ if (w.sessionPaths && typeof w.sessionPaths.set === "function") w.sessionPaths.set(sid, canonical);
259
+ await target.attachSession(sid);
260
+ return {
261
+ ok: true,
262
+ moved: true,
263
+ workspaceId: target.id,
264
+ workspaceTitle: target.title,
265
+ workspacePath: canonical
266
+ };
267
+ }
268
+ async function listWorkspaces() {
269
+ const out = [];
270
+ try {
271
+ for (const ent of w.list()) out.push({ workspaceId: ent.id, title: ent.title, path: ent.path });
272
+ } catch (e) {
273
+ }
274
+ return out;
275
+ }
276
+ async function archiveOne(sid) {
277
+ const state = await archivedState();
278
+ const list = state.archivedSessionIds.map(String);
279
+ if (list.includes(sid)) return { ok: true, archived: false };
280
+ await w.archiveSession(sid);
281
+ return { ok: true, archived: true };
282
+ }
283
+ async function allSessionItems() {
284
+ let materialized = /* @__PURE__ */ new Set();
285
+ let live = ctx.get("sessions");
286
+ try {
287
+ const headers = await sp.list();
288
+ materialized = new Set(headers.map((h) => String(h.id)));
289
+ } catch (e) {
290
+ }
291
+ const ids = [];
292
+ try {
293
+ for (const header of await sp.list()) ids.push(String(header.id));
294
+ } catch (e) {
295
+ }
296
+ if (live) {
297
+ try {
298
+ live.list().forEach((s) => {
299
+ if (!ids.includes(String(s.id))) ids.push(String(s.id));
300
+ });
301
+ } catch (e) {
302
+ }
303
+ }
304
+ wsByPath = {};
305
+ try {
306
+ for (const ent of w.list()) wsByPath[ent.path] = ent;
307
+ } catch (e) {
308
+ wsByPath = {};
309
+ }
310
+ const currentArchived = new Set((await archivedState().catch(() => ({ archivedSessionIds: [] }))).archivedSessionIds || []);
311
+ const items = [];
312
+ const CHUNK = 6;
313
+ for (let i = 0; i < ids.length; i += CHUNK) {
314
+ const res2 = await Promise.all(ids.slice(i, i + CHUNK).map(resolveOne));
315
+ for (const it of res2) items.push({ ...it, archived: currentArchived.has(it.sessionId) });
316
+ }
317
+ return items;
318
+ }
163
319
  ctx.effect(() => {
164
320
  const disposers = [];
165
321
  disposers.push(ctx.webServer.register({
@@ -267,6 +423,80 @@ function apply(ctx) {
267
423
  }
268
424
  }
269
425
  }));
426
+ disposers.push(ctx.webServer.register({
427
+ kind: "exact",
428
+ path: "/archived-sessions/sessions",
429
+ handler: async (req, res) => {
430
+ try {
431
+ json(res, { items: await allSessionItems() });
432
+ } catch (e) {
433
+ json(res, { error: String(e && e.message || e) }, 500);
434
+ }
435
+ }
436
+ }));
437
+ disposers.push(ctx.webServer.register({
438
+ kind: "exact",
439
+ path: "/archived-sessions/workspaces",
440
+ handler: async (req, res) => {
441
+ try {
442
+ json(res, { items: await listWorkspaces() });
443
+ } catch (e) {
444
+ json(res, { error: String(e && e.message || e) }, 500);
445
+ }
446
+ }
447
+ }));
448
+ disposers.push(ctx.webServer.register({
449
+ kind: "exact",
450
+ path: "/archived-sessions/move",
451
+ handler: async (req, res) => {
452
+ try {
453
+ const body = await readJsonBody(req);
454
+ const sid = body && typeof body.sessionId === "string" ? body.sessionId : null;
455
+ const target = body && typeof body.targetPath === "string" ? body.targetPath : null;
456
+ if (!sid) return json(res, { ok: false, error: "missing sessionId" }, 400);
457
+ if (!target) return json(res, { ok: false, error: "missing targetPath" }, 400);
458
+ json(res, { sessionId: sid, ...await moveOne(sid, target) });
459
+ } catch (e) {
460
+ json(res, { ok: false, error: String(e && e.message || e) }, 500);
461
+ }
462
+ }
463
+ }));
464
+ disposers.push(ctx.webServer.register({
465
+ kind: "exact",
466
+ path: "/archived-sessions/archive",
467
+ handler: async (req, res) => {
468
+ try {
469
+ const body = await readJsonBody(req);
470
+ const sid = body && typeof body.sessionId === "string" ? body.sessionId : null;
471
+ if (!sid) return json(res, { ok: false, error: "missing sessionId" }, 400);
472
+ json(res, { sessionId: sid, ...await archiveOne(sid) });
473
+ } catch (e) {
474
+ json(res, { ok: false, error: String(e && e.message || e) }, 500);
475
+ }
476
+ }
477
+ }));
478
+ disposers.push(ctx.webServer.register({
479
+ kind: "exact",
480
+ path: "/archived-sessions/archive-many",
481
+ handler: async (req, res) => {
482
+ try {
483
+ const body = await readJsonBody(req);
484
+ const ids = parseIds(body);
485
+ if (!ids || ids.length === 0) return json(res, { ok: false, error: "missing sessionIds" }, 400);
486
+ const results = [];
487
+ for (const sid of ids) {
488
+ try {
489
+ results.push({ sessionId: sid, ok: true, ...await archiveOne(sid) });
490
+ } catch (e) {
491
+ results.push({ sessionId: sid, ok: false, error: String(e && e.message || e) });
492
+ }
493
+ }
494
+ json(res, { ok: true, archived: results.filter((r) => r.ok).length, results });
495
+ } catch (e) {
496
+ json(res, { ok: false, error: String(e && e.message || e) }, 500);
497
+ }
498
+ }
499
+ }));
270
500
  return () => {
271
501
  for (const d of disposers) d();
272
502
  };
package/lib/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["// dsh-archived-sessions \u2014 host half.\n//\n// Serves /archived-sessions/* JSON routes (list / restore / restore-many /\n// delete / delete-many) over the host `webServer`. The browser Settings\n// section (\"\u5F52\u6863\u4F1A\u8BDD\") talks to these. Reads/writes the durable workspace\n// archive set (workspaceRegistry + storageDomain), folds titles/dates/workspace\n// tags from session persistence, and physically removes a session's log file\n// on delete.\nimport { unlink } from 'node:fs/promises'\n\nexport const name = 'dsh-archived-sessions'\nexport const inject = ['webServer', 'workspaceRegistry', 'sessionPersistence', 'sessionQuery', 'storageDomain']\n\nconst MAX_TITLE = 80\n\nfunction json(res, value, status = 200) {\n res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' })\n res.end(JSON.stringify(value))\n}\n\nasync function readJsonBody(req) {\n const chunks = []\n let total = 0\n for await (const chunk of req) {\n chunks.push(chunk)\n total += chunk.length\n if (total > 1 << 20) return null\n }\n try {\n return JSON.parse(Buffer.concat(chunks).toString('utf8'))\n } catch {\n return null\n }\n}\n\nfunction parseIds(body) {\n const raw = body && body.sessionIds\n if (!Array.isArray(raw)) return null\n const ids = []\n for (const v of raw) if (typeof v === 'string' && v) ids.push(v)\n return ids\n}\n\nfunction foldTitle(events) {\n let found = null\n let firstUser = null\n for (const ev of events) {\n if (ev.type === 'session/title' && ev.data && typeof ev.data.title === 'string' && ev.data.title.length) {\n found = ev.data.title\n }\n if (firstUser === null && ev.type === 'user/message' && ev.data && Array.isArray(ev.data.content)) {\n const txt = ev.data.content.filter((b) => b && b.type === 'text').map((b) => b.text).filter(Boolean).join(' ').trim()\n if (txt) firstUser = txt\n }\n }\n return found || firstUser || null\n}\n\nexport function apply(ctx) {\n const w = ctx.workspaceRegistry\n const sp = ctx.sessionPersistence\n const sq = ctx.sessionQuery\n const dom = () => ctx.storageDomain.get('workspace')\n\n async function archivedState() {\n const d = dom()\n if (!d) throw new Error('workspace domain is not open')\n return d.global.get()\n }\n\n async function writeArchived(nextIds) {\n const d = dom()\n if (!d) throw new Error('workspace domain is not open')\n const cur = d.global.get()\n const next = Object.assign({}, cur, { archivedSessionIds: nextIds })\n await d.global.set(next)\n // Keep the registry's in-memory cache in sync so the live sidebar refreshes.\n if (w && 'state' in w) { try { w.state = next } catch (e) { /* best-effort */ } }\n return next\n }\n\n let wsByPath = {}\n\n async function resolveOne(id) {\n let title = null, createdAt = null, cwd = null\n try {\n const o = await sq.readTitleSnapshot(id)\n if (o) {\n if (o.title && o.title.title) title = String(o.title.title)\n if (o.session) { cwd = o.session.cwd || null; createdAt = o.session.createdAt || null }\n }\n } catch (e) { /* fall back to raw log */ }\n if (!title || !cwd) {\n try {\n const r = await sp.readFrom(id, 0)\n if (r.meta) {\n if (!cwd) cwd = r.meta.cwd || null\n if (!createdAt) createdAt = r.meta.createdAt || null\n }\n if (!title && Array.isArray(r.events)) title = foldTitle(r.events)\n } catch (e2) { /* keep what we have */ }\n }\n const ws = cwd ? wsByPath[cwd] : undefined\n const workspaceGone = !!(cwd && !ws)\n const display = title ? (String(title).length > MAX_TITLE ? String(title).slice(0, MAX_TITLE) + '\u2026' : String(title)) : null\n return {\n sessionId: id,\n title: display,\n createdAt: createdAt || null,\n workspacePath: cwd || null,\n workspaceTitle: (ws && ws.title) ? ws.title : null,\n workspaceGone: workspaceGone ? true : false,\n hasWorkspace: !!cwd,\n }\n }\n\n // Restore (unarchive) one session; throws on failure.\n async function restoreOne(sid) {\n const state = await archivedState()\n const list = state.archivedSessionIds.map(String)\n if (!list.includes(sid)) return { ok: true, restored: false }\n await writeArchived(list.filter((x) => x !== sid))\n return { ok: true, restored: true }\n }\n\n // Physically delete one session log + clear archive/workspace accounting;\n // throws on failure (live sessions are rejected).\n async function deleteOne(sid) {\n const sessions = ctx.get('sessions')\n if (sessions && sessions.get(sid)) {\n throw new Error('\u8BE5\u4F1A\u8BDD\u5F53\u524D\u5904\u4E8E\u6253\u5F00\u72B6\u6001\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u522B\u7684\u4F1A\u8BDD\u518D\u5220\u9664\u3002')\n }\n let removedPath = null\n try {\n const headers = await sp.list()\n const header = headers.find((h) => String(h.id) === sid)\n if (header) {\n const loc = sp.locate(header)\n if (loc && typeof loc.path === 'string') removedPath = loc.path\n } else {\n // Session not in the materialized list \u2014 use its header cwd to locate the log anyway.\n const r = await sp.readFrom(sid, 0)\n if (r && r.meta && r.meta.cwd) {\n const loc = sp.locate({ id: sid, cwd: r.meta.cwd })\n if (loc && typeof loc.path === 'string') removedPath = loc.path\n }\n }\n } catch (e) { /* best-effort */ }\n if (removedPath) {\n try {\n await unlink(removedPath)\n } catch (e) {\n if (e && e.code !== 'ENOENT') throw new Error('\u5220\u9664\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25\uFF1A' + String((e && e.message) || e))\n }\n }\n try {\n for (const ent of w.list()) {\n if (ent.sessionIds.includes(sid)) { try { await ent.detachSession(sid) } catch (e) { /* ignore */ } }\n }\n } catch (e) { /* ignore */ }\n try { if (w.sessionPaths && w.sessionPaths.delete) w.sessionPaths.delete(sid) } catch (e) {}\n try { if (w.headers && w.headers.delete) w.headers.delete(sid) } catch (e) {}\n // NOTE: intentionally do NOT unarchive (keep the id in the archive set).\n // Removing it from the archive set would make DSH re-show the session in the\n // sidebar; with its workspace gone it would land in \u672A\u5206\u7EC4 until the index\n // rebuilds. Keeping it hidden keeps the deleted session out of every list\n // immediately. The stale hidden id is inert (no log -> no session resolves).\n return { ok: true, deleted: true, removedPath }\n }\n\n ctx.effect(() => {\n const disposers = []\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/list',\n handler: async (req, res) => {\n try {\n const state = await archivedState()\n const ids = state.archivedSessionIds || []\n // Only surface archived ids that still exist (materialized log or live).\n // Deleted sessions keep a hidden archive id but no log, so they drop out here.\n let materialized = new Set()\n let live = ctx.get('sessions')\n try {\n const headers = await sp.list()\n materialized = new Set(headers.map((h) => String(h.id)))\n } catch (e) { /* best-effort */ }\n const idStrs = ids.map(String).filter((id) => materialized.has(id) || (live && live.get(id)))\n wsByPath = {}\n try { for (const ent of w.list()) wsByPath[ent.path] = ent } catch (e) { wsByPath = {} }\n const items = []\n const CHUNK = 6\n for (let i = 0; i < idStrs.length; i += CHUNK) {\n const res2 = await Promise.all(idStrs.slice(i, i + CHUNK).map(resolveOne))\n items.push.apply(items, res2)\n }\n json(res, { items })\n } catch (e) {\n json(res, { error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/restore',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n json(res, await restoreOne(sid))\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/restore-many',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const ids = parseIds(body)\n if (!ids || ids.length === 0) return json(res, { ok: false, error: 'missing sessionIds' }, 400)\n const results = []\n for (const sid of ids) {\n try { results.push({ sessionId: sid, ok: true, ...(await restoreOne(sid)) }) }\n catch (e) { results.push({ sessionId: sid, ok: false, error: String((e && e.message) || e) }) }\n }\n json(res, { ok: true, restored: results.filter((r) => r.ok).length, results })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/delete',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n json(res, await deleteOne(sid))\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/delete-many',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const ids = parseIds(body)\n if (!ids || ids.length === 0) return json(res, { ok: false, error: 'missing sessionIds' }, 400)\n const results = []\n for (const sid of ids) {\n try { results.push({ sessionId: sid, ok: true, ...(await deleteOne(sid)) }) }\n catch (e) { results.push({ sessionId: sid, ok: false, error: String((e && e.message) || e) }) }\n }\n json(res, { ok: true, deleted: results.filter((r) => r.ok).length, results })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n return () => { for (const d of disposers) d() }\n }, 'dsh-archived-sessions: routes')\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// dsh-archived-sessions \u2014 host half.\n//\n// Serves /archived-sessions/* JSON routes (list / restore / restore-many /\n// delete / delete-many / sessions / workspaces / move) over the host\n// `webServer`. The browser Settings sections (\"\u5F52\u6863\u4F1A\u8BDD\" & \"\u79FB\u52A8\u4F1A\u8BDD\") talk to\n// these. Reads/writes the durable workspace archive set\n// (workspaceRegistry + storageDomain), folds titles/dates/workspace tags from\n// session persistence, physically removes a session's log file on delete, and\n// relocates a conversation (session) between workspaces on move.\nimport { mkdir, realpath, rename, unlink } from 'node:fs/promises'\nimport { basename, isAbsolute, join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport const name = 'dsh-archived-sessions'\nexport const inject = ['webServer', 'workspaceRegistry', 'sessionPersistence', 'sessionQuery', 'storageDomain']\n\nconst MAX_TITLE = 80\n\nfunction json(res, value, status = 200) {\n res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' })\n res.end(JSON.stringify(value))\n}\n\nasync function readJsonBody(req) {\n const chunks = []\n let total = 0\n for await (const chunk of req) {\n chunks.push(chunk)\n total += chunk.length\n if (total > 1 << 20) return null\n }\n try {\n return JSON.parse(Buffer.concat(chunks).toString('utf8'))\n } catch {\n return null\n }\n}\n\nfunction parseIds(body) {\n const raw = body && body.sessionIds\n if (!Array.isArray(raw)) return null\n const ids = []\n for (const v of raw) if (typeof v === 'string' && v) ids.push(v)\n return ids\n}\n\nfunction foldTitle(events) {\n let found = null\n let firstUser = null\n for (const ev of events) {\n if (ev.type === 'session/title' && ev.data && typeof ev.data.title === 'string' && ev.data.title.length) {\n found = ev.data.title\n }\n if (firstUser === null && ev.type === 'user/message' && ev.data && Array.isArray(ev.data.content)) {\n const txt = ev.data.content.filter((b) => b && b.type === 'text').map((b) => b.text).filter(Boolean).join(' ').trim()\n if (txt) firstUser = txt\n }\n }\n return found || firstUser || null\n}\n\nexport function apply(ctx) {\n const w = ctx.workspaceRegistry\n const sp = ctx.sessionPersistence\n const sq = ctx.sessionQuery\n const dom = () => ctx.storageDomain.get('workspace')\n\n async function archivedState() {\n const d = dom()\n if (!d) throw new Error('workspace domain is not open')\n return d.global.get()\n }\n\n async function writeArchived(nextIds) {\n const d = dom()\n if (!d) throw new Error('workspace domain is not open')\n const cur = d.global.get()\n const next = Object.assign({}, cur, { archivedSessionIds: nextIds })\n await d.global.set(next)\n // Keep the registry's in-memory cache in sync so the live sidebar refreshes.\n if (w && 'state' in w) { try { w.state = next } catch (e) { /* best-effort */ } }\n return next\n }\n\n let wsByPath = {}\n\n async function resolveOne(id) {\n let title = null, createdAt = null, cwd = null\n try {\n const o = await sq.readTitleSnapshot(id)\n if (o) {\n if (o.title && o.title.title) title = String(o.title.title)\n if (o.session) { cwd = o.session.cwd || null; createdAt = o.session.createdAt || null }\n }\n } catch (e) { /* fall back to raw log */ }\n if (!title || !cwd) {\n try {\n const r = await sp.readFrom(id, 0)\n if (r.meta) {\n if (!cwd) cwd = r.meta.cwd || null\n if (!createdAt) createdAt = r.meta.createdAt || null\n }\n if (!title && Array.isArray(r.events)) title = foldTitle(r.events)\n } catch (e2) { /* keep what we have */ }\n }\n const ws = cwd ? wsByPath[cwd] : undefined\n const workspaceGone = !!(cwd && !ws)\n const display = title ? (String(title).length > MAX_TITLE ? String(title).slice(0, MAX_TITLE) + '\u2026' : String(title)) : null\n return {\n sessionId: id,\n title: display,\n createdAt: createdAt || null,\n workspacePath: cwd || null,\n workspaceTitle: (ws && ws.title) ? ws.title : null,\n workspaceGone: workspaceGone ? true : false,\n hasWorkspace: !!cwd,\n }\n }\n\n // Restore (unarchive) one session; throws on failure.\n async function restoreOne(sid) {\n const state = await archivedState()\n const list = state.archivedSessionIds.map(String)\n if (!list.includes(sid)) return { ok: true, restored: false }\n await writeArchived(list.filter((x) => x !== sid))\n return { ok: true, restored: true }\n }\n\n // Physically delete one session log + clear archive/workspace accounting;\n // throws on failure (live sessions are rejected).\n async function deleteOne(sid) {\n const sessions = ctx.get('sessions')\n if (sessions && sessions.get(sid)) {\n throw new Error('\u8BE5\u4F1A\u8BDD\u5F53\u524D\u5904\u4E8E\u6253\u5F00\u72B6\u6001\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u522B\u7684\u4F1A\u8BDD\u518D\u5220\u9664\u3002')\n }\n let removedPath = null\n try {\n const headers = await sp.list()\n const header = headers.find((h) => String(h.id) === sid)\n if (header) {\n const loc = sp.locate(header)\n if (loc && typeof loc.path === 'string') removedPath = loc.path\n } else {\n // Session not in the materialized list \u2014 use its header cwd to locate the log anyway.\n const r = await sp.readFrom(sid, 0)\n if (r && r.meta && r.meta.cwd) {\n const loc = sp.locate({ id: sid, cwd: r.meta.cwd })\n if (loc && typeof loc.path === 'string') removedPath = loc.path\n }\n }\n } catch (e) { /* best-effort */ }\n if (removedPath) {\n try {\n await unlink(removedPath)\n } catch (e) {\n if (e && e.code !== 'ENOENT') throw new Error('\u5220\u9664\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25\uFF1A' + String((e && e.message) || e))\n }\n }\n try {\n for (const ent of w.list()) {\n if (ent.sessionIds.includes(sid)) { try { await ent.detachSession(sid) } catch (e) { /* ignore */ } }\n }\n } catch (e) { /* ignore */ }\n try { if (w.sessionPaths && w.sessionPaths.delete) w.sessionPaths.delete(sid) } catch (e) {}\n try { if (w.headers && w.headers.delete) w.headers.delete(sid) } catch (e) {}\n // NOTE: intentionally do NOT unarchive (keep the id in the archive set).\n // Removing it from the archive set would make DSH re-show the session in the\n // sidebar; with its workspace gone it would land in \u672A\u5206\u7EC4 until the index\n // rebuilds. Keeping it hidden keeps the deleted session out of every list\n // immediately. The stale hidden id is inert (no log -> no session resolves).\n return { ok: true, deleted: true, removedPath }\n }\n\n // ---- \"move conversation between workspaces\" helper -----------------------\n // DSH binds a conversation to the workspace whose canonical directory path\n // equals the session's stored cwd. Moving it therefore means: (1) adopt the\n // target path as a workspace (create if needed), (2) durably relocate the\n // session's log so its header carries the new cwd, and (3) reassign the\n // workspace membership (detach everywhere, attach to target). The log\n // relocation goes through the persistence service's own encoder (handles the\n // zstd artifact encoding) with a backup + rollback so a failure never leaves\n // the session half-moved.\n\n async function moveTargetWorkspace(rawPath) {\n if (typeof rawPath !== 'string' || !rawPath.trim()) throw new Error('\u7F3A\u5C11\u76EE\u6807\u5DE5\u4F5C\u533A\u8DEF\u5F84')\n let p = String(rawPath).trim()\n if (p.startsWith('~/')) p = join(homedir(), p.slice(2))\n if (!isAbsolute(p)) p = join(homedir(), p)\n let canonical = null\n try { canonical = await realpath(p) } catch (e) { canonical = null }\n if (canonical === null) {\n await mkdir(p, { recursive: true })\n canonical = await realpath(p)\n }\n return { canonical, entity: await w.create(canonical, basename(canonical) || 'workspace') }\n }\n\n async function moveOne(sid, targetPath) {\n const sessions = ctx.get('sessions')\n if (sessions && sessions.get(sid)) {\n throw new Error('\u8BE5\u4F1A\u8BDD\u5F53\u524D\u5904\u4E8E\u6253\u5F00\u72B6\u6001\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u522B\u7684\u4F1A\u8BDD\u518D\u79FB\u52A8\u3002')\n }\n const r = await sp.readFrom(sid, 0)\n if (!r || !r.meta) throw new Error('\u65E0\u6CD5\u8BFB\u53D6\u8BE5\u4F1A\u8BDD\u7684\u65E5\u5FD7')\n const meta = r.meta\n const events = r.events\n const oldCwd = meta.cwd || null\n\n const { canonical, entity: target } = await moveTargetWorkspace(targetPath)\n\n if (oldCwd) {\n let oldCanon = null\n try { oldCanon = await realpath(oldCwd) } catch (e) { oldCanon = null }\n if (oldCanon === canonical) {\n return { ok: true, already: true, workspaceId: target.id, workspaceTitle: target.title }\n }\n }\n\n const newHeader = Object.assign({}, meta, { cwd: canonical })\n\n // 1) Back up the current log artifact before touching anything.\n let oldPath = null\n let backupPath = null\n try {\n const loc = sp.locate(meta)\n if (loc && typeof loc.path === 'string' && loc.path) oldPath = loc.path\n } catch (e) { oldPath = null }\n if (oldPath) {\n backupPath = `${oldPath}.move-backup-${Date.now()}`\n try {\n await rename(oldPath, backupPath)\n } catch (e) {\n if (e && e.code !== 'ENOENT') throw new Error('\u79FB\u52A8\u5931\u8D25\uFF1A\u65E0\u6CD5\u5907\u4EFD\u65E7\u7684\u4F1A\u8BDD\u65E5\u5FD7')\n backupPath = null\n }\n }\n\n const restore = async () => {\n if (backupPath && oldPath) {\n try { await rename(backupPath, oldPath) } catch (e) { /* best-effort */ }\n }\n }\n\n // 2) Relocate the log through the persistence service (re-encodes header).\n if (typeof sp.create !== 'function' || typeof sp.append !== 'function') {\n await restore()\n throw new Error('\u5F53\u524D\u4F1A\u8BDD\u5B58\u50A8\u540E\u7AEF\u4E0D\u652F\u6301\u5B89\u5168\u79FB\u52A8\uFF0C\u5DF2\u4E2D\u6B62\u3002')\n }\n try {\n await sp.create(newHeader)\n await sp.append(sid, events)\n const check = await sp.readFrom(sid, 0)\n if (!check || !check.meta || check.meta.cwd !== canonical) {\n throw new Error('\u79FB\u52A8\u540E\u6821\u9A8C\u5931\u8D25\uFF1A\u4F1A\u8BDD\u5DE5\u4F5C\u76EE\u5F55\u672A\u6B63\u786E\u66F4\u65B0')\n }\n } catch (e) {\n await restore()\n throw new Error('\u79FB\u52A8\u4F1A\u8BDD\u65E5\u5FD7\u5931\u8D25\uFF1A' + String((e && e.message) || e))\n }\n if (backupPath) { try { await unlink(backupPath) } catch (e) { /* best-effort */ } }\n\n // 3) Reassign workspace membership (durable records + in-memory index).\n for (const ent of w.list()) {\n try { await ent.detachSession(sid) } catch (e) { /* ignore */ }\n }\n if (w.headers && typeof w.headers.set === 'function') w.headers.set(sid, newHeader)\n if (w.sessionPaths && typeof w.sessionPaths.set === 'function') w.sessionPaths.set(sid, canonical)\n await target.attachSession(sid)\n\n return {\n ok: true,\n moved: true,\n workspaceId: target.id,\n workspaceTitle: target.title,\n workspacePath: canonical,\n }\n }\n\n async function listWorkspaces() {\n const out = []\n try {\n for (const ent of w.list()) out.push({ workspaceId: ent.id, title: ent.title, path: ent.path })\n } catch (e) { /* ignore */ }\n return out\n }\n\n // Archive (hide) one session: adds its id to the durable archive set so it\n // is dropped out of the sidebar. DSH requires the session to exist (live or\n // persisted) \u2014 a genuine miss surfaces as an error.\n async function archiveOne(sid) {\n const state = await archivedState()\n const list = state.archivedSessionIds.map(String)\n if (list.includes(sid)) return { ok: true, archived: false }\n await w.archiveSession(sid)\n return { ok: true, archived: true }\n }\n\n async function allSessionItems() {\n let materialized = new Set()\n let live = ctx.get('sessions')\n try {\n const headers = await sp.list()\n materialized = new Set(headers.map((h) => String(h.id)))\n } catch (e) { /* best-effort */ }\n const ids = []\n try { for (const header of await sp.list()) ids.push(String(header.id)) } catch (e) { /* ignore */ }\n if (live) { try { live.list().forEach((s) => { if (!ids.includes(String(s.id))) ids.push(String(s.id)) }) } catch (e) { /* ignore */ } }\n wsByPath = {}\n try { for (const ent of w.list()) wsByPath[ent.path] = ent } catch (e) { wsByPath = {} }\n const currentArchived = new Set((await archivedState().catch(() => ({ archivedSessionIds: [] }))).archivedSessionIds || [])\n const items = []\n const CHUNK = 6\n for (let i = 0; i < ids.length; i += CHUNK) {\n const res2 = await Promise.all(ids.slice(i, i + CHUNK).map(resolveOne))\n for (const it of res2) items.push({ ...it, archived: currentArchived.has(it.sessionId) })\n }\n return items\n }\n\n ctx.effect(() => {\n const disposers = []\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/list',\n handler: async (req, res) => {\n try {\n const state = await archivedState()\n const ids = state.archivedSessionIds || []\n // Only surface archived ids that still exist (materialized log or live).\n // Deleted sessions keep a hidden archive id but no log, so they drop out here.\n let materialized = new Set()\n let live = ctx.get('sessions')\n try {\n const headers = await sp.list()\n materialized = new Set(headers.map((h) => String(h.id)))\n } catch (e) { /* best-effort */ }\n const idStrs = ids.map(String).filter((id) => materialized.has(id) || (live && live.get(id)))\n wsByPath = {}\n try { for (const ent of w.list()) wsByPath[ent.path] = ent } catch (e) { wsByPath = {} }\n const items = []\n const CHUNK = 6\n for (let i = 0; i < idStrs.length; i += CHUNK) {\n const res2 = await Promise.all(idStrs.slice(i, i + CHUNK).map(resolveOne))\n items.push.apply(items, res2)\n }\n json(res, { items })\n } catch (e) {\n json(res, { error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/restore',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n json(res, await restoreOne(sid))\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/restore-many',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const ids = parseIds(body)\n if (!ids || ids.length === 0) return json(res, { ok: false, error: 'missing sessionIds' }, 400)\n const results = []\n for (const sid of ids) {\n try { results.push({ sessionId: sid, ok: true, ...(await restoreOne(sid)) }) }\n catch (e) { results.push({ sessionId: sid, ok: false, error: String((e && e.message) || e) }) }\n }\n json(res, { ok: true, restored: results.filter((r) => r.ok).length, results })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/delete',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n json(res, await deleteOne(sid))\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/delete-many',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const ids = parseIds(body)\n if (!ids || ids.length === 0) return json(res, { ok: false, error: 'missing sessionIds' }, 400)\n const results = []\n for (const sid of ids) {\n try { results.push({ sessionId: sid, ok: true, ...(await deleteOne(sid)) }) }\n catch (e) { results.push({ sessionId: sid, ok: false, error: String((e && e.message) || e) }) }\n }\n json(res, { ok: true, deleted: results.filter((r) => r.ok).length, results })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n // All conversations (for the \"\u79FB\u52A8\u4F1A\u8BDD\" panel).\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/sessions',\n handler: async (req, res) => {\n try {\n json(res, { items: await allSessionItems() })\n } catch (e) {\n json(res, { error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n // Available target workspaces (for the move picker).\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/workspaces',\n handler: async (req, res) => {\n try {\n json(res, { items: await listWorkspaces() })\n } catch (e) {\n json(res, { error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n // Move one conversation to a target workspace (existing path or a new one).\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/move',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n const target = body && typeof body.targetPath === 'string' ? body.targetPath : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n if (!target) return json(res, { ok: false, error: 'missing targetPath' }, 400)\n json(res, { sessionId: sid, ...(await moveOne(sid, target)) })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n // Archive (hide) one session.\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/archive',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const sid = body && typeof body.sessionId === 'string' ? body.sessionId : null\n if (!sid) return json(res, { ok: false, error: 'missing sessionId' }, 400)\n json(res, { sessionId: sid, ...(await archiveOne(sid)) })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n // Archive (hide) many sessions.\n disposers.push(ctx.webServer.register({\n kind: 'exact',\n path: '/archived-sessions/archive-many',\n handler: async (req, res) => {\n try {\n const body = await readJsonBody(req)\n const ids = parseIds(body)\n if (!ids || ids.length === 0) return json(res, { ok: false, error: 'missing sessionIds' }, 400)\n const results = []\n for (const sid of ids) {\n try { results.push({ sessionId: sid, ok: true, ...(await archiveOne(sid)) }) }\n catch (e) { results.push({ sessionId: sid, ok: false, error: String((e && e.message) || e) }) }\n }\n json(res, { ok: true, archived: results.filter((r) => r.ok).length, results })\n } catch (e) {\n json(res, { ok: false, error: String((e && e.message) || e) }, 500)\n }\n },\n }))\n\n return () => { for (const d of disposers) d() }\n }, 'dsh-archived-sessions: routes')\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tobycaimf/dsh-archived-sessions",
3
- "description": "DSH 设置面板「归档会话」管理器:查看、恢复、彻底删除已归档的 session,带所属工作区标签与会话日期。",
4
- "version": "1.0.0",
3
+ "description": "DSH 设置面板会话管理器:归档 / 恢复 / 彻底删除 / 移动到其他工作区,带工作区标签与会话日期;统一「会话管理」面板。",
4
+ "version": "1.0.2",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {