cortico-world-hands 0.2.1 → 0.3.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 +206 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -215,6 +215,134 @@ var HANDS_LOOK_CONFIG_GROUP = {
|
|
|
215
215
|
// src/world.ts
|
|
216
216
|
import { fileURLToPath } from "node:url";
|
|
217
217
|
|
|
218
|
+
// src/policy.ts
|
|
219
|
+
var PASS_RULES = [
|
|
220
|
+
["\u504F\u597D", /(喜欢|爱吃|爱喝|偏好|口味|不喜欢|讨厌|习惯|只喝|只吃|过敏)/],
|
|
221
|
+
["\u7EA6\u5B9A", /(约定|约好|说好|规矩|不许|别再|不要再|以后都|每次都|提醒我|叫我)/],
|
|
222
|
+
["\u91CD\u8981\u65E5\u5B50", /(生日|纪念日|周年|节日|那天|周[一二三四五六日天]|每月|每年)/],
|
|
223
|
+
["\u6B63\u5728\u505A\u7684\u4E8B", /(正在做|在做|最近在|这几天在|手上在做|进度|项目|在弄|在做的东西)/],
|
|
224
|
+
["\u7B54\u5E94\u8FC7\u7684\u4E8B", /(答应|承诺|保证|说好了|我会|我给你|给你做|欠你)/],
|
|
225
|
+
["\u8EAB\u4EFD\u8BBE\u5B9A", /(我是谁|人格|自称|称呼|名字|叫我|身份|人设|性格|口癖|说话的样子)/]
|
|
226
|
+
];
|
|
227
|
+
var DROP_RULES = [
|
|
228
|
+
["\u64CD\u4F5C\u56DE\u6267", /(已安装|安装成功|已重启|重启完成|已卸载|装好|loaded=|exit code|退出码|回执|已同步|同步失败)/i],
|
|
229
|
+
["\u6280\u672F\u7EC6\u8282", /(端口|pnpm|lockfile|ERR_[A-Z_]+|版本号|v?\d+\.\d+\.\d+|API key|token|\/root\/|\/assets\/|\/sdcard\/)/i],
|
|
230
|
+
["\u5750\u6807\u4E0E\u5206\u8FA8\u7387", /(\d{3,4}\s*[×x]\s*\d{3,4}|坐标|分辨率|截图渲染|×2\.15)/],
|
|
231
|
+
["\u4E00\u6B21\u6027\u4E8B\u4EF6", /(刚才|刚刚|今天|昨天|还剩|第\s*\d+\s*次|已经提醒|提醒过|配额)/],
|
|
232
|
+
["\u8FC7\u7A0B\u53D9\u8FF0", /(试了|计划要|打算把|当时想|中间方案|做法是|先改成|原来是)/],
|
|
233
|
+
["\u754C\u9762\u63CF\u8FF0", /(状态栏|面板|按钮|页签|界面写着|显示着)/]
|
|
234
|
+
];
|
|
235
|
+
var PROMISE_OVERRIDE = /(答应|约好|说好|承诺|周五|周六|周日|下周|明天|生日|纪念日)/;
|
|
236
|
+
function hits(rules, text) {
|
|
237
|
+
const out = [];
|
|
238
|
+
for (const [name, re] of rules) {
|
|
239
|
+
const m = text.match(re);
|
|
240
|
+
if (m) out.push([name, m[0]]);
|
|
241
|
+
}
|
|
242
|
+
return out;
|
|
243
|
+
}
|
|
244
|
+
function classify(key, value) {
|
|
245
|
+
const text = `${key} ${value}`;
|
|
246
|
+
if (PROMISE_OVERRIDE.test(text)) {
|
|
247
|
+
return { verdict: "pass", category: "\u7B54\u5E94\u8FC7\u7684\u4E8B", reason: `\u547D\u4E2D\u627F\u8BFA\u53E5\u5F0F\u300C${text.match(PROMISE_OVERRIDE)[0]}\u300D` };
|
|
248
|
+
}
|
|
249
|
+
const pass = hits(PASS_RULES, text);
|
|
250
|
+
const drop = hits(DROP_RULES, text);
|
|
251
|
+
if (drop.length > 0 && pass.length === 0) {
|
|
252
|
+
return { verdict: "drop", category: drop[0][0], reason: `\u6D41\u6C34\u7279\u5F81\u300C${drop[0][1]}\u300D` };
|
|
253
|
+
}
|
|
254
|
+
if (drop.length > 0 && pass.length > 0) {
|
|
255
|
+
return { verdict: "buffer", category: pass[0][0], reason: `\u540C\u65F6\u50CF\u4E8B\u5B9E\u4E0E\u6D41\u6C34\uFF08${pass[0][1]} / ${drop[0][1]}\uFF09` };
|
|
256
|
+
}
|
|
257
|
+
if (pass.length > 0) {
|
|
258
|
+
return { verdict: "pass", category: pass[0][0], reason: `\u547D\u4E2D\u300C${pass[0][1]}\u300D` };
|
|
259
|
+
}
|
|
260
|
+
return { verdict: "buffer", category: "\u672A\u5206\u7C7B", reason: "\u6CA1\u6709\u547D\u4E2D\u653E\u884C\u6216\u4E22\u5F03\u89C4\u5219" };
|
|
261
|
+
}
|
|
262
|
+
var MemoryDigest = class {
|
|
263
|
+
items = [];
|
|
264
|
+
cap;
|
|
265
|
+
constructor(cap = 200) {
|
|
266
|
+
this.cap = cap;
|
|
267
|
+
}
|
|
268
|
+
push(key, value, d) {
|
|
269
|
+
this.items.push({ key, value, category: d.category, reason: d.reason, at: Date.now() });
|
|
270
|
+
while (this.items.length > this.cap) this.items.shift();
|
|
271
|
+
return this.items.length;
|
|
272
|
+
}
|
|
273
|
+
size() {
|
|
274
|
+
return this.items.length;
|
|
275
|
+
}
|
|
276
|
+
/** 攒够时间就把同一类的拼成一句,返回一条摘要;没有可传的就返回 null。 */
|
|
277
|
+
buildDigest(now = Date.now()) {
|
|
278
|
+
if (this.items.length === 0) return null;
|
|
279
|
+
const byCat = /* @__PURE__ */ new Map();
|
|
280
|
+
for (const it of this.items) {
|
|
281
|
+
const list = byCat.get(it.category) ?? [];
|
|
282
|
+
list.push(it);
|
|
283
|
+
byCat.set(it.category, list);
|
|
284
|
+
}
|
|
285
|
+
const parts = [];
|
|
286
|
+
for (const [cat, list] of byCat) {
|
|
287
|
+
const uniq = dedupe(list.map((x) => `${x.key}\uFF1A${x.value}`));
|
|
288
|
+
parts.push(`\u3010${cat}\u3011${uniq.slice(0, 6).join("\uFF1B")}`);
|
|
289
|
+
}
|
|
290
|
+
const day = new Date(now).toISOString().slice(0, 10);
|
|
291
|
+
return { key: `\u8FD1\u51B5\u6458\u8981 ${day}`, sentence: parts.join(" ") };
|
|
292
|
+
}
|
|
293
|
+
drain() {
|
|
294
|
+
const out = this.items;
|
|
295
|
+
this.items = [];
|
|
296
|
+
return out;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
function dedupe(lines) {
|
|
300
|
+
const seen = /* @__PURE__ */ new Set();
|
|
301
|
+
const out = [];
|
|
302
|
+
for (const line of lines) {
|
|
303
|
+
const k = line.replace(/\s+/g, "");
|
|
304
|
+
if (seen.has(k)) continue;
|
|
305
|
+
seen.add(k);
|
|
306
|
+
out.push(line);
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
function audit(rows, opts = {}) {
|
|
311
|
+
const keepDays = opts.keepDays ?? 30;
|
|
312
|
+
const now = Date.now();
|
|
313
|
+
const seen = /* @__PURE__ */ new Map();
|
|
314
|
+
const out = [];
|
|
315
|
+
for (const row of rows) {
|
|
316
|
+
const content = (row.content || "").trim();
|
|
317
|
+
if (!content) {
|
|
318
|
+
out.push({ id: row.id, verdict: "delete", why: "\u7A7A\u5185\u5BB9" });
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (/(紫月月|口令|暗号|深夜模式|猫耳|外搭)/.test(content)) {
|
|
322
|
+
out.push({ id: row.id, verdict: "delete", why: "\u6D89\u53CA\u5DF2\u64A4\u9500\u7684\u529F\u80FD" });
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (/(已安装|已重启|loaded=|退出码|端口|pnpm|lockfile)/i.test(content)) {
|
|
326
|
+
out.push({ id: row.id, verdict: "delete", why: "\u64CD\u4F5C\u56DE\u6267/\u6280\u672F\u6D41\u6C34" });
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const norm = content.replace(/[\s,。,.!?!?…::;;、「」“”()()【】]/g, "").slice(0, 30);
|
|
330
|
+
const prev = seen.get(norm);
|
|
331
|
+
if (prev) {
|
|
332
|
+
out.push({ id: row.id, verdict: "merge", why: `\u4E0E\u524D\u4E00\u6761\u91CD\u590D\uFF08${prev}\uFF09` });
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
seen.set(norm, row.id);
|
|
336
|
+
const created = row.created_at ? Date.parse(row.created_at) : Number.NaN;
|
|
337
|
+
if (Number.isFinite(created) && now - created > keepDays * 864e5 && /(今天|昨天|刚才|还剩)/.test(content)) {
|
|
338
|
+
out.push({ id: row.id, verdict: "delete", why: `\u8D85\u8FC7 ${keepDays} \u5929\u7684\u4E00\u6B21\u6027\u63CF\u8FF0` });
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
out.push({ id: row.id, verdict: "keep", why: "\u50CF\u957F\u671F\u4E8B\u5B9E" });
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
}
|
|
345
|
+
|
|
218
346
|
// src/honcho.ts
|
|
219
347
|
var TIMEOUT_MS = 12e3;
|
|
220
348
|
var Honcho = class {
|
|
@@ -283,20 +411,20 @@ var Honcho = class {
|
|
|
283
411
|
query,
|
|
284
412
|
limit
|
|
285
413
|
});
|
|
286
|
-
const
|
|
414
|
+
const hits2 = [];
|
|
287
415
|
const push = (item, source) => {
|
|
288
416
|
if (typeof item === "string") {
|
|
289
|
-
|
|
417
|
+
hits2.push({ text: item, source });
|
|
290
418
|
return;
|
|
291
419
|
}
|
|
292
420
|
if (!item || typeof item !== "object") return;
|
|
293
421
|
const row = item;
|
|
294
422
|
const text = [row.content, row.text, row.conclusion, row.observation].find((v) => typeof v === "string" && v.trim().length > 0);
|
|
295
|
-
if (text)
|
|
423
|
+
if (text) hits2.push({ text: text.trim(), source: String(row.session_id || row.type || source) });
|
|
296
424
|
};
|
|
297
425
|
const list = Array.isArray(raw) ? raw : raw.results || raw.messages || raw.conclusions || [];
|
|
298
426
|
for (const item of list) push(item, "\u7ED3\u8BBA");
|
|
299
|
-
return
|
|
427
|
+
return hits2.slice(0, limit);
|
|
300
428
|
}
|
|
301
429
|
/** 让 Honcho 用自己的推理回答一个关于主人的问题(慢,但更“懂”)。 */
|
|
302
430
|
async ask(question) {
|
|
@@ -664,14 +792,14 @@ var Hands = class {
|
|
|
664
792
|
if (!query) return [];
|
|
665
793
|
const ui = await this.eyes.ui();
|
|
666
794
|
if (!ui.ok) throw new HandError(ui.error ?? "\u8BFB\u4E0D\u5230\u5C4F\u5E55\u4E0A\u7684\u5B57\u3002");
|
|
667
|
-
const
|
|
795
|
+
const hits2 = [];
|
|
668
796
|
for (const item of ui.items) {
|
|
669
797
|
if (!item.center) continue;
|
|
670
798
|
if (!item.text.toLowerCase().includes(query)) continue;
|
|
671
|
-
|
|
672
|
-
if (
|
|
799
|
+
hits2.push({ text: item.text, center: item.center });
|
|
800
|
+
if (hits2.length >= 20) break;
|
|
673
801
|
}
|
|
674
|
-
return
|
|
802
|
+
return hits2;
|
|
675
803
|
}
|
|
676
804
|
/** 手势令牌:文件里有就用它;读不到就是空(服务那边也不校验)。 */
|
|
677
805
|
tokenCache = { value: "", at: 0 };
|
|
@@ -1175,6 +1303,17 @@ var HANDS_TOOL_DECLS = [
|
|
|
1175
1303
|
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",
|
|
1176
1304
|
parameters: { type: "object", properties: {}, required: [] }
|
|
1177
1305
|
},
|
|
1306
|
+
{
|
|
1307
|
+
name: "memory_audit",
|
|
1308
|
+
tags: ["read"],
|
|
1309
|
+
description: "\u8BB0\u5FC6\u4F53\u68C0\uFF08\u53EA\u8BFB\uFF09\uFF1A\u628A\u4E91\u7AEF\u957F\u671F\u8BB0\u5FC6\u626B\u4E00\u904D\uFF0C\u5217\u51FA\u91CD\u590D/\u8FC7\u671F/\u50CF\u6D41\u6C34\u7684\u6761\u76EE\uFF0C\u53EA\u7ED9\u6E05\u5355\uFF0C\u4E0D\u5220\u4EFB\u4F55\u4E1C\u897F\u3002",
|
|
1310
|
+
parameters: {
|
|
1311
|
+
type: "object",
|
|
1312
|
+
properties: {
|
|
1313
|
+
cloud: { type: "boolean", description: "true \u8868\u793A\u8FDE\u4E91\u7AEF\u4E00\u8D77\u67E5\uFF08\u9700\u8981 Honcho \u5DF2\u914D\u7F6E\uFF09\u3002" }
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1178
1317
|
{
|
|
1179
1318
|
name: "unlock_pages",
|
|
1180
1319
|
tags: ["act"],
|
|
@@ -1356,6 +1495,8 @@ var HandsWorld = class {
|
|
|
1356
1495
|
return await this.unlockPages(args);
|
|
1357
1496
|
case "memory_save":
|
|
1358
1497
|
return await this.memorySave(args);
|
|
1498
|
+
case "memory_audit":
|
|
1499
|
+
return await this.memoryAudit(args);
|
|
1359
1500
|
case "memory_search":
|
|
1360
1501
|
return await this.memorySearch(args);
|
|
1361
1502
|
case "memory_forget":
|
|
@@ -1416,13 +1557,44 @@ var HandsWorld = class {
|
|
|
1416
1557
|
const r = await this.hands.unlockPages(page, Math.max(1, Math.min(60, minutes)));
|
|
1417
1558
|
return r.ok ? `\u6253\u5F00\u4E86\uFF08${page}\uFF09\uFF0C\u4FDD\u6301 ${minutes} \u5206\u949F\u3002` : failed(`\u6CA1\u6253\u5F00\uFF1A${r.detail || "\u624B\u6CA1\u54CD\u5E94"}`);
|
|
1418
1559
|
}
|
|
1560
|
+
digest = new MemoryDigest();
|
|
1561
|
+
digestTimer = null;
|
|
1562
|
+
/** 第二道闸:暂存区每 10 分钟聚合成一条摘要上传,回执类直接丢。 */
|
|
1563
|
+
startDigestLoop() {
|
|
1564
|
+
if (this.digestTimer) return;
|
|
1565
|
+
this.digestTimer = setInterval(() => {
|
|
1566
|
+
void this.flushDigest();
|
|
1567
|
+
}, 10 * 60 * 1e3);
|
|
1568
|
+
}
|
|
1569
|
+
async flushDigest() {
|
|
1570
|
+
const honcho = this.honcho();
|
|
1571
|
+
const built = this.digest.buildDigest();
|
|
1572
|
+
if (!built) return "";
|
|
1573
|
+
this.digest.drain();
|
|
1574
|
+
if (!honcho.configured) return "";
|
|
1575
|
+
try {
|
|
1576
|
+
await honcho.remember(built.sentence);
|
|
1577
|
+
return built.key;
|
|
1578
|
+
} catch {
|
|
1579
|
+
return "";
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1419
1582
|
async memorySave(args) {
|
|
1420
1583
|
const key = typeof args.key === "string" ? args.key.trim() : "";
|
|
1421
1584
|
const value = typeof args.value === "string" ? args.value.trim() : "";
|
|
1422
1585
|
if (!key || !value) return failed("\u8981 key \u548C value\u3002");
|
|
1423
1586
|
const tags = typeof args.tags === "string" ? args.tags : void 0;
|
|
1587
|
+
const decision = classify(key, value);
|
|
1424
1588
|
const r = await this.hands.memorySave(key, value, tags);
|
|
1425
1589
|
if (!r.ok) return failed(`\u6CA1\u8BB0\u4F4F\uFF1A${r.detail || "\u624B\u6CA1\u54CD\u5E94"}`);
|
|
1590
|
+
this.startDigestLoop();
|
|
1591
|
+
if (decision.verdict === "drop") {
|
|
1592
|
+
return `\u672C\u5730\u8BB0\u4E0B\u4E86\u300C${key}\u300D\uFF0C\u4F46\u8FD9\u6761\u50CF${decision.category}\uFF08${decision.reason}\uFF09\uFF0C\u4E0D\u4E0A\u4E91\u3002`;
|
|
1593
|
+
}
|
|
1594
|
+
if (decision.verdict === "buffer") {
|
|
1595
|
+
const n = this.digest.push(key, value, decision);
|
|
1596
|
+
return `\u672C\u5730\u8BB0\u4E0B\u4E86\u300C${key}\u300D\uFF0C\u5148\u653E\u6682\u5B58\u533A\uFF08${decision.reason}\uFF0C\u5DF2\u5B58 ${n} \u6761\uFF09\uFF0C10 \u5206\u949F\u805A\u5408\u6210\u4E00\u6761\u518D\u4E0A\u4F20\u3002`;
|
|
1597
|
+
}
|
|
1426
1598
|
let cloud = "";
|
|
1427
1599
|
const honcho = this.honcho();
|
|
1428
1600
|
if (honcho.configured) {
|
|
@@ -1435,6 +1607,22 @@ var HandsWorld = class {
|
|
|
1435
1607
|
}
|
|
1436
1608
|
return `\u8BB0\u7262\u4E86\uFF1A\u300C${key}\u300D\u2192 ${value}${cloud}`;
|
|
1437
1609
|
}
|
|
1610
|
+
/** 第三道闸:只读体检,出清单不删。 */
|
|
1611
|
+
async memoryAudit(args) {
|
|
1612
|
+
const rows = await this.hands.memorySearch();
|
|
1613
|
+
const local = rows.map((r) => ({ id: r.key, content: `${r.key}\uFF1A${r.value}`, created_at: r.ts }));
|
|
1614
|
+
const findings = audit(local.map((r) => ({ id: r.id, content: r.content, created_at: r.created_at })));
|
|
1615
|
+
const del = findings.filter((f) => f.verdict === "delete");
|
|
1616
|
+
const merge = findings.filter((f) => f.verdict === "merge");
|
|
1617
|
+
const lines = [
|
|
1618
|
+
`\u672C\u5730\u8BB0\u5FC6 ${findings.length} \u6761\uFF1A\u5EFA\u8BAE\u5220 ${del.length}\uFF0C\u5EFA\u8BAE\u5408\u5E76 ${merge.length}\uFF0C\u5176\u4F59\u4FDD\u7559\u3002`,
|
|
1619
|
+
...del.slice(0, 20).map((f) => `\u5220 ${f.id}\uFF08${f.why}\uFF09`),
|
|
1620
|
+
...merge.slice(0, 20).map((f) => `\u5E76 ${f.id}\uFF08${f.why}\uFF09`),
|
|
1621
|
+
"\u4E91\u7AEF\u90A3\u4EFD\u8981\u5355\u72EC\u8DD1\uFF08\u8FD9\u91CC\u53EA\u8BFB\u672C\u5730\uFF09\u3002"
|
|
1622
|
+
];
|
|
1623
|
+
if (args.cloud === true) lines.push("\uFF08\u4E91\u7AEF\u4F53\u68C0\u6211\u8FD9\u8FB9\u8FD8\u6CA1\u63A5\uFF0C\u5148\u7ED9\u672C\u5730\u7684\u3002\uFF09");
|
|
1624
|
+
return lines.join("\n");
|
|
1625
|
+
}
|
|
1438
1626
|
async memorySearch(args) {
|
|
1439
1627
|
const query = typeof args.query === "string" ? args.query.trim() : "";
|
|
1440
1628
|
const rows = await this.hands.memorySearch(query);
|
|
@@ -1444,8 +1632,8 @@ var HandsWorld = class {
|
|
|
1444
1632
|
const honcho = this.honcho();
|
|
1445
1633
|
if (honcho.configured && query) {
|
|
1446
1634
|
try {
|
|
1447
|
-
const
|
|
1448
|
-
cloudHits =
|
|
1635
|
+
const hits2 = await honcho.search(query);
|
|
1636
|
+
cloudHits = hits2.map((h) => `- ${h.text}`);
|
|
1449
1637
|
if (cloudHits.length > 0) cloudNote = `
|
|
1450
1638
|
|
|
1451
1639
|
Honcho \u8865\u5145 ${cloudHits.length} \u6761\uFF1A`;
|
|
@@ -1535,22 +1723,22 @@ ${lines || "\uFF08\u90FD\u5212\u6389\u4E86\uFF09"}`;
|
|
|
1535
1723
|
async tap(args) {
|
|
1536
1724
|
const text = typeof args.text === "string" ? args.text.trim() : "";
|
|
1537
1725
|
if (text) {
|
|
1538
|
-
const
|
|
1539
|
-
if (
|
|
1726
|
+
const hits2 = await this.hands.findText(text);
|
|
1727
|
+
if (hits2.length === 0) return failed(`\u5C4F\u5E55\u4E0A\u6CA1\u627E\u5230\u300C${text}\u300D\uFF0C\u5148 hand_look \u770B\u770B\u73B0\u5728\u662F\u4EC0\u4E48\u753B\u9762\u3002`);
|
|
1540
1728
|
const nth = args.nth === void 0 ? void 0 : Math.max(0, Math.round(Number(args.nth)));
|
|
1541
1729
|
if (nth === void 0) {
|
|
1542
|
-
if (
|
|
1543
|
-
const list =
|
|
1544
|
-
return failed(`\u300C${text}\u300D\u5728\u5C4F\u5E55\u4E0A\u6709 ${
|
|
1730
|
+
if (hits2.length > 1) {
|
|
1731
|
+
const list = hits2.slice(0, 8).map((h, i) => `${i}. \u300C${h.text}\u300D@(${h.center.x},${h.center.y})`).join("\n");
|
|
1732
|
+
return failed(`\u300C${text}\u300D\u5728\u5C4F\u5E55\u4E0A\u6709 ${hits2.length} \u5904\uFF0C\u8BF4\u6E05\u695A\u70B9\u54EA\u4E2A\uFF08nth\uFF09\uFF1A
|
|
1545
1733
|
${list}`);
|
|
1546
1734
|
}
|
|
1547
|
-
const only =
|
|
1735
|
+
const only = hits2[0];
|
|
1548
1736
|
const receipt3 = await this.hands.tap(only.center.x, only.center.y);
|
|
1549
1737
|
this.note(receipt3);
|
|
1550
1738
|
return `${receipt3.text}\uFF08\u70B9\u7684\u662F\u300C${only.text}\u300D\uFF09`;
|
|
1551
1739
|
}
|
|
1552
|
-
const hit =
|
|
1553
|
-
if (!hit) return failed(`\u300C${text}\u300D\u53EA\u6709 ${
|
|
1740
|
+
const hit = hits2[nth];
|
|
1741
|
+
if (!hit) return failed(`\u300C${text}\u300D\u53EA\u6709 ${hits2.length} \u5904\uFF0C\u6CA1\u6709\u7B2C ${nth} \u4E2A\u3002`);
|
|
1554
1742
|
const receipt2 = await this.hands.tap(hit.center.x, hit.center.y);
|
|
1555
1743
|
this.note(receipt2);
|
|
1556
1744
|
return `${receipt2.text}\uFF08\u70B9\u7684\u662F\u300C${hit.text}\u300D\uFF09`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|