feat: 完成 J 群組 — 委託子系統

Task 資料表與自然語句解析(單次提醒)、依原型的接案/觸發/逾期追擊演出、
委託與關係帳本/情緒的回饋迴路(含默契旗標)、主動關照(待辦偵測+作息交叉比對,
稀有度節流不重複台詞)、排程器可靠性(服務重啟後重新掃描 PENDING 任務掛回
JobQueue,逾期立即補觸發)。J.mjs 以 spawnSync 實際重啟服務驗證 J-7。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jeffery
2026-08-13 14:35:16 +08:00
co-authored by Claude Sonnet 5
parent d82b834e47
commit 3503cc0be6
16 changed files with 1117 additions and 8 deletions
@@ -0,0 +1,32 @@
-- CreateTable
CREATE TABLE "tasks" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"type" TEXT NOT NULL,
"content" TEXT NOT NULL,
"rawText" TEXT NOT NULL,
"triggerAt" DATETIME,
"cronExpression" TEXT,
"condition" TEXT,
"status" TEXT NOT NULL DEFAULT 'PENDING',
"triggeredAt" DATETIME,
"triggerMessage" TEXT,
"overdueNudgeCount" INTEGER NOT NULL DEFAULT 0,
"lastNudgeAt" DATETIME,
"completedAt" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "tasks_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "tasks_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "proactive_care_logs" (
"id" TEXT NOT NULL PRIMARY KEY,
"characterId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"message" TEXT NOT NULL,
"triggeredAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "proactive_care_logs_characterId_fkey" FOREIGN KEY ("characterId") REFERENCES "characters" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
+63
View File
@@ -58,6 +58,23 @@ enum ScheduleSlotStatus {
FREE // 空閒
}
// J-1 委託類型
enum TaskType {
ONE_TIME // 單次提醒
RECURRING // 週期提醒
CONDITIONAL // 條件提醒
QUERY_ORGANIZE // 查詢整理
TODO_TRACKING // 代辦追蹤
}
enum TaskStatus {
PENDING // 尚未觸發
TRIGGERED // 已觸發,等候使用者回應
COMPLETED // 已完成
FAILED // 執行失敗
CANCELLED // 已取消
}
model User {
id String @id @default(cuid())
name String
@@ -66,6 +83,7 @@ model User {
relationships Relationship[]
relatedMemories EpisodicMemory[]
tasks Task[]
@@map("users")
}
@@ -114,6 +132,8 @@ model Character {
scheduleSlots ScheduleSlot[]
specialDays SpecialDay[]
scheduleExceptions ScheduleExceptionLog[]
tasks Task[]
proactiveCareLogs ProactiveCareLog[]
@@map("characters")
}
@@ -270,3 +290,46 @@ model SentimentLedgerEntry {
@@map("sentiment_ledger_entries")
}
// J-1 委託:使用者請角色做的事。執行(觸發準時度)是引擎責任,演出(接案/觸發/追擊的台詞)是角色責任。
model Task {
id String @id @default(cuid())
characterId String
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
type TaskType
content String // 委託內容(去除時間片語後的純委託描述,例如「開會」)
rawText String // 使用者原始輸入,供回顧/記憶引用
triggerAt DateTime? // 單次提醒的觸發時間;週期提醒改用 cronExpression
cronExpression String? // 週期提醒(node-cron 表達式)
condition String? // 條件提醒的條件描述(MVP 為文字紀錄,不做真實環境條件監測)
status TaskStatus @default(PENDING)
triggeredAt DateTime? // 最近一次實際觸發的時間
triggerMessage String? // 最近一次觸發演出的訊息內容(供前端/測試輪詢)
overdueNudgeCount Int @default(0) // J-4 逾期追擊次數
lastNudgeAt DateTime?
completedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("tasks")
}
// J-6 主動關照:記錄每次主動關心的觸發時間與內容,供稀有度節流與「不重複台詞」判定。
model ProactiveCareLog {
id String @id @default(cuid())
characterId String
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
userId String
message String
triggeredAt DateTime @default(now())
@@map("proactive_care_logs")
}