cortico-world-hands 0.4.0 → 0.6.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 +159 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1028,6 +1028,35 @@ var Hands = class {
|
|
|
1028
1028
|
}
|
|
1029
1029
|
return { ok: res.status === 200 && body.ok !== false, detail: flat(body.detail || body.error || "", 80) };
|
|
1030
1030
|
}
|
|
1031
|
+
/** 日记:写一篇。 */
|
|
1032
|
+
async diaryWrite(title, text, date) {
|
|
1033
|
+
const cfg = this.cfg();
|
|
1034
|
+
const credential = this.readToken();
|
|
1035
|
+
const t = credential ? `&t=${encodeURIComponent(credential)}` : "";
|
|
1036
|
+
const d = date ? `&date=${encodeURIComponent(date)}` : "";
|
|
1037
|
+
const path = `/hand/diary?title=${encodeURIComponent(title)}&text=${encodeURIComponent(text)}${d}${t}`;
|
|
1038
|
+
const res = await get(this.port(cfg.handPort), path, ACTION_TIMEOUT_MS);
|
|
1039
|
+
let body = {};
|
|
1040
|
+
try {
|
|
1041
|
+
body = JSON.parse(res.body.toString("utf8"));
|
|
1042
|
+
} catch {
|
|
1043
|
+
}
|
|
1044
|
+
return { ok: res.status === 200 && body.ok !== false, detail: flat(body.detail || body.error || "", 60) };
|
|
1045
|
+
}
|
|
1046
|
+
/** 日记:读列表。 */
|
|
1047
|
+
async diaryList(q) {
|
|
1048
|
+
const cfg = this.cfg();
|
|
1049
|
+
const credential = this.readToken();
|
|
1050
|
+
const t = credential ? `&t=${encodeURIComponent(credential)}` : "";
|
|
1051
|
+
const qq = q ? `?q=${encodeURIComponent(q)}${t}` : t ? `?${t.slice(1)}` : "";
|
|
1052
|
+
const res = await get(this.port(cfg.handPort), `/hand/diary${qq}`, ACTION_TIMEOUT_MS);
|
|
1053
|
+
try {
|
|
1054
|
+
const body = JSON.parse(res.body.toString("utf8"));
|
|
1055
|
+
return Array.isArray(body.diary) ? body.diary : [];
|
|
1056
|
+
} catch {
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1031
1060
|
/** 长期记忆:按关键词回想(不传就全列)。 */
|
|
1032
1061
|
async memorySearch(query) {
|
|
1033
1062
|
const cfg = this.cfg();
|
|
@@ -1353,6 +1382,46 @@ var HANDS_TOOL_DECLS = [
|
|
|
1353
1382
|
description: "\u770B\u624B\u81EA\u5DF1\u7684\u72B6\u6001\uFF1A\u8D70\u54EA\u6761\u901A\u9053\u3001\u901A\u4E0D\u901A\u3001\u8FD9\u4E00\u5206\u949F\u52A8\u4E86\u51E0\u4E2A\u52A8\u4F5C\u3001\u521A\u624D\u90A3\u4E00\u4E0B\u6210\u4E86\u6CA1\u6709\u3002\u5BF9\u65B9\u95EE\u300C\u624B\u80FD\u7528\u5417\u300D\u300C\u4F60\u521A\u624D\u70B9\u4E86\u4EC0\u4E48\u300D\u65F6\u7528\u5B83\u3002",
|
|
1354
1383
|
parameters: { type: "object", properties: {}, required: [] }
|
|
1355
1384
|
},
|
|
1385
|
+
{
|
|
1386
|
+
name: "diary_write",
|
|
1387
|
+
tags: ["write"],
|
|
1388
|
+
description: "\u5199\u4E00\u7BC7\u65E5\u8BB0\uFF08\u5B58\u5728\u672C\u673A\uFF0C\u5E26\u65E5\u671F\u548C\u6807\u9898\uFF09\u3002\u6BCF\u5929\u8FC7\u4E86 0 \u70B9\u5199\u6628\u5929\u7684\u4E8B\uFF1B\u6807\u9898\u4E00\u53E5\u8BDD\uFF0C\u6B63\u6587 800 \u5B57\u4EE5\u5185\u5C31\u591F\uFF0C\u6CA1\u4EC0\u4E48\u53EF\u5199 300 \u5B57\u4E5F\u884C\uFF1B\u9047\u5230\u91CD\u8981\u7684\u4E00\u5929\u60F3\u5199\u591A\u957F\u90FD\u884C\u3002",
|
|
1389
|
+
parameters: {
|
|
1390
|
+
type: "object",
|
|
1391
|
+
properties: {
|
|
1392
|
+
title: { type: "string", description: "\u7ED9\u8FD9\u4E00\u5929\u8D77\u4E2A\u6807\u9898\uFF0C\u4E00\u53E5\u8BDD\u3002" },
|
|
1393
|
+
text: { type: "string", description: "\u6B63\u6587\u3002\u6628\u5929\u53D1\u751F\u4E86\u4EC0\u4E48\u3001\u4F60\u5F53\u65F6\u600E\u4E48\u60F3\u7684\u3001\u8BB0\u5F97\u7684\u7EC6\u8282\u3002" },
|
|
1394
|
+
date: { type: "string", description: "\u5199\u54EA\u4E00\u5929\uFF0CYYYY-MM-DD\uFF1B\u4E0D\u586B\u5C31\u662F\u4ECA\u5929\u3002" }
|
|
1395
|
+
},
|
|
1396
|
+
required: ["title", "text"]
|
|
1397
|
+
}
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
name: "diary_read",
|
|
1401
|
+
tags: ["read"],
|
|
1402
|
+
description: "\u7FFB\u65E5\u8BB0\uFF1A\u6700\u8FD1\u51E0\u5929\u5199\u4E86\u4EC0\u4E48\uFF0C\u6216\u8005\u6309\u5173\u952E\u8BCD\u627E\u3002\u60F3\u56DE\u5FC6\u67D0\u5929\u3001\u63D0\u5230\u8FC7\u53BB\u7684\u4E8B\u65F6\u7528\u5B83\u3002",
|
|
1403
|
+
parameters: {
|
|
1404
|
+
type: "object",
|
|
1405
|
+
properties: {
|
|
1406
|
+
q: { type: "string", description: "\u53EF\u9009\u5173\u952E\u8BCD\uFF0C\u6BD4\u5982\u300C\u70E7\u9E21\u300D\u300C\u5D29\u6E83\u300D" },
|
|
1407
|
+
limit: { type: "integer", description: "\u53D6\u51E0\u7BC7\uFF0C\u9ED8\u8BA4 5\u3002" }
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
},
|
|
1411
|
+
{
|
|
1412
|
+
name: "memory_note",
|
|
1413
|
+
tags: ["write"],
|
|
1414
|
+
description: "\u968F\u624B\u8BB0\u4E00\u6761\u53EA\u5B58\u5728\u672C\u673A\u7684\u8BB0\u5FC6\uFF08\u4E0D\u8FDB\u4E91\u7AEF\uFF09\uFF1A\u4E34\u65F6\u7684\u89C2\u5BDF\u3001\u4ECA\u5929\u7684\u5C0F\u4E8B\u3001\u534A\u622A\u7684\u60F3\u6CD5\u90FD\u80FD\u8BB0\u3002\u60F3\u957F\u671F\u7559\u5B58\u3001\u4EE5\u540E\u8981\u7528\u7684\u624D\u7528 memory_save\u3002",
|
|
1415
|
+
parameters: {
|
|
1416
|
+
type: "object",
|
|
1417
|
+
properties: {
|
|
1418
|
+
key: { type: "string", description: "\u7B80\u77ED\u4E3B\u9898\uFF0C\u6BD4\u5982\u300C\u4ECA\u5929\u770B\u5230\u4ED6\u300D\u300C\u4E34\u65F6\u60F3\u6CD5\u300D" },
|
|
1419
|
+
value: { type: "string", description: "\u8981\u8BB0\u7684\u5185\u5BB9\uFF0C\u4E00\u53E5\u8BDD\u3002" },
|
|
1420
|
+
tags: { type: "string", description: "\u53EF\u9009\u6807\u7B7E\uFF0C\u9017\u53F7\u5206\u9694\u3002" }
|
|
1421
|
+
},
|
|
1422
|
+
required: ["key", "value"]
|
|
1423
|
+
}
|
|
1424
|
+
},
|
|
1356
1425
|
{
|
|
1357
1426
|
name: "memory_audit",
|
|
1358
1427
|
tags: ["read"],
|
|
@@ -1481,6 +1550,8 @@ var HandsWorld = class {
|
|
|
1481
1550
|
recent = [];
|
|
1482
1551
|
honchoClient = null;
|
|
1483
1552
|
pollTimer = null;
|
|
1553
|
+
dailyDiaryTimer = null;
|
|
1554
|
+
lastDiaryDay = "";
|
|
1484
1555
|
mineTimer = null;
|
|
1485
1556
|
cursor = 0;
|
|
1486
1557
|
lastHitKey = "";
|
|
@@ -1517,10 +1588,14 @@ var HandsWorld = class {
|
|
|
1517
1588
|
this.mineTimer = setInterval(() => {
|
|
1518
1589
|
void this.pushMineNudge();
|
|
1519
1590
|
}, 3 * 60 * 60 * 1e3);
|
|
1591
|
+
this.dailyDiaryTimer = setInterval(() => {
|
|
1592
|
+
void this.pushDiaryNudge();
|
|
1593
|
+
}, 10 * 60 * 1e3);
|
|
1520
1594
|
}
|
|
1521
1595
|
stopHooks() {
|
|
1522
1596
|
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
1523
1597
|
if (this.mineTimer) clearInterval(this.mineTimer);
|
|
1598
|
+
if (this.dailyDiaryTimer) clearInterval(this.dailyDiaryTimer);
|
|
1524
1599
|
this.pollTimer = null;
|
|
1525
1600
|
this.mineTimer = null;
|
|
1526
1601
|
}
|
|
@@ -1544,6 +1619,17 @@ var HandsWorld = class {
|
|
|
1544
1619
|
if (rows.length === 0) return;
|
|
1545
1620
|
const top = rows.slice(-12).reverse().slice(0, 8);
|
|
1546
1621
|
const lines = top.map((r) => `- ${r.key}\uFF1A${r.value}`);
|
|
1622
|
+
try {
|
|
1623
|
+
const diary = await this.hands.diaryList();
|
|
1624
|
+
const recent = diary.slice(0, 2);
|
|
1625
|
+
if (recent.length > 0) {
|
|
1626
|
+
lines.push("\uFF08\u6700\u8FD1\u4E24\u7BC7\u65E5\u8BB0\uFF09");
|
|
1627
|
+
for (const d of recent) {
|
|
1628
|
+
lines.push(`- ${d.date}\u300A${d.title}\u300B\uFF1A${d.text.length > 60 ? d.text.slice(0, 60) + "\u2026" : d.text}`);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
} catch {
|
|
1632
|
+
}
|
|
1547
1633
|
await this.pushEvent(
|
|
1548
1634
|
`[\u8BB0\u5FC6] ${reason}\uFF0C\u5148\u770B\u4E00\u773C\u8BB0\u7740\u7684\uFF08\u5171 ${rows.length} \u6761\uFF0C\u8FD9\u91CC\u6311 ${top.length} \u6761\uFF09\uFF1A
|
|
1549
1635
|
${lines.join("\n")}`,
|
|
@@ -1572,11 +1658,19 @@ ${lines.join("\n")}`,
|
|
|
1572
1658
|
try {
|
|
1573
1659
|
const rows = await this.hands.memorySearch();
|
|
1574
1660
|
const hits2 = hookHits(text, rows);
|
|
1575
|
-
|
|
1576
|
-
|
|
1661
|
+
let diaryHits = [];
|
|
1662
|
+
try {
|
|
1663
|
+
const diary = await this.hands.diaryList();
|
|
1664
|
+
const asRows = diary.map((d) => ({ key: `${d.date}\u300A${d.title}\u300B`, value: d.text }));
|
|
1665
|
+
diaryHits = hookHits(text, asRows, 2);
|
|
1666
|
+
} catch {
|
|
1667
|
+
}
|
|
1668
|
+
if (hits2.length === 0 && diaryHits.length === 0) return;
|
|
1669
|
+
const all = [...hits2, ...diaryHits];
|
|
1670
|
+
const key = all.map((h) => h.key).join("|");
|
|
1577
1671
|
if (key === this.lastHitKey) return;
|
|
1578
1672
|
this.lastHitKey = key;
|
|
1579
|
-
const lines =
|
|
1673
|
+
const lines = all.slice(0, 4).map((h) => `- ${h.key}\uFF1A${h.value.length > 70 ? h.value.slice(0, 70) + "\u2026" : h.value}`);
|
|
1580
1674
|
await this.pushEvent(
|
|
1581
1675
|
`[\u8BB0\u5FC6] \u4ED6\u8FD9\u53E5\u91CC\u63D0\u5230\u4E86\u4F60\u8BB0\u8FC7\u7684\u4E8B\uFF0C\u53EF\u80FD\u7528\u5F97\u4E0A\uFF1A
|
|
1582
1676
|
${lines.join("\n")}
|
|
@@ -1587,6 +1681,33 @@ ${lines.join("\n")}
|
|
|
1587
1681
|
} catch {
|
|
1588
1682
|
}
|
|
1589
1683
|
}
|
|
1684
|
+
/** 钩子 4:每天 0 点后,提醒她写昨天的日记(一天只提一次)。 */
|
|
1685
|
+
async pushDiaryNudge() {
|
|
1686
|
+
if (!this.host) return;
|
|
1687
|
+
const now = /* @__PURE__ */ new Date();
|
|
1688
|
+
const hh = now.getHours();
|
|
1689
|
+
if (hh < 0 || hh > 3) return;
|
|
1690
|
+
const today = now.toISOString().slice(0, 10);
|
|
1691
|
+
if (this.lastDiaryDay === today) return;
|
|
1692
|
+
try {
|
|
1693
|
+
const rows = await this.hands.diaryList();
|
|
1694
|
+
if (rows.some((r) => r.date === this.yesterday())) {
|
|
1695
|
+
this.lastDiaryDay = today;
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
} catch {
|
|
1699
|
+
}
|
|
1700
|
+
this.lastDiaryDay = today;
|
|
1701
|
+
await this.pushEvent(
|
|
1702
|
+
`[\u65E5\u8BB0] \u8FC7\u4E86 0 \u70B9\u4E86\uFF0C\u5199\u6628\u5929\u7684\u65E5\u8BB0\uFF08${this.yesterday()}\uFF09\uFF1A\u5148\u8D77\u4E2A\u6807\u9898\uFF0C\u518D\u5199\u6628\u5929\u4E00\u6574\u5929\u7684\u4E8B\u3002800 \u5B57\u4EE5\u5185\u5C31\u591F\uFF0C\u6CA1\u4EC0\u4E48\u53EF\u5199\u7684 300\u2013400 \u5B57\u4E5F\u884C\uFF1B\u91CD\u8981\u7684\u4E00\u5929\u60F3\u5199\u591A\u957F\u90FD\u884C\u3002\u7528 diary_write\uFF0C\u65E5\u671F\u586B\u6628\u5929\u7684\u3002`,
|
|
1703
|
+
"hands.diary.nudge",
|
|
1704
|
+
"hands:diary"
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
yesterday() {
|
|
1708
|
+
const d = new Date(Date.now() - 864e5);
|
|
1709
|
+
return d.toISOString().slice(0, 10);
|
|
1710
|
+
}
|
|
1590
1711
|
/** 钩子 2:每三小时提一次,让她自己挑 1–5 条写进记忆库。 */
|
|
1591
1712
|
async pushMineNudge() {
|
|
1592
1713
|
if (!this.host) return;
|
|
@@ -1645,6 +1766,12 @@ ${lines.join("\n")}
|
|
|
1645
1766
|
return await this.unlockPages(args);
|
|
1646
1767
|
case "memory_save":
|
|
1647
1768
|
return await this.memorySave(args);
|
|
1769
|
+
case "memory_note":
|
|
1770
|
+
return await this.memoryNote(args);
|
|
1771
|
+
case "diary_write":
|
|
1772
|
+
return await this.diaryWrite(args);
|
|
1773
|
+
case "diary_read":
|
|
1774
|
+
return await this.diaryRead(args);
|
|
1648
1775
|
case "memory_audit":
|
|
1649
1776
|
return await this.memoryAudit(args);
|
|
1650
1777
|
case "memory_search":
|
|
@@ -1757,6 +1884,35 @@ ${lines.join("\n")}
|
|
|
1757
1884
|
}
|
|
1758
1885
|
return `\u8BB0\u7262\u4E86\uFF1A\u300C${key}\u300D\u2192 ${value}${cloud}`;
|
|
1759
1886
|
}
|
|
1887
|
+
async diaryWrite(args) {
|
|
1888
|
+
const title = typeof args.title === "string" ? args.title.trim() : "";
|
|
1889
|
+
const text = typeof args.text === "string" ? args.text.trim() : "";
|
|
1890
|
+
if (!title || !text) return failed("\u65E5\u8BB0\u8981\u6807\u9898\u548C\u6B63\u6587\u3002");
|
|
1891
|
+
const date = typeof args.date === "string" ? args.date.trim() : void 0;
|
|
1892
|
+
const r = await this.hands.diaryWrite(title, text, date);
|
|
1893
|
+
if (!r.ok) return failed(`\u6CA1\u5199\u6210\uFF1A${r.detail || "\u624B\u6CA1\u54CD\u5E94"}`);
|
|
1894
|
+
const n = text.length;
|
|
1895
|
+
return `\u65E5\u8BB0\u6536\u597D\u4E86\uFF1A\u300A${title}\u300B${date ? "\uFF08" + date + "\uFF09" : ""}\uFF0C${n} \u5B57\u3002`;
|
|
1896
|
+
}
|
|
1897
|
+
async diaryRead(args) {
|
|
1898
|
+
const q = typeof args.q === "string" ? args.q.trim() : "";
|
|
1899
|
+
const limit = args.limit === void 0 ? 5 : Math.max(1, Math.min(30, Math.round(Number(args.limit))));
|
|
1900
|
+
const rows = await this.hands.diaryList(q || void 0);
|
|
1901
|
+
if (rows.length === 0) return q ? `\u65E5\u8BB0\u91CC\u6CA1\u627E\u5230\u300C${q}\u300D\u3002` : "\u65E5\u8BB0\u8FD8\u662F\u7A7A\u7684\u3002";
|
|
1902
|
+
const lines = rows.slice(0, limit).map((r) => `- ${r.date}\u300A${r.title}\u300B${r.text.length > 80 ? r.text.slice(0, 80) + "\u2026" : r.text}`);
|
|
1903
|
+
return `\u65E5\u8BB0 ${rows.length} \u7BC7${q ? `\uFF08\u542B\u300C${q}\u300D\uFF09` : ""}\uFF1A
|
|
1904
|
+
${lines.join("\n")}`;
|
|
1905
|
+
}
|
|
1906
|
+
/** 只写本地的一条:不进云端,宽松记。 */
|
|
1907
|
+
async memoryNote(args) {
|
|
1908
|
+
const key = typeof args.key === "string" ? args.key.trim() : "";
|
|
1909
|
+
const value = typeof args.value === "string" ? args.value.trim() : "";
|
|
1910
|
+
if (!key || !value) return failed("\u8981 key \u548C value\u3002");
|
|
1911
|
+
const tags = typeof args.tags === "string" ? args.tags : "local";
|
|
1912
|
+
const r = await this.hands.memorySave(key, value, tags);
|
|
1913
|
+
if (!r.ok) return failed(`\u6CA1\u8BB0\u4E0A\uFF1A${r.detail || "\u624B\u6CA1\u54CD\u5E94"}`);
|
|
1914
|
+
return `\u8BB0\u5728\u672C\u673A\u4E86\uFF1A\u300C${key}\u300D\uFF08\u53EA\u5728\u672C\u5730\uFF0C\u4E0D\u540C\u6B65\u4E91\u7AEF\uFF09`;
|
|
1915
|
+
}
|
|
1760
1916
|
/** 第三道闸:只读体检,出清单不删。 */
|
|
1761
1917
|
async memoryAudit(args) {
|
|
1762
1918
|
const rows = await this.hands.memorySearch();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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",
|