cortico-world-hands 0.20.3 → 0.20.5
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 +126 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -719,6 +719,12 @@ var MIN_GESTURE_MS = 20;
|
|
|
719
719
|
var MAX_GESTURE_MS = 2e4;
|
|
720
720
|
var HandError = class extends Error {
|
|
721
721
|
};
|
|
722
|
+
function parseRect(raw) {
|
|
723
|
+
if (!raw) return void 0;
|
|
724
|
+
const m = raw.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
|
|
725
|
+
if (!m) return void 0;
|
|
726
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])];
|
|
727
|
+
}
|
|
722
728
|
function get(port, path, timeoutMs) {
|
|
723
729
|
return new Promise((resolve2, reject) => {
|
|
724
730
|
const req = httpGet({ host: "127.0.0.1", port, path, timeout: timeoutMs }, (res) => {
|
|
@@ -1016,6 +1022,20 @@ var EyesClient = class {
|
|
|
1016
1022
|
}
|
|
1017
1023
|
return { ok: body.ok !== false, pkg: flat(body.pkg, 120), items };
|
|
1018
1024
|
}
|
|
1025
|
+
/** 只截一块并放大:x,y,w,h 是真实像素。 */
|
|
1026
|
+
async zoom(x, y, w, h, maxWidth = 1080, quality = 80) {
|
|
1027
|
+
const cfg = this.cfg();
|
|
1028
|
+
const path = `/screen.jpg?x=${Math.max(0, Math.round(x))}&y=${Math.max(0, Math.round(y))}&w=${Math.max(8, Math.round(w))}&h=${Math.max(8, Math.round(h))}&max=${Math.round(maxWidth)}&q=${Math.round(quality)}`;
|
|
1029
|
+
const res = await get(this.handPort(), path, 12e3);
|
|
1030
|
+
if (res.status !== 200 || res.body.length === 0) return null;
|
|
1031
|
+
return {
|
|
1032
|
+
bytes: new Uint8Array(res.body),
|
|
1033
|
+
width: Number.parseInt(res.header("x-width"), 10) || 0,
|
|
1034
|
+
height: Number.parseInt(res.header("x-height"), 10) || 0,
|
|
1035
|
+
pkg: "",
|
|
1036
|
+
ageMs: 0
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1019
1039
|
async frame(maxWidth, quality) {
|
|
1020
1040
|
try {
|
|
1021
1041
|
const w = Math.max(160, Math.min(2160, Math.round(maxWidth)));
|
|
@@ -1051,6 +1071,10 @@ var describeCommand = (command) => {
|
|
|
1051
1071
|
}
|
|
1052
1072
|
};
|
|
1053
1073
|
var Hands = class {
|
|
1074
|
+
/** 读屏幕上的字(转发给眼睛客户端)。 */
|
|
1075
|
+
async uiSnapshot() {
|
|
1076
|
+
return this.eyes.ui();
|
|
1077
|
+
}
|
|
1054
1078
|
eyes;
|
|
1055
1079
|
rootActuator;
|
|
1056
1080
|
shellActuator;
|
|
@@ -1096,7 +1120,7 @@ var Hands = class {
|
|
|
1096
1120
|
for (const item of ui.items) {
|
|
1097
1121
|
if (!item.center) continue;
|
|
1098
1122
|
if (!item.text.toLowerCase().includes(query)) continue;
|
|
1099
|
-
hits2.push({ text: item.text, center: item.center });
|
|
1123
|
+
hits2.push({ text: item.text, center: item.center, rect: parseRect(item.bounds) });
|
|
1100
1124
|
if (hits2.length >= 20) break;
|
|
1101
1125
|
}
|
|
1102
1126
|
return hits2;
|
|
@@ -2122,6 +2146,45 @@ var HANDS_TOOL_DECLS = [
|
|
|
2122
2146
|
},
|
|
2123
2147
|
required: ["content"]
|
|
2124
2148
|
}
|
|
2149
|
+
},
|
|
2150
|
+
{
|
|
2151
|
+
name: "hand_zoom",
|
|
2152
|
+
tags: ["read"],
|
|
2153
|
+
description: "\u53EA\u622A\u5C4F\u5E55\u7684\u4E00\u5C0F\u5757\u5E76\u653E\u5927\u2014\u2014\u5C0F\u5B57\u3001\u5C0F\u6309\u94AE\u770B\u4E0D\u6E05\u65F6\u7528\u5B83\u3002\u5148 hand_see \u62FF\u5230\u5750\u6807\uFF0C\u518D\u628A\u8FD9\u5757\u7684 x/y/\u5BBD/\u9AD8 \u4EA4\u7ED9\u5B83\u3002",
|
|
2154
|
+
parameters: {
|
|
2155
|
+
type: "object",
|
|
2156
|
+
properties: {
|
|
2157
|
+
x: { type: "integer", description: "\u5DE6\u4E0A\u89D2\u6A2A\u5750\u6807\uFF08\u771F\u5B9E\u50CF\u7D20\uFF09" },
|
|
2158
|
+
y: { type: "integer", description: "\u5DE6\u4E0A\u89D2\u7EB5\u5750\u6807" },
|
|
2159
|
+
w: { type: "integer", description: "\u5BBD" },
|
|
2160
|
+
h: { type: "integer", description: "\u9AD8" }
|
|
2161
|
+
},
|
|
2162
|
+
required: ["x", "y", "w", "h"]
|
|
2163
|
+
}
|
|
2164
|
+
},
|
|
2165
|
+
{
|
|
2166
|
+
name: "hand_read_page",
|
|
2167
|
+
tags: ["read"],
|
|
2168
|
+
description: "\u628A\u4E00\u6574\u9875\u8BFB\u5B8C\uFF1A\u5F53\u524D\u5C4F\u7684\u6587\u5B57 + \u5F80\u4E0A\u6EDA\u51E0\u6B21\u628A\u540E\u9762\u7684\u4E5F\u8BFB\u8FDB\u6765\uFF0C\u53BB\u91CD\u540E\u62FC\u6210\u4E00\u6BB5\u3002\u957F\u5217\u8868\u3001\u957F\u6587\u7AE0\u7528\u5B83\uFF0C\u522B\u4E00\u5C4F\u4E00\u5C4F\u95EE\u3002",
|
|
2169
|
+
parameters: {
|
|
2170
|
+
type: "object",
|
|
2171
|
+
properties: {
|
|
2172
|
+
pages: { type: "integer", description: "\u6700\u591A\u7FFB\u51E0\u5C4F\uFF0C\u9ED8\u8BA4 3\uFF0C\u6700\u591A 8" }
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
},
|
|
2176
|
+
{
|
|
2177
|
+
name: "hand_read_text",
|
|
2178
|
+
tags: ["read"],
|
|
2179
|
+
description: "\u8BFB\u67D0\u4E00\u5904\u6587\u5B57\uFF1B\u5B57\u592A\u5C0F\uFF08\u9AD8\u5EA6\u4E0D\u8DB3 40 \u50CF\u7D20\uFF09\u4F1A\u81EA\u52A8\u628A\u90A3\u4E00\u5757\u653E\u5927\u518D\u7ED9\u4F60\u770B\uFF0C\u7701\u5F97\u4F60\u81EA\u5DF1\u8C03 hand_zoom\u3002",
|
|
2180
|
+
parameters: {
|
|
2181
|
+
type: "object",
|
|
2182
|
+
properties: {
|
|
2183
|
+
text: { type: "string", description: "\u8981\u8BFB\u7684\u90A3\u5904\u6587\u5B57\uFF08\u53EF\u4EE5\u53EA\u7ED9\u4E00\u90E8\u5206\uFF09" },
|
|
2184
|
+
nth: { type: "integer", description: "\u540C\u540D\u591A\u5904\u65F6\u53D6\u7B2C\u51E0\u4E2A\uFF0C\u4ECE 0 \u5F00\u59CB" }
|
|
2185
|
+
},
|
|
2186
|
+
required: ["text"]
|
|
2187
|
+
}
|
|
2125
2188
|
}
|
|
2126
2189
|
];
|
|
2127
2190
|
|
|
@@ -2530,6 +2593,67 @@ ${lines.join("\n")}
|
|
|
2530
2593
|
return await this.runSync(true);
|
|
2531
2594
|
case "sync_status":
|
|
2532
2595
|
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";
|
|
2596
|
+
case "hand_read_page": {
|
|
2597
|
+
const pages = Math.max(1, Math.min(8, Math.round(Number(args.pages) || 3)));
|
|
2598
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2599
|
+
const out = [];
|
|
2600
|
+
for (let i = 0; i < pages; i++) {
|
|
2601
|
+
const ui = await this.hands.uiSnapshot();
|
|
2602
|
+
if (!ui.ok) break;
|
|
2603
|
+
for (const item of ui.items) {
|
|
2604
|
+
const t = (item.text || "").trim();
|
|
2605
|
+
if (!t || t.length < 2 || seen.has(t)) continue;
|
|
2606
|
+
seen.add(t);
|
|
2607
|
+
out.push(t);
|
|
2608
|
+
}
|
|
2609
|
+
if (i < pages - 1) {
|
|
2610
|
+
await this.hands.swipe(1550, 1500, 1550, 700, 420);
|
|
2611
|
+
await new Promise((r) => setTimeout(r, 550));
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
if (out.length === 0) return failed("\u8FD9\u4E00\u9875\u6CA1\u8BFB\u5230\u80FD\u5FF5\u7684\u5B57");
|
|
2615
|
+
const text = out.join("\uFF5C");
|
|
2616
|
+
return `\u8FD9\u4E00\u9875\u8BFB\u4E86 ${out.length} \u6BB5
|
|
2617
|
+
${text.slice(0, 2200)}`;
|
|
2618
|
+
}
|
|
2619
|
+
case "hand_read_text": {
|
|
2620
|
+
const needle = typeof args.text === "string" ? args.text.trim() : "";
|
|
2621
|
+
if (!needle) return failed("\u8981\u8BFB\u54EA\u4E00\u6BB5\uFF1F\u7ED9 text");
|
|
2622
|
+
const hits2 = await this.hands.findText(needle);
|
|
2623
|
+
if (hits2.length === 0) return failed(`\u5C4F\u5E55\u4E0A\u6CA1\u627E\u5230\u300C${needle}\u300D`);
|
|
2624
|
+
const nth = args.nth === void 0 ? 0 : Math.max(0, Math.round(Number(args.nth)));
|
|
2625
|
+
const hit = hits2[nth];
|
|
2626
|
+
if (!hit) return failed(`\u300C${needle}\u300D\u53EA\u6709 ${hits2.length} \u5904`);
|
|
2627
|
+
const b = hit.rect;
|
|
2628
|
+
const h = b ? b[3] - b[1] : 0;
|
|
2629
|
+
if (h > 0 && h < 40) {
|
|
2630
|
+
const pad = 12;
|
|
2631
|
+
const f = await this.hands.zoom(
|
|
2632
|
+
Math.max(0, b[0] - pad),
|
|
2633
|
+
Math.max(0, b[1] - pad),
|
|
2634
|
+
Math.max(16, b[2] - b[0] + pad * 2),
|
|
2635
|
+
Math.max(16, b[3] - b[1] + pad * 2)
|
|
2636
|
+
);
|
|
2637
|
+
if (f) {
|
|
2638
|
+
return {
|
|
2639
|
+
text: `\u300C${hit.text}\u300D\u5B57\u592A\u5C0F\uFF08\u9AD8 ${h}px\uFF09\uFF0C\u6211\u628A\u8FD9\u5757\u653E\u5927\u4E86`,
|
|
2640
|
+
blobs: [{ bytes: f.bytes, mime: "image/jpeg", name: "zoom.jpg", fallbackText: "\uFF08\u8FD9\u4E00\u5757\u7684\u653E\u5927\u56FE\uFF09" }]
|
|
2641
|
+
};
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
return `\u300C${hit.text}\u300D@(${hit.center.x},${hit.center.y})`;
|
|
2645
|
+
}
|
|
2646
|
+
case "hand_zoom": {
|
|
2647
|
+
const n = (v) => Math.round(Number(v));
|
|
2648
|
+
const x = n(args.x), y = n(args.y), w = n(args.w), h = n(args.h);
|
|
2649
|
+
if (![x, y, w, h].every(Number.isFinite) || w <= 0 || h <= 0) return failed("\u8981\u7ED9 x/y/w/h\uFF08\u771F\u5B9E\u50CF\u7D20\uFF09");
|
|
2650
|
+
const f = await this.hands.zoom(x, y, w, h);
|
|
2651
|
+
if (!f) return failed("\u8FD9\u4E00\u5757\u6CA1\u622A\u5230\uFF08\u5750\u6807\u53EF\u80FD\u8D85\u51FA\u5C4F\u5E55\uFF09");
|
|
2652
|
+
return {
|
|
2653
|
+
text: `\u653E\u5927\u770B @(${x},${y}) ${w}\xD7${h}`,
|
|
2654
|
+
blobs: [{ bytes: f.bytes, mime: "image/jpeg", name: "zoom.jpg", fallbackText: "\uFF08\u8FD9\u662F\u4ED6\u6307\u5B9A\u90A3\u4E00\u5757\u653E\u5927\u540E\u7684\u622A\u56FE\uFF09" }]
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2533
2657
|
case "hand_see":
|
|
2534
2658
|
return await this.see();
|
|
2535
2659
|
case "hand_look":
|
|
@@ -2689,7 +2813,7 @@ ${lines.join("\n")}
|
|
|
2689
2813
|
async verifyChange(beforePkg) {
|
|
2690
2814
|
try {
|
|
2691
2815
|
await new Promise((r) => setTimeout(r, 450));
|
|
2692
|
-
const ui = await this.hands.
|
|
2816
|
+
const ui = await this.hands.uiSnapshot();
|
|
2693
2817
|
const now = ui.ok ? ui.pkg : "";
|
|
2694
2818
|
if (beforePkg && now && beforePkg !== now) return `\uFF0C\u754C\u9762\u5DF2\u7ECF\u5207\u5230 ${now}`;
|
|
2695
2819
|
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";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.5",
|
|
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",
|