@rynx-ai/daemon 0.1.9 → 0.1.10-beta.2
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/app-browser-host-supervisor.d.ts +97 -0
- package/dist/app-browser-host-supervisor.js +529 -0
- package/dist/browser-artifact-management.d.ts +20 -0
- package/dist/browser-artifact-management.js +61 -0
- package/dist/chrome-for-testing-store.js +1 -1
- package/dist/chrome-inspection-gateway.d.ts +58 -0
- package/dist/chrome-inspection-gateway.js +806 -0
- package/dist/chrome-inspection-manager.d.ts +94 -0
- package/dist/chrome-inspection-manager.js +573 -0
- package/dist/cli.js +13 -2
- package/dist/control-client.d.ts +9 -0
- package/dist/control-client.js +63 -0
- package/dist/daemon-build-status.d.ts +8 -0
- package/dist/daemon-build-status.js +18 -0
- package/dist/daemon-server.d.ts +19 -2
- package/dist/daemon-server.js +615 -59
- package/dist/db.js +56 -0
- package/dist/desktop-browser-host-client.d.ts +2 -1
- package/dist/desktop-browser-host-client.js +3 -1
- package/dist/direct-runtime-authenticator.js +11 -6
- package/dist/headless-browser-host.js +18 -1
- package/dist/index-daemon.js +28 -1
- package/dist/maintenance-management.d.ts +11 -0
- package/dist/maintenance-management.js +13 -0
- package/dist/plugin-installer.d.ts +35 -0
- package/dist/plugin-installer.js +195 -94
- package/dist/plugin-management-service.d.ts +58 -0
- package/dist/plugin-management-service.js +240 -0
- package/dist/plugin-package.d.ts +26 -3
- package/dist/plugin-package.js +235 -56
- package/dist/pm2.js +37 -5
- package/dist/remote-runtime-access-store.d.ts +1 -0
- package/dist/remote-runtime-access-store.js +7 -0
- package/dist/remote-runtime-admin.d.ts +3 -0
- package/dist/remote-runtime-admin.js +3 -0
- package/dist/remote-runtime-connection-manager.d.ts +12 -1
- package/dist/remote-runtime-connection-manager.js +170 -4
- package/dist/remote-runtime-target-control.d.ts +5 -1
- package/dist/remote-runtime-target-control.js +62 -7
- package/dist/remote-runtime-target-store.d.ts +4 -1
- package/dist/remote-runtime-target-store.js +21 -2
- package/dist/session-log-store.js +29 -0
- package/dist/session-meta-store.js +3 -1
- package/dist/session-pending-message-store.d.ts +2 -0
- package/dist/session-pending-message-store.js +41 -0
- package/dist/session-resource-store.d.ts +32 -0
- package/dist/session-resource-store.js +700 -0
- package/dist/setup.d.ts +16 -0
- package/dist/setup.js +136 -2
- package/package.json +14 -9
package/dist/setup.d.ts
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
+
type ControlListenMode = "loopback" | "host";
|
|
2
|
+
type ManagedBrowserSetupPlan = {
|
|
3
|
+
kind: "ready";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "unsupported";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "offer";
|
|
8
|
+
installByDefault: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function controlListenModeFromHost(host: unknown): ControlListenMode;
|
|
11
|
+
export declare function controlHostForListenMode(mode: ControlListenMode): "127.0.0.1" | "0.0.0.0";
|
|
12
|
+
export declare function managedBrowserSetupPlan(listenMode: ControlListenMode, browser: {
|
|
13
|
+
supported: boolean;
|
|
14
|
+
installed: boolean;
|
|
15
|
+
}): ManagedBrowserSetupPlan;
|
|
1
16
|
/** Walk the user through config.json step by step. Returns a process exit code. */
|
|
2
17
|
export declare function runSetup(): Promise<number>;
|
|
3
18
|
/** Read-only diagnostics. Returns a process exit code (0 ok, 1 on any failure). */
|
|
4
19
|
export declare function runDoctor(): Promise<number>;
|
|
20
|
+
export {};
|
package/dist/setup.js
CHANGED
|
@@ -15,11 +15,32 @@ import { join } from "node:path";
|
|
|
15
15
|
import * as p from "@clack/prompts";
|
|
16
16
|
import { AGENT_RUNTIME_IDS, getRuntimeProfile, listAgentSpecs, loadConfig, resolveRuntimeHome, rynxAgentsDir, rynxConfigFile, rynxHome, } from "@rynx-ai/core";
|
|
17
17
|
import { listChannels } from "./channel-store.js";
|
|
18
|
+
import { resolveChromeForTestingRelease } from "./chrome-for-testing-release-resolver.js";
|
|
19
|
+
import { createChromeForTestingArtifactStore, isChromeForTestingHostSupported, } from "./chrome-for-testing-store.js";
|
|
18
20
|
import { dbPath } from "./db.js";
|
|
19
21
|
import { listInstances } from "./instance-store.js";
|
|
20
22
|
import { isRunnablePluginRecord, listPlugins } from "./plugin-store.js";
|
|
21
23
|
import { formatControlUrl } from "./pm2.js";
|
|
22
24
|
const MIN_NODE_MAJOR = 20;
|
|
25
|
+
export function controlListenModeFromHost(host) {
|
|
26
|
+
const normalized = typeof host === "string" ? host.trim().replace(/^\[|\]$/g, "") : "";
|
|
27
|
+
return normalized === "" ||
|
|
28
|
+
normalized === "127.0.0.1" ||
|
|
29
|
+
normalized === "::1" ||
|
|
30
|
+
normalized.toLowerCase() === "localhost"
|
|
31
|
+
? "loopback"
|
|
32
|
+
: "host";
|
|
33
|
+
}
|
|
34
|
+
export function controlHostForListenMode(mode) {
|
|
35
|
+
return mode === "host" ? "0.0.0.0" : "127.0.0.1";
|
|
36
|
+
}
|
|
37
|
+
export function managedBrowserSetupPlan(listenMode, browser) {
|
|
38
|
+
if (!browser.supported)
|
|
39
|
+
return { kind: "unsupported" };
|
|
40
|
+
if (browser.installed)
|
|
41
|
+
return { kind: "ready" };
|
|
42
|
+
return { kind: "offer", installByDefault: listenMode === "host" };
|
|
43
|
+
}
|
|
23
44
|
// ── rynx setup — interactive wizard ─────────────────────────────────────────
|
|
24
45
|
/** Walk the user through config.json step by step. Returns a process exit code. */
|
|
25
46
|
export async function runSetup() {
|
|
@@ -27,8 +48,12 @@ export async function runSetup() {
|
|
|
27
48
|
// Non-interactive (CI / piped): never block on a prompt — just ensure defaults.
|
|
28
49
|
if (!existsSync(rynxConfigFile()))
|
|
29
50
|
writeConfig({ HOST: "127.0.0.1", PORT: 3000, LOG_LEVEL: "info" });
|
|
51
|
+
const browser = inspectManagedBrowser();
|
|
30
52
|
console.log(`非交互环境:已确保 ${rynxConfigFile()} 存在(默认值)。` +
|
|
31
|
-
"在终端(TTY)下重跑 `rynx setup` 可分步配置,或直接编辑该文件。"
|
|
53
|
+
"在终端(TTY)下重跑 `rynx setup` 可分步配置,或直接编辑该文件。" +
|
|
54
|
+
(browser.supported && !browser.installed
|
|
55
|
+
? "\nSession Browser 尚未安装;需要时运行 `rynx browser install`。"
|
|
56
|
+
: ""));
|
|
32
57
|
return 0;
|
|
33
58
|
}
|
|
34
59
|
p.intro("rynx setup · 配置 ~/.rynx");
|
|
@@ -81,15 +106,89 @@ export async function runSetup() {
|
|
|
81
106
|
if (p.isCancel(port))
|
|
82
107
|
return bail();
|
|
83
108
|
cfg.PORT = Number(port);
|
|
84
|
-
|
|
109
|
+
const listenMode = await p.select({
|
|
110
|
+
message: "控制台访问范围 HOST",
|
|
111
|
+
initialValue: controlListenModeFromHost(cfg.HOST),
|
|
112
|
+
options: [
|
|
113
|
+
{
|
|
114
|
+
value: "loopback",
|
|
115
|
+
label: "仅本机(Loopback,推荐)",
|
|
116
|
+
hint: "绑定 127.0.0.1",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
value: "host",
|
|
120
|
+
label: "网络访问(Host)",
|
|
121
|
+
hint: "绑定 0.0.0.0,可信网络可通过机器 IP 访问",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
if (p.isCancel(listenMode))
|
|
126
|
+
return bail();
|
|
127
|
+
cfg.HOST = controlHostForListenMode(listenMode);
|
|
85
128
|
cfg.LOG_LEVEL = cfg.LOG_LEVEL ?? "info";
|
|
129
|
+
const browserBeforeSetup = inspectManagedBrowser();
|
|
130
|
+
const browserPlan = managedBrowserSetupPlan(listenMode, {
|
|
131
|
+
supported: browserBeforeSetup.supported,
|
|
132
|
+
installed: Boolean(browserBeforeSetup.installed),
|
|
133
|
+
});
|
|
134
|
+
let installBrowser = false;
|
|
135
|
+
if (browserPlan.kind === "ready") {
|
|
136
|
+
p.log.success(`Session Browser 已就绪 · Chrome for Testing ${browserBeforeSetup.installed.version}`);
|
|
137
|
+
}
|
|
138
|
+
else if (browserPlan.kind === "unsupported") {
|
|
139
|
+
p.log.info(`当前平台 ${process.platform}-${process.arch} 不支持 managed Chrome for Testing;跳过 Browser 安装。`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
p.note([
|
|
143
|
+
"Session Browser 让 agent 在当前 Runtime 上打开和操作网页。",
|
|
144
|
+
listenMode === "host"
|
|
145
|
+
? "网络访问模式下,外部浏览器不能提供 Desktop Browser Host,因此推荐安装无头 Browser。"
|
|
146
|
+
: "桌面 App 可使用内置 Browser;独立 daemon 或远端 Runtime 仍需要无头 Browser。",
|
|
147
|
+
"安装会从 Chrome for Testing 官方源下载浏览器,不会改动系统浏览器。",
|
|
148
|
+
...(process.platform === "linux"
|
|
149
|
+
? ["Linux 的动态库和字体依赖仍需由系统或主机镜像提供。"]
|
|
150
|
+
: []),
|
|
151
|
+
].join("\n"), "Session Browser(可选)");
|
|
152
|
+
const choice = await p.confirm({
|
|
153
|
+
message: "现在安装 managed Chrome for Testing?",
|
|
154
|
+
initialValue: browserPlan.installByDefault,
|
|
155
|
+
});
|
|
156
|
+
if (p.isCancel(choice))
|
|
157
|
+
return bail();
|
|
158
|
+
installBrowser = choice;
|
|
159
|
+
}
|
|
86
160
|
writeConfig(cfg);
|
|
87
161
|
p.log.success(`已写入 ${rynxConfigFile()}(chmod 600)`);
|
|
88
162
|
p.log.message(`HOST=${cfg.HOST} PORT=${cfg.PORT} AGENT_RUNTIME=${cfg.AGENT_RUNTIME ?? "(默认)"}`);
|
|
163
|
+
let browserReady = browserPlan.kind === "ready";
|
|
164
|
+
if (installBrowser) {
|
|
165
|
+
const spinner = p.spinner();
|
|
166
|
+
spinner.start("准备安装 Stable Chrome for Testing");
|
|
167
|
+
try {
|
|
168
|
+
const release = await resolveChromeForTestingRelease({
|
|
169
|
+
kind: "channel",
|
|
170
|
+
channel: "Stable",
|
|
171
|
+
});
|
|
172
|
+
const installedBrowser = await createChromeForTestingArtifactStore().installResolved(release, { onProgress: (message) => spinner.message(message) });
|
|
173
|
+
browserReady = true;
|
|
174
|
+
spinner.stop(`Session Browser 已就绪 · Chrome for Testing ${installedBrowser.version}`);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
spinner.error("Session Browser 安装失败");
|
|
178
|
+
p.log.warn(`${error instanceof Error ? error.message : String(error)}\n` +
|
|
179
|
+
"配置已保存;修复网络或系统依赖后运行 `rynx browser install` 重试。");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else if (browserPlan.kind === "offer") {
|
|
183
|
+
p.log.info("已跳过 Browser 安装;需要时运行 `rynx browser install`。");
|
|
184
|
+
}
|
|
89
185
|
const url = formatControlUrl(String(cfg.HOST ?? "127.0.0.1"), Number(cfg.PORT ?? 3000));
|
|
90
186
|
p.note([
|
|
91
187
|
`启动常驻服务 rynx start`,
|
|
92
188
|
`打开控制台 ${url}`,
|
|
189
|
+
browserReady
|
|
190
|
+
? "Session Browser 已就绪"
|
|
191
|
+
: "启用 Browser rynx browser install",
|
|
93
192
|
`新建 agent rynx agent add <id>`,
|
|
94
193
|
`随时体检 rynx doctor`,
|
|
95
194
|
].join("\n"), "下一步");
|
|
@@ -158,6 +257,24 @@ export async function runDoctor() {
|
|
|
158
257
|
(p.log.warn("还没有 channel —— 在 Web 控制台新建并授权"), warn++);
|
|
159
258
|
}
|
|
160
259
|
p.log.info(`agent:${(await listAgentSpecs()).length} 个(${rynxAgentsDir()})`);
|
|
260
|
+
const browser = inspectManagedBrowser();
|
|
261
|
+
if (!browser.supported) {
|
|
262
|
+
p.log.info(`Session Browser:当前平台 ${process.platform}-${process.arch} 不受支持`);
|
|
263
|
+
}
|
|
264
|
+
else if (browser.installed) {
|
|
265
|
+
p.log.success(`Session Browser:Chrome for Testing ${browser.installed.version} 已安装`);
|
|
266
|
+
if (process.platform === "linux") {
|
|
267
|
+
p.log.info("Linux Browser 动态库和字体依赖由系统或主机镜像提供");
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else if (browser.error) {
|
|
271
|
+
p.log.warn(`Session Browser 安装无效:${browser.error} —— 运行 \`rynx browser install\` 修复`);
|
|
272
|
+
warn++;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
p.log.warn("Session Browser 未安装 —— 运行 `rynx browser install`");
|
|
276
|
+
warn++;
|
|
277
|
+
}
|
|
161
278
|
if (fail > 0) {
|
|
162
279
|
p.outro(`体检发现 ${fail} 个失败项(警告 ${warn})—— 处理后重跑 rynx doctor`);
|
|
163
280
|
return 1;
|
|
@@ -165,6 +282,23 @@ export async function runDoctor() {
|
|
|
165
282
|
p.outro(warn > 0 ? `基本就绪,有 ${warn} 个警告` : "全部通过 ✓");
|
|
166
283
|
return 0;
|
|
167
284
|
}
|
|
285
|
+
function inspectManagedBrowser() {
|
|
286
|
+
if (!isChromeForTestingHostSupported())
|
|
287
|
+
return { supported: false };
|
|
288
|
+
try {
|
|
289
|
+
return {
|
|
290
|
+
supported: true,
|
|
291
|
+
installed: createChromeForTestingArtifactStore().readActive(),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
return {
|
|
296
|
+
supported: true,
|
|
297
|
+
installed: undefined,
|
|
298
|
+
error: error instanceof Error ? error.message : String(error),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
}
|
|
168
302
|
function runtimeState(id) {
|
|
169
303
|
const profile = getRuntimeProfile(id);
|
|
170
304
|
const installed = onPath(profile.defaultBinary);
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/daemon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10-beta.2",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
7
|
+
"directory": "packages/daemon"
|
|
8
|
+
},
|
|
4
9
|
"description": "Rynx daemon CLI: supervises the local agent control plane and isolated optional plugin runtimes.",
|
|
5
10
|
"type": "module",
|
|
6
11
|
"publishConfig": {
|
|
@@ -22,18 +27,18 @@
|
|
|
22
27
|
},
|
|
23
28
|
"dependencies": {
|
|
24
29
|
"@clack/prompts": "^1.6.0",
|
|
25
|
-
"@electron-internal/extract-zip": "^1.0.4",
|
|
26
30
|
"better-sqlite3": "^12.11.1",
|
|
31
|
+
"extract-zip": "2.0.1",
|
|
27
32
|
"pm2": "^6.0.0",
|
|
28
33
|
"tar": "^7.5.19",
|
|
29
34
|
"ws": "^8.21.0",
|
|
30
|
-
"@rynx-ai/
|
|
31
|
-
"@rynx-ai/
|
|
32
|
-
"@rynx-ai/plugin-runner": "0.1.
|
|
33
|
-
"@rynx-ai/
|
|
34
|
-
"@rynx-ai/
|
|
35
|
-
"@rynx-ai/remote-runtime-client": "0.1.
|
|
36
|
-
"@rynx-ai/server": "0.1.
|
|
35
|
+
"@rynx-ai/core": "0.1.10-beta.2",
|
|
36
|
+
"@rynx-ai/emulator": "0.1.10-beta.2",
|
|
37
|
+
"@rynx-ai/plugin-runner": "0.1.10-beta.2",
|
|
38
|
+
"@rynx-ai/plugin-sdk": "0.1.10-beta.2",
|
|
39
|
+
"@rynx-ai/protocol": "0.1.10-beta.2",
|
|
40
|
+
"@rynx-ai/remote-runtime-client": "0.1.10-beta.2",
|
|
41
|
+
"@rynx-ai/server": "0.1.10-beta.2"
|
|
37
42
|
},
|
|
38
43
|
"devDependencies": {
|
|
39
44
|
"@types/ws": "^8.18.1"
|