cortico-world-hands 0.15.0 → 0.17.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 +59 -0
  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,32 @@ ${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
+ },
1372
1408
  {
1373
1409
  name: "hand_see",
1374
1410
  tags: ["read"],
@@ -2040,6 +2076,10 @@ ${lines.join("\n")}
2040
2076
  await this.guard();
2041
2077
  ctx.signal?.throwIfAborted();
2042
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);
2043
2083
  case "hand_see":
2044
2084
  return await this.see();
2045
2085
  case "hand_look":
@@ -2143,6 +2183,25 @@ ${lines.join("\n")}
2143
2183
  return "";
2144
2184
  }
2145
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.band === "hit" && r.ok) {
2195
+ return `${tap ? "\u70B9\u4E86" : "\u627E\u5230\u4E86"}\u300C${name}\u300D@(${r.x},${r.y})\uFF0C\u5206\u6570 ${r.score}\uFF0C${r.ms}ms`;
2196
+ }
2197
+ if (r.band === "uncertain") {
2198
+ return `\u300C${name}\u300D\u50CF\u662F\u6709\uFF0C\u4F46\u5206\u6570\u53EA\u6709 ${r.score}\uFF080.4\u20130.7\uFF09\uFF0C**\u6211\u6CA1\u70B9**\uFF0C\u5750\u6807 @(${r.x},${r.y})\u3002\u4F60\u5B9A\u8981\u4E0D\u8981\u70B9\u3002`;
2199
+ }
2200
+ return failed(r.error || `\u5C4F\u5E55\u4E0A\u6CA1\u627E\u5230\u300C${name}\u300D`);
2201
+ } catch {
2202
+ return failed(raw.slice(0, 120));
2203
+ }
2204
+ }
2146
2205
  /** 纯文字版看屏:快,不带图。 */
2147
2206
  async see() {
2148
2207
  return await this.hands.look("text").then((r) => r.text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cortico-world-hands",
3
- "version": "0.15.0",
3
+ "version": "0.17.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",