cortico-world-hands 0.14.1 → 0.16.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 +84 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1105,6 +1105,16 @@ var Hands = class {
1105
1105
  const res = await post(this.port(cfg.handPort), `/hand/qq/reply?${t}${toq}&text=${encodeURIComponent(text)}`, "", 2e4);
1106
1106
  return res.body.toString("utf8");
1107
1107
  }
1108
+ /** 本地模板匹配:找图(可选直接点)。 */
1109
+ async matchImage(name, opts = {}) {
1110
+ const cfg = this.cfg();
1111
+ const credential = this.readToken();
1112
+ const t = credential ? `t=${encodeURIComponent(credential)}` : "";
1113
+ const th = opts.threshold ? `&threshold=${opts.threshold}` : "";
1114
+ const path = opts.tap ? "/hand/tap_image" : "/hand/match";
1115
+ const res = await get(this.port(cfg.handPort), `${path}?name=${encodeURIComponent(name)}${th}&${t}`, 15e3);
1116
+ return res.body.toString("utf8");
1117
+ }
1108
1118
  /** QQ 兜底:打开 QQ → 找到对话 → 粘贴 → 发送 → 切回。 */
1109
1119
  async qqOpenReply(text, to) {
1110
1120
  const cfg = this.cfg();
@@ -1369,6 +1379,38 @@ ${lines.join("\n")}`);
1369
1379
 
1370
1380
  // src/tools.ts
1371
1381
  var HANDS_TOOL_DECLS = [
1382
+ {
1383
+ name: "hand_match",
1384
+ tags: ["read"],
1385
+ description: "\u5728\u5C4F\u5E55\u4E0A\u627E\u4E00\u5F20\u5C0F\u56FE\uFF08\u6A21\u677F\uFF09\uFF1A\u8FD4\u56DE\u5B83\u7684\u771F\u5B9E\u5750\u6807\u548C\u76F8\u4F3C\u5EA6\u3002\u9002\u5408\u6E38\u620F\u6309\u94AE\u3001\u56FE\u6807\u8FD9\u7C7B\u6CA1\u6709\u6587\u5B57\u7684\u76EE\u6807\u3002",
1386
+ parameters: {
1387
+ type: "object",
1388
+ properties: {
1389
+ name: { type: "string", description: "\u6A21\u677F\u540D\uFF08\u653E\u8FDB App \u7684 tpl \u76EE\u5F55\u7684 png \u6587\u4EF6\u540D\uFF0C\u53EF\u4E0D\u5E26 .png\uFF09" },
1390
+ threshold: { type: "number", description: "\u76F8\u4F3C\u5EA6\u95E8\u69DB 0-1\uFF0C\u9ED8\u8BA4 0.86\uFF1B\u627E\u4E0D\u5230\u5C31\u8C03\u4F4E\u4E00\u70B9" }
1391
+ },
1392
+ required: ["name"]
1393
+ }
1394
+ },
1395
+ {
1396
+ name: "hand_tap_image",
1397
+ tags: ["act"],
1398
+ description: "\u627E\u5230\u90A3\u5F20\u5C0F\u56FE\u5E76\u70B9\u5B83\u2014\u2014\u6BD4\u6309\u5750\u6807\u70B9\u51C6\uFF0C\u4E5F\u4E0D\u4F1A\u70B9\u6B6A\u3002",
1399
+ parameters: {
1400
+ type: "object",
1401
+ properties: {
1402
+ name: { type: "string", description: "\u6A21\u677F\u540D" },
1403
+ threshold: { type: "number", description: "\u76F8\u4F3C\u5EA6\u95E8\u69DB\uFF0C\u9ED8\u8BA4 0.86" }
1404
+ },
1405
+ required: ["name"]
1406
+ }
1407
+ },
1408
+ {
1409
+ name: "hand_see",
1410
+ tags: ["read"],
1411
+ description: "\u53EA\u770B\u6587\u5B57\uFF1A\u5F53\u524D\u524D\u53F0\u662F\u8C01\u3001\u5C4F\u5E55\u4E0A\u6709\u54EA\u4E9B\u80FD\u70B9\u7684\u5B57\u3001\u5404\u81EA\u7684\u771F\u5B9E\u5750\u6807\u3002\u6BD4 hand_look \u5FEB\uFF08\u4E0D\u622A\u56FE\uFF09\uFF0C\u60F3\u5FEB\u901F\u770B\u6E05\u5C4F\u5E55\u65F6\u7528\u5B83\u3002",
1412
+ parameters: { type: "object", properties: {} }
1413
+ },
1372
1414
  {
1373
1415
  name: "hand_look",
1374
1416
  tags: ["read", "snapshot"],
@@ -2034,6 +2076,12 @@ ${lines.join("\n")}
2034
2076
  await this.guard();
2035
2077
  ctx.signal?.throwIfAborted();
2036
2078
  switch (name) {
2079
+ case "hand_match":
2080
+ return await this.matchImage(args, false);
2081
+ case "hand_tap_image":
2082
+ return await this.matchImage(args, true);
2083
+ case "hand_see":
2084
+ return await this.see();
2037
2085
  case "hand_look":
2038
2086
  return await this.look(args);
2039
2087
  case "hand_tap":
@@ -2123,6 +2171,38 @@ ${lines.join("\n")}
2123
2171
  this.recent.unshift(`${stamp} ${receipt.text}`);
2124
2172
  if (this.recent.length > 6) this.recent.length = 6;
2125
2173
  }
2174
+ /** 点完等半秒,看前台有没有变;变了说一声,没变提醒她可能点歪了。 */
2175
+ async verifyChange(beforePkg) {
2176
+ try {
2177
+ await new Promise((r) => setTimeout(r, 450));
2178
+ const ui = await this.hands.ui();
2179
+ const now = ui.ok ? ui.pkg : "";
2180
+ if (beforePkg && now && beforePkg !== now) return `\uFF0C\u754C\u9762\u5DF2\u7ECF\u5207\u5230 ${now}`;
2181
+ return "\uFF08\u5C4F\u5E55\u770B\u8D77\u6765\u6CA1\u53D8\uFF1B\u5982\u679C\u8BE5\u6709\u53CD\u5E94\uFF0C\u5148 hand_see \u770B\u4E00\u773C\u518D\u70B9\uFF09";
2182
+ } catch {
2183
+ return "";
2184
+ }
2185
+ }
2186
+ /** 模板匹配:找图 / 找到就点。 */
2187
+ async matchImage(args, tap) {
2188
+ const name = typeof args.name === "string" ? args.name.trim() : "";
2189
+ if (!name) return failed("\u8981\u6A21\u677F\u540D\uFF08png \u6587\u4EF6\u540D\uFF09");
2190
+ const threshold = args.threshold === void 0 ? void 0 : Number(args.threshold);
2191
+ const raw = await this.hands.matchImage(name, { threshold, tap });
2192
+ try {
2193
+ const r = JSON.parse(raw);
2194
+ if (r.ok && r.found) {
2195
+ return `${tap ? "\u70B9\u5230\u4E86" : "\u627E\u5230\u4E86"}\u300C${name}\u300D@(${r.x},${r.y})\uFF0C\u76F8\u4F3C\u5EA6 ${r.score}\uFF0C\u7528\u4E86 ${r.ms}ms`;
2196
+ }
2197
+ return failed(r.error || `\u5C4F\u5E55\u4E0A\u6CA1\u627E\u5230\u300C${name}\u300D\uFF08\u53EF\u4EE5\u8C03\u4F4E threshold \u518D\u8BD5\uFF09`);
2198
+ } catch {
2199
+ return failed(raw.slice(0, 120));
2200
+ }
2201
+ }
2202
+ /** 纯文字版看屏:快,不带图。 */
2203
+ async see() {
2204
+ return await this.hands.look("text").then((r) => r.text);
2205
+ }
2126
2206
  async look(args) {
2127
2207
  const detail = args.detail === "screen" || args.detail === "text" ? args.detail : "both";
2128
2208
  const report = await this.hands.look(detail);
@@ -2456,9 +2536,12 @@ ${lines || "\uFF08\u90FD\u5212\u6389\u4E86\uFF09"}`;
2456
2536
  ${list}`);
2457
2537
  }
2458
2538
  const only = hits2[0];
2539
+ const beforeUi = await this.hands.ui().catch(() => null);
2540
+ const before = beforeUi && beforeUi.ok ? beforeUi.pkg : "";
2459
2541
  const receipt3 = await this.hands.tap(only.center.x, only.center.y);
2460
2542
  this.note(receipt3);
2461
- return `${receipt3.text}\uFF08\u70B9\u7684\u662F\u300C${only.text}\u300D\uFF09`;
2543
+ const after = await this.verifyChange(before);
2544
+ return `${receipt3.text}\uFF08\u70B9\u7684\u662F\u300C${only.text}\u300D\uFF09${after}`;
2462
2545
  }
2463
2546
  const hit = hits2[nth];
2464
2547
  if (!hit) return failed(`\u300C${text}\u300D\u53EA\u6709 ${hits2.length} \u5904\uFF0C\u6CA1\u6709\u7B2C ${nth} \u4E2A\u3002`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cortico-world-hands",
3
- "version": "0.14.1",
3
+ "version": "0.16.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",