@rynx-ai/daemon 0.1.11-beta.14 → 0.1.11-beta.16
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/lifecycle.d.ts +1 -0
- package/dist/lifecycle.js +1 -0
- package/dist/plugin-cli.d.ts +10 -0
- package/dist/plugin-cli.js +17 -1
- package/dist/setup-service.d.ts +1 -1
- package/dist/setup-service.js +1 -1
- package/dist/system-dependencies.d.ts +4 -6
- package/dist/system-dependencies.js +28 -91
- package/package.json +13 -9
package/dist/lifecycle.d.ts
CHANGED
package/dist/lifecycle.js
CHANGED
|
@@ -11,6 +11,7 @@ export function startDaemon(options) {
|
|
|
11
11
|
RYNX_DISTRIBUTION: "standalone",
|
|
12
12
|
RYNX_PRODUCT_VERSION: options.context.productVersion,
|
|
13
13
|
RYNX_DAEMON_LIFECYCLE: "standalone",
|
|
14
|
+
...(options.context.tmuxBin ? { RYNX_TMUX_BIN: options.context.tmuxBin } : {}),
|
|
14
15
|
},
|
|
15
16
|
});
|
|
16
17
|
}
|
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;
|
package/dist/setup-service.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { inspectSystemDependencies, type SystemDependencySnapshot, verifySystemDependencies, } from "./system-dependencies.js";
|
|
2
2
|
export interface DaemonDiagnosticSnapshot {
|
|
3
3
|
databasePath: string;
|
|
4
4
|
databaseExists: boolean;
|
package/dist/setup-service.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createChromeForTestingArtifactStore, isChromeForTestingHostSupported }
|
|
|
4
4
|
import { ensureBundledOfficialPlugins } from "./bundled-plugins.js";
|
|
5
5
|
import { dbPath } from "./db.js";
|
|
6
6
|
import { listPlugins } from "./plugin-store.js";
|
|
7
|
-
export {
|
|
7
|
+
export { inspectSystemDependencies, verifySystemDependencies, } from "./system-dependencies.js";
|
|
8
8
|
export async function prepareBundledPlugins() {
|
|
9
9
|
return ensureBundledOfficialPlugins();
|
|
10
10
|
}
|
|
@@ -16,11 +16,9 @@ export interface SystemDependencyCommandOptions {
|
|
|
16
16
|
}
|
|
17
17
|
export type SystemDependencyCommandRunner = (command: string, args: readonly string[], options: SystemDependencyCommandOptions) => Promise<SystemDependencyCommandResult>;
|
|
18
18
|
export interface SystemDependencyOptions {
|
|
19
|
-
platform?: string;
|
|
20
|
-
getuid?: () => number | undefined;
|
|
21
|
-
findSystemExecutable?: (name: string) => Promise<string | undefined>;
|
|
22
19
|
runCommand?: SystemDependencyCommandRunner;
|
|
23
|
-
|
|
20
|
+
tmuxBin?: string;
|
|
24
21
|
}
|
|
25
|
-
export declare function inspectSystemDependencies(options?: Pick<SystemDependencyOptions, "runCommand">): Promise<SystemDependencySnapshot>;
|
|
26
|
-
|
|
22
|
+
export declare function inspectSystemDependencies(options?: Pick<SystemDependencyOptions, "runCommand" | "tmuxBin">): Promise<SystemDependencySnapshot>;
|
|
23
|
+
/** Validate the selected executable without installing or changing the host. */
|
|
24
|
+
export declare function verifySystemDependencies(options?: SystemDependencyOptions): Promise<SystemDependencySnapshot>;
|
|
@@ -1,128 +1,65 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { constants } from "node:fs";
|
|
3
|
-
import { access } from "node:fs/promises";
|
|
4
2
|
const PROBE_TIMEOUT_MS = 10_000;
|
|
5
|
-
const INSTALL_TIMEOUT_MS = 5 * 60_000;
|
|
6
3
|
const MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
4
|
+
const MINIMUM_TMUX_VERSION = { major: 3, minor: 4 };
|
|
7
5
|
export async function inspectSystemDependencies(options = {}) {
|
|
8
6
|
const runCommand = options.runCommand ?? runSystemDependencyCommand;
|
|
9
|
-
const probe = await probeTmux(runCommand);
|
|
7
|
+
const probe = await probeTmux(runCommand, options.tmuxBin ?? "tmux");
|
|
10
8
|
return {
|
|
11
9
|
tmux: probe.installed
|
|
12
10
|
? { installed: true }
|
|
13
11
|
: { installed: false, detail: probe.detail },
|
|
14
12
|
};
|
|
15
13
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
throw new Error(before.detail);
|
|
23
|
-
}
|
|
24
|
-
const platform = options.platform ?? process.platform;
|
|
25
|
-
const findSystemExecutable = options.findSystemExecutable ?? findSystemCommand;
|
|
26
|
-
const manager = await resolvePackageManager(platform, findSystemExecutable);
|
|
27
|
-
if (!manager) {
|
|
28
|
-
throw new Error(platform === "darwin"
|
|
29
|
-
? "tmux is required for live Sessions, but Homebrew is unavailable; install tmux and retry"
|
|
30
|
-
: "tmux is required for live Sessions, but no supported package manager (apt-get, dnf, or yum) is available");
|
|
31
|
-
}
|
|
32
|
-
const installArgs = manager.family === "apt"
|
|
33
|
-
? ["install", "-y", "--no-install-recommends", "tmux"]
|
|
34
|
-
: manager.family === "brew"
|
|
35
|
-
? ["install", "tmux"]
|
|
36
|
-
: ["install", "-y", "tmux"];
|
|
37
|
-
let command = manager.path;
|
|
38
|
-
let args = installArgs;
|
|
39
|
-
if (manager.family !== "brew") {
|
|
40
|
-
const getuid = options.getuid ?? (() => process.getuid?.());
|
|
41
|
-
if (getuid() !== 0) {
|
|
42
|
-
const sudo = await findSystemExecutable("sudo");
|
|
43
|
-
const sudoReady = sudo
|
|
44
|
-
? await runCommand(sudo, ["-n", "true"], { timeoutMs: PROBE_TIMEOUT_MS })
|
|
45
|
-
: undefined;
|
|
46
|
-
if (!sudo || sudoReady?.exitCode !== 0) {
|
|
47
|
-
throw new Error(`tmux is required for live Sessions; install it as an administrator and retry: ` +
|
|
48
|
-
`${manager.commandForHumans} install -y tmux`);
|
|
49
|
-
}
|
|
50
|
-
command = sudo;
|
|
51
|
-
args = ["-n", manager.path, ...installArgs];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
options.onProgress?.("正在安装系统依赖 tmux");
|
|
55
|
-
const installed = await runCommand(command, args, { timeoutMs: INSTALL_TIMEOUT_MS });
|
|
56
|
-
if (installed.exitCode !== 0) {
|
|
57
|
-
throw new Error(`failed to install required system dependency tmux: ${commandFailure(installed)}`);
|
|
58
|
-
}
|
|
59
|
-
const after = await inspectSystemDependencies({ runCommand });
|
|
60
|
-
if (!after.tmux.installed) {
|
|
61
|
-
throw new Error(`tmux installation completed but tmux is still unavailable: ${after.tmux.detail}`);
|
|
62
|
-
}
|
|
63
|
-
options.onProgress?.("tmux 安装并验证完成");
|
|
64
|
-
return after;
|
|
14
|
+
/** Validate the selected executable without installing or changing the host. */
|
|
15
|
+
export async function verifySystemDependencies(options = {}) {
|
|
16
|
+
const snapshot = await inspectSystemDependencies(options);
|
|
17
|
+
if (!snapshot.tmux.installed)
|
|
18
|
+
throw new Error(snapshot.tmux.detail);
|
|
19
|
+
return snapshot;
|
|
65
20
|
}
|
|
66
21
|
/**
|
|
67
22
|
* A version probe only proves the binary can start. Live Sessions need tmux to
|
|
68
23
|
* create a server and socket, so exercise that path with a private probe server
|
|
69
24
|
* that cannot interfere with a user's existing tmux sessions.
|
|
70
25
|
*/
|
|
71
|
-
async function probeTmux(runCommand) {
|
|
72
|
-
const version = await runCommand(
|
|
26
|
+
async function probeTmux(runCommand, tmuxBin) {
|
|
27
|
+
const version = await runCommand(tmuxBin, ["-V"], { timeoutMs: PROBE_TIMEOUT_MS });
|
|
73
28
|
if (version.exitCode !== 0) {
|
|
74
29
|
return {
|
|
75
30
|
installed: false,
|
|
76
|
-
binaryPresent: version.errorCode !== "ENOENT",
|
|
77
31
|
detail: `tmux -V failed: ${commandFailure(version)}`,
|
|
78
32
|
};
|
|
79
33
|
}
|
|
34
|
+
if (!isSupportedTmuxVersion(version.stdout)) {
|
|
35
|
+
return {
|
|
36
|
+
installed: false,
|
|
37
|
+
detail: `${version.stdout.trim() || tmuxBin} is too old; ` +
|
|
38
|
+
`Rynx requires tmux ${MINIMUM_TMUX_VERSION.major}.${MINIMUM_TMUX_VERSION.minor} or newer`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
80
41
|
const socketName = `rynx-setup-probe-${process.pid}-${Date.now()}`;
|
|
81
|
-
const functional = await runCommand(
|
|
82
|
-
await runCommand(
|
|
42
|
+
const functional = await runCommand(tmuxBin, ["-L", socketName, "new-session", "-d", "-s", "probe", "true"], { timeoutMs: PROBE_TIMEOUT_MS });
|
|
43
|
+
await runCommand(tmuxBin, ["-L", socketName, "kill-server"], {
|
|
83
44
|
timeoutMs: PROBE_TIMEOUT_MS,
|
|
84
45
|
});
|
|
85
46
|
if (functional.exitCode !== 0) {
|
|
86
47
|
return {
|
|
87
48
|
installed: false,
|
|
88
|
-
binaryPresent: true,
|
|
89
49
|
detail: `${version.stdout.trim() || "tmux"} is installed but cannot start a server: ` +
|
|
90
50
|
commandFailure(functional),
|
|
91
51
|
};
|
|
92
52
|
}
|
|
93
|
-
return { installed: true
|
|
53
|
+
return { installed: true };
|
|
94
54
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (apt)
|
|
104
|
-
return { family: "apt", path: apt, commandForHumans: "apt-get" };
|
|
105
|
-
const dnf = await findExecutable("dnf");
|
|
106
|
-
if (dnf)
|
|
107
|
-
return { family: "rpm", path: dnf, commandForHumans: "dnf" };
|
|
108
|
-
const yum = await findExecutable("yum");
|
|
109
|
-
return yum ? { family: "rpm", path: yum, commandForHumans: "yum" } : undefined;
|
|
110
|
-
}
|
|
111
|
-
async function findSystemCommand(name) {
|
|
112
|
-
const directories = name === "brew"
|
|
113
|
-
? ["/opt/homebrew/bin", "/usr/local/bin"]
|
|
114
|
-
: ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
115
|
-
for (const directory of directories) {
|
|
116
|
-
const candidate = `${directory}/${name}`;
|
|
117
|
-
try {
|
|
118
|
-
await access(candidate, constants.X_OK);
|
|
119
|
-
return candidate;
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// Try the next standard system directory.
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return undefined;
|
|
55
|
+
function isSupportedTmuxVersion(stdout) {
|
|
56
|
+
const match = /^tmux\s+(\d+)\.(\d+)/i.exec(stdout.trim());
|
|
57
|
+
if (!match)
|
|
58
|
+
return false;
|
|
59
|
+
const major = Number(match[1]);
|
|
60
|
+
const minor = Number(match[2]);
|
|
61
|
+
return major > MINIMUM_TMUX_VERSION.major ||
|
|
62
|
+
(major === MINIMUM_TMUX_VERSION.major && minor >= MINIMUM_TMUX_VERSION.minor);
|
|
126
63
|
}
|
|
127
64
|
function runSystemDependencyCommand(command, args, options) {
|
|
128
65
|
return new Promise((resolveResult) => {
|
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.16",
|
|
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/core": "0.1.11-beta.
|
|
50
|
-
"@rynx-ai/emulator": "0.1.11-beta.
|
|
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/core": "0.1.11-beta.16",
|
|
54
|
+
"@rynx-ai/emulator": "0.1.11-beta.16",
|
|
55
|
+
"@rynx-ai/plugin-runner": "0.1.11-beta.16",
|
|
56
|
+
"@rynx-ai/plugin-sdk": "0.1.11-beta.16",
|
|
57
|
+
"@rynx-ai/protocol": "0.1.11-beta.16",
|
|
58
|
+
"@rynx-ai/remote-runtime-client": "0.1.11-beta.16",
|
|
59
|
+
"@rynx-ai/server": "0.1.11-beta.16"
|
|
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.16"
|
|
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",
|