finch-ego-lite 0.1.4 → 0.2.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/README.md CHANGED
@@ -33,12 +33,12 @@ Task spaces are isolated from your everyday browser windows while still being ab
33
33
 
34
34
  ## Get started
35
35
 
36
- 1. Install and launch [Ego Lite](https://lite.ego.app/) on macOS. Ego Lite is a browser designed for collaboration between people and AI Agents, and provides the web environment used by this mini tool.
37
- 2. Enable this mini tool in Finch.
36
+ 1. Install and launch [Ego Lite](https://lite.ego.app/) on macOS or Windows. Ego Lite is a browser designed for collaboration between people and AI Agents, and provides the web environment used by this mini tool.
37
+ 2. Finish Ego Lite's first-time setup so it registers the `ego-browser` command, then enable this mini tool in Finch. If Finch was already running while you installed Ego Lite, restart Finch so it picks up the new command.
38
38
  3. Tell Finch which website to visit and what you want done.
39
39
  4. Use the Ego button beside the Composer to follow progress, open pages, or take control.
40
40
 
41
- > Ego Lite currently supports macOS only. On Windows or Linux, this mini tool explains that the platform is not supported and provides a link to the Ego Lite website for future updates.
41
+ > Ego Lite currently runs on macOS and Windows. On other platforms, this mini tool explains that the platform is not supported and provides a link to the Ego Lite website.
42
42
 
43
43
  ## About Finch
44
44
 
@@ -83,12 +83,12 @@ Finch 会在 Ego Lite 的独立任务空间中打开网页。你不需要学习
83
83
 
84
84
  ## 开始使用
85
85
 
86
- 1. 在 macOS 上安装并启动 [Ego Lite](https://lite.ego.app/)。Ego Lite 是专为人与 AI Agent 协作设计的浏览器,也是本小工具连接网页的运行环境。
87
- 2. 在 Finch 中启用本小工具。
86
+ 1. 在 macOS 或 Windows 上安装并启动 [Ego Lite](https://lite.ego.app/)。Ego Lite 是专为人与 AI Agent 协作设计的浏览器,也是本小工具连接网页的运行环境。
87
+ 2. 完成 Ego Lite 的首次引导,让它注册 `ego-browser` 命令,然后在 Finch 中启用本小工具。如果安装 Ego Lite 时 Finch 已经开着,重启一次 Finch 才能读到新命令。
88
88
  3. 直接告诉 Finch 想访问的网站和要完成的事情。
89
89
  4. 通过输入框旁的 Ego 按钮查看进度、打开页面或接管操作。
90
90
 
91
- > Ego Lite 目前仅支持 macOS。在 Windows 或 Linux 上,本小工具会显示平台暂不支持,并提供 Ego Lite 官网入口了解后续进展。
91
+ > Ego Lite 目前可在 macOS 和 Windows 上运行。其他平台上,本小工具会提示平台暂不支持,并提供 Ego Lite 官网入口。
92
92
 
93
93
  ## 关于 Finch
94
94
 
package/dist/index.js CHANGED
@@ -2,21 +2,59 @@
2
2
  import { execFile } from "node:child_process";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
- import { join } from "node:path";
5
+ import { delimiter, join } from "node:path";
6
6
  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();
12
+ var SUPPORTED_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "win32"]);
13
+ function isSupportedPlatform() {
14
+ return SUPPORTED_PLATFORMS.has(process.platform);
15
+ }
16
+ function localBinDir() {
17
+ return join(homedir(), ".local", "bin");
18
+ }
11
19
  function egoBinary() {
12
- const local = join(homedir(), ".local", "bin", "ego-browser");
13
- if (existsSync(local)) return local;
20
+ const names = process.platform === "win32" ? ["ego-browser.exe", "ego-browser"] : ["ego-browser"];
21
+ for (const name of names) {
22
+ const local = join(localBinDir(), name);
23
+ if (existsSync(local)) return local;
24
+ }
14
25
  return "ego-browser";
15
26
  }
27
+ function egoAppPath() {
28
+ if (process.platform !== "win32") return void 0;
29
+ const env = process.env;
30
+ const roots = [
31
+ env.ProgramFiles,
32
+ env["ProgramFiles(x86)"],
33
+ env.LOCALAPPDATA ? join(env.LOCALAPPDATA, "Programs") : void 0,
34
+ env.LOCALAPPDATA
35
+ ].filter((root) => Boolean(root));
36
+ const layouts = [
37
+ ["Citro Labs", "ego lite", "Application", "ego.exe"],
38
+ ["ego lite", "Application", "ego.exe"],
39
+ ["Citro Labs", "ego lite", "ego.exe"],
40
+ ["ego lite", "ego.exe"]
41
+ ];
42
+ for (const root of roots) {
43
+ for (const layout of layouts) {
44
+ const candidate = join(root, ...layout);
45
+ if (existsSync(candidate)) return candidate;
46
+ }
47
+ }
48
+ return void 0;
49
+ }
16
50
  async function processRunning() {
17
- if (process.platform !== "darwin") return false;
51
+ if (!isSupportedPlatform()) return false;
18
52
  const probe = async () => {
19
53
  try {
54
+ if (process.platform === "win32") {
55
+ const { stdout } = await execFileAsync("tasklist", ["/FI", "IMAGENAME eq ego.exe", "/NH"], { timeout: 3e3 });
56
+ return /\bego\.exe\b/i.test(stdout);
57
+ }
20
58
  await execFileAsync("pgrep", ["-f", "/ego lite.app/Contents/MacOS/ego lite"], { timeout: 2e3 });
21
59
  return true;
22
60
  } catch {
@@ -33,7 +71,7 @@ async function runCommand(file, args, timeout = 2e4) {
33
71
  const child = execFile(file, args, {
34
72
  timeout,
35
73
  maxBuffer: 10 * 1024 * 1024,
36
- env: { ...process.env, PATH: `${join(homedir(), ".local", "bin")}:${process.env.PATH ?? ""}` }
74
+ env: { ...process.env, PATH: `${localBinDir()}${delimiter}${process.env.PATH ?? ""}` }
37
75
  }, (error, stdout, stderr) => {
38
76
  const output = [stdout, stderr].filter(Boolean).join("\n").trim();
39
77
  if (error) {
@@ -56,6 +94,26 @@ async function installedVersion(binary) {
56
94
  return void 0;
57
95
  }
58
96
  }
97
+ var VERSION_TTL = 5 * 6e4;
98
+ var cachedVersion;
99
+ async function probeVersion(binary) {
100
+ if (cachedVersion && Date.now() - cachedVersion.at < VERSION_TTL) return cachedVersion.value;
101
+ const value = await installedVersion(binary);
102
+ if (value) cachedVersion = { value, at: Date.now() };
103
+ return value;
104
+ }
105
+ async function probeInstall(binary, running) {
106
+ const version = running && cachedVersion?.value || await probeVersion(binary);
107
+ return { installed: running || Boolean(version), version };
108
+ }
109
+ async function waitForRunning(deadlineMs = 12e3) {
110
+ const until = Date.now() + deadlineMs;
111
+ for (; ; ) {
112
+ if (await processRunning()) return true;
113
+ if (Date.now() >= until) return false;
114
+ await new Promise((resolve) => setTimeout(resolve, 400));
115
+ }
116
+ }
59
117
  function statusScript(detailed) {
60
118
  return `
61
119
  const spaces = await listTaskSpaces();
@@ -94,15 +152,14 @@ function parseSpaces(output) {
94
152
  return JSON.parse(json);
95
153
  }
96
154
  async function getStatus(detailed = false) {
97
- if (process.platform !== "darwin") {
155
+ if (!isSupportedPlatform()) {
98
156
  return { supported: false, installed: false, running: false, spaces: [], pageCount: 0 };
99
157
  }
100
158
  const binary = egoBinary();
101
- if (!binary) return { supported: true, installed: false, running: false, spaces: [], pageCount: 0 };
102
- const version = await installedVersion(binary);
103
- if (!version) return { supported: true, installed: false, running: false, spaces: [], pageCount: 0 };
104
159
  const running = await processRunning();
105
- if (!running) return { supported: true, installed: true, running: false, version, spaces: [], pageCount: 0 };
160
+ const { installed, version } = await probeInstall(binary, running);
161
+ const base = { supported: true, installed, running, version, spaces: [], pageCount: 0 };
162
+ if (!running || !version) return base;
106
163
  try {
107
164
  const output = await runCommand(binary, ["nodejs", "-e", statusScript(detailed)], 1e4);
108
165
  const spaces = parseSpaces(output);
@@ -110,27 +167,57 @@ async function getStatus(detailed = false) {
110
167
  if (space.tabs) return sum + space.tabs.length;
111
168
  return sum + (space.recentTabTitles?.length ?? 0);
112
169
  }, 0);
113
- return { supported: true, installed: true, running: true, version, spaces, pageCount };
170
+ return { ...base, spaces, pageCount };
114
171
  } catch (error) {
115
172
  return {
116
- supported: true,
117
- installed: true,
118
- running: true,
119
- version,
120
- spaces: [],
121
- pageCount: 0,
173
+ ...base,
122
174
  error: error instanceof Error ? error.message : String(error)
123
175
  };
124
176
  }
125
177
  }
178
+ async function probeStatus(previous) {
179
+ if (!isSupportedPlatform()) {
180
+ return { supported: false, installed: false, running: false, spaces: [], pageCount: 0 };
181
+ }
182
+ const running = await processRunning();
183
+ const { installed, version } = await probeInstall(egoBinary(), running);
184
+ return {
185
+ supported: true,
186
+ installed,
187
+ running,
188
+ version: version ?? previous?.version,
189
+ // A cached space list is meaningless once the process is gone.
190
+ spaces: running ? previous?.spaces ?? [] : [],
191
+ pageCount: running ? previous?.pageCount ?? 0 : 0
192
+ };
193
+ }
126
194
  async function launchEgo() {
127
- if (process.platform !== "darwin") throw new Error("Ego Lite currently supports macOS only.");
128
- await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 });
195
+ if (process.platform === "darwin") {
196
+ await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 });
197
+ return;
198
+ }
199
+ if (process.platform === "win32") {
200
+ const exe = egoAppPath();
201
+ if (!exe) {
202
+ throw new Error(`The ego lite app was not found on this PC. Open it from the Start menu, or reinstall it from ${WEBSITE}.`);
203
+ }
204
+ await execFileAsync("cmd", ["/c", "start", "", exe], { timeout: 5e3 });
205
+ return;
206
+ }
207
+ throw new Error(`Ego Lite does not run on this platform (${process.platform}).`);
129
208
  }
130
209
  async function focusEgo() {
131
- if (process.platform !== "darwin") return;
132
- await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 }).catch(() => {
133
- });
210
+ if (process.platform === "darwin") {
211
+ await execFileAsync("open", ["-a", "ego lite"], { timeout: 5e3 }).catch(() => {
212
+ });
213
+ return;
214
+ }
215
+ if (process.platform === "win32") {
216
+ const exe = egoAppPath();
217
+ if (!exe) return;
218
+ await execFileAsync("cmd", ["/c", "start", "", exe], { timeout: 5e3 }).catch(() => {
219
+ });
220
+ }
134
221
  }
135
222
  async function openWebsite() {
136
223
  const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
@@ -299,19 +386,45 @@ function activate(ctx) {
299
386
  }
300
387
  }));
301
388
  let cachedStatus;
302
- let lastRefreshAt = 0;
389
+ let lastDetailAt = 0;
390
+ let offlineMisses = 0;
391
+ let recheckTimer;
303
392
  let refreshInFlight;
304
393
  let pendingDetailedRefresh = false;
394
+ const isOnline = (status) => status?.installed === true && status.running === true;
395
+ const publishStatus = (next, detailed) => {
396
+ if (isOnline(cachedStatus) && !isOnline(next) && offlineMisses + 1 < OFFLINE_CONFIRMATIONS) {
397
+ offlineMisses += 1;
398
+ if (!recheckTimer) {
399
+ recheckTimer = setTimeout(() => {
400
+ recheckTimer = void 0;
401
+ void refreshStatus(false);
402
+ }, 600);
403
+ }
404
+ return;
405
+ }
406
+ const previousOnline = isOnline(cachedStatus);
407
+ const same = JSON.stringify(cachedStatus ?? null) === JSON.stringify(next);
408
+ offlineMisses = 0;
409
+ cachedStatus = next;
410
+ if (detailed) lastDetailAt = Date.now();
411
+ if (previousOnline !== isOnline(next)) {
412
+ ctx.logger.info("Ego online state changed", {
413
+ online: isOnline(next),
414
+ running: next.running,
415
+ installed: next.installed,
416
+ version: next.version,
417
+ error: next.error
418
+ });
419
+ }
420
+ if (!same) action.notifyUpdate();
421
+ };
305
422
  const refreshStatus = (detailed = false) => {
306
423
  if (refreshInFlight) {
307
424
  if (detailed) pendingDetailedRefresh = true;
308
425
  return refreshInFlight;
309
426
  }
310
- refreshInFlight = getStatus(detailed).then((status) => {
311
- cachedStatus = status;
312
- lastRefreshAt = Date.now();
313
- action.notifyUpdate();
314
- }).catch((error) => ctx.logger.warn("Ego background status refresh failed", error)).finally(() => {
427
+ refreshInFlight = (detailed ? getStatus(true) : probeStatus(cachedStatus)).then((status) => publishStatus(status, detailed)).catch((error) => ctx.logger.warn("Ego background status refresh failed", error)).finally(() => {
315
428
  refreshInFlight = void 0;
316
429
  if (pendingDetailedRefresh) {
317
430
  pendingDetailedRefresh = false;
@@ -322,12 +435,11 @@ function activate(ctx) {
322
435
  };
323
436
  const action = ctx.composerActions.register("ego-browser", {
324
437
  async getBadge() {
325
- const online = cachedStatus?.installed === true && cachedStatus.running === true && !cachedStatus.error;
326
438
  if (cachedStatus?.supported === false) return { text: t("badge.unsupported"), active: false };
327
- return online ? { text: t("badge.online"), active: true } : { text: t("badge.offline"), active: false };
439
+ return isOnline(cachedStatus) ? { text: t("badge.online"), active: true } : { text: t("badge.offline"), active: false };
328
440
  },
329
441
  async getMenu() {
330
- if (cachedStatus === void 0 || Date.now() - lastRefreshAt > 3e3) {
442
+ if (cachedStatus === void 0 || Date.now() - lastDetailAt > 3e3) {
331
443
  await refreshStatus(true);
332
444
  }
333
445
  if (!cachedStatus) {
@@ -394,6 +506,9 @@ function activate(ctx) {
394
506
  id: "__summary__",
395
507
  label: t("menu.summary.spaces", { count: status.spaces.length }),
396
508
  description: t("menu.summary.pages", { count: status.pageCount }),
509
+ // When the space read fails while Ego is up, say so here instead of
510
+ // showing an empty list with no explanation.
511
+ hoverText: status.error ? t("status.error", { error: status.error }) : void 0,
397
512
  iconName: "ext:ego-browser-icons/compass",
398
513
  disabled: true
399
514
  }, {
@@ -472,7 +587,7 @@ ${domainOf(tab.url, t("site.unknown"))}`,
472
587
  await ctx.ui.showToast({ title: t("toast.launched"), variant: "success", position: "TC" });
473
588
  cachedStatus = void 0;
474
589
  action.notifyUpdate();
475
- refreshStatus(true);
590
+ void waitForRunning().then(() => refreshStatus(true));
476
591
  return;
477
592
  }
478
593
  if (itemId.startsWith("resume:")) {
@@ -497,13 +612,14 @@ ${domainOf(tab.url, t("site.unknown"))}`,
497
612
  const script = `const result = await completeTaskSpace(${JSON.stringify(spaceId)}, { keep: false }); cliLog(JSON.stringify(result));`;
498
613
  await runCommand(binary, ["nodejs", "-e", script], 15e3);
499
614
  action.notifyUpdate();
500
- refreshStatus(true);
615
+ refreshStatus(false);
501
616
  await ctx.ui.showToast({ title: t("toast.closed"), variant: "success", position: "TC" });
502
617
  return;
503
618
  }
504
619
  if (itemId.startsWith("tab:")) {
505
620
  const [spaceId, targetId] = unkey(itemId.slice("tab:".length));
506
621
  await launchEgo();
622
+ if (!await waitForRunning()) throw new Error(t("error.launchTimeout"));
507
623
  const binary = egoBinary();
508
624
  const script = `await switchTaskSpace(${JSON.stringify(spaceId)}); await switchTab(${JSON.stringify(targetId)}); cliLog('ok');`;
509
625
  await runCommand(binary, ["nodejs", "-e", script], 1e4);
@@ -566,8 +682,7 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
566
682
  const actionName = request.action ?? "";
567
683
  if (actionName === "status") {
568
684
  const status = await getStatus(true);
569
- cachedStatus = status;
570
- action.notifyUpdate();
685
+ publishStatus(status, true);
571
686
  return { content: [{ type: "text", text: statusText(status, t) }], isError: !status.supported || Boolean(status.error) };
572
687
  }
573
688
  if (!ACTION_STAGES[actionName]) {
@@ -596,14 +711,14 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
596
711
  if (actionName === "switch_tab" && !request.target_id) {
597
712
  return { content: [{ type: "text", text: "action=switch_tab requires target_id from action=status." }], isError: true };
598
713
  }
599
- if (process.platform !== "darwin") {
714
+ if (!isSupportedPlatform()) {
600
715
  return { content: [{ type: "text", text: t("status.unsupported", { platform: process.platform }) }], isError: true };
601
716
  }
602
717
  const binary = egoBinary();
603
- const version = binary ? await installedVersion(binary) : void 0;
604
- if (!binary || !version) {
718
+ const version = await probeVersion(binary);
719
+ if (!version && !await processRunning()) {
605
720
  return {
606
- content: [{ type: "text", text: `Ego Lite is not installed. Install it from ${WEBSITE}, finish onboarding, then retry.` }],
721
+ content: [{ type: "text", text: t("status.notInstalled", { website: WEBSITE }) }],
607
722
  isError: true
608
723
  };
609
724
  }
@@ -620,7 +735,9 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
620
735
  if (!await processRunning()) {
621
736
  exec.progress.report({ stage: "launching", message: pickProgress(t, "launching") });
622
737
  await launchEgo();
623
- await new Promise((resolve) => setTimeout(resolve, 1800));
738
+ if (!await waitForRunning()) {
739
+ return { content: [{ type: "text", text: t("error.launchTimeout") }], isError: true };
740
+ }
624
741
  } else {
625
742
  await focusEgo();
626
743
  }
@@ -629,8 +746,7 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
629
746
  exec.progress.report({ stage: ACTION_STAGES[actionName], message: pickProgress(t, ACTION_STAGES[actionName] ?? "browsing") });
630
747
  try {
631
748
  const output = await runCommand(binary, ["nodejs", "-e", script], timeout);
632
- action.notifyUpdate();
633
- refreshStatus(true);
749
+ refreshStatus(false);
634
750
  if (actionName === "screenshot") {
635
751
  const path = output.split("__EGO_SHOT__").pop()?.split("\n")[0]?.trim();
636
752
  if (!path || !existsSync(path)) {
@@ -646,15 +762,14 @@ Reuse task spaces, respect user ownership, verify meaningful actions, and comple
646
762
  }
647
763
  return { content: [{ type: "text", text: output || "ok" }] };
648
764
  } catch (error) {
649
- action.notifyUpdate();
650
- refreshStatus(true);
765
+ refreshStatus(false);
651
766
  const message = error instanceof Error ? error.message : String(error);
652
767
  return { content: [{ type: "text", text: message }], isError: true };
653
768
  }
654
769
  }
655
770
  }));
656
771
  refreshStatus(true);
657
- const timer = setInterval(() => refreshStatus(true), 5e3);
772
+ const timer = setInterval(() => refreshStatus(false), 5e3);
658
773
  ctx.subscriptions.push({ dispose: () => clearInterval(timer) });
659
774
  ctx.logger.info("ego-browser mini tool activated", { cached: Boolean(cachedStatus) });
660
775
  }
package/i18n/en-US.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "badge": {
14
14
  "online": "Ego online",
15
15
  "offline": "Ego offline",
16
- "unsupported": "macOS only"
16
+ "unsupported": "Not supported"
17
17
  },
18
18
  "menu": {
19
19
  "checking": {
@@ -27,9 +27,9 @@
27
27
  "label": "Learn about Ego Lite"
28
28
  },
29
29
  "unsupported": {
30
- "label": "Ego Lite requires macOS",
30
+ "label": "Ego Lite needs macOS or Windows",
31
31
  "description": "This device is not supported",
32
- "hover": "Ego Lite currently runs on macOS only. Current platform: {platform}."
32
+ "hover": "Ego Lite currently runs on macOS and Windows. Current platform: {platform}."
33
33
  },
34
34
  "install": {
35
35
  "label": "Install Ego Lite",
@@ -72,7 +72,7 @@
72
72
  "user": "User control"
73
73
  },
74
74
  "status": {
75
- "unsupported": "Ego Lite currently supports macOS only. Current platform: {platform}.",
75
+ "unsupported": "Ego Lite currently supports macOS and Windows. Current platform: {platform}.",
76
76
  "notInstalled": "Ego Lite is not installed. Install it from {website} and finish first-time setup.",
77
77
  "notRunning": "Ego Lite {version} is installed but not running.",
78
78
  "error": "Ego Lite is running, but its status could not be read: {error}"
@@ -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…",
package/i18n/zh-CN.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "badge": {
14
14
  "online": "Ego 在线",
15
15
  "offline": "Ego 离线",
16
- "unsupported": "仅支持 macOS"
16
+ "unsupported": "平台不支持"
17
17
  },
18
18
  "menu": {
19
19
  "checking": {
@@ -27,9 +27,9 @@
27
27
  "label": "了解 Ego Lite"
28
28
  },
29
29
  "unsupported": {
30
- "label": "Ego Lite 仅支持 macOS",
30
+ "label": "Ego Lite 支持 macOS 与 Windows",
31
31
  "description": "当前设备暂不可用",
32
- "hover": "Ego Lite 目前只能在 macOS 上运行。当前平台:{platform}。"
32
+ "hover": "Ego Lite 目前可在 macOS 和 Windows 上运行。当前平台:{platform}。"
33
33
  },
34
34
  "install": {
35
35
  "label": "安装 Ego Lite",
@@ -72,7 +72,7 @@
72
72
  "user": "用户控制"
73
73
  },
74
74
  "status": {
75
- "unsupported": "Ego Lite 目前仅支持 macOS。当前平台:{platform}。",
75
+ "unsupported": "Ego Lite 目前支持 macOS 和 Windows。当前平台:{platform}。",
76
76
  "notInstalled": "Ego Lite 未安装。请从 {website} 安装并完成首次引导。",
77
77
  "notRunning": "Ego Lite 已安装({version}),当前未运行。",
78
78
  "error": "Ego Lite 正在运行,但状态读取失败:{error}"
@@ -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 正在伸懒腰…",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "finch-ego-lite",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Let Finch browse the web in isolated Ego Lite task spaces while you follow every page it opens.",
5
5
  "author": {
6
6
  "name": "PuterJam",
@@ -21,6 +21,7 @@
21
21
  "scripts": {
22
22
  "build": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node18 --outfile=dist/index.js",
23
23
  "typecheck": "tsc --noEmit",
24
+ "smoke": "node tools/smoke.mjs",
24
25
  "prepublishOnly": "npm run typecheck && npm run build && npx @finchtoys/minitools doctor ."
25
26
  },
26
27
  "finch": {