feat(role): 新增閒置小睡整理
This commit is contained in:
+48
-3
@@ -4,7 +4,7 @@
|
||||
// inbox,(2) 產生 SessionStart 要注入的記憶區塊,(3) 睡眠整理時輸出待整理
|
||||
// 素材並套用整理結果(NREM 鞏固/REM 整合、分類、去重、標籤、總結、
|
||||
// 優先度、關聯、壓縮歸檔),(4) 依使用頻率與優先度遺忘日常與其他類記憶。
|
||||
// 更新時間:2026/07/28 13:50:43
|
||||
// 更新時間:2026/07/28 14:36:00
|
||||
// 相依:Node.js 標準庫。
|
||||
// 退出碼:0 成功;1 無內容可處理;2 參數錯誤。呼叫端(hook)一律不得因此中斷。
|
||||
// ==============================================================================
|
||||
@@ -537,7 +537,13 @@ function cmdLoad(args) {
|
||||
if (digest) blocks.push(`> 上次睡眠摘要:${digest}`);
|
||||
|
||||
const pending = listInbox(args.role).length;
|
||||
if (pending) blocks.push(`> 尚有 ${pending} 則未整理記憶,將於下次睡眠時段歸檔。`);
|
||||
if (pending) {
|
||||
if (pending >= args.batch) {
|
||||
blocks.push(`> 尚有 ${pending} 則未整理記憶,已達一批睡眠整理量;請以角色語氣主動提醒使用者「想睡覺」或需要整理記憶。這是建議整理/歸檔的提醒,不代表停止協助。`);
|
||||
} else {
|
||||
blocks.push(`> 尚有 ${pending} 則未整理記憶,將於下次睡眠時段歸檔。`);
|
||||
}
|
||||
}
|
||||
if (!blocks.length) return 1;
|
||||
|
||||
let text = blocks.join("\n\n");
|
||||
@@ -776,6 +782,7 @@ function cmdStats(args) {
|
||||
rows.push("");
|
||||
rows.push(`- 記憶目錄:${memoryRoot(args.role)}`);
|
||||
rows.push(`- 個人記憶同意狀態:${consentStatusValue(args.role)}`);
|
||||
rows.push(`- 上次互動:${state.last_activity || "尚未記錄"}`);
|
||||
rows.push(`- 上次睡眠整理:${state.last_sleep || "尚未整理"}`);
|
||||
rows.push(`- 上次睡眠摘要:${state.last_sleep_digest || "尚無"}`);
|
||||
rows.push(`- 上次遺忘:${state.last_forget || "尚未執行"}`);
|
||||
@@ -790,6 +797,14 @@ function cmdMarkSleep(args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function cmdMarkActivity(args) {
|
||||
const patch = { last_activity: nowStamp(), last_activity_epoch: nowEpoch() };
|
||||
if (args.project) patch.last_activity_project = args.project;
|
||||
writeState(args.role, patch);
|
||||
process.stdout.write("已更新上次互動時間");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function cmdNeedSleep(args) {
|
||||
if (!listInbox(args.role).length) {
|
||||
process.stdout.write("no");
|
||||
@@ -804,6 +819,30 @@ function cmdNeedSleep(args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function cmdNeedNap(args) {
|
||||
const pending = listInbox(args.role).length;
|
||||
if (pending < args.minInbox) {
|
||||
process.stdout.write("no");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const state = readState(args.role);
|
||||
const lastEpoch = Number.parseInt(state.last_activity_epoch || "", 10);
|
||||
let lastMs = Number.isFinite(lastEpoch) && lastEpoch > 0 ? lastEpoch * 1000 : null;
|
||||
if (lastMs === null) {
|
||||
const last = parseStamp(state.last_activity);
|
||||
lastMs = last ? last.getTime() : null;
|
||||
}
|
||||
if (lastMs === null) {
|
||||
process.stdout.write("no");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const idleMinutes = (Date.now() - lastMs) / 60000;
|
||||
process.stdout.write(idleMinutes >= args.idleMinutes ? "yes" : "no");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function cmdConsent(args) {
|
||||
const value = String(args.value || "").trim().toLowerCase();
|
||||
const normalized = {
|
||||
@@ -892,7 +931,7 @@ function requireRole(args) {
|
||||
function main(argv) {
|
||||
const args = parseArgs(argv);
|
||||
if (!args.command || args.command === "-h" || args.command === "--help") {
|
||||
process.stdout.write(`用法:memory.js <子命令> [參數]\n\n子命令:write、seed、load、collect、apply、forget、stats、mark-sleep、need-sleep、consent、consent-status\n`);
|
||||
process.stdout.write(`用法:memory.js <子命令> [參數]\n\n子命令:write、seed、load、collect、apply、forget、stats、mark-sleep、mark-activity、need-sleep、need-nap、consent、consent-status\n`);
|
||||
return 0;
|
||||
}
|
||||
if (!requireRole(args)) return 2;
|
||||
@@ -903,6 +942,8 @@ function main(argv) {
|
||||
args.fullMinPriority = Number.parseInt(args.fullMinPriority || "", 10);
|
||||
args.digestMinPriority = Number.parseInt(args.digestMinPriority || "", 10);
|
||||
args.hours = Number.parseFloat(args.hours || "");
|
||||
args.idleMinutes = Number.parseFloat(args.idleMinutes || "");
|
||||
args.minInbox = Number.parseInt(args.minInbox || "", 10);
|
||||
|
||||
if (!Number.isFinite(args.limit)) args.limit = args.command === "load" ? envInt("ROLE_LOAD_LIMIT", DEFAULT_LOAD_LIMIT) : envInt("ROLE_SLEEP_COLLECT_LIMIT", COLLECT_LIMIT);
|
||||
if (!Number.isFinite(args.batch)) args.batch = envInt("ROLE_SLEEP_BATCH", SLEEP_BATCH);
|
||||
@@ -910,6 +951,8 @@ function main(argv) {
|
||||
if (!Number.isFinite(args.fullMinPriority)) args.fullMinPriority = envInt("ROLE_LOAD_FULL_MIN_PRIORITY", DEFAULT_FULL_MIN_PRIORITY);
|
||||
if (!Number.isFinite(args.digestMinPriority)) args.digestMinPriority = envInt("ROLE_LOAD_DIGEST_MIN_PRIORITY", DEFAULT_DIGEST_MIN_PRIORITY);
|
||||
if (!Number.isFinite(args.hours)) args.hours = 20.0;
|
||||
if (!Number.isFinite(args.idleMinutes)) args.idleMinutes = 45.0;
|
||||
if (!Number.isFinite(args.minInbox)) args.minInbox = 3;
|
||||
args.category ||= "important";
|
||||
args.tags ||= "";
|
||||
args.source ||= "";
|
||||
@@ -929,7 +972,9 @@ function main(argv) {
|
||||
forget: cmdForget,
|
||||
stats: cmdStats,
|
||||
"mark-sleep": cmdMarkSleep,
|
||||
"mark-activity": cmdMarkActivity,
|
||||
"need-sleep": cmdNeedSleep,
|
||||
"need-nap": cmdNeedNap,
|
||||
consent: cmdConsent,
|
||||
"consent-status": cmdConsentStatus,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user