cortico-world-hands 0.5.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.
Files changed (2) hide show
  1. package/dist/index.js +133 -3
  2. 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,32 @@ 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
+ },
1356
1411
  {
1357
1412
  name: "memory_note",
1358
1413
  tags: ["write"],
@@ -1495,6 +1550,8 @@ var HandsWorld = class {
1495
1550
  recent = [];
1496
1551
  honchoClient = null;
1497
1552
  pollTimer = null;
1553
+ dailyDiaryTimer = null;
1554
+ lastDiaryDay = "";
1498
1555
  mineTimer = null;
1499
1556
  cursor = 0;
1500
1557
  lastHitKey = "";
@@ -1531,10 +1588,14 @@ var HandsWorld = class {
1531
1588
  this.mineTimer = setInterval(() => {
1532
1589
  void this.pushMineNudge();
1533
1590
  }, 3 * 60 * 60 * 1e3);
1591
+ this.dailyDiaryTimer = setInterval(() => {
1592
+ void this.pushDiaryNudge();
1593
+ }, 10 * 60 * 1e3);
1534
1594
  }
1535
1595
  stopHooks() {
1536
1596
  if (this.pollTimer) clearInterval(this.pollTimer);
1537
1597
  if (this.mineTimer) clearInterval(this.mineTimer);
1598
+ if (this.dailyDiaryTimer) clearInterval(this.dailyDiaryTimer);
1538
1599
  this.pollTimer = null;
1539
1600
  this.mineTimer = null;
1540
1601
  }
@@ -1558,6 +1619,17 @@ var HandsWorld = class {
1558
1619
  if (rows.length === 0) return;
1559
1620
  const top = rows.slice(-12).reverse().slice(0, 8);
1560
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
+ }
1561
1633
  await this.pushEvent(
1562
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
1563
1635
  ${lines.join("\n")}`,
@@ -1586,11 +1658,19 @@ ${lines.join("\n")}`,
1586
1658
  try {
1587
1659
  const rows = await this.hands.memorySearch();
1588
1660
  const hits2 = hookHits(text, rows);
1589
- if (hits2.length === 0) return;
1590
- const key = hits2.map((h) => h.key).join("|");
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("|");
1591
1671
  if (key === this.lastHitKey) return;
1592
1672
  this.lastHitKey = key;
1593
- const lines = hits2.slice(0, 4).map((h) => `- ${h.key}\uFF1A${h.value}`);
1673
+ const lines = all.slice(0, 4).map((h) => `- ${h.key}\uFF1A${h.value.length > 70 ? h.value.slice(0, 70) + "\u2026" : h.value}`);
1594
1674
  await this.pushEvent(
1595
1675
  `[\u8BB0\u5FC6] \u4ED6\u8FD9\u53E5\u91CC\u63D0\u5230\u4E86\u4F60\u8BB0\u8FC7\u7684\u4E8B\uFF0C\u53EF\u80FD\u7528\u5F97\u4E0A\uFF1A
1596
1676
  ${lines.join("\n")}
@@ -1601,6 +1681,33 @@ ${lines.join("\n")}
1601
1681
  } catch {
1602
1682
  }
1603
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
+ }
1604
1711
  /** 钩子 2:每三小时提一次,让她自己挑 1–5 条写进记忆库。 */
1605
1712
  async pushMineNudge() {
1606
1713
  if (!this.host) return;
@@ -1661,6 +1768,10 @@ ${lines.join("\n")}
1661
1768
  return await this.memorySave(args);
1662
1769
  case "memory_note":
1663
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);
1664
1775
  case "memory_audit":
1665
1776
  return await this.memoryAudit(args);
1666
1777
  case "memory_search":
@@ -1773,6 +1884,25 @@ ${lines.join("\n")}
1773
1884
  }
1774
1885
  return `\u8BB0\u7262\u4E86\uFF1A\u300C${key}\u300D\u2192 ${value}${cloud}`;
1775
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
+ }
1776
1906
  /** 只写本地的一条:不进云端,宽松记。 */
1777
1907
  async memoryNote(args) {
1778
1908
  const key = typeof args.key === "string" ? args.key.trim() : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cortico-world-hands",
3
- "version": "0.5.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",