@rynx-ai/daemon 0.1.11-beta.13 → 0.1.11-beta.15
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/bundled-plugins/plugins/lark/package.json +1 -1
- package/dist/browser-artifact-management.js +4 -1
- package/dist/chrome-for-testing-runtime.js +4 -3
- package/dist/chrome-for-testing-store.js +24 -2
- package/dist/plugin-cli.d.ts +10 -0
- package/dist/plugin-cli.js +17 -1
- package/dist/system-dependencies.js +2 -2
- package/package.json +13 -9
|
@@ -18,7 +18,6 @@ export function createBrowserArtifactManagementService(options = {}) {
|
|
|
18
18
|
kind: "channel",
|
|
19
19
|
channel: releaseChannel(input.channel ?? "stable"),
|
|
20
20
|
};
|
|
21
|
-
const resolved = await resolveRelease(selector, { signal: context.signal });
|
|
22
21
|
const messages = [];
|
|
23
22
|
let messageBytes = 0;
|
|
24
23
|
const onProgress = (message) => {
|
|
@@ -32,6 +31,10 @@ export function createBrowserArtifactManagementService(options = {}) {
|
|
|
32
31
|
messageBytes += bytes;
|
|
33
32
|
messages.push(bounded);
|
|
34
33
|
};
|
|
34
|
+
onProgress(selector.kind === "version"
|
|
35
|
+
? `正在解析 Chrome for Testing ${selector.version}`
|
|
36
|
+
: `正在解析 Chrome for Testing ${selector.channel} 通道版本`);
|
|
37
|
+
const resolved = await resolveRelease(selector, { signal: context.signal });
|
|
35
38
|
const installed = await artifactStore().installResolved(resolved, {
|
|
36
39
|
signal: context.signal,
|
|
37
40
|
onProgress,
|
|
@@ -76,9 +76,10 @@ export async function ensureChromeForTestingRuntime(build, options = {}) {
|
|
|
76
76
|
options.signal?.throwIfAborted();
|
|
77
77
|
return result;
|
|
78
78
|
};
|
|
79
|
+
options.onProgress?.(`正在校验 Chrome for Testing ${build.version} 运行环境`);
|
|
79
80
|
const initialProbe = await run(build.executablePath, ["--version"]);
|
|
80
81
|
if (initialProbe.exitCode === 0) {
|
|
81
|
-
options.onProgress?.(`
|
|
82
|
+
options.onProgress?.(`Chrome for Testing ${build.version} 运行校验通过`);
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
85
|
if ((options.platform ?? process.platform) !== "linux") {
|
|
@@ -113,7 +114,7 @@ export async function ensureChromeForTestingRuntime(build, options = {}) {
|
|
|
113
114
|
command = sudo;
|
|
114
115
|
args = ["-n", packageManager.path, ...installArgs];
|
|
115
116
|
}
|
|
116
|
-
options.onProgress?.(
|
|
117
|
+
options.onProgress?.(`正在安装 Chrome for Testing 系统依赖:${packages.join(" ")}`);
|
|
117
118
|
const installation = await run(command, args, INSTALL_TIMEOUT_MS);
|
|
118
119
|
if (installation.exitCode !== 0) {
|
|
119
120
|
throw new Error(`failed to install Chrome for Testing system dependencies (${packages.join(" ")}): ` +
|
|
@@ -122,7 +123,7 @@ export async function ensureChromeForTestingRuntime(build, options = {}) {
|
|
|
122
123
|
const finalProbe = await run(build.executablePath, ["--version"]);
|
|
123
124
|
if (finalProbe.exitCode !== 0)
|
|
124
125
|
throw browserLaunchError(build, finalProbe);
|
|
125
|
-
options.onProgress?.(`
|
|
126
|
+
options.onProgress?.(`Chrome for Testing ${build.version} 运行校验通过`);
|
|
126
127
|
}
|
|
127
128
|
export function parseMissingSharedLibraries(output) {
|
|
128
129
|
const libraries = new Set();
|
|
@@ -20,6 +20,8 @@ const STORE_LOCK_FILE = ".rynx-cft-store.sqlite";
|
|
|
20
20
|
const MAX_METADATA_BYTES = 8 * 1024;
|
|
21
21
|
const DEFAULT_MAX_ARCHIVE_BYTES = 1_024 * 1_024 * 1_024;
|
|
22
22
|
const DEFAULT_STAGING_MAX_AGE_MS = 24 * 60 * 60 * 1_000;
|
|
23
|
+
const DOWNLOAD_PROGRESS_PERCENT_STEP = 10;
|
|
24
|
+
const DOWNLOAD_PROGRESS_BYTES_STEP = 16 * 1_024 * 1_024;
|
|
23
25
|
const STAGING_NAME_PATTERN = /^install-([A-Za-z0-9]{6})$/;
|
|
24
26
|
const HEADLESS_PROFILE_NAME_PATTERN = /^session-([a-f0-9]{64})$/;
|
|
25
27
|
const VERSION_PATTERN = /^\d{1,6}\.\d{1,6}\.\d{1,6}\.\d{1,6}$/;
|
|
@@ -128,7 +130,7 @@ export function createChromeForTestingArtifactStore(options = {}) {
|
|
|
128
130
|
const archivePath = join(transactionDir, "artifact.zip");
|
|
129
131
|
const payloadPath = join(transactionDir, "payload");
|
|
130
132
|
try {
|
|
131
|
-
installOptions.onProgress?.(
|
|
133
|
+
installOptions.onProgress?.(`正在下载 Chrome for Testing ${release.version} (${release.platform})`);
|
|
132
134
|
const sha256 = await downloadArchive({
|
|
133
135
|
url: release.url,
|
|
134
136
|
expectedSha256,
|
|
@@ -136,6 +138,7 @@ export function createChromeForTestingArtifactStore(options = {}) {
|
|
|
136
138
|
fetchArtifact,
|
|
137
139
|
maxArchiveBytes,
|
|
138
140
|
signal: installOptions.signal,
|
|
141
|
+
onProgress: installOptions.onProgress,
|
|
139
142
|
});
|
|
140
143
|
throwIfAborted(installOptions.signal);
|
|
141
144
|
const build = { ...release, sha256 };
|
|
@@ -147,6 +150,7 @@ export function createChromeForTestingArtifactStore(options = {}) {
|
|
|
147
150
|
return existing;
|
|
148
151
|
}
|
|
149
152
|
mkdirOwnedDirectory(payloadPath, paths.root);
|
|
153
|
+
installOptions.onProgress?.(`正在解压 Chrome for Testing ${release.version} (${release.platform})`);
|
|
150
154
|
await extractZip(archivePath, payloadPath);
|
|
151
155
|
throwIfAborted(installOptions.signal);
|
|
152
156
|
validateExecutable(payloadPath, platform.executableRelativePath);
|
|
@@ -175,7 +179,7 @@ export function createChromeForTestingArtifactStore(options = {}) {
|
|
|
175
179
|
const installed = requireInstalledBuild(finalPath, paths.buildsRoot, platform, build);
|
|
176
180
|
await verifyBeforeActivate(installed);
|
|
177
181
|
writeActiveManifest(paths.root, installed);
|
|
178
|
-
installOptions.onProgress?.(`
|
|
182
|
+
installOptions.onProgress?.(`Chrome for Testing ${build.version} 已安装 (${build.sha256})`);
|
|
179
183
|
return installed;
|
|
180
184
|
}
|
|
181
185
|
finally {
|
|
@@ -459,6 +463,8 @@ async function downloadArchive(options) {
|
|
|
459
463
|
const hash = createHash("sha256");
|
|
460
464
|
const descriptor = openSync(options.destination, "wx", 0o600);
|
|
461
465
|
let bytes = 0;
|
|
466
|
+
let nextPercent = DOWNLOAD_PROGRESS_PERCENT_STEP;
|
|
467
|
+
let nextBytes = DOWNLOAD_PROGRESS_BYTES_STEP;
|
|
462
468
|
const reader = response.body.getReader();
|
|
463
469
|
try {
|
|
464
470
|
while (true) {
|
|
@@ -473,6 +479,19 @@ async function downloadArchive(options) {
|
|
|
473
479
|
}
|
|
474
480
|
hash.update(chunk);
|
|
475
481
|
writeAll(descriptor, chunk);
|
|
482
|
+
if (length !== undefined && length > 0) {
|
|
483
|
+
const completed = Math.min(100, Math.floor(bytes * 100 / length));
|
|
484
|
+
while (nextPercent <= completed) {
|
|
485
|
+
options.onProgress?.(`Chrome for Testing 下载进度:${nextPercent}%`);
|
|
486
|
+
nextPercent += DOWNLOAD_PROGRESS_PERCENT_STEP;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
while (nextBytes <= bytes) {
|
|
491
|
+
options.onProgress?.(`Chrome for Testing 已下载:${formatDownloadBytes(nextBytes)}`);
|
|
492
|
+
nextBytes += DOWNLOAD_PROGRESS_BYTES_STEP;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
476
495
|
}
|
|
477
496
|
}
|
|
478
497
|
finally {
|
|
@@ -485,6 +504,9 @@ async function downloadArchive(options) {
|
|
|
485
504
|
}
|
|
486
505
|
return actual;
|
|
487
506
|
}
|
|
507
|
+
function formatDownloadBytes(bytes) {
|
|
508
|
+
return `${Math.floor(bytes / (1_024 * 1_024))} MiB`;
|
|
509
|
+
}
|
|
488
510
|
function writeAll(descriptor, value) {
|
|
489
511
|
let offset = 0;
|
|
490
512
|
while (offset < value.byteLength) {
|
package/dist/plugin-cli.d.ts
CHANGED
|
@@ -20,6 +20,16 @@ export interface PluginCliCommandResult {
|
|
|
20
20
|
stderrTruncated: boolean;
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
export interface InstalledPluginListItem {
|
|
24
|
+
id: string;
|
|
25
|
+
version: string;
|
|
26
|
+
source: "local" | "git";
|
|
27
|
+
state: "enabled" | "disabled";
|
|
28
|
+
}
|
|
29
|
+
/** Read the durable installed-plugin inventory without contacting the daemon. */
|
|
30
|
+
export declare function listInstalledPlugins(): InstalledPluginListItem[];
|
|
31
|
+
/** Render manifest-declared command help without executing plugin code. */
|
|
32
|
+
export declare function installedPluginCommandUsage(pluginId: string): string;
|
|
23
33
|
/** Execute one statically declared, language-neutral plugin command. */
|
|
24
34
|
export declare function runPluginCliCommand(pluginId: string, args: readonly string[], options?: RunPluginCliOptions): Promise<PluginCliCommandResult>;
|
|
25
35
|
export declare function pluginCommandUsage(record: RunnablePluginRecord): string;
|
package/dist/plugin-cli.js
CHANGED
|
@@ -6,10 +6,26 @@ import { db } from "./db.js";
|
|
|
6
6
|
import { transaction } from "./sqlite.js";
|
|
7
7
|
import { pluginDataDir, pluginRuntimeCacheDir } from "./plugin-installer.js";
|
|
8
8
|
import { validatePluginPackageSnapshot } from "./plugin-package.js";
|
|
9
|
-
import { getPlugin } from "./plugin-store.js";
|
|
9
|
+
import { getPlugin, listPlugins, } from "./plugin-store.js";
|
|
10
10
|
import { loadOrCreateDaemonInstallationIdentitySync } from "./installation-id.js";
|
|
11
11
|
const DEFAULT_TERMINATION_GRACE_MS = 2_000;
|
|
12
12
|
const MAX_TERMINATION_GRACE_MS = 30_000;
|
|
13
|
+
/** Read the durable installed-plugin inventory without contacting the daemon. */
|
|
14
|
+
export function listInstalledPlugins() {
|
|
15
|
+
return listPlugins().map((record) => ({
|
|
16
|
+
id: record.canonicalId,
|
|
17
|
+
version: record.version,
|
|
18
|
+
source: record.source,
|
|
19
|
+
state: record.enabled ? "enabled" : "disabled",
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
/** Render manifest-declared command help without executing plugin code. */
|
|
23
|
+
export function installedPluginCommandUsage(pluginId) {
|
|
24
|
+
const record = getPlugin(pluginId);
|
|
25
|
+
if (!record)
|
|
26
|
+
throw new Error(`plugin "${pluginId}" is not installed`);
|
|
27
|
+
return pluginCommandUsage(record);
|
|
28
|
+
}
|
|
13
29
|
/** Execute one statically declared, language-neutral plugin command. */
|
|
14
30
|
export async function runPluginCliCommand(pluginId, args, options = {}) {
|
|
15
31
|
const hostEnv = options.env ?? process.env;
|
|
@@ -51,7 +51,7 @@ export async function ensureSystemDependencies(options = {}) {
|
|
|
51
51
|
args = ["-n", manager.path, ...installArgs];
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
options.onProgress?.("
|
|
54
|
+
options.onProgress?.("正在安装系统依赖 tmux");
|
|
55
55
|
const installed = await runCommand(command, args, { timeoutMs: INSTALL_TIMEOUT_MS });
|
|
56
56
|
if (installed.exitCode !== 0) {
|
|
57
57
|
throw new Error(`failed to install required system dependency tmux: ${commandFailure(installed)}`);
|
|
@@ -60,7 +60,7 @@ export async function ensureSystemDependencies(options = {}) {
|
|
|
60
60
|
if (!after.tmux.installed) {
|
|
61
61
|
throw new Error(`tmux installation completed but tmux is still unavailable: ${after.tmux.detail}`);
|
|
62
62
|
}
|
|
63
|
-
options.onProgress?.("
|
|
63
|
+
options.onProgress?.("tmux 安装并验证完成");
|
|
64
64
|
return after;
|
|
65
65
|
}
|
|
66
66
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/daemon",
|
|
3
|
-
"version": "0.1.11-beta.
|
|
3
|
+
"version": "0.1.11-beta.15",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
"types": "./dist/setup-service.d.ts",
|
|
37
37
|
"default": "./dist/setup-service.js"
|
|
38
38
|
},
|
|
39
|
+
"./plugin-cli": {
|
|
40
|
+
"types": "./dist/plugin-cli.d.ts",
|
|
41
|
+
"default": "./dist/plugin-cli.js"
|
|
42
|
+
},
|
|
39
43
|
"./internal/process": {
|
|
40
44
|
"types": "./dist/process.d.ts",
|
|
41
45
|
"default": "./dist/process.js"
|
|
@@ -46,17 +50,17 @@
|
|
|
46
50
|
"pm2": "^6.0.0",
|
|
47
51
|
"tar": "^7.5.19",
|
|
48
52
|
"ws": "^8.21.0",
|
|
49
|
-
"@rynx-ai/
|
|
50
|
-
"@rynx-ai/
|
|
51
|
-
"@rynx-ai/plugin-runner": "0.1.11-beta.
|
|
52
|
-
"@rynx-ai/plugin-sdk": "0.1.11-beta.
|
|
53
|
-
"@rynx-ai/protocol": "0.1.11-beta.
|
|
54
|
-
"@rynx-ai/remote-runtime-client": "0.1.11-beta.
|
|
55
|
-
"@rynx-ai/server": "0.1.11-beta.
|
|
53
|
+
"@rynx-ai/emulator": "0.1.11-beta.15",
|
|
54
|
+
"@rynx-ai/core": "0.1.11-beta.15",
|
|
55
|
+
"@rynx-ai/plugin-runner": "0.1.11-beta.15",
|
|
56
|
+
"@rynx-ai/plugin-sdk": "0.1.11-beta.15",
|
|
57
|
+
"@rynx-ai/protocol": "0.1.11-beta.15",
|
|
58
|
+
"@rynx-ai/remote-runtime-client": "0.1.11-beta.15",
|
|
59
|
+
"@rynx-ai/server": "0.1.11-beta.15"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
58
62
|
"@types/ws": "^8.18.1",
|
|
59
|
-
"@rynx-ai/plugin-channel-lark": "0.1.11-beta.
|
|
63
|
+
"@rynx-ai/plugin-channel-lark": "0.1.11-beta.15"
|
|
60
64
|
},
|
|
61
65
|
"scripts": {
|
|
62
66
|
"build": "rm -rf dist bundled-plugins && tsc -p tsconfig.json && chmod +x dist/index-daemon.js && node ../../scripts/stage-bundled-plugins.mjs",
|