finch-ego-lite 0.1.3 → 0.1.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 +145 -54
- package/i18n/en-US.json +3 -1
- package/i18n/zh-CN.json +3 -1
- package/package.json +1 -1
- package/skills/ego-browser/SKILL.md +2 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { promisify } from "node:util";
|
|
|
7
7
|
var execFileAsync = promisify(execFile);
|
|
8
8
|
var WEBSITE = "https://lite.ego.app/";
|
|
9
9
|
var STATUS_MARKER = "__EGO_STATUS__";
|
|
10
|
+
var OFFLINE_CONFIRMATIONS = 2;
|
|
10
11
|
var commandQueue = Promise.resolve();
|
|
11
12
|
function egoBinary() {
|
|
12
13
|
const local = join(homedir(), ".local", "bin", "ego-browser");
|
|
@@ -15,12 +16,18 @@ function egoBinary() {
|
|
|
15
16
|
}
|
|
16
17
|
async function processRunning() {
|
|
17
18
|
if (process.platform !== "darwin") return false;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
const probe = async () => {
|
|
20
|
+
try {
|
|
21
|
+
await execFileAsync("pgrep", ["-f", "/ego lite.app/Contents/MacOS/ego lite"], { timeout: 2e3 });
|
|
22
|
+
return true;
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const first = await probe();
|
|
28
|
+
if (first) return true;
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
30
|
+
return probe();
|
|
24
31
|
}
|
|
25
32
|
async function runCommand(file, args, timeout = 2e4) {
|
|
26
33
|
const execute = () => new Promise((resolve, reject) => {
|
|
@@ -50,6 +57,26 @@ async function installedVersion(binary) {
|
|
|
50
57
|
return void 0;
|
|
51
58
|
}
|
|
52
59
|
}
|
|
60
|
+
var VERSION_TTL = 5 * 6e4;
|
|
61
|
+
var cachedVersion;
|
|
62
|
+
async function probeVersion(binary) {
|
|
63
|
+
if (cachedVersion && Date.now() - cachedVersion.at < VERSION_TTL) return cachedVersion.value;
|
|
64
|
+
const value = await installedVersion(binary);
|
|
65
|
+
if (value) cachedVersion = { value, at: Date.now() };
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
async function probeInstall(binary, running) {
|
|
69
|
+
const version = running && cachedVersion?.value || await probeVersion(binary);
|
|
70
|
+
return { installed: running || Boolean(version), version };
|
|
71
|
+
}
|
|
72
|
+
async function waitForRunning(deadlineMs = 12e3) {
|
|
73
|
+
const until = Date.now() + deadlineMs;
|
|
74
|
+
for (; ; ) {
|
|
75
|
+
if (await processRunning()) return true;
|
|
76
|
+
if (Date.now() >= until) return false;
|
|
77
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
53
80
|
function statusScript(detailed) {
|
|
54
81
|
return `
|
|
55
82
|
const spaces = await listTaskSpaces();
|
|
@@ -92,11 +119,10 @@ async function getStatus(detailed = false) {
|
|
|
92
119
|
return { supported: false, installed: false, running: false, spaces: [], pageCount: 0 };
|
|
93
120
|
}
|
|
94
121
|
const binary = egoBinary();
|
|
95
|
-
if (!binary) return { supported: true, installed: false, running: false, spaces: [], pageCount: 0 };
|
|
96
|
-
const version = await installedVersion(binary);
|
|
97
|
-
if (!version) return { supported: true, installed: false, running: false, spaces: [], pageCount: 0 };
|
|
98
122
|
const running = await processRunning();
|
|
99
|
-
|
|
123
|
+
const { installed, version } = await probeInstall(binary, running);
|
|
124
|
+
const base = { supported: true, installed, running, version, spaces: [], pageCount: 0 };
|
|
125
|
+
if (!running || !version) return base;
|
|
100
126
|
try {
|
|
101
127
|
const output = await runCommand(binary, ["nodejs", "-e", statusScript(detailed)], 1e4);
|
|
102
128
|
const spaces = parseSpaces(output);
|
|
@@ -104,23 +130,39 @@ async function getStatus(detailed = false) {
|
|
|
104
130
|
if (space.tabs) return sum + space.tabs.length;
|
|
105
131
|
return sum + (space.recentTabTitles?.length ?? 0);
|
|
106
132
|
}, 0);
|
|
107
|
-
return {
|
|
133
|
+
return { ...base, spaces, pageCount };
|
|
108
134
|
} catch (error) {
|
|
109
135
|
return {
|
|
110
|
-
|
|
111
|
-
installed: true,
|
|
112
|
-
running: true,
|
|
113
|
-
version,
|
|
114
|
-
spaces: [],
|
|
115
|
-
pageCount: 0,
|
|
136
|
+
...base,
|
|
116
137
|
error: error instanceof Error ? error.message : String(error)
|
|
117
138
|
};
|
|
118
139
|
}
|
|
119
140
|
}
|
|
141
|
+
async function probeStatus(previous) {
|
|
142
|
+
if (process.platform !== "darwin") {
|
|
143
|
+
return { supported: false, installed: false, running: false, spaces: [], pageCount: 0 };
|
|
144
|
+
}
|
|
145
|
+
const running = await processRunning();
|
|
146
|
+
const { installed, version } = await probeInstall(egoBinary(), running);
|
|
147
|
+
return {
|
|
148
|
+
supported: true,
|
|
149
|
+
installed,
|
|
150
|
+
running,
|
|
151
|
+
version: version ?? previous?.version,
|
|
152
|
+
// A cached space list is meaningless once the process is gone.
|
|
153
|
+
spaces: running ? previous?.spaces ?? [] : [],
|
|
154
|
+
pageCount: running ? previous?.pageCount ?? 0 : 0
|
|
155
|
+
};
|
|
156
|
+
}
|
|
120
157
|
async function launchEgo() {
|
|
121
158
|
if (process.platform !== "darwin") throw new Error("Ego Lite currently supports macOS only.");
|
|
122
159
|
await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 });
|
|
123
160
|
}
|
|
161
|
+
async function focusEgo() {
|
|
162
|
+
if (process.platform !== "darwin") return;
|
|
163
|
+
await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 }).catch(() => {
|
|
164
|
+
});
|
|
165
|
+
}
|
|
124
166
|
async function openWebsite() {
|
|
125
167
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
126
168
|
const args = process.platform === "win32" ? ["/c", "start", "", WEBSITE] : [WEBSITE];
|
|
@@ -136,6 +178,7 @@ var ACTION_STAGES = {
|
|
|
136
178
|
press_key: "acting",
|
|
137
179
|
scroll: "scrolling",
|
|
138
180
|
screenshot: "shooting",
|
|
181
|
+
switch_tab: "switching",
|
|
139
182
|
close_space: "closing",
|
|
140
183
|
run: "running"
|
|
141
184
|
};
|
|
@@ -159,7 +202,14 @@ function buildScript(action, input, spaceId) {
|
|
|
159
202
|
case "open_url": {
|
|
160
203
|
const name = input.space_name || "web task";
|
|
161
204
|
const timeout = input.timeout_seconds ?? 20;
|
|
205
|
+
if (spaceId !== void 0) {
|
|
206
|
+
return `await switchTaskSpace(${spaceId});
|
|
207
|
+
await openOrReuseTab(${q(input.url ?? "")}, { wait: true, timeout: ${timeout} });
|
|
208
|
+
const tab = await currentTab();
|
|
209
|
+
cliLog(JSON.stringify({ spaceId: ${spaceId}, url: tab.url, title: tab.title }));`;
|
|
210
|
+
}
|
|
162
211
|
return `const space = await useOrCreateTaskSpace(${q(name)});
|
|
212
|
+
await switchTaskSpace(space.id);
|
|
163
213
|
await openOrReuseTab(${q(input.url ?? "")}, { wait: true, timeout: ${timeout} });
|
|
164
214
|
const tab = await currentTab();
|
|
165
215
|
cliLog(JSON.stringify({ spaceId: space.id, url: tab.url, title: tab.title }));`;
|
|
@@ -206,6 +256,12 @@ cliLog(JSON.stringify({ ok: true, sy: info.sy }));`;
|
|
|
206
256
|
return `${spaceLine}
|
|
207
257
|
const path = await captureScreenshot();
|
|
208
258
|
cliLog('__EGO_SHOT__' + path);`;
|
|
259
|
+
case "switch_tab":
|
|
260
|
+
return `await switchTaskSpace(${spaceId});
|
|
261
|
+
await switchTab(${q(input.target_id ?? "")});
|
|
262
|
+
await waitForLoad({ timeout: 15 }).catch(() => {});
|
|
263
|
+
const info = await pageInfo();
|
|
264
|
+
cliLog(JSON.stringify({ ok: true, spaceId: ${spaceId}, url: info.url, title: info.title }));`;
|
|
209
265
|
case "close_space":
|
|
210
266
|
return `await completeTaskSpace(${spaceId}, { keep: false });
|
|
211
267
|
cliLog('ok');`;
|
|
@@ -274,18 +330,62 @@ function activate(ctx) {
|
|
|
274
330
|
}
|
|
275
331
|
}));
|
|
276
332
|
let cachedStatus;
|
|
333
|
+
let lastDetailAt = 0;
|
|
334
|
+
let offlineMisses = 0;
|
|
335
|
+
let recheckTimer;
|
|
277
336
|
let refreshInFlight;
|
|
278
337
|
let pendingDetailedRefresh = false;
|
|
279
|
-
|
|
338
|
+
const isOnline = (status) => status?.installed === true && status.running === true;
|
|
339
|
+
const publishStatus = (next, detailed) => {
|
|
340
|
+
if (isOnline(cachedStatus) && !isOnline(next) && offlineMisses + 1 < OFFLINE_CONFIRMATIONS) {
|
|
341
|
+
offlineMisses += 1;
|
|
342
|
+
if (!recheckTimer) {
|
|
343
|
+
recheckTimer = setTimeout(() => {
|
|
344
|
+
recheckTimer = void 0;
|
|
345
|
+
void refreshStatus(false);
|
|
346
|
+
}, 600);
|
|
347
|
+
}
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const previousOnline = isOnline(cachedStatus);
|
|
351
|
+
const same = JSON.stringify(cachedStatus ?? null) === JSON.stringify(next);
|
|
352
|
+
offlineMisses = 0;
|
|
353
|
+
cachedStatus = next;
|
|
354
|
+
if (detailed) lastDetailAt = Date.now();
|
|
355
|
+
if (previousOnline !== isOnline(next)) {
|
|
356
|
+
ctx.logger.info("Ego online state changed", {
|
|
357
|
+
online: isOnline(next),
|
|
358
|
+
running: next.running,
|
|
359
|
+
installed: next.installed,
|
|
360
|
+
version: next.version,
|
|
361
|
+
error: next.error
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
if (!same) action.notifyUpdate();
|
|
365
|
+
};
|
|
366
|
+
const refreshStatus = (detailed = false) => {
|
|
367
|
+
if (refreshInFlight) {
|
|
368
|
+
if (detailed) pendingDetailedRefresh = true;
|
|
369
|
+
return refreshInFlight;
|
|
370
|
+
}
|
|
371
|
+
refreshInFlight = (detailed ? getStatus(true) : probeStatus(cachedStatus)).then((status) => publishStatus(status, detailed)).catch((error) => ctx.logger.warn("Ego background status refresh failed", error)).finally(() => {
|
|
372
|
+
refreshInFlight = void 0;
|
|
373
|
+
if (pendingDetailedRefresh) {
|
|
374
|
+
pendingDetailedRefresh = false;
|
|
375
|
+
refreshStatus(true);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
return refreshInFlight;
|
|
280
379
|
};
|
|
281
380
|
const action = ctx.composerActions.register("ego-browser", {
|
|
282
381
|
async getBadge() {
|
|
283
|
-
const online = cachedStatus?.installed === true && cachedStatus.running === true && !cachedStatus.error;
|
|
284
382
|
if (cachedStatus?.supported === false) return { text: t("badge.unsupported"), active: false };
|
|
285
|
-
return
|
|
383
|
+
return isOnline(cachedStatus) ? { text: t("badge.online"), active: true } : { text: t("badge.offline"), active: false };
|
|
286
384
|
},
|
|
287
385
|
async getMenu() {
|
|
288
|
-
|
|
386
|
+
if (cachedStatus === void 0 || Date.now() - lastDetailAt > 3e3) {
|
|
387
|
+
await refreshStatus(true);
|
|
388
|
+
}
|
|
289
389
|
if (!cachedStatus) {
|
|
290
390
|
return [{
|
|
291
391
|
id: "__checking__",
|
|
@@ -350,6 +450,9 @@ function activate(ctx) {
|
|
|
350
450
|
id: "__summary__",
|
|
351
451
|
label: t("menu.summary.spaces", { count: status.spaces.length }),
|
|
352
452
|
description: t("menu.summary.pages", { count: status.pageCount }),
|
|
453
|
+
// When the space read fails while Ego is up, say so here instead of
|
|
454
|
+
// showing an empty list with no explanation.
|
|
455
|
+
hoverText: status.error ? t("status.error", { error: status.error }) : void 0,
|
|
353
456
|
iconName: "ext:ego-browser-icons/compass",
|
|
354
457
|
disabled: true
|
|
355
458
|
}, {
|
|
@@ -428,7 +531,7 @@ ${domainOf(tab.url, t("site.unknown"))}`,
|
|
|
428
531
|
await ctx.ui.showToast({ title: t("toast.launched"), variant: "success", position: "TC" });
|
|
429
532
|
cachedStatus = void 0;
|
|
430
533
|
action.notifyUpdate();
|
|
431
|
-
refreshStatus(true);
|
|
534
|
+
void waitForRunning().then(() => refreshStatus(true));
|
|
432
535
|
return;
|
|
433
536
|
}
|
|
434
537
|
if (itemId.startsWith("resume:")) {
|
|
@@ -452,15 +555,15 @@ ${domainOf(tab.url, t("site.unknown"))}`,
|
|
|
452
555
|
if (!binary || !await installedVersion(binary)) throw new Error(t("error.notInstalled"));
|
|
453
556
|
const script = `const result = await completeTaskSpace(${JSON.stringify(spaceId)}, { keep: false }); cliLog(JSON.stringify(result));`;
|
|
454
557
|
await runCommand(binary, ["nodejs", "-e", script], 15e3);
|
|
455
|
-
cachedStatus = void 0;
|
|
456
558
|
action.notifyUpdate();
|
|
457
|
-
refreshStatus(
|
|
559
|
+
refreshStatus(false);
|
|
458
560
|
await ctx.ui.showToast({ title: t("toast.closed"), variant: "success", position: "TC" });
|
|
459
561
|
return;
|
|
460
562
|
}
|
|
461
563
|
if (itemId.startsWith("tab:")) {
|
|
462
564
|
const [spaceId, targetId] = unkey(itemId.slice("tab:".length));
|
|
463
565
|
await launchEgo();
|
|
566
|
+
if (!await waitForRunning()) throw new Error(t("error.launchTimeout"));
|
|
464
567
|
const binary = egoBinary();
|
|
465
568
|
const script = `await switchTaskSpace(${JSON.stringify(spaceId)}); await switchTab(${JSON.stringify(targetId)}); cliLog('ok');`;
|
|
466
569
|
await runCommand(binary, ["nodejs", "-e", script], 1e4);
|
|
@@ -492,6 +595,7 @@ action:
|
|
|
492
595
|
press_key \u2014 press a key: Enter, Tab, Escape, ArrowDown... (space_id?, key)
|
|
493
596
|
scroll \u2014 scroll down by pixels (space_id?, delta_y?)
|
|
494
597
|
screenshot \u2014 capture the page and return it as an image (space_id?)
|
|
598
|
+
switch_tab \u2014 switch to a task space and activate one of its pages (space_id, target_id from status)
|
|
495
599
|
extract \u2014 extract innerText of a CSS selector, or the whole page (space_id?, selector?)
|
|
496
600
|
close_space \u2014 close a task space (space_id)
|
|
497
601
|
run \u2014 advanced: run a raw Ego Browser script (script, timeout_seconds?)
|
|
@@ -500,10 +604,11 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
|
|
|
500
604
|
inputSchema: {
|
|
501
605
|
type: "object",
|
|
502
606
|
properties: {
|
|
503
|
-
action: { type: "string", enum: ["status", "open_url", "snapshot", "click", "fill", "type", "press_key", "scroll", "screenshot", "extract", "close_space", "run"] },
|
|
607
|
+
action: { type: "string", enum: ["status", "open_url", "snapshot", "click", "fill", "type", "press_key", "scroll", "screenshot", "switch_tab", "extract", "close_space", "run"] },
|
|
504
608
|
url: { type: "string", description: "URL to open (action=open_url)." },
|
|
505
609
|
space_id: { type: "number", description: "Task space id from status/open_url. Optional when only one agent space exists." },
|
|
506
610
|
space_name: { type: "string", description: "Semantic name for the task space (action=open_url)." },
|
|
611
|
+
target_id: { type: "string", description: "Tab target id from action=status (action=switch_tab)." },
|
|
507
612
|
selector: { type: "string", description: "CSS selector of the target element (click/fill/type/extract)." },
|
|
508
613
|
text: { type: "string", description: "Text to type (action=type)." },
|
|
509
614
|
value: { type: "string", description: "Value to fill into the field (action=fill)." },
|
|
@@ -514,15 +619,14 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
|
|
|
514
619
|
},
|
|
515
620
|
required: ["action"]
|
|
516
621
|
},
|
|
517
|
-
risk: "
|
|
622
|
+
risk: "medium",
|
|
518
623
|
defaultEnabled: true,
|
|
519
624
|
async execute(input, exec) {
|
|
520
625
|
const request = input;
|
|
521
626
|
const actionName = request.action ?? "";
|
|
522
627
|
if (actionName === "status") {
|
|
523
628
|
const status = await getStatus(true);
|
|
524
|
-
|
|
525
|
-
action.notifyUpdate();
|
|
629
|
+
publishStatus(status, true);
|
|
526
630
|
return { content: [{ type: "text", text: statusText(status, t) }], isError: !status.supported || Boolean(status.error) };
|
|
527
631
|
}
|
|
528
632
|
if (!ACTION_STAGES[actionName]) {
|
|
@@ -548,21 +652,24 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
|
|
|
548
652
|
if (actionName === "type" && !request.text) {
|
|
549
653
|
return { content: [{ type: "text", text: "action=type requires text." }], isError: true };
|
|
550
654
|
}
|
|
655
|
+
if (actionName === "switch_tab" && !request.target_id) {
|
|
656
|
+
return { content: [{ type: "text", text: "action=switch_tab requires target_id from action=status." }], isError: true };
|
|
657
|
+
}
|
|
551
658
|
if (process.platform !== "darwin") {
|
|
552
659
|
return { content: [{ type: "text", text: t("status.unsupported", { platform: process.platform }) }], isError: true };
|
|
553
660
|
}
|
|
554
661
|
const binary = egoBinary();
|
|
555
|
-
const version =
|
|
556
|
-
if (!
|
|
662
|
+
const version = await probeVersion(binary);
|
|
663
|
+
if (!version && !await processRunning()) {
|
|
557
664
|
return {
|
|
558
665
|
content: [{ type: "text", text: `Ego Lite is not installed. Install it from ${WEBSITE}, finish onboarding, then retry.` }],
|
|
559
666
|
isError: true
|
|
560
667
|
};
|
|
561
668
|
}
|
|
562
669
|
let spaceId;
|
|
563
|
-
if (actionName !== "
|
|
670
|
+
if (actionName !== "run") {
|
|
564
671
|
spaceId = await resolveSpaceId(request.space_id);
|
|
565
|
-
if (spaceId === void 0) {
|
|
672
|
+
if (spaceId === void 0 && actionName !== "open_url") {
|
|
566
673
|
return {
|
|
567
674
|
content: [{ type: "text", text: "No task space resolved. Call action=status or action=open_url first, then pass its space_id." }],
|
|
568
675
|
isError: true
|
|
@@ -572,15 +679,17 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
|
|
|
572
679
|
if (!await processRunning()) {
|
|
573
680
|
exec.progress.report({ stage: "launching", message: pickProgress(t, "launching") });
|
|
574
681
|
await launchEgo();
|
|
575
|
-
|
|
682
|
+
if (!await waitForRunning()) {
|
|
683
|
+
return { content: [{ type: "text", text: t("error.launchTimeout") }], isError: true };
|
|
684
|
+
}
|
|
685
|
+
} else {
|
|
686
|
+
await focusEgo();
|
|
576
687
|
}
|
|
577
688
|
const script = buildScript(actionName, request, spaceId);
|
|
578
689
|
const timeout = Math.min(300, Math.max(1, request.timeout_seconds ?? 60)) * 1e3;
|
|
579
690
|
exec.progress.report({ stage: ACTION_STAGES[actionName], message: pickProgress(t, ACTION_STAGES[actionName] ?? "browsing") });
|
|
580
691
|
try {
|
|
581
692
|
const output = await runCommand(binary, ["nodejs", "-e", script], timeout);
|
|
582
|
-
cachedStatus = void 0;
|
|
583
|
-
action.notifyUpdate();
|
|
584
693
|
refreshStatus(false);
|
|
585
694
|
if (actionName === "screenshot") {
|
|
586
695
|
const path = output.split("__EGO_SHOT__").pop()?.split("\n")[0]?.trim();
|
|
@@ -597,32 +706,14 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
|
|
|
597
706
|
}
|
|
598
707
|
return { content: [{ type: "text", text: output || "ok" }] };
|
|
599
708
|
} catch (error) {
|
|
600
|
-
cachedStatus = void 0;
|
|
601
|
-
action.notifyUpdate();
|
|
602
709
|
refreshStatus(false);
|
|
603
710
|
const message = error instanceof Error ? error.message : String(error);
|
|
604
711
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
605
712
|
}
|
|
606
713
|
}
|
|
607
714
|
}));
|
|
608
|
-
refreshStatus = (detailed = false) => {
|
|
609
|
-
if (refreshInFlight) {
|
|
610
|
-
pendingDetailedRefresh ||= detailed;
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
refreshInFlight = getStatus(detailed).then((status) => {
|
|
614
|
-
cachedStatus = status;
|
|
615
|
-
action.notifyUpdate();
|
|
616
|
-
}).catch((error) => ctx.logger.warn("Ego background status refresh failed", error)).finally(() => {
|
|
617
|
-
refreshInFlight = void 0;
|
|
618
|
-
if (pendingDetailedRefresh) {
|
|
619
|
-
pendingDetailedRefresh = false;
|
|
620
|
-
refreshStatus(true);
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
};
|
|
624
715
|
refreshStatus(true);
|
|
625
|
-
const timer = setInterval(() => refreshStatus(
|
|
716
|
+
const timer = setInterval(() => refreshStatus(false), 5e3);
|
|
626
717
|
ctx.subscriptions.push({ dispose: () => clearInterval(timer) });
|
|
627
718
|
ctx.logger.info("ego-browser mini tool activated", { cached: Boolean(cachedStatus) });
|
|
628
719
|
}
|
package/i18n/en-US.json
CHANGED
|
@@ -95,7 +95,8 @@
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"error": {
|
|
98
|
-
"notInstalled": "Ego Browser is not installed"
|
|
98
|
+
"notInstalled": "Ego Browser is not installed",
|
|
99
|
+
"launchTimeout": "Ego Lite was launched but is not ready yet. Wait a moment and try again."
|
|
99
100
|
},
|
|
100
101
|
"progress": {
|
|
101
102
|
"launching": "Waking up Ego Browser…|Pouring a coffee for the browser…|Ego is stretching…",
|
|
@@ -104,6 +105,7 @@
|
|
|
104
105
|
"acting": "Clicking gently…|Tapping the button…|Filling things in…",
|
|
105
106
|
"scrolling": "Scrolling down…|Rolling the wheel…",
|
|
106
107
|
"shooting": "Saying cheese! 📸|Freezing the moment…",
|
|
108
|
+
"switching": "Switching windows…|Jumping to another page…|Ego is changing its view…",
|
|
107
109
|
"closing": "Tidying up…|Closing the tab circus…|Wrapping up…",
|
|
108
110
|
"running": "Ego is doing its thing…|Browser magic in progress…",
|
|
109
111
|
"browsing": "Agent is working in Ego Browser…"
|
package/i18n/zh-CN.json
CHANGED
|
@@ -95,7 +95,8 @@
|
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
97
|
"error": {
|
|
98
|
-
"notInstalled": "Ego Browser 未安装"
|
|
98
|
+
"notInstalled": "Ego Browser 未安装",
|
|
99
|
+
"launchTimeout": "Ego Lite 已启动但还没就绪,请稍等片刻再试。"
|
|
99
100
|
},
|
|
100
101
|
"progress": {
|
|
101
102
|
"launching": "正在唤醒 Ego 浏览器…|给浏览器泡杯咖啡…|Ego 正在伸懒腰…",
|
|
@@ -104,6 +105,7 @@
|
|
|
104
105
|
"acting": "轻轻点了一下…|正在按下按钮…|正在填写…",
|
|
105
106
|
"scrolling": "正在往下滚动…|鼠标滚轮转起来了…",
|
|
106
107
|
"shooting": "咔嚓!拍照留念 📸|定格这一刻…",
|
|
108
|
+
"switching": "换个窗口看看…|跳到另一个页面…|Ego 正在切换视野…",
|
|
107
109
|
"closing": "正在收摊…|正在收拾战场…|任务完成,整理中…",
|
|
108
110
|
"running": "Ego 正在忙活…|浏览器魔法进行中…",
|
|
109
111
|
"browsing": "Agent 正在操作 Ego Browser…"
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: ego-browser
|
|
3
3
|
description: Use Ego Browser whenever the user needs to open a website, navigate pages, click, type, upload, take screenshots, extract page data, test web apps, log in, or automate browser actions. Ego gives Agents isolated task spaces that reuse the user's login state without competing with normal browser windows.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "0.1.
|
|
5
|
+
version: "0.1.3"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Ego Browser 工具使用指南
|
|
@@ -31,6 +31,7 @@ metadata:
|
|
|
31
31
|
| press_key | space_id?, key | 按键:Enter/Tab/Escape… |
|
|
32
32
|
| scroll | space_id?, delta_y? | 向下滚动(默认 300px) |
|
|
33
33
|
| screenshot | space_id? | 截图并作为图片返回 |
|
|
34
|
+
| switch_tab | space_id, target_id | 先切到任务空间,再激活其中某个页面(target_id 来自 status 的 tabs) |
|
|
34
35
|
| extract | space_id?, selector? | 提取区域 innerText 或整页文本 |
|
|
35
36
|
| close_space | space_id | 关闭任务空间 |
|
|
36
37
|
| run | script, timeout_seconds? | 高级:执行原始 Ego 脚本 |
|