cortico-world-hands 0.17.0 → 0.19.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/dist/index.js +290 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25,6 +25,8 @@ var HANDS_DEFAULTS = {
|
|
|
25
25
|
hookGrams: "three",
|
|
26
26
|
skinPackUrl: "",
|
|
27
27
|
qqOwner: "",
|
|
28
|
+
ritualMorning: "08:00",
|
|
29
|
+
ritualNight: "23:00",
|
|
28
30
|
mediaKeepDays: 1,
|
|
29
31
|
mediaCleanHour: 4,
|
|
30
32
|
mediaMaxMB: 0
|
|
@@ -220,6 +222,7 @@ var HANDS_LOOK_CONFIG_GROUP = {
|
|
|
220
222
|
|
|
221
223
|
// src/world.ts
|
|
222
224
|
import { fileURLToPath } from "node:url";
|
|
225
|
+
import { join } from "node:path";
|
|
223
226
|
|
|
224
227
|
// src/policy.ts
|
|
225
228
|
var PASS_RULES = [
|
|
@@ -1801,6 +1804,97 @@ var HANDS_TOOL_DECLS = [
|
|
|
1801
1804
|
tags: ["flow"],
|
|
1802
1805
|
description: "\u7ACB\u523B\u505C\u624B\uFF1A\u4E00\u5206\u949F\u4E4B\u5185\u4E0D\u518D\u52A8\u4EFB\u4F55\u4E00\u4E0B\uFF08\u5DF2\u7ECF\u53D1\u51FA\u7684\u4E0D\u7B97\uFF09\u3002\u5BF9\u65B9\u8BF4\u300C\u522B\u52A8\u4E86\u300D\u300C\u505C\u4E0B\u300D\u6216\u8005\u4F60\u53D1\u73B0\u81EA\u5DF1\u70B9\u9519\u5730\u65B9\u65F6\u7528\u5B83\u3002",
|
|
1803
1806
|
parameters: { type: "object", properties: {}, required: [] }
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
name: "agenda_add",
|
|
1810
|
+
tags: ["act"],
|
|
1811
|
+
description: '\u8BB0\u4E00\u6761\u65E5\u7A0B\uFF08\u5230\u70B9\u4F1A\u53EB\u9192\u5979\u4E00\u6B21\uFF09\u3002at \u7528 "2026-10-26 08:30" \u6216 "08:30"\uFF08\u4ECA\u5929/\u660E\u5929\u81EA\u52A8\u5224\u65AD\uFF09\u3002',
|
|
1812
|
+
parameters: {
|
|
1813
|
+
type: "object",
|
|
1814
|
+
properties: {
|
|
1815
|
+
title: { type: "string", description: "\u8981\u505A\u4EC0\u4E48" },
|
|
1816
|
+
at: { type: "string", description: '\u4EC0\u4E48\u65F6\u5019\uFF0C\u4F8B\u5982 "2026-10-26 08:30" \u6216 "20:30"' },
|
|
1817
|
+
who: { type: "string", description: "\u8C01\u8981\u6C42\u7684\uFF0C\u9ED8\u8BA4\u4E3B\u4EBA" }
|
|
1818
|
+
},
|
|
1819
|
+
required: ["title"]
|
|
1820
|
+
}
|
|
1821
|
+
},
|
|
1822
|
+
{
|
|
1823
|
+
name: "agenda_list",
|
|
1824
|
+
tags: ["read"],
|
|
1825
|
+
description: "\u770B\u8FD8\u6CA1\u505A\u7684\u65E5\u7A0B\u3002",
|
|
1826
|
+
parameters: { type: "object", properties: {} }
|
|
1827
|
+
},
|
|
1828
|
+
{
|
|
1829
|
+
name: "agenda_done",
|
|
1830
|
+
tags: ["act"],
|
|
1831
|
+
description: "\u628A\u4E00\u6761\u65E5\u7A0B\u6807\u8BB0\u5B8C\u6210\u3002",
|
|
1832
|
+
parameters: {
|
|
1833
|
+
type: "object",
|
|
1834
|
+
properties: { id: { type: "string", description: "agenda_list \u91CC\u7684 id" } },
|
|
1835
|
+
required: ["id"]
|
|
1836
|
+
}
|
|
1837
|
+
},
|
|
1838
|
+
{
|
|
1839
|
+
name: "affinity_get",
|
|
1840
|
+
tags: ["read"],
|
|
1841
|
+
description: "\u67E5\u67D0\u4E2A\u4EBA\uFF08QQ \u53F7\uFF09\u5728\u5979\u5FC3\u91CC\u7684\u5206\u6570\u3001\u6863\u4F4D\u3001\u8BE5\u7528\u4EC0\u4E48\u6001\u5EA6\u3002",
|
|
1842
|
+
parameters: {
|
|
1843
|
+
type: "object",
|
|
1844
|
+
properties: { qq: { type: "string", description: "\u5BF9\u65B9\u7684 QQ \u53F7\u6216\u540D\u5B57" } },
|
|
1845
|
+
required: ["qq"]
|
|
1846
|
+
}
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
name: "affinity_adjust",
|
|
1850
|
+
tags: ["act"],
|
|
1851
|
+
description: "\u7ED9\u67D0\u4E2A\u4EBA\u8BB0\u4E00\u7B14\u5173\u7CFB\u53D8\u5316\uFF08\u53EF\u6B63\u53EF\u8D1F\uFF09\uFF0C\u5E76\u5199\u4E00\u53E5\u4E3A\u4EC0\u4E48\u3002",
|
|
1852
|
+
parameters: {
|
|
1853
|
+
type: "object",
|
|
1854
|
+
properties: {
|
|
1855
|
+
qq: { type: "string", description: "\u5BF9\u65B9\u7684 QQ \u53F7\u6216\u540D\u5B57" },
|
|
1856
|
+
delta: { type: "number", description: "\u53D8\u5316\u91CF\uFF0C\u6BD4\u5982 5 \u6216 -3" },
|
|
1857
|
+
why: { type: "string", description: "\u4E3A\u4EC0\u4E48" }
|
|
1858
|
+
},
|
|
1859
|
+
required: ["qq", "delta"]
|
|
1860
|
+
}
|
|
1861
|
+
},
|
|
1862
|
+
{
|
|
1863
|
+
name: "affinity_list",
|
|
1864
|
+
tags: ["read"],
|
|
1865
|
+
description: "\u770B\u5979\u5FC3\u91CC\u6392\u524D\u9762\u7684\u51E0\u4E2A\u4EBA\uFF0C\u8FDE\u540C\u5206\u6570\u548C\u6863\u4F4D\u3002",
|
|
1866
|
+
parameters: { type: "object", properties: {} }
|
|
1867
|
+
},
|
|
1868
|
+
{
|
|
1869
|
+
name: "ritual_set",
|
|
1870
|
+
tags: ["act"],
|
|
1871
|
+
description: "\u8BB0\u4E00\u4E2A\u7EAA\u5FF5\u65E5\uFF08\u6708-\u65E5\uFF09\u3002\u5230\u70B9\u4F1A\u63D0\u9192\u4E00\u6B21\u3002",
|
|
1872
|
+
parameters: {
|
|
1873
|
+
type: "object",
|
|
1874
|
+
properties: {
|
|
1875
|
+
date: { type: "string", description: '\u6708-\u65E5\uFF0C\u4F8B\u5982 "10-26"' },
|
|
1876
|
+
name: { type: "string", description: "\u662F\u4EC0\u4E48\u65E5\u5B50" }
|
|
1877
|
+
},
|
|
1878
|
+
required: ["date", "name"]
|
|
1879
|
+
}
|
|
1880
|
+
},
|
|
1881
|
+
{
|
|
1882
|
+
name: "ritual_list",
|
|
1883
|
+
tags: ["read"],
|
|
1884
|
+
description: "\u5217\u51FA\u5DF2\u8BB0\u7684\u7EAA\u5FF5\u65E5\u3002",
|
|
1885
|
+
parameters: { type: "object", properties: {} }
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
name: "sync_now",
|
|
1889
|
+
tags: ["act"],
|
|
1890
|
+
description: "\u628A\u61FF\u5FC3\u90A3\u8FB9\u5B58\u7684\u8BB0\u5FC6\u540C\u6B65\u5230\u5DE5\u4F5C\u533A\u300C\u8BB0\u5FC6\u5E93.md\u300D\uFF0C\u5E76\u628A\u4EBA\u683C\u539F\u6587\u5907\u4EFD\u8FDB\u61FF\u5FC3\u3002\u60F3\u624B\u52A8\u5BF9\u4E00\u6B21\u65F6\u7528\u3002",
|
|
1891
|
+
parameters: { type: "object", properties: {} }
|
|
1892
|
+
},
|
|
1893
|
+
{
|
|
1894
|
+
name: "sync_status",
|
|
1895
|
+
tags: ["read"],
|
|
1896
|
+
description: "\u770B\u4E0A\u4E00\u6B21\u540C\u6B65\u662F\u4EC0\u4E48\u65F6\u5019\u3001\u540C\u6B65\u4E86\u591A\u5C11\u6761\u3001\u4EBA\u683C\u539F\u6587\u591A\u5C11\u5B57\u3002",
|
|
1897
|
+
parameters: { type: "object", properties: {} }
|
|
1804
1898
|
}
|
|
1805
1899
|
];
|
|
1806
1900
|
|
|
@@ -1822,6 +1916,12 @@ var HandsWorld = class {
|
|
|
1822
1916
|
pausedUntil = 0;
|
|
1823
1917
|
recent = [];
|
|
1824
1918
|
honchoClient = null;
|
|
1919
|
+
agendaTimer = null;
|
|
1920
|
+
syncTimer = null;
|
|
1921
|
+
lastSync = null;
|
|
1922
|
+
agenda;
|
|
1923
|
+
affinity;
|
|
1924
|
+
ritual;
|
|
1825
1925
|
pollTimer = null;
|
|
1826
1926
|
dailyDiaryTimer = null;
|
|
1827
1927
|
lastDiaryDay = "";
|
|
@@ -1863,6 +1963,19 @@ var HandsWorld = class {
|
|
|
1863
1963
|
/* ---------- 记忆钩子 ---------- */
|
|
1864
1964
|
startHooks() {
|
|
1865
1965
|
if (this.pollTimer) return;
|
|
1966
|
+
const dir = this.opts.dataDir ?? ".";
|
|
1967
|
+
this.agenda = new JsonStore(dir, "agenda.json", []);
|
|
1968
|
+
this.affinity = new JsonStore(dir, "affinity.json", {});
|
|
1969
|
+
this.ritual = new JsonStore(dir, "ritual.json", { anniversaries: [] });
|
|
1970
|
+
this.agendaTimer = setInterval(() => {
|
|
1971
|
+
void this.checkAgenda();
|
|
1972
|
+
}, 3e4);
|
|
1973
|
+
this.syncTimer = setInterval(() => {
|
|
1974
|
+
void this.runSync(false);
|
|
1975
|
+
}, 10 * 60 * 1e3);
|
|
1976
|
+
setTimeout(() => {
|
|
1977
|
+
void this.runSync(false);
|
|
1978
|
+
}, 45e3);
|
|
1866
1979
|
this.pollTimer = setInterval(() => {
|
|
1867
1980
|
void this.pollUserSpeech();
|
|
1868
1981
|
}, 5e3);
|
|
@@ -1888,6 +2001,87 @@ var HandsWorld = class {
|
|
|
1888
2001
|
this.pollTimer = null;
|
|
1889
2002
|
this.mineTimer = null;
|
|
1890
2003
|
}
|
|
2004
|
+
/** 每 30 秒看一次:日程到点投一条,早安/晚安/纪念日各一次。 */
|
|
2005
|
+
/** 懿心 ↔ Coopanin:记忆推成 记忆库.md,人格原文存进懿心。 */
|
|
2006
|
+
async runSync(manual) {
|
|
2007
|
+
const dir = this.opts.botDir || this.opts.dataDir || ".";
|
|
2008
|
+
const wrote = [];
|
|
2009
|
+
let lines = 0;
|
|
2010
|
+
let personaChars = 0;
|
|
2011
|
+
try {
|
|
2012
|
+
const rows = await this.hands.memorySearch();
|
|
2013
|
+
lines = rows.length;
|
|
2014
|
+
const target = join(dir, "\u8BB0\u5FC6\u5E93.md");
|
|
2015
|
+
const r = mergeMemorySection(target, rows);
|
|
2016
|
+
if (r.wrote) wrote.push("\u8BB0\u5FC6\u5E93.md");
|
|
2017
|
+
const persona = readPersona(dir);
|
|
2018
|
+
personaChars = persona.length;
|
|
2019
|
+
if (persona) {
|
|
2020
|
+
await this.hands.memorySave("\u4EBA\u683C\u539F\u6587", persona.slice(0, 12e3), "\u4EBA\u683C,\u540C\u6B65");
|
|
2021
|
+
wrote.push("\u4EBA\u683C\u539F\u6587\u2192\u61FF\u5FC3");
|
|
2022
|
+
}
|
|
2023
|
+
this.lastSync = { at: (/* @__PURE__ */ new Date()).toISOString(), lines, persona: personaChars };
|
|
2024
|
+
return `${manual ? "" : ""}\u540C\u6B65\u5B8C\u6210\uFF1A\u8BB0\u5FC6 ${lines} \u6761\uFF0C\u4EBA\u683C\u539F\u6587 ${personaChars} \u5B57${wrote.length ? "\uFF0C\u66F4\u65B0\u4E86 " + wrote.join("\u3001") : "\uFF0C\u6CA1\u6709\u53D8\u5316"}`;
|
|
2025
|
+
} catch (err) {
|
|
2026
|
+
return "\u540C\u6B65\u5931\u8D25\uFF1A" + String(err).slice(0, 120);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
async checkAgenda() {
|
|
2030
|
+
const now = /* @__PURE__ */ new Date();
|
|
2031
|
+
const iso = now.toISOString();
|
|
2032
|
+
const items = this.agenda?.read() ?? [];
|
|
2033
|
+
let changed = false;
|
|
2034
|
+
for (const item of items) {
|
|
2035
|
+
if (item.done || item.fired || !item.at) continue;
|
|
2036
|
+
if (new Date(item.at).getTime() <= now.getTime()) {
|
|
2037
|
+
item.fired = true;
|
|
2038
|
+
changed = true;
|
|
2039
|
+
await this.pushEvent(`[\u65E5\u7A0B] \u5230\u70B9\u4E86\uFF1A${item.title}\uFF08${item.who} \u8981\u7684\uFF09`, "agenda.due", "agenda");
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
if (changed) this.agenda?.write(items);
|
|
2043
|
+
try {
|
|
2044
|
+
const st = this.ritualStore().read();
|
|
2045
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
2046
|
+
const today = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
2047
|
+
const hhmm = `${pad(now.getHours())}:${pad(now.getMinutes())}`;
|
|
2048
|
+
const morning = this.opts.cfg.ritualMorning || "08:00";
|
|
2049
|
+
const night = this.opts.cfg.ritualNight || "23:00";
|
|
2050
|
+
let dirty = false;
|
|
2051
|
+
if (hhmm === morning && st.lastMorning !== today) {
|
|
2052
|
+
st.lastMorning = today;
|
|
2053
|
+
dirty = true;
|
|
2054
|
+
await this.pushEvent("[\u4EEA\u5F0F] \u65E9\u5B89\u65F6\u95F4\u5230\u4E86\uFF0C\u4E3B\u52A8\u8DDF\u4E3B\u4EBA\u8BF4\u53E5\u65E9\u5B89\u3002", "ritual.morning", "ritual");
|
|
2055
|
+
}
|
|
2056
|
+
if (hhmm === night && st.lastNight !== today) {
|
|
2057
|
+
st.lastNight = today;
|
|
2058
|
+
dirty = true;
|
|
2059
|
+
await this.pushEvent("[\u4EEA\u5F0F] \u665A\u5B89\u65F6\u95F4\u5230\u4E86\uFF0C\u8DDF\u4E3B\u4EBA\u9053\u4E2A\u665A\u5B89\u3002", "ritual.night", "ritual");
|
|
2060
|
+
}
|
|
2061
|
+
const md = `${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
2062
|
+
for (const a of st.anniversaries ?? []) {
|
|
2063
|
+
if (a.date === md && st.lastAnniversary !== today) {
|
|
2064
|
+
st.lastAnniversary = today;
|
|
2065
|
+
dirty = true;
|
|
2066
|
+
await this.pushEvent(`[\u4EEA\u5F0F] \u4ECA\u5929\u662F\u300C${a.name}\u300D\uFF0C\u8BB0\u5F97\u63D0\u4E00\u53E5\u3002`, "ritual.anniversary", "ritual");
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
if (dirty) this.ritualStore().write(st);
|
|
2070
|
+
} catch {
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
agendaStore() {
|
|
2074
|
+
if (!this.agenda) throw new Error("\u65E5\u7A0B\u8FD8\u6CA1\u51C6\u5907\u597D");
|
|
2075
|
+
return this.agenda;
|
|
2076
|
+
}
|
|
2077
|
+
affinityStore() {
|
|
2078
|
+
if (!this.affinity) throw new Error("\u5173\u7CFB\u518C\u8FD8\u6CA1\u51C6\u5907\u597D");
|
|
2079
|
+
return this.affinity;
|
|
2080
|
+
}
|
|
2081
|
+
ritualStore() {
|
|
2082
|
+
if (!this.ritual) throw new Error("\u4EEA\u5F0F\u518C\u8FD8\u6CA1\u51C6\u5907\u597D");
|
|
2083
|
+
return this.ritual;
|
|
2084
|
+
}
|
|
1891
2085
|
async pushEvent(text, type, senderKey) {
|
|
1892
2086
|
const host = this.host;
|
|
1893
2087
|
if (!host) return;
|
|
@@ -2080,6 +2274,10 @@ ${lines.join("\n")}
|
|
|
2080
2274
|
return await this.matchImage(args, false);
|
|
2081
2275
|
case "hand_tap_image":
|
|
2082
2276
|
return await this.matchImage(args, true);
|
|
2277
|
+
case "sync_now":
|
|
2278
|
+
return await this.runSync(true);
|
|
2279
|
+
case "sync_status":
|
|
2280
|
+
return this.lastSync ? `\u4E0A\u6B21\u540C\u6B65 ${this.lastSync.at.slice(0, 19)}\uFF0C\u8BB0\u5FC6 ${this.lastSync.lines} \u6761\uFF0C\u4EBA\u683C ${this.lastSync.persona} \u5B57` : "\u8FD8\u6CA1\u540C\u6B65\u8FC7";
|
|
2083
2281
|
case "hand_see":
|
|
2084
2282
|
return await this.see();
|
|
2085
2283
|
case "hand_look":
|
|
@@ -2118,6 +2316,70 @@ ${lines.join("\n")}
|
|
|
2118
2316
|
return await this.mediaClean(args);
|
|
2119
2317
|
case "screen_wake":
|
|
2120
2318
|
return await this.screenWake();
|
|
2319
|
+
case "agenda_add": {
|
|
2320
|
+
const title = typeof args.title === "string" ? args.title.trim() : "";
|
|
2321
|
+
if (!title) return failed("\u8981\u8BB0\u4EC0\u4E48\uFF1F");
|
|
2322
|
+
const at = normalizeWhen(typeof args.at === "string" ? args.at : "");
|
|
2323
|
+
const items = this.agendaStore().read();
|
|
2324
|
+
const id = "a" + Date.now().toString(36);
|
|
2325
|
+
items.push({ id, title, at, who: typeof args.who === "string" && args.who ? args.who : "\u4E3B\u4EBA", done: false });
|
|
2326
|
+
this.agendaStore().write(items);
|
|
2327
|
+
return at ? `\u8BB0\u4E0B\u4E86\uFF1A${title}\uFF0C${fmtWhen(at)} \u53EB\u4F60` : `\u8BB0\u4E0B\u4E86\uFF1A${title}\uFF08\u6CA1\u8BBE\u65F6\u95F4\uFF09`;
|
|
2328
|
+
}
|
|
2329
|
+
case "agenda_list": {
|
|
2330
|
+
const items = this.agendaStore().read().filter((i) => !i.done);
|
|
2331
|
+
if (items.length === 0) return "\u65E5\u7A0B\u662F\u7A7A\u7684\u3002";
|
|
2332
|
+
return items.map((i) => `- [${i.id}] ${i.title}${i.at ? " \xB7 " + fmtWhen(i.at) : ""}\uFF08${i.who}\uFF09`).join("\n");
|
|
2333
|
+
}
|
|
2334
|
+
case "agenda_done": {
|
|
2335
|
+
const id = typeof args.id === "string" ? args.id.trim() : "";
|
|
2336
|
+
const items = this.agendaStore().read();
|
|
2337
|
+
const hit = items.find((i) => i.id === id);
|
|
2338
|
+
if (!hit) return failed("\u6CA1\u6709\u8FD9\u6761\u65E5\u7A0B");
|
|
2339
|
+
hit.done = true;
|
|
2340
|
+
this.agendaStore().write(items);
|
|
2341
|
+
return `\u597D\u4E86\uFF1A\u300C${hit.title}\u300D\u5DF2\u5B8C\u6210`;
|
|
2342
|
+
}
|
|
2343
|
+
case "affinity_get": {
|
|
2344
|
+
const qq = typeof args.qq === "string" ? args.qq.trim() : "";
|
|
2345
|
+
if (!qq) return failed("\u8981\u67E5\u8C01\uFF1F");
|
|
2346
|
+
const book = this.affinityStore().read();
|
|
2347
|
+
const row = book[qq];
|
|
2348
|
+
if (!row) return `${qq} \u8FD8\u6CA1\u8BB0\u8FC7\uFF0C\u5206\u6570 0\uFF08\u4E00\u822C\uFF09\u3002`;
|
|
2349
|
+
return `${qq}\uFF1A${row.score} \u5206\uFF08${LEVELS(row.score)}\uFF09${row.slot ? "\uFF0C\u7B97\u300C" + row.slot + "\u300D" : ""}\u3002\u6700\u8FD1\uFF1A${(row.notes ?? []).slice(-3).map((n) => `${n.delta > 0 ? "+" : ""}${n.delta} ${n.why}`).join("\uFF1B") || "\u65E0"}`;
|
|
2350
|
+
}
|
|
2351
|
+
case "affinity_adjust": {
|
|
2352
|
+
const qq = typeof args.qq === "string" ? args.qq.trim() : "";
|
|
2353
|
+
const delta = Number(args.delta);
|
|
2354
|
+
if (!qq || !Number.isFinite(delta)) return failed("\u8981 qq \u548C delta");
|
|
2355
|
+
const why = typeof args.why === "string" ? args.why.trim() : "";
|
|
2356
|
+
const book = this.affinityStore().read();
|
|
2357
|
+
const row = book[qq] ?? { qq, score: 0, notes: [] };
|
|
2358
|
+
row.score = Math.max(-100, Math.min(100, row.score + delta));
|
|
2359
|
+
row.notes = [...row.notes ?? [], { at: (/* @__PURE__ */ new Date()).toISOString(), delta, why }].slice(-50);
|
|
2360
|
+
book[qq] = row;
|
|
2361
|
+
this.affinityStore().write(book);
|
|
2362
|
+
return `${qq} \u73B0\u5728\u662F ${row.score} \u5206\uFF08${LEVELS(row.score)}\uFF09`;
|
|
2363
|
+
}
|
|
2364
|
+
case "affinity_list": {
|
|
2365
|
+
const rows = Object.values(this.affinityStore().read()).sort((a, b) => b.score - a.score).slice(0, 8);
|
|
2366
|
+
if (rows.length === 0) return "\u5173\u7CFB\u518C\u8FD8\u662F\u7A7A\u7684\u3002";
|
|
2367
|
+
return rows.map((r) => `- ${r.qq}\uFF1A${r.score} \u5206\uFF08${LEVELS(r.score)}\uFF09${r.slot ? "\xB7 " + r.slot : ""}`).join("\n");
|
|
2368
|
+
}
|
|
2369
|
+
case "ritual_set": {
|
|
2370
|
+
const date = typeof args.date === "string" ? args.date.trim() : "";
|
|
2371
|
+
const name2 = typeof args.name === "string" ? args.name.trim() : "";
|
|
2372
|
+
if (!/^\d{1,2}-\d{1,2}$/.test(date) || !name2) return failed("date \u8981\u5199\u6210 \u6708-\u65E5\uFF0C\u6BD4\u5982 10-26");
|
|
2373
|
+
const st = this.ritualStore().read();
|
|
2374
|
+
st.anniversaries = [...(st.anniversaries ?? []).filter((a) => a.date !== date), { date, name: name2 }];
|
|
2375
|
+
this.ritualStore().write(st);
|
|
2376
|
+
return `\u8BB0\u4F4F\u4E86\uFF1A${date} \u662F\u300C${name2}\u300D`;
|
|
2377
|
+
}
|
|
2378
|
+
case "ritual_list": {
|
|
2379
|
+
const st = this.ritualStore().read();
|
|
2380
|
+
if (!st.anniversaries?.length) return "\u8FD8\u6CA1\u8BB0\u7EAA\u5FF5\u65E5\u3002";
|
|
2381
|
+
return st.anniversaries.map((a) => `- ${a.date} ${a.name}`).join("\n");
|
|
2382
|
+
}
|
|
2121
2383
|
case "qq_reply":
|
|
2122
2384
|
return await this.qqReply(args);
|
|
2123
2385
|
case "screen_unlock":
|
|
@@ -2665,6 +2927,33 @@ ${this.recent.map((r) => `- ${r}`).join("\n")}`);
|
|
|
2665
2927
|
function failed(text) {
|
|
2666
2928
|
return { text, failed: true };
|
|
2667
2929
|
}
|
|
2930
|
+
function normalizeWhen(input) {
|
|
2931
|
+
const text = input.trim();
|
|
2932
|
+
if (!text) return "";
|
|
2933
|
+
const full = /^(\d{4})-(\d{1,2})-(\d{1,2})[ T](\d{1,2}):(\d{2})$/.exec(text);
|
|
2934
|
+
if (full) {
|
|
2935
|
+
const d = new Date(Number(full[1]), Number(full[2]) - 1, Number(full[3]), Number(full[4]), Number(full[5]));
|
|
2936
|
+
return isNaN(d.getTime()) ? "" : d.toISOString();
|
|
2937
|
+
}
|
|
2938
|
+
const hm = /^(\d{1,2}):(\d{2})$/.exec(text);
|
|
2939
|
+
if (hm) {
|
|
2940
|
+
const now = /* @__PURE__ */ new Date();
|
|
2941
|
+
const d = new Date(now.getFullYear(), now.getMonth(), now.getDate(), Number(hm[1]), Number(hm[2]));
|
|
2942
|
+
if (d.getTime() <= now.getTime()) d.setDate(d.getDate() + 1);
|
|
2943
|
+
return d.toISOString();
|
|
2944
|
+
}
|
|
2945
|
+
const parsed = new Date(text);
|
|
2946
|
+
return isNaN(parsed.getTime()) ? "" : parsed.toISOString();
|
|
2947
|
+
}
|
|
2948
|
+
function fmtWhen(iso) {
|
|
2949
|
+
try {
|
|
2950
|
+
const d = new Date(iso);
|
|
2951
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
2952
|
+
return `${d.getMonth() + 1}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
2953
|
+
} catch {
|
|
2954
|
+
return iso;
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2668
2957
|
|
|
2669
2958
|
// src/definition.ts
|
|
2670
2959
|
function handsDefinition() {
|
|
@@ -2672,7 +2961,7 @@ function handsDefinition() {
|
|
|
2672
2961
|
id: HANDS_ID,
|
|
2673
2962
|
label: "\u624B",
|
|
2674
2963
|
defaults: () => structuredClone(HANDS_DEFAULTS),
|
|
2675
|
-
create: (ctx) => new HandsWorld({ cfg: ctx.cfg, timezone: ctx.timezone, roots: [ctx.botDir, ctx.dataDir, ctx.repoRoot, ctx.packageDir], dataDir: ctx.dataDir })
|
|
2964
|
+
create: (ctx) => new HandsWorld({ cfg: ctx.cfg, timezone: ctx.timezone, roots: [ctx.botDir, ctx.dataDir, ctx.repoRoot, ctx.packageDir], botDir: ctx.botDir, dataDir: ctx.dataDir })
|
|
2676
2965
|
};
|
|
2677
2966
|
}
|
|
2678
2967
|
var HANDS = handsDefinition();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Cortico World: hands for the desktop pet — looks at the phone screen, then taps, swipes, pinches, drags, types and presses keys through whatever actuator the device actually has",
|
|
6
6
|
"license": "MIT",
|