feat: companion 作息、主動發話、適應度與外部素材
- 作息與疲勞、想念累積與時間感,主動發話沿用 care.ts 的冷卻、日限、靜音 - 想家與適應度(9.13) - 獨立腳本 fetch-materials.mjs 由系統排程寫入快取,hook 只讀、不連網 - 新增 /jsc-mod-companion:materials 與 setup location=、feeds= - 天氣微調心情基準,新聞依適應度每天最多 2 則並寫入情節記憶 - 版本 0.0.5 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { readJson } from './fs'
|
||||
import type { Fs } from './fs'
|
||||
import { MATERIALS as M, WEATHER_MOOD } from './rules'
|
||||
|
||||
// 外部素材快取:由系統排程執行的 scripts/fetch-materials.mjs 寫入,hook 只讀、不連網。
|
||||
// 只存標題、摘要、連結與時間(at 為抓取時間,毫秒)。
|
||||
export type Item = { title: string; summary: string; link: string; at: number }
|
||||
export type Materials = { weather: Item | null; news: Item[] }
|
||||
|
||||
export const EMPTY: Materials = { weather: null, news: [] }
|
||||
|
||||
const isItem = (x: unknown): x is Item => {
|
||||
const i = x as Item
|
||||
return !!i && typeof i.title === 'string' && typeof i.summary === 'string' && typeof i.link === 'string' && typeof i.at === 'number'
|
||||
}
|
||||
|
||||
/** 讀快取並丟掉過期項目:天氣 6 小時、新聞 24 小時;檔案缺失或壞掉就是沒查 */
|
||||
export async function readMaterials(fs: Fs, path: string, now: number): Promise<Materials> {
|
||||
const raw = await readJson<{ weather?: unknown; news?: unknown }>(fs, path)
|
||||
if (!raw) return EMPTY
|
||||
const weather = isItem(raw.weather) && now - raw.weather.at < M.weatherTtlMs ? raw.weather : null
|
||||
const news = (Array.isArray(raw.news) ? raw.news : []).filter(isItem).filter(n => now - n.at < M.newsTtlMs)
|
||||
return { weather, news }
|
||||
}
|
||||
|
||||
/** 天氣對心情基準的微調;未知狀況為 0,且不超過上限 */
|
||||
export function weatherShift(w: Item | null): number {
|
||||
if (!w) return 0
|
||||
const v = WEATHER_MOOD[w.title] ?? 0
|
||||
return Math.max(-M.weatherCap, Math.min(M.weatherCap, v))
|
||||
}
|
||||
Reference in New Issue
Block a user