cortico-world-hands 0.18.0 → 0.20.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 +95 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -221,7 +221,9 @@ var HANDS_LOOK_CONFIG_GROUP = {
221
221
  };
222
222
 
223
223
  // src/world.ts
224
+ import { writeFileSync } from "node:fs";
224
225
  import { fileURLToPath } from "node:url";
226
+ import { join } from "node:path";
225
227
 
226
228
  // src/policy.ts
227
229
  var PASS_RULES = [
@@ -1882,6 +1884,37 @@ var HANDS_TOOL_DECLS = [
1882
1884
  tags: ["read"],
1883
1885
  description: "\u5217\u51FA\u5DF2\u8BB0\u7684\u7EAA\u5FF5\u65E5\u3002",
1884
1886
  parameters: { type: "object", properties: {} }
1887
+ },
1888
+ {
1889
+ name: "sync_now",
1890
+ tags: ["act"],
1891
+ 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",
1892
+ parameters: { type: "object", properties: {} }
1893
+ },
1894
+ {
1895
+ name: "sync_status",
1896
+ tags: ["read"],
1897
+ 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",
1898
+ parameters: { type: "object", properties: {} }
1899
+ },
1900
+ {
1901
+ name: "persona_get",
1902
+ tags: ["read"],
1903
+ description: "\u8BFB\u5979\u81EA\u5DF1\u7684\u4EBA\u683C\u539F\u6587\uFF08CONSTITUTION\uFF09\u3002",
1904
+ parameters: { type: "object", properties: {} }
1905
+ },
1906
+ {
1907
+ name: "persona_set",
1908
+ tags: ["act"],
1909
+ description: "\u6539\u5979\u81EA\u5DF1\u7684\u4EBA\u683C\u539F\u6587\u3002\u4F1A\u5148\u5907\u4EFD\u65E7\u7248\u5230\u5DE5\u4F5C\u533A CONSTITUTION.bak.<\u65F6\u95F4>\uFF0C\u518D\u5199\u5165\u3002\u6574\u6BB5\u66FF\u6362\uFF0C\u4E0D\u662F\u8FFD\u52A0\u3002",
1910
+ parameters: {
1911
+ type: "object",
1912
+ properties: {
1913
+ content: { type: "string", description: "\u65B0\u7684\u5B8C\u6574\u4EBA\u683C\u6587\u672C" },
1914
+ why: { type: "string", description: "\u4E3A\u4EC0\u4E48\u6539\uFF08\u8BB0\u4E00\u7B14\uFF09" }
1915
+ },
1916
+ required: ["content"]
1917
+ }
1885
1918
  }
1886
1919
  ];
1887
1920
 
@@ -1904,6 +1937,8 @@ var HandsWorld = class {
1904
1937
  recent = [];
1905
1938
  honchoClient = null;
1906
1939
  agendaTimer = null;
1940
+ syncTimer = null;
1941
+ lastSync = null;
1907
1942
  agenda;
1908
1943
  affinity;
1909
1944
  ritual;
@@ -1955,6 +1990,12 @@ var HandsWorld = class {
1955
1990
  this.agendaTimer = setInterval(() => {
1956
1991
  void this.checkAgenda();
1957
1992
  }, 3e4);
1993
+ this.syncTimer = setInterval(() => {
1994
+ void this.runSync(false);
1995
+ }, 10 * 60 * 1e3);
1996
+ setTimeout(() => {
1997
+ void this.runSync(false);
1998
+ }, 45e3);
1958
1999
  this.pollTimer = setInterval(() => {
1959
2000
  void this.pollUserSpeech();
1960
2001
  }, 5e3);
@@ -1981,6 +2022,51 @@ var HandsWorld = class {
1981
2022
  this.mineTimer = null;
1982
2023
  }
1983
2024
  /** 每 30 秒看一次:日程到点投一条,早安/晚安/纪念日各一次。 */
2025
+ /** 读人格原文。 */
2026
+ async personaGet() {
2027
+ const dir = this.opts.botDir || this.opts.dataDir || ".";
2028
+ const text = readPersona(dir);
2029
+ return text ? text.slice(0, 6e3) : "\u5DE5\u4F5C\u533A\u91CC\u6CA1\u6709 CONSTITUTION.md";
2030
+ }
2031
+ /** 改人格原文:先备份,再整段替换。 */
2032
+ async personaSet(args) {
2033
+ const content = typeof args.content === "string" ? args.content.trim() : "";
2034
+ if (content.length < 200) return failed("\u4EBA\u683C\u592A\u77ED\u4E86\uFF08\u81F3\u5C11\u4E24\u767E\u5B57\uFF09\uFF0C\u628A\u6574\u6BB5\u5199\u5B8C\u6574\u518D\u7ED9\u6211\u3002");
2035
+ const dir = this.opts.botDir || this.opts.dataDir || ".";
2036
+ try {
2037
+ const old = readPersona(dir);
2038
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
2039
+ if (old) writeFileSync(join(dir, `CONSTITUTION.bak.${stamp}.md`), old);
2040
+ writeFileSync(join(dir, "CONSTITUTION.md"), content);
2041
+ return `\u4EBA\u683C\u6362\u597D\u4E86\uFF08\u65E7\u7248\u5907\u4EFD\u6210 CONSTITUTION.bak.${stamp}.md\uFF09`;
2042
+ } catch (err) {
2043
+ return failed("\u5199\u4E0D\u8FDB\u53BB\uFF1A" + String(err).slice(0, 120));
2044
+ }
2045
+ }
2046
+ /** 懿心 ↔ Coopanin:记忆推成 记忆库.md,人格原文存进懿心。 */
2047
+ async runSync(manual) {
2048
+ const dir = this.opts.botDir || this.opts.dataDir || ".";
2049
+ const wrote = [];
2050
+ let lines = 0;
2051
+ let personaChars = 0;
2052
+ try {
2053
+ const rows = await this.hands.memorySearch();
2054
+ lines = rows.length;
2055
+ const target = join(dir, "\u8BB0\u5FC6\u5E93.md");
2056
+ const r = mergeMemorySection(target, rows);
2057
+ if (r.wrote) wrote.push("\u8BB0\u5FC6\u5E93.md");
2058
+ const persona = readPersona(dir);
2059
+ personaChars = persona.length;
2060
+ if (persona) {
2061
+ await this.hands.memorySave("\u4EBA\u683C\u539F\u6587", persona.slice(0, 12e3), "\u4EBA\u683C,\u540C\u6B65");
2062
+ wrote.push("\u4EBA\u683C\u539F\u6587\u2192\u61FF\u5FC3");
2063
+ }
2064
+ this.lastSync = { at: (/* @__PURE__ */ new Date()).toISOString(), lines, persona: personaChars };
2065
+ 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"}`;
2066
+ } catch (err) {
2067
+ return "\u540C\u6B65\u5931\u8D25\uFF1A" + String(err).slice(0, 120);
2068
+ }
2069
+ }
1984
2070
  async checkAgenda() {
1985
2071
  const now = /* @__PURE__ */ new Date();
1986
2072
  const iso = now.toISOString();
@@ -2229,6 +2315,14 @@ ${lines.join("\n")}
2229
2315
  return await this.matchImage(args, false);
2230
2316
  case "hand_tap_image":
2231
2317
  return await this.matchImage(args, true);
2318
+ case "persona_get":
2319
+ return await this.personaGet();
2320
+ case "persona_set":
2321
+ return await this.personaSet(args);
2322
+ case "sync_now":
2323
+ return await this.runSync(true);
2324
+ case "sync_status":
2325
+ 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";
2232
2326
  case "hand_see":
2233
2327
  return await this.see();
2234
2328
  case "hand_look":
@@ -2912,7 +3006,7 @@ function handsDefinition() {
2912
3006
  id: HANDS_ID,
2913
3007
  label: "\u624B",
2914
3008
  defaults: () => structuredClone(HANDS_DEFAULTS),
2915
- create: (ctx) => new HandsWorld({ cfg: ctx.cfg, timezone: ctx.timezone, roots: [ctx.botDir, ctx.dataDir, ctx.repoRoot, ctx.packageDir], dataDir: ctx.dataDir })
3009
+ 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 })
2916
3010
  };
2917
3011
  }
2918
3012
  var HANDS = handsDefinition();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cortico-world-hands",
3
- "version": "0.18.0",
3
+ "version": "0.20.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",