cortico-world-hands 0.7.0 → 0.9.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.
- package/dist/index.js +200 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -496,7 +496,7 @@ var Honcho = class {
|
|
|
496
496
|
// src/hands.ts
|
|
497
497
|
import { execFile } from "node:child_process";
|
|
498
498
|
import { readFileSync } from "node:fs";
|
|
499
|
-
import { get as httpGet } from "node:http";
|
|
499
|
+
import { get as httpGet, request as httpRequest } from "node:http";
|
|
500
500
|
var ACTION_TIMEOUT_MS = 6e3;
|
|
501
501
|
var PROBE_TTL_MS = 2e4;
|
|
502
502
|
var COORD_LIMIT = 2e4;
|
|
@@ -524,6 +524,38 @@ function get(port, path, timeoutMs) {
|
|
|
524
524
|
req.on("error", (err) => reject(err));
|
|
525
525
|
});
|
|
526
526
|
}
|
|
527
|
+
async function post(port, path, body, timeoutMs) {
|
|
528
|
+
return new Promise((resolve, reject) => {
|
|
529
|
+
const data = Buffer.from(body, "utf8");
|
|
530
|
+
const req = httpRequest(
|
|
531
|
+
{
|
|
532
|
+
host: "127.0.0.1",
|
|
533
|
+
port,
|
|
534
|
+
path,
|
|
535
|
+
method: "POST",
|
|
536
|
+
timeout: timeoutMs,
|
|
537
|
+
headers: { "content-type": "application/json", "content-length": data.length }
|
|
538
|
+
},
|
|
539
|
+
(res) => {
|
|
540
|
+
const chunks = [];
|
|
541
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
542
|
+
res.on("end", () => {
|
|
543
|
+
resolve({
|
|
544
|
+
status: res.statusCode ?? 0,
|
|
545
|
+
body: Buffer.concat(chunks),
|
|
546
|
+
header: (name) => {
|
|
547
|
+
const value = res.headers[name.toLowerCase()];
|
|
548
|
+
return Array.isArray(value) ? value[0] ?? "" : value ?? "";
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
);
|
|
554
|
+
req.on("timeout", () => req.destroy(new Error(`\u7B49\u592A\u4E45\uFF08${timeoutMs}ms\uFF09`)));
|
|
555
|
+
req.on("error", (err) => reject(err));
|
|
556
|
+
req.end(data);
|
|
557
|
+
});
|
|
558
|
+
}
|
|
527
559
|
async function getJson(port, path, timeoutMs = 6e3) {
|
|
528
560
|
try {
|
|
529
561
|
const res = await get(port, path, timeoutMs);
|
|
@@ -1031,6 +1063,47 @@ var Hands = class {
|
|
|
1031
1063
|
}
|
|
1032
1064
|
return { ok: res.status === 200 && body.ok !== false, detail: flat(body.detail || body.error || "", 80) };
|
|
1033
1065
|
}
|
|
1066
|
+
/** 唤醒屏幕(用 Shizuku 的 input keyevent 224)。 */
|
|
1067
|
+
async wakeScreen() {
|
|
1068
|
+
const cfg = this.cfg();
|
|
1069
|
+
const credential = this.readToken();
|
|
1070
|
+
const t = credential ? `t=${encodeURIComponent(credential)}` : "";
|
|
1071
|
+
const res = await post(this.port(cfg.handPort), `/hand/wake?${t}`, "", 15e3);
|
|
1072
|
+
return res.body.toString("utf8");
|
|
1073
|
+
}
|
|
1074
|
+
/** 息屏(可选,用来自己测唤醒)。 */
|
|
1075
|
+
async sleepScreen() {
|
|
1076
|
+
const cfg = this.cfg();
|
|
1077
|
+
const credential = this.readToken();
|
|
1078
|
+
const t = credential ? `t=${encodeURIComponent(credential)}` : "";
|
|
1079
|
+
const res = await post(this.port(cfg.handPort), `/hand/sleep?${t}`, "", 15e3);
|
|
1080
|
+
return res.body.toString("utf8");
|
|
1081
|
+
}
|
|
1082
|
+
/** 画板:新开一张。 */
|
|
1083
|
+
async canvasNew(w = 512, h = 512, bg = "transparent") {
|
|
1084
|
+
const cfg = this.cfg();
|
|
1085
|
+
const credential = this.readToken();
|
|
1086
|
+
const t = credential ? `&t=${encodeURIComponent(credential)}` : "";
|
|
1087
|
+
const res = await get(this.port(cfg.handPort), `/canvas/new?w=${w}&h=${h}&bg=${encodeURIComponent(bg)}${t}`, ACTION_TIMEOUT_MS);
|
|
1088
|
+
return res.body.toString("utf8");
|
|
1089
|
+
}
|
|
1090
|
+
/** 画板:画一笔。 */
|
|
1091
|
+
async canvasStroke(points, color = "#111111", width = 4) {
|
|
1092
|
+
const cfg = this.cfg();
|
|
1093
|
+
const credential = this.readToken();
|
|
1094
|
+
const t = credential ? `t=${encodeURIComponent(credential)}` : "";
|
|
1095
|
+
const body = JSON.stringify({ points, color, width });
|
|
1096
|
+
const res = await post(this.port(cfg.handPort), `/canvas/stroke?${t}`, body, ACTION_TIMEOUT_MS);
|
|
1097
|
+
return res.body.toString("utf8");
|
|
1098
|
+
}
|
|
1099
|
+
/** 画板:撤销 / 清空 / 保存 / 列表。 */
|
|
1100
|
+
async canvasOp(op) {
|
|
1101
|
+
const cfg = this.cfg();
|
|
1102
|
+
const credential = this.readToken();
|
|
1103
|
+
const t = credential ? `t=${encodeURIComponent(credential)}` : "";
|
|
1104
|
+
const res = op === "list" || op === "state" ? await get(this.port(cfg.handPort), `/canvas/${op}?${t}`, ACTION_TIMEOUT_MS) : await post(this.port(cfg.handPort), `/canvas/${op}?${t}`, "", ACTION_TIMEOUT_MS);
|
|
1105
|
+
return res.body.toString("utf8");
|
|
1106
|
+
}
|
|
1034
1107
|
/** 日记:写一篇。 */
|
|
1035
1108
|
async diaryWrite(title, text, date) {
|
|
1036
1109
|
const cfg = this.cfg();
|
|
@@ -1385,6 +1458,69 @@ var HANDS_TOOL_DECLS = [
|
|
|
1385
1458
|
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",
|
|
1386
1459
|
parameters: { type: "object", properties: {}, required: [] }
|
|
1387
1460
|
},
|
|
1461
|
+
{
|
|
1462
|
+
name: "screen_wake",
|
|
1463
|
+
tags: ["act"],
|
|
1464
|
+
description: "\u70B9\u4EAE\u5C4F\u5E55\uFF1A\u5C4F\u5E55\u9ED1\u7740\u4E5F\u80FD\u5524\u9192\uFF08\u7528 Shizuku \u7684\u7CFB\u7EDF\u6309\u952E\uFF0Croot/Shizuku \u4EFB\u4E00\u901A\u9053\uFF09\u3002\u4E3B\u4EBA\u8BF4\u300C\u4EAE\u4E00\u4E0B\u5C4F\u300D\u300C\u5E2E\u6211\u628A\u5C4F\u5E55\u70B9\u4EAE\u300D\u65F6\u7528\u5B83\uFF1B\u5931\u8D25\u4F1A\u8FD4\u56DE\u539F\u56E0\u3002",
|
|
1465
|
+
parameters: { type: "object", properties: {} }
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
name: "screen_sleep",
|
|
1469
|
+
tags: ["act"],
|
|
1470
|
+
description: "\u628A\u5C4F\u5E55\u5173\u6389\uFF08\u606F\u5C4F\uFF09\u3002\u4E3B\u4EBA\u8BF4\u8981\u5173\u5C4F\u3001\u6216\u8005\u4F60\u60F3\u81EA\u5DF1\u6D4B\u4E00\u4E0B\u5524\u9192\u662F\u5426\u7BA1\u7528\u65F6\u7528\u5B83\u3002",
|
|
1471
|
+
parameters: { type: "object", properties: {} }
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
name: "canvas_new",
|
|
1475
|
+
tags: ["act"],
|
|
1476
|
+
description: "\u65B0\u5F00\u4E00\u5F20\u753B\u5E03\uFF08\u9ED8\u8BA4 512\xD7512\uFF0C\u80CC\u666F\u900F\u660E\u6216\u767D\u8272\uFF09\uFF0C\u4F1A\u628A\u5F53\u524D\u8FD9\u5F20\u6E05\u6389\u3002",
|
|
1477
|
+
parameters: {
|
|
1478
|
+
type: "object",
|
|
1479
|
+
properties: {
|
|
1480
|
+
w: { type: "integer", description: "\u5BBD\uFF0C\u9ED8\u8BA4 512" },
|
|
1481
|
+
h: { type: "integer", description: "\u9AD8\uFF0C\u9ED8\u8BA4 512" },
|
|
1482
|
+
bg: { type: "string", description: "transparent \u6216 white" }
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
name: "canvas_stroke",
|
|
1488
|
+
tags: ["act"],
|
|
1489
|
+
description: "\u5728\u753B\u5E03\u4E0A\u753B\u4E00\u7B14\uFF1A\u7ED9\u4E00\u4E32\u5750\u6807\u70B9\u3001\u989C\u8272\u3001\u7C97\u7EC6\u3002\u60F3\u753B\u66F2\u7EBF\u5C31\u591A\u7ED9\u70B9\uFF0C\u6BCF\u7B14\u6700\u591A\u51E0\u5341\u4E2A\u70B9\uFF1B\u753B\u6B6A\u4E86\u5C31 canvas_undo\u3002",
|
|
1490
|
+
parameters: {
|
|
1491
|
+
type: "object",
|
|
1492
|
+
properties: {
|
|
1493
|
+
points: { type: "array", description: "\u5750\u6807 [[x,y],[x,y],\u2026]\uFF0C\u539F\u70B9\u662F\u753B\u5E03\u5DE6\u4E0A\u89D2" },
|
|
1494
|
+
color: { type: "string", description: "\u989C\u8272\uFF0C#RRGGBB" },
|
|
1495
|
+
width: { type: "integer", description: "\u7B14\u753B\u7C97\u7EC6\uFF0C\u9ED8\u8BA4 4" }
|
|
1496
|
+
},
|
|
1497
|
+
required: ["points"]
|
|
1498
|
+
}
|
|
1499
|
+
},
|
|
1500
|
+
{
|
|
1501
|
+
name: "canvas_undo",
|
|
1502
|
+
tags: ["act"],
|
|
1503
|
+
description: "\u64A4\u9500\u521A\u624D\u90A3\u4E00\u7B14\uFF08\u53EF\u4EE5\u8FDE\u7740\u64A4\u9500\uFF09\u3002",
|
|
1504
|
+
parameters: { type: "object", properties: {} }
|
|
1505
|
+
},
|
|
1506
|
+
{
|
|
1507
|
+
name: "canvas_clear",
|
|
1508
|
+
tags: ["act"],
|
|
1509
|
+
description: "\u6E05\u7A7A\u6574\u5F20\u753B\u5E03\uFF08\u53EA\u6E05\u7B14\u753B\uFF0C\u4E0D\u5220\u6587\u4EF6\uFF09\u3002",
|
|
1510
|
+
parameters: { type: "object", properties: {} }
|
|
1511
|
+
},
|
|
1512
|
+
{
|
|
1513
|
+
name: "canvas_save",
|
|
1514
|
+
tags: ["act"],
|
|
1515
|
+
description: "\u628A\u753B\u5E03\u5B58\u6210 PNG\uFF0C\u843D\u5230 blobs/drawings/\u65E5\u671F-\u65F6\u95F4.png\uFF0C\u8FD4\u56DE\u8DEF\u5F84\u3002\u53EA\u65B0\u589E\u6587\u4EF6\uFF0C\u4E0D\u8986\u76D6\u65E7\u56FE\u3002",
|
|
1516
|
+
parameters: { type: "object", properties: {} }
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
name: "canvas_list",
|
|
1520
|
+
tags: ["read"],
|
|
1521
|
+
description: "\u770B\u770B\u81EA\u5DF1\u753B\u8FC7\u54EA\u4E9B\u56FE\uFF08\u6587\u4EF6\u540D\u548C\u5730\u5740\uFF09\u3002",
|
|
1522
|
+
parameters: { type: "object", properties: {} }
|
|
1523
|
+
},
|
|
1388
1524
|
{
|
|
1389
1525
|
name: "skin_install",
|
|
1390
1526
|
tags: ["act"],
|
|
@@ -1793,6 +1929,22 @@ ${lines.join("\n")}
|
|
|
1793
1929
|
return await this.diaryRead(args);
|
|
1794
1930
|
case "skin_install":
|
|
1795
1931
|
return await this.skinInstall(args);
|
|
1932
|
+
case "screen_wake":
|
|
1933
|
+
return await this.screenWake();
|
|
1934
|
+
case "screen_sleep":
|
|
1935
|
+
return await this.screenSleep();
|
|
1936
|
+
case "canvas_new":
|
|
1937
|
+
return await this.canvasNew(args);
|
|
1938
|
+
case "canvas_stroke":
|
|
1939
|
+
return await this.canvasStroke(args);
|
|
1940
|
+
case "canvas_undo":
|
|
1941
|
+
return await this.canvasSimple("undo");
|
|
1942
|
+
case "canvas_clear":
|
|
1943
|
+
return await this.canvasSimple("clear");
|
|
1944
|
+
case "canvas_save":
|
|
1945
|
+
return await this.canvasSimple("save");
|
|
1946
|
+
case "canvas_list":
|
|
1947
|
+
return await this.canvasSimple("list");
|
|
1796
1948
|
case "memory_audit":
|
|
1797
1949
|
return await this.memoryAudit(args);
|
|
1798
1950
|
case "memory_search":
|
|
@@ -1905,6 +2057,53 @@ ${lines.join("\n")}
|
|
|
1905
2057
|
}
|
|
1906
2058
|
return `\u8BB0\u7262\u4E86\uFF1A\u300C${key}\u300D\u2192 ${value}${cloud}`;
|
|
1907
2059
|
}
|
|
2060
|
+
/** 点亮屏幕:成功说清楚,失败给原因。 */
|
|
2061
|
+
async screenWake() {
|
|
2062
|
+
const raw = await this.hands.wakeScreen();
|
|
2063
|
+
try {
|
|
2064
|
+
const r = JSON.parse(raw);
|
|
2065
|
+
if (r.ok) {
|
|
2066
|
+
return r.litBefore ? "\u5C4F\u5E55\u672C\u6765\u5C31\u662F\u4EAE\u7684\u3002" : "\u5C4F\u5E55\u70B9\u4EAE\u4E86\u3002";
|
|
2067
|
+
}
|
|
2068
|
+
return failed(r.error || "\u6CA1\u70B9\u4EAE\uFF0C\u539F\u56E0\u4E0D\u660E");
|
|
2069
|
+
} catch {
|
|
2070
|
+
return failed(raw.slice(0, 120));
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
async screenSleep() {
|
|
2074
|
+
const raw = await this.hands.sleepScreen();
|
|
2075
|
+
try {
|
|
2076
|
+
const r = JSON.parse(raw);
|
|
2077
|
+
return r.ok ? "\u5C4F\u5E55\u5173\u6389\u4E86\u3002" : failed(r.error || "\u6CA1\u5173\u6389\uFF0C\u539F\u56E0\u4E0D\u660E");
|
|
2078
|
+
} catch {
|
|
2079
|
+
return failed(raw.slice(0, 120));
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
async canvasNew(args) {
|
|
2083
|
+
const w = args.w === void 0 ? 512 : Math.max(64, Math.min(2048, Math.round(Number(args.w))));
|
|
2084
|
+
const h = args.h === void 0 ? 512 : Math.max(64, Math.min(2048, Math.round(Number(args.h))));
|
|
2085
|
+
const bg = typeof args.bg === "string" && args.bg ? args.bg : "transparent";
|
|
2086
|
+
return await this.hands.canvasNew(w, h, bg);
|
|
2087
|
+
}
|
|
2088
|
+
async canvasStroke(args) {
|
|
2089
|
+
const raw = args.points;
|
|
2090
|
+
if (!Array.isArray(raw) || raw.length === 0) return failed("\u8981 points\uFF0C\u50CF [[10,10],[20,30]]\u3002");
|
|
2091
|
+
const points = [];
|
|
2092
|
+
for (const p of raw.slice(0, 200)) {
|
|
2093
|
+
if (Array.isArray(p) && p.length >= 2) {
|
|
2094
|
+
const x = Number(p[0]);
|
|
2095
|
+
const y = Number(p[1]);
|
|
2096
|
+
if (Number.isFinite(x) && Number.isFinite(y)) points.push([x, y]);
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (points.length === 0) return failed("points \u91CC\u6CA1\u6709\u5408\u6CD5\u5750\u6807\u3002");
|
|
2100
|
+
const color = typeof args.color === "string" && /^#[0-9a-fA-F]{6}$/.test(args.color) ? args.color : "#111111";
|
|
2101
|
+
const width = args.width === void 0 ? 4 : Math.max(1, Math.min(40, Math.round(Number(args.width))));
|
|
2102
|
+
return await this.hands.canvasStroke(points, color, width);
|
|
2103
|
+
}
|
|
2104
|
+
async canvasSimple(op) {
|
|
2105
|
+
return await this.hands.canvasOp(op);
|
|
2106
|
+
}
|
|
1908
2107
|
/** 装一件外部服装包:从本地 HTTP 拿包,写进桌宠 web 目录。 */
|
|
1909
2108
|
async skinInstall(args) {
|
|
1910
2109
|
const url = typeof args.url === "string" && args.url.trim() ? args.url.trim() : this.opts.cfg.skinPackUrl || "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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",
|