sage-mem 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +63 -25
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -2038,7 +2038,7 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2038
2038
|
// ⚠️ 可发现性不靠抽屉本身,靠头部带常显的「体检 N 个问题」徽标 —— 那是整个
|
|
2039
2039
|
// 抽屉方案能成立的前提(否则三个能力就退回「藏起来」了)。
|
|
2040
2040
|
".smem-drawer{position:relative;flex:none;}",
|
|
2041
|
-
".smem-drawer-pop{position:absolute;right:0;top:calc(100% + 6px);z-index:6;min-width:236px;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.10);padding:6px;display:flex;flex-direction:column;gap:2px;}",
|
|
2041
|
+
".smem-drawer-pop{position:absolute;right:0;top:calc(100% + 6px);z-index:6;min-width:236px;max-width:min(320px,calc(100vw - 24px));background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,.10);padding:6px;display:flex;flex-direction:column;gap:2px;}",
|
|
2042
2042
|
".smem-drawer-item{display:flex;align-items:center;gap:8px;border:0;background:transparent;font-family:inherit;font-size:12.5px;color:var(--dsw-alias-label-primary);text-align:left;padding:6px 8px;border-radius:8px;cursor:pointer;}",
|
|
2043
2043
|
".smem-drawer-item:hover{background:var(--dsw-alias-bg-layer-2);}",
|
|
2044
2044
|
'.smem-drawer-item[data-on="1"]{background:var(--dsw-alias-bg-layer-2);font-weight:600;}',
|
|
@@ -2089,7 +2089,7 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2089
2089
|
'.smem-subtab--on:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;border-radius:2px 2px 0 0;background:var(--dsw-alias-label-primary);}',
|
|
2090
2090
|
".smem-subtab-n{opacity:.6;margin-left:5px;font-variant-numeric:tabular-nums;}",
|
|
2091
2091
|
// 五个注入参数排两列:一行放两个,扫读反而更清楚(吸收方案 A 的做法)。
|
|
2092
|
-
".smem-ad-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(
|
|
2092
|
+
".smem-ad-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:4px 18px;}",
|
|
2093
2093
|
".smem-ad-field{display:flex;align-items:center;gap:8px;min-width:0;}",
|
|
2094
2094
|
".smem-ad-field .smem-autodream-key{min-width:96px;}",
|
|
2095
2095
|
".smem-actions{display:flex;gap:6px;}",
|
|
@@ -2113,7 +2113,7 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2113
2113
|
'.smem-tab--on:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;border-radius:2px 2px 0 0;background:var(--dsw-alias-label-primary);}',
|
|
2114
2114
|
// 高度预算压到 62vh(原 70vh):设置弹窗本身高度有限,
|
|
2115
2115
|
// 70vh 在较矮的设置弹窗视口下会把星图底部的图例和计数挤出面板之外。
|
|
2116
|
-
".smem-starmap{display:flex;flex-direction:column;height:
|
|
2116
|
+
".smem-starmap{display:flex;flex-direction:column;height:clamp(320px,55vh,620px);min-height:280px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;overflow:hidden;}",
|
|
2117
2117
|
// ── 「自动做梦」面板 ──
|
|
2118
2118
|
// 融入型:全部走宿主变量,控件复用已有的 chip / input / btn 语言,不另造一套。
|
|
2119
2119
|
".smem-autodream{display:flex;flex-direction:column;gap:12px;}",
|
|
@@ -2160,6 +2160,16 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2160
2160
|
".smem-update{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px solid var(--dsw-alias-brand-primary,#4d76e6);border-radius:8px;padding:6px 10px;font-size:12px;background:var(--dsw-alias-bg-layer-1);}",
|
|
2161
2161
|
".smem-update-link{color:var(--dsw-alias-brand-primary,#4d76e6);text-decoration:underline;}",
|
|
2162
2162
|
".smem-update-x{margin-left:auto;border:0;background:transparent;color:inherit;cursor:pointer;font-size:14px;line-height:1;padding:0 2px;}",
|
|
2163
|
+
// ── 1.5.0:动作分组 / 长文 clamp / 空态骨架 / 窄窗口 ──
|
|
2164
|
+
".smem-actions-sep{width:1px;height:16px;background:var(--dsw-alias-border-l2);margin:0 2px;align-self:center;}",
|
|
2165
|
+
".smem-clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;cursor:pointer;}",
|
|
2166
|
+
".smem-clamp-2--open{-webkit-line-clamp:unset;display:block;}",
|
|
2167
|
+
".smem-skeleton{display:flex;flex-direction:column;gap:10px;padding:6px 0;}",
|
|
2168
|
+
".smem-skeleton-row{height:44px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);opacity:.55;}",
|
|
2169
|
+
".smem-empty{display:flex;flex-direction:column;align-items:flex-start;gap:8px;}",
|
|
2170
|
+
".smem-tabs-sep{width:1px;align-self:stretch;margin:6px 2px;background:var(--dsw-alias-border-l2);}",
|
|
2171
|
+
// 窄窗口(≤420px):头部带与筛选条各让一行,卡片动作允许换行、分隔符隐藏。
|
|
2172
|
+
"@media (max-width:420px){.smem-root{gap:10px;}.smem-head{gap:6px;}.smem-card-title{min-width:0;word-break:break-word;}.smem-actions{flex-wrap:wrap;}.smem-actions-sep{display:none;}.smem-num{width:56px;}.smem-search{min-width:100px;}}",
|
|
2163
2173
|
// ── 底部一行仓库链接(引流,不抢视线)──
|
|
2164
2174
|
".smem-star{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;font-size:12px;color:var(--dsw-alias-label-tertiary,#8b93a1);padding:2px 2px 0;}",
|
|
2165
2175
|
".smem-star-link{color:var(--dsw-alias-brand-primary,#4d76e6);text-decoration:underline;}",
|
|
@@ -2474,6 +2484,8 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2474
2484
|
]
|
|
2475
2485
|
: [
|
|
2476
2486
|
h("button", { type: "button", className: "smem-btn", key: "edit", onClick: function () { props.onEdit(item.file); } }, "编辑"),
|
|
2487
|
+
// 语义分组:左边只放「编辑」(安全、可逆),右边放「锁定 / 归档 / 删除」(对这条记忆的退役/保护决定)。
|
|
2488
|
+
h("span", { key: "sep", className: "smem-actions-sep", "aria-hidden": "true" }),
|
|
2477
2489
|
/**
|
|
2478
2490
|
* 锁定排在「编辑」与「归档」之间(用户 2026-10-11 指定):
|
|
2479
2491
|
* 它是「别归档这条」的开关,紧挨着归档才说得通。
|
|
@@ -2524,6 +2536,9 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2524
2536
|
function ArchivedCard(props) {
|
|
2525
2537
|
const item = props.item;
|
|
2526
2538
|
const meta = TYPE_META[item.type] || TYPE_META.reference;
|
|
2539
|
+
// 描述与归档理由都可能很长:默认各 clamp(描述 3 行 / 理由 2 行),点一下展开全文。
|
|
2540
|
+
const sDescOpen = react.useState(false);
|
|
2541
|
+
const descOpen = sDescOpen[0], setDescOpen = sDescOpen[1];
|
|
2527
2542
|
return h("div", { className: "smem-card smem-card--archived", key: item.file }, [
|
|
2528
2543
|
h("div", { className: "smem-card-head", key: "head" }, [
|
|
2529
2544
|
h("span", { className: "smem-badge", key: "badge", title: "类型 " + String(item.type) }, meta[0] + " " + meta[1]),
|
|
@@ -2539,9 +2554,18 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2539
2554
|
// 描述留在活动卡片里的同一个位置(标签下面),归档留痕块再往下 ——
|
|
2540
2555
|
// 否则「归档理由」像卡片结尾,后面孤零零一行描述没人认得它是什么。
|
|
2541
2556
|
item.description
|
|
2542
|
-
? h("div", {
|
|
2557
|
+
? h("div", {
|
|
2558
|
+
className: "smem-narrative", key: "desc",
|
|
2559
|
+
"data-clamp": descOpen ? "0" : "1",
|
|
2560
|
+
title: descOpen ? "点击收起" : "点击展开全文",
|
|
2561
|
+
onClick: function () { setDescOpen(!descOpen); },
|
|
2562
|
+
}, String(item.description))
|
|
2543
2563
|
: null,
|
|
2544
|
-
h("div", {
|
|
2564
|
+
h("div", {
|
|
2565
|
+
className: "smem-ar-reason smem-clamp-2" + (descOpen ? " smem-clamp-2--open" : ""),
|
|
2566
|
+
key: "why", title: "归档理由:" + (item.archivedReason || "(没写)"),
|
|
2567
|
+
onClick: function () { setDescOpen(!descOpen); },
|
|
2568
|
+
}, "归档理由:" + (item.archivedReason || "(没写)")),
|
|
2545
2569
|
props.editing
|
|
2546
2570
|
? h("div", { className: "smem-ar-edit", key: "edit" }, [
|
|
2547
2571
|
h("div", { className: "smem-ar-hint", key: "note" },
|
|
@@ -2578,7 +2602,8 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
2578
2602
|
disabled: props.busy,
|
|
2579
2603
|
onClick: function () { props.onEdit(item.file); },
|
|
2580
2604
|
}, "编辑"),
|
|
2581
|
-
|
|
2605
|
+
h("span", { key: "sep", className: "smem-actions-sep", "aria-hidden": "true" }),
|
|
2606
|
+
h("button", {
|
|
2582
2607
|
type: "button", className: "smem-btn smem-btn-primary", key: "restore",
|
|
2583
2608
|
disabled: props.busy,
|
|
2584
2609
|
onClick: function () { props.onRestore(item.file); },
|
|
@@ -4356,18 +4381,29 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
4356
4381
|
// banner 只在**专门看归档**时出现,切到全部时不重复说一遍。
|
|
4357
4382
|
let filesView;
|
|
4358
4383
|
if (loading && totalCount === 0) {
|
|
4359
|
-
filesView = h("div", { className: "smem-
|
|
4384
|
+
filesView = h("div", { className: "smem-skeleton", key: "loading", "data-loading": "1" }, [0, 1, 2].map(function (i) {
|
|
4385
|
+
return h("div", { className: "smem-skeleton-row", key: i });
|
|
4386
|
+
}));
|
|
4360
4387
|
} else if (totalCount === 0) {
|
|
4361
|
-
filesView = h("div", { className: "smem-empty", key: "empty" },
|
|
4362
|
-
"
|
|
4388
|
+
filesView = h("div", { className: "smem-empty", key: "empty" }, [
|
|
4389
|
+
h("div", { key: "t" }, "还没有记忆文件。对话中值得记住的事会写到这里,也可以手动写入。"),
|
|
4390
|
+
h("button", { type: "button", className: "smem-btn smem-btn-primary", key: "add", onClick: openAdd }, "+ 添加记忆"),
|
|
4391
|
+
]);
|
|
4363
4392
|
} else if (statusFilter === "archived" && archiveItems.length === 0) {
|
|
4364
|
-
filesView = h("div", { className: "smem-empty", key: "empty" },
|
|
4365
|
-
"档案馆是空的 —— 在活动记忆那张卡上点「归档」,它就会收到这里。")
|
|
4393
|
+
filesView = h("div", { className: "smem-empty", key: "empty" }, [
|
|
4394
|
+
h("div", { key: "t" }, "档案馆是空的 —— 在活动记忆那张卡上点「归档」,它就会收到这里。"),
|
|
4395
|
+
h("button", { type: "button", className: "smem-btn", key: "back", onClick: function () { setStatusFilter("active"); } }, "回文件列表"),
|
|
4396
|
+
]);
|
|
4366
4397
|
} else if (statusFilter === "active" && items.length === 0) {
|
|
4367
|
-
filesView = h("div", { className: "smem-empty", key: "empty" },
|
|
4368
|
-
"活动记忆是空的 —— 状态筛到「已归档」还能捞出 " + archiveItems.length + " 条。")
|
|
4398
|
+
filesView = h("div", { className: "smem-empty", key: "empty" }, [
|
|
4399
|
+
h("div", { key: "t" }, "活动记忆是空的 —— 状态筛到「已归档」还能捞出 " + archiveItems.length + " 条。"),
|
|
4400
|
+
h("button", { type: "button", className: "smem-btn", key: "go", onClick: function () { setStatusFilter("archived"); } }, "切到已归档"),
|
|
4401
|
+
]);
|
|
4369
4402
|
} else if (filtered.length === 0) {
|
|
4370
|
-
filesView = h("div", { className: "smem-empty", key: "empty" },
|
|
4403
|
+
filesView = h("div", { className: "smem-empty", key: "empty" }, [
|
|
4404
|
+
h("div", { key: "t" }, "没有符合搜索或筛选条件的文件。"),
|
|
4405
|
+
h("button", { type: "button", className: "smem-btn", key: "clear", onClick: function () { setStatusFilter("all"); setTypeFilter([]); setTagFilter([]); setQuery(""); } }, "清除筛选"),
|
|
4406
|
+
]);
|
|
4371
4407
|
} else {
|
|
4372
4408
|
const list = h("div", { className: "smem-list", key: "list" }, filtered.map(function (it) {
|
|
4373
4409
|
if (it.archived === true) {
|
|
@@ -4427,25 +4463,26 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
4427
4463
|
}
|
|
4428
4464
|
|
|
4429
4465
|
return h("div", { className: "smem-root" }, [
|
|
4430
|
-
h("div", { className: "smem-tabs", key: "tabs" }, [
|
|
4431
|
-
h("button", { type: "button", className: "smem-tab" + (tab === "files" ? " smem-tab--on" : ""), key: "f", onClick: function () { setTab("files"); } }, "文件列表"),
|
|
4432
|
-
h("button", { type: "button", className: "smem-tab" + (tab === "star" ? " smem-tab--on" : ""), key: "s", onClick: function () { setTab("star"); } }, "记忆星图"),
|
|
4433
|
-
h("button", { type: "button", className: "smem-tab" + (tab === "autodream" ? " smem-tab--on" : ""), key: "d", onClick: function () { setTab("autodream"); } }, "自动做梦"),
|
|
4466
|
+
h("div", { className: "smem-tabs", key: "tabs", role: "tablist" }, [
|
|
4467
|
+
h("button", { type: "button", className: "smem-tab" + (tab === "files" ? " smem-tab--on" : ""), key: "f", role: "tab", "aria-selected": tab === "files" ? "true" : "false", onClick: function () { setTab("files"); } }, "文件列表"),
|
|
4468
|
+
h("button", { type: "button", className: "smem-tab" + (tab === "star" ? " smem-tab--on" : ""), key: "s", role: "tab", "aria-selected": tab === "star" ? "true" : "false", onClick: function () { setTab("star"); } }, "记忆星图"),
|
|
4469
|
+
h("button", { type: "button", className: "smem-tab" + (tab === "autodream" ? " smem-tab--on" : ""), key: "d", role: "tab", "aria-selected": tab === "autodream" ? "true" : "false", onClick: function () { setTab("autodream"); } }, "自动做梦"),
|
|
4470
|
+
// 视觉分组:左边「看」(文件列表 / 星图),右边「设置 · 自动化」。
|
|
4471
|
+
h("span", { className: "smem-tabs-sep", key: "sep", "aria-hidden": "true" }),
|
|
4434
4472
|
// 「自动归档」排在自动做梦之后:归档是**确定性规则**(按闲置天数算,不调模型),
|
|
4435
4473
|
// 和「让模型整理记忆」是两件事。塞在自动做梦的设置里用户找不到
|
|
4436
4474
|
// (2026-10-11 用户原话:「扔这里连我都找不到」)。
|
|
4437
|
-
h("button", { type: "button", className: "smem-tab" + (tab === "archive" ? " smem-tab--on" : ""), key: "ar", onClick: function () { setTab("archive"); } }, "自动归档"),
|
|
4475
|
+
h("button", { type: "button", className: "smem-tab" + (tab === "archive" ? " smem-tab--on" : ""), key: "ar", role: "tab", "aria-selected": tab === "archive" ? "true" : "false", onClick: function () { setTab("archive"); } }, "自动归档"),
|
|
4438
4476
|
// 体检再排在「自动归档」之后、独立成一屏:它只报告不修改,和「文件列表」里的
|
|
4439
4477
|
// 增删改是两件事,塞在工具抽屉里会让人以为它是个动作按钮。
|
|
4440
|
-
h("button", { type: "button", className: "smem-tab" + (tab === "audit" ? " smem-tab--on" : ""), key: "a", onClick: openAuditTab }, "体检"),
|
|
4478
|
+
h("button", { type: "button", className: "smem-tab" + (tab === "audit" ? " smem-tab--on" : ""), key: "a", role: "tab", "aria-selected": tab === "audit" ? "true" : "false", onClick: openAuditTab }, "体检"),
|
|
4441
4479
|
]),
|
|
4442
4480
|
// 四个 tab 共用的一条头部带:我在哪 · 目录状态 · 活动/归档计数 · 体检徽标 · 待重启徽标 · 主操作。
|
|
4443
4481
|
// 层级形状固定:导航=下划线(.smem-tabs)、筛选=chip、动作=按钮,三种不混用。
|
|
4444
4482
|
h("div", { className: "smem-head", key: "head" }, [
|
|
4445
4483
|
h("span", { className: "smem-title", key: "t" }, "记忆管理"),
|
|
4446
|
-
|
|
4447
|
-
h("span", { className: "smem-dot" + (dirOk ? "" : " smem-dot--bad"), key: "dot", title: dirOk ? "memory 目录可读" : "memory 目录不可读" }),
|
|
4448
|
-
h("span", { className: "smem-muted", key: "st" }, dirOk ? "目录可读" : "目录不可读"),
|
|
4484
|
+
// 目录状态收进状态点的 title(不可读时下面另有一条 smem-err,错误本来就该显眼)。
|
|
4485
|
+
h("span", { className: "smem-dot" + (dirOk ? "" : " smem-dot--bad"), key: "dot", title: (dirOk ? "memory 目录可读" : "memory 目录不可读") + " · " + String(TAB_LABEL[tab] || "") }),
|
|
4449
4486
|
h("span", { className: "smem-badge", key: "cnt" }, headerCount),
|
|
4450
4487
|
// 体检徽标:**抽屉关着也一直看得见**,点它就切到「体检」那一屏。
|
|
4451
4488
|
h("button", {
|
|
@@ -4496,6 +4533,7 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
4496
4533
|
type: "button", key: "btn",
|
|
4497
4534
|
className: "smem-btn" + (drawer ? " smem-btn-primary" : ""),
|
|
4498
4535
|
"aria-expanded": drawer ? "true" : "false",
|
|
4536
|
+
"aria-haspopup": "menu",
|
|
4499
4537
|
title: "归档候选 / 保留名编辑",
|
|
4500
4538
|
onClick: function () { setDrawer(!drawer); },
|
|
4501
4539
|
}, "工具 ▾"),
|
|
@@ -4615,8 +4653,8 @@ const StarmapRuntime = (function (require, _react) {
|
|
|
4615
4653
|
: null,
|
|
4616
4654
|
])
|
|
4617
4655
|
: null,
|
|
4618
|
-
error ? h("div", { className: "smem-err", key: "err" }, "⚠ " + error) : null,
|
|
4619
|
-
notice && !error ? h("div", { className: "smem-ok", key: "ok" }, "✓ " + notice) : null,
|
|
4656
|
+
error ? h("div", { className: "smem-err", key: "err", role: "alert" }, "⚠ " + error) : null,
|
|
4657
|
+
notice && !error ? h("div", { className: "smem-ok", key: "ok", role: "status" }, "✓ " + notice) : null,
|
|
4620
4658
|
formOpen
|
|
4621
4659
|
? h("div", { className: "smem-form", key: "form" }, [
|
|
4622
4660
|
h("div", { className: "smem-form-title", key: "ft" }, editingFile ? "编辑 " + editingFile : "添加记忆"),
|
package/package.json
CHANGED