@rynx-ai/cli 0.1.11-beta.3 → 0.1.11-beta.30
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/commands/browser.js +14 -6
- package/dist/commands/plugin.js +52 -26
- package/dist/commands/setup.js +59 -10
- package/dist/commands/skills.js +2 -2
- package/dist/progress-display.d.ts +7 -0
- package/dist/progress-display.js +78 -0
- package/dist/standalone.js +3 -0
- package/dist/usage.d.ts +1 -1
- package/dist/usage.js +1 -1
- package/package.json +8 -7
package/dist/commands/browser.js
CHANGED
|
@@ -4,6 +4,7 @@ import { connectBrowserAutomation, } from "@rynx-ai/browser-cdp";
|
|
|
4
4
|
import WebSocket from "ws";
|
|
5
5
|
import { parseBrowserCliArgs, resolveBrowserCliTarget, } from "../browser-cli-args.js";
|
|
6
6
|
import { callManagedRuntimeBrowser, callResidentRuntime, getResidentRuntimeLocalBrowserAutomationAccess, getResidentRuntimeLocalBrowserEndpoint, readOptionalManagedRuntimeBrowserCredential, } from "../control-client.js";
|
|
7
|
+
import { createProgressDisplay } from "../progress-display.js";
|
|
7
8
|
import { fail } from "./errors.js";
|
|
8
9
|
export async function runBrowserCommand(args) {
|
|
9
10
|
let parsed;
|
|
@@ -20,9 +21,18 @@ export async function runBrowserCommand(args) {
|
|
|
20
21
|
const channel = browserReleaseChannel(parsed.channel);
|
|
21
22
|
const { createBrowserArtifactManagementService } = await import("@rynx-ai/daemon/browser-artifacts");
|
|
22
23
|
const artifacts = createBrowserArtifactManagementService();
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
const progress = parsed.json ? undefined : createProgressDisplay();
|
|
25
|
+
progress?.start(parsed.subcommand === "install" ? "正在安装 Rynx Browser" : "正在更新 Rynx Browser");
|
|
26
|
+
let result;
|
|
27
|
+
try {
|
|
28
|
+
result = parsed.subcommand === "install"
|
|
29
|
+
? await artifacts.install(parsed.version ? { version: parsed.version } : { channel }, progress ? { onProgress: (message) => progress.update(message) } : {})
|
|
30
|
+
: await artifacts.update({ channel }, progress ? { onProgress: (message) => progress.update(message) } : {});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
progress?.clear();
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
26
36
|
if (parsed.json) {
|
|
27
37
|
console.log(JSON.stringify({
|
|
28
38
|
resolved: result.resolved,
|
|
@@ -30,9 +40,7 @@ export async function runBrowserCommand(args) {
|
|
|
30
40
|
}, null, 2));
|
|
31
41
|
}
|
|
32
42
|
else {
|
|
33
|
-
|
|
34
|
-
console.log(message);
|
|
35
|
-
console.log(`Active Browser engine: Chrome for Testing ${result.installed.version}.`);
|
|
43
|
+
progress.succeed(`Rynx Browser 已就绪:Chrome for Testing ${result.installed.version}`);
|
|
36
44
|
}
|
|
37
45
|
return 0;
|
|
38
46
|
}
|
package/dist/commands/plugin.js
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import { createInterface } from "node:readline/promises";
|
|
2
|
-
import { cancelResidentPluginInstallation, commitResidentPluginInstallation,
|
|
2
|
+
import { cancelResidentPluginInstallation, commitResidentPluginInstallation, prepareResidentPluginInstallation, setResidentPluginEnabled, uninstallResidentPlugin, } from "../control-client.js";
|
|
3
3
|
import { fail } from "./errors.js";
|
|
4
|
-
const PLUGIN_STDIN_MAX_BYTES = 256 * 1024;
|
|
5
4
|
const PLUGIN_DIGEST_PATTERN = /^sha256-[A-Za-z0-9+/]{43}={0,2}$/;
|
|
6
5
|
const CANONICAL_PLUGIN_ID_PATTERN = /^[a-z][a-z0-9-]{0,62}@[a-z0-9][a-z0-9-]{0,62}(?:\/[a-z0-9][a-z0-9._-]{0,99})?$/;
|
|
6
|
+
const PLUGIN_USAGE = `Usage: rynx plugin <command|plugin-id>
|
|
7
|
+
|
|
8
|
+
Management:
|
|
9
|
+
list
|
|
10
|
+
install <source|plugin@market> [--force] [--expect-digest <sha256-...>]
|
|
11
|
+
update <plugin@market> [--expect-digest <sha256-...>]
|
|
12
|
+
enable|disable|uninstall <plugin@market>
|
|
13
|
+
|
|
14
|
+
Plugin commands:
|
|
15
|
+
<plugin-id> <command> [args...]
|
|
16
|
+
<plugin-id> --help`;
|
|
7
17
|
export async function runPluginManageCommand(args, options = {}) {
|
|
8
18
|
const [subcommand, pluginId] = args;
|
|
9
19
|
switch (subcommand) {
|
|
10
20
|
case "list": {
|
|
11
|
-
const
|
|
21
|
+
const { listInstalledPlugins } = await import("@rynx-ai/daemon/plugin-cli");
|
|
22
|
+
const plugins = listInstalledPlugins();
|
|
12
23
|
console.log("Plugins");
|
|
13
24
|
if (plugins.length === 0) {
|
|
14
25
|
console.log(" (none)");
|
|
@@ -126,23 +137,50 @@ export async function runPluginCommand(args) {
|
|
|
126
137
|
const [pluginId, command] = args;
|
|
127
138
|
if (!pluginId)
|
|
128
139
|
fail("plugin: missing plugin id");
|
|
140
|
+
if (pluginId === "--help" || pluginId === "-h" || pluginId === "help") {
|
|
141
|
+
console.log(PLUGIN_USAGE);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
129
144
|
if (["list", "install", "update", "uninstall", "enable", "disable"].includes(pluginId)) {
|
|
130
145
|
return runPluginManageCommand(args);
|
|
131
146
|
}
|
|
132
147
|
if (!command)
|
|
133
148
|
fail(`plugin ${pluginId}: missing command`);
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
const pluginCli = await import("@rynx-ai/daemon/plugin-cli");
|
|
150
|
+
if (command === "--help" || command === "-h") {
|
|
151
|
+
console.log(pluginCli.installedPluginCommandUsage(pluginId));
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
return runPluginCliWithForwardedSignals((signal) => pluginCli.runPluginCliCommand(pluginId, args.slice(1), {
|
|
155
|
+
stdio: "inherit",
|
|
156
|
+
signal,
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
159
|
+
async function runPluginCliWithForwardedSignals(run) {
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
let interruptedBy;
|
|
162
|
+
const interrupt = (signal) => {
|
|
163
|
+
interruptedBy ??= signal;
|
|
164
|
+
if (!controller.signal.aborted) {
|
|
165
|
+
controller.abort(new Error(`plugin command interrupted by ${signal}`));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const onSigint = () => interrupt("SIGINT");
|
|
169
|
+
const onSigterm = () => interrupt("SIGTERM");
|
|
170
|
+
process.on("SIGINT", onSigint);
|
|
171
|
+
process.on("SIGTERM", onSigterm);
|
|
172
|
+
try {
|
|
173
|
+
return (await run(controller.signal)).code;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (interruptedBy)
|
|
177
|
+
return interruptedBy === "SIGINT" ? 130 : 143;
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
process.off("SIGINT", onSigint);
|
|
182
|
+
process.off("SIGTERM", onSigterm);
|
|
144
183
|
}
|
|
145
|
-
return result.code;
|
|
146
184
|
}
|
|
147
185
|
function parseInstallationArgs(operation, args) {
|
|
148
186
|
const target = args[0];
|
|
@@ -219,15 +257,3 @@ async function confirmInTerminal(message) {
|
|
|
219
257
|
prompt.close();
|
|
220
258
|
}
|
|
221
259
|
}
|
|
222
|
-
async function readStdinBounded(maxBytes) {
|
|
223
|
-
const chunks = [];
|
|
224
|
-
let bytes = 0;
|
|
225
|
-
for await (const chunk of process.stdin) {
|
|
226
|
-
const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
227
|
-
bytes += value.byteLength;
|
|
228
|
-
if (bytes > maxBytes)
|
|
229
|
-
fail(`plugin stdin exceeds ${maxBytes} bytes`);
|
|
230
|
-
chunks.push(value);
|
|
231
|
-
}
|
|
232
|
-
return Buffer.concat(chunks, bytes).toString("utf8");
|
|
233
|
-
}
|
package/dist/commands/setup.js
CHANGED
|
@@ -3,10 +3,13 @@ import { chmodSync, existsSync, mkdirSync, openSync, closeSync, readFileSync, re
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import * as prompts from "@clack/prompts";
|
|
5
5
|
import { AGENT_RUNTIME_IDS, getRuntimeProfile, loadConfig, rynxConfigFile, } from "@rynx-ai/core";
|
|
6
|
-
import { inspectDaemonDiagnostics, prepareBundledPlugins, } from "@rynx-ai/daemon/setup-service";
|
|
6
|
+
import { inspectDaemonDiagnostics, inspectSystemDependencies, prepareBundledPlugins, } from "@rynx-ai/daemon/setup-service";
|
|
7
|
+
import { BUNDLED_TMUX_UNAVAILABLE_MESSAGE, resolveBundledTmux, } from "@rynx-ai/tmux";
|
|
8
|
+
import { createProgressDisplay } from "../progress-display.js";
|
|
7
9
|
import { fail } from "./errors.js";
|
|
8
10
|
export async function runSetupCommand(args) {
|
|
9
11
|
const options = parseSetupOptions(args);
|
|
12
|
+
const progress = options.json ? undefined : createProgressDisplay();
|
|
10
13
|
const interactive = !options.nonInteractive &&
|
|
11
14
|
!options.hasConfigurationArguments &&
|
|
12
15
|
Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -50,23 +53,30 @@ export async function runSetupCommand(args) {
|
|
|
50
53
|
},
|
|
51
54
|
};
|
|
52
55
|
let failed = false;
|
|
56
|
+
progress?.start("正在准备 Rynx 内置插件");
|
|
53
57
|
try {
|
|
54
58
|
const plugins = await prepareBundledPlugins();
|
|
55
59
|
result.plugins = {
|
|
56
60
|
status: plugins.status,
|
|
57
61
|
changed: [...plugins.installed, ...plugins.updated],
|
|
58
62
|
};
|
|
63
|
+
progress?.succeed("Rynx 内置插件已就绪");
|
|
59
64
|
}
|
|
60
65
|
catch (error) {
|
|
61
66
|
failed = true;
|
|
67
|
+
progress?.clear();
|
|
68
|
+
const detail = errorMessage(error);
|
|
62
69
|
result.plugins = {
|
|
63
70
|
status: "error",
|
|
64
|
-
detail
|
|
71
|
+
detail,
|
|
65
72
|
};
|
|
73
|
+
console.error(`Rynx 内置插件准备失败:${detail}`);
|
|
66
74
|
}
|
|
75
|
+
progress?.start("正在检查 Rynx Browser");
|
|
67
76
|
const diagnostics = await inspectDaemonDiagnostics();
|
|
68
77
|
if (!diagnostics.browser.supported) {
|
|
69
78
|
result.browser = { action: options.browser, status: "unsupported" };
|
|
79
|
+
progress?.succeed("当前平台不支持 Rynx Browser");
|
|
70
80
|
}
|
|
71
81
|
else if (diagnostics.browser.installedVersion) {
|
|
72
82
|
result.browser = {
|
|
@@ -74,29 +84,39 @@ export async function runSetupCommand(args) {
|
|
|
74
84
|
status: "ready",
|
|
75
85
|
version: diagnostics.browser.installedVersion,
|
|
76
86
|
};
|
|
87
|
+
progress?.succeed(`Rynx Browser 已就绪:${diagnostics.browser.installedVersion}`);
|
|
77
88
|
}
|
|
78
89
|
else if (options.browser !== "skip") {
|
|
90
|
+
progress?.update("正在安装 Rynx Browser");
|
|
79
91
|
try {
|
|
80
92
|
const { createBrowserArtifactManagementService } = await import("@rynx-ai/daemon/browser-artifacts");
|
|
81
|
-
const installed = await createBrowserArtifactManagementService().install({ channel: "stable" },
|
|
82
|
-
? {}
|
|
83
|
-
: { onProgress: (message) => console.error(message) });
|
|
93
|
+
const installed = await createBrowserArtifactManagementService().install({ channel: "stable" }, progress ? { onProgress: (message) => progress.update(message) } : {});
|
|
84
94
|
result.browser = {
|
|
85
95
|
action: options.browser,
|
|
86
96
|
status: "ready",
|
|
87
97
|
version: installed.installed.version,
|
|
88
98
|
};
|
|
99
|
+
progress?.succeed(`Rynx Browser 已就绪:${installed.installed.version}`);
|
|
89
100
|
}
|
|
90
101
|
catch (error) {
|
|
91
102
|
failed = true;
|
|
103
|
+
progress?.clear();
|
|
104
|
+
const detail = errorMessage(error);
|
|
92
105
|
result.browser = {
|
|
93
106
|
action: options.browser,
|
|
94
107
|
status: "error",
|
|
95
|
-
detail
|
|
108
|
+
detail,
|
|
96
109
|
};
|
|
110
|
+
console.error(`Rynx Browser 安装失败:${detail}`);
|
|
97
111
|
}
|
|
98
112
|
}
|
|
99
|
-
|
|
113
|
+
else {
|
|
114
|
+
progress?.succeed("已跳过 Rynx Browser 安装");
|
|
115
|
+
}
|
|
116
|
+
if (options.resultFile) {
|
|
117
|
+
writeJsonAtomically(options.resultFile, result);
|
|
118
|
+
}
|
|
119
|
+
else if (options.json) {
|
|
100
120
|
console.log(JSON.stringify(result, null, 2));
|
|
101
121
|
}
|
|
102
122
|
else if (interactive) {
|
|
@@ -140,13 +160,25 @@ export async function runDoctorCommand(args) {
|
|
|
140
160
|
return { id, installed: !probe.error && probe.status === 0 };
|
|
141
161
|
});
|
|
142
162
|
const daemon = await inspectDaemonDiagnostics();
|
|
163
|
+
const tmuxBin = resolveBundledTmux();
|
|
164
|
+
const systemDependencies = tmuxBin
|
|
165
|
+
? await inspectSystemDependencies({ tmuxBin })
|
|
166
|
+
: {
|
|
167
|
+
tmux: {
|
|
168
|
+
installed: false,
|
|
169
|
+
detail: BUNDLED_TMUX_UNAVAILABLE_MESSAGE,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
143
172
|
const result = {
|
|
144
|
-
ok: configError === undefined &&
|
|
173
|
+
ok: configError === undefined &&
|
|
174
|
+
runtimes.some((runtime) => runtime.installed) &&
|
|
175
|
+
systemDependencies.tmux.installed,
|
|
145
176
|
configPath: rynxConfigFile(),
|
|
146
177
|
config,
|
|
147
178
|
configError,
|
|
148
179
|
runtimes,
|
|
149
180
|
daemon,
|
|
181
|
+
systemDependencies,
|
|
150
182
|
};
|
|
151
183
|
if (json)
|
|
152
184
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -159,6 +191,7 @@ export async function runDoctorCommand(args) {
|
|
|
159
191
|
for (const runtime of runtimes) {
|
|
160
192
|
console.log(`${runtime.id}: ${runtime.installed ? "installed" : "not installed"}`);
|
|
161
193
|
}
|
|
194
|
+
console.log(`tmux: ${systemDependencies.tmux.installed ? "installed" : "not installed"}`);
|
|
162
195
|
if (daemon.browser.supported) {
|
|
163
196
|
console.log(`browser: ${daemon.browser.installedVersion ?? daemon.browser.error ?? "not installed"}`);
|
|
164
197
|
}
|
|
@@ -186,6 +219,17 @@ function parseSetupOptions(args) {
|
|
|
186
219
|
options.nonInteractive = true;
|
|
187
220
|
continue;
|
|
188
221
|
}
|
|
222
|
+
if (arg === "--result-file") {
|
|
223
|
+
if (options.resultFile !== undefined)
|
|
224
|
+
fail("setup: duplicate option --result-file");
|
|
225
|
+
const value = args[index + 1];
|
|
226
|
+
if (!value || value.startsWith("--"))
|
|
227
|
+
fail("setup: --result-file requires a value");
|
|
228
|
+
options.resultFile = path.resolve(value);
|
|
229
|
+
options.nonInteractive = true;
|
|
230
|
+
index += 1;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
189
233
|
if (arg === "--install-browser" || arg === "--skip-browser") {
|
|
190
234
|
if (options.browser !== "auto")
|
|
191
235
|
fail("setup: choose only one Browser action");
|
|
@@ -225,6 +269,9 @@ function parseSetupOptions(args) {
|
|
|
225
269
|
fail(`setup: unknown option ${arg}`);
|
|
226
270
|
}
|
|
227
271
|
}
|
|
272
|
+
if (options.json && options.resultFile) {
|
|
273
|
+
fail("setup: choose either --json or --result-file");
|
|
274
|
+
}
|
|
228
275
|
return options;
|
|
229
276
|
}
|
|
230
277
|
async function collectInteractiveSetup(config) {
|
|
@@ -290,14 +337,16 @@ function readRawConfig() {
|
|
|
290
337
|
}
|
|
291
338
|
}
|
|
292
339
|
function writeConfigAtomically(config) {
|
|
293
|
-
|
|
340
|
+
writeJsonAtomically(rynxConfigFile(), config);
|
|
341
|
+
}
|
|
342
|
+
function writeJsonAtomically(file, value) {
|
|
294
343
|
const directory = path.dirname(file);
|
|
295
344
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
296
345
|
const temporary = path.join(directory, `.${path.basename(file)}.${process.pid}.tmp`);
|
|
297
346
|
let descriptor;
|
|
298
347
|
try {
|
|
299
348
|
descriptor = openSync(temporary, "wx", 0o600);
|
|
300
|
-
writeFileSync(descriptor, `${JSON.stringify(
|
|
349
|
+
writeFileSync(descriptor, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
301
350
|
closeSync(descriptor);
|
|
302
351
|
descriptor = undefined;
|
|
303
352
|
renameSync(temporary, file);
|
package/dist/commands/skills.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { isSkillPathComponent } from "@rynx-ai/core";
|
|
4
5
|
import { fail } from "./errors.js";
|
|
5
|
-
const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
6
6
|
const MAX_SKILL_BYTES = 256 * 1024;
|
|
7
7
|
const BUILTIN_SKILL_NAMES = ["browser", "emulator"];
|
|
8
8
|
export async function runSkillsCommand(args) {
|
|
@@ -55,7 +55,7 @@ export async function listBuiltinSkills() {
|
|
|
55
55
|
return guides.filter((guide) => guide !== null);
|
|
56
56
|
}
|
|
57
57
|
export async function readBuiltinSkill(name, full = false) {
|
|
58
|
-
if (!
|
|
58
|
+
if (!isSkillPathComponent(name))
|
|
59
59
|
return null;
|
|
60
60
|
if (!BUILTIN_SKILL_NAMES.includes(name))
|
|
61
61
|
return null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as prompts from "@clack/prompts";
|
|
2
|
+
const DOWNLOAD_PERCENT_PATTERN = /下载进度:(\d{1,3})%$/u;
|
|
3
|
+
export function createProgressDisplay() {
|
|
4
|
+
if (!prompts.isTTY(process.stdout) || prompts.isCI()) {
|
|
5
|
+
return {
|
|
6
|
+
start: (message) => console.log(message),
|
|
7
|
+
update: (message) => console.log(message),
|
|
8
|
+
succeed: (message) => console.log(message),
|
|
9
|
+
clear: () => undefined,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const spinner = prompts.spinner({ output: process.stdout });
|
|
13
|
+
const progress = prompts.progress({
|
|
14
|
+
output: process.stdout,
|
|
15
|
+
max: 100,
|
|
16
|
+
size: 28,
|
|
17
|
+
style: "block",
|
|
18
|
+
});
|
|
19
|
+
let spinnerActive = false;
|
|
20
|
+
let progressActive = false;
|
|
21
|
+
let completedPercent = 0;
|
|
22
|
+
const clear = () => {
|
|
23
|
+
if (progressActive)
|
|
24
|
+
progress.clear();
|
|
25
|
+
if (spinnerActive)
|
|
26
|
+
spinner.clear();
|
|
27
|
+
progressActive = false;
|
|
28
|
+
spinnerActive = false;
|
|
29
|
+
completedPercent = 0;
|
|
30
|
+
};
|
|
31
|
+
const finishDownload = () => {
|
|
32
|
+
if (!progressActive)
|
|
33
|
+
return;
|
|
34
|
+
progress.stop("Chrome for Testing 下载完成");
|
|
35
|
+
progressActive = false;
|
|
36
|
+
completedPercent = 0;
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
start(message) {
|
|
40
|
+
clear();
|
|
41
|
+
spinner.start(message);
|
|
42
|
+
spinnerActive = true;
|
|
43
|
+
},
|
|
44
|
+
update(message) {
|
|
45
|
+
const match = DOWNLOAD_PERCENT_PATTERN.exec(message);
|
|
46
|
+
if (match) {
|
|
47
|
+
const percent = Math.min(100, Number(match[1]));
|
|
48
|
+
if (spinnerActive) {
|
|
49
|
+
spinner.clear();
|
|
50
|
+
spinnerActive = false;
|
|
51
|
+
}
|
|
52
|
+
if (!progressActive) {
|
|
53
|
+
progress.start(message);
|
|
54
|
+
progressActive = true;
|
|
55
|
+
}
|
|
56
|
+
progress.advance(percent - completedPercent, message);
|
|
57
|
+
completedPercent = percent;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
finishDownload();
|
|
61
|
+
if (spinnerActive)
|
|
62
|
+
spinner.message(message);
|
|
63
|
+
else {
|
|
64
|
+
spinner.start(message);
|
|
65
|
+
spinnerActive = true;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
succeed(message) {
|
|
69
|
+
finishDownload();
|
|
70
|
+
if (spinnerActive)
|
|
71
|
+
spinner.stop(message);
|
|
72
|
+
else
|
|
73
|
+
prompts.log.success(message);
|
|
74
|
+
spinnerActive = false;
|
|
75
|
+
},
|
|
76
|
+
clear,
|
|
77
|
+
};
|
|
78
|
+
}
|
package/dist/standalone.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { resolveBundledTmux } from "@rynx-ai/tmux";
|
|
3
4
|
import { installedVersion } from "./version.js";
|
|
4
5
|
import { ensureDaemonControlEndpoint, resolveDaemonControlEndpoint, } from "./control-endpoint.js";
|
|
5
6
|
/** Resolve the canonical Builtin Skill directory shipped by this exact CLI. */
|
|
@@ -8,6 +9,7 @@ export function standaloneBuiltinSkillsDirectory(moduleUrl = import.meta.url) {
|
|
|
8
9
|
}
|
|
9
10
|
export async function startStandaloneDaemon(options = {}) {
|
|
10
11
|
const cliVersion = installedVersion();
|
|
12
|
+
const tmuxBin = resolveBundledTmux();
|
|
11
13
|
const { startDaemon } = await import("@rynx-ai/daemon/lifecycle");
|
|
12
14
|
return startDaemon({
|
|
13
15
|
force: options.restart ?? false,
|
|
@@ -16,6 +18,7 @@ export async function startStandaloneDaemon(options = {}) {
|
|
|
16
18
|
builtinSkillsDir: standaloneBuiltinSkillsDirectory(),
|
|
17
19
|
cliVersion,
|
|
18
20
|
productVersion: cliVersion,
|
|
21
|
+
...(tmuxBin ? { tmuxBin } : {}),
|
|
19
22
|
},
|
|
20
23
|
});
|
|
21
24
|
}
|
package/dist/usage.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const USAGE = "Usage: rynx <command>\n\nGeneral:\n version [--json] | --version\n print the installed Rynx version\n\nSetup:\n setup [--non-interactive] [--default-runtime <codex|traex|claude>]\n [--host <host>] [--port <port>] [--log-level <level>]\n [--install-browser|--skip-browser] [--json]\n initialize configuration and local dependencies\n doctor read-only health check\n\nLifecycle:\n start | restart | stop | status | logs\n update [version] [--check] [--json]\n\nPlugins:\n market list\n market add <git-or-local-source> [--alias <id>]\n market refresh [market-id]\n market remove <market-id>\n plugin list\n plugin install <source|plugin@market> [--force] [--expect-digest <sha256-...>]\n plugin update <plugin@market> [--expect-digest <sha256-...>]\n plugin enable|disable|uninstall <plugin@market>\n plugin <plugin@market> <command> invoke a plugin-owned command\n\nAgents:\n agent list\n agent show <id>\n agent add <id>\n agent rm <id>\n\nBuiltin Skills:\n skills list [--json]\n skills get <browser|emulator> [--full] [--json]\n\nMaintenance:\n cleanup sessions [--dry-run]\n\nEmulator:\n emulator <args...>\n\nRemote Runtime:\n runtime share --address <host|ws-url> [--label <label>] [--json]\n runtime add --pairing-code <rynx://...> [--name <name>]\n runtime list [--json]\n runtime test <local|daemon-id> [--json]\n runtime forget <daemon-id>\n runtime clients list [--json]\n runtime clients revoke <grant-id>\n\nSessions:\n session fork <session-id> [--title <title>] [--json]\n\nBrowser:\n browser install|update|version|clean [...]\n browser open [url] [--session <id>] [--runtime <local|daemon-id>] [--json]\n browser status|pages|close [--session <id>] [--runtime <local|daemon-id>] [--json]\n browser endpoint [--ensure] [--session <local-id>] [--json]\n browser snapshot [--session <local-id>] [--json]\n browser navigate <url> [--session <local-id>] [--json]\n browser click (--ref <ref>|--selector <css>|--x <n> --y <n>) [--session <local-id>] [--json]\n browser type (--ref <ref>|--selector <css>) --text <text> [--session <local-id>] [--json]\n browser screenshot --output <absolute-path> [--session <local-id>] [--json]\n";
|
|
1
|
+
export declare const USAGE = "Usage: rynx <command>\n\nGeneral:\n version [--json] | --version\n print the installed Rynx version\n\nSetup:\n setup [--non-interactive] [--default-runtime <codex|traex|claude>]\n [--host <host>] [--port <port>] [--log-level <level>]\n [--install-browser|--skip-browser] [--json|--result-file <path>]\n initialize configuration and local dependencies\n doctor read-only health check\n\nLifecycle:\n start | restart | stop | status | logs\n update [version] [--check] [--json]\n\nPlugins:\n market list\n market add <git-or-local-source> [--alias <id>]\n market refresh [market-id]\n market remove <market-id>\n plugin list\n plugin install <source|plugin@market> [--force] [--expect-digest <sha256-...>]\n plugin update <plugin@market> [--expect-digest <sha256-...>]\n plugin enable|disable|uninstall <plugin@market>\n plugin <plugin@market> <command> invoke a plugin-owned command\n\nAgents:\n agent list\n agent show <id>\n agent add <id>\n agent rm <id>\n\nBuiltin Skills:\n skills list [--json]\n skills get <browser|emulator> [--full] [--json]\n\nMaintenance:\n cleanup sessions [--dry-run]\n\nEmulator:\n emulator <args...>\n\nRemote Runtime:\n runtime share --address <host|ws-url> [--label <label>] [--json]\n runtime add --pairing-code <rynx://...> [--name <name>]\n runtime list [--json]\n runtime test <local|daemon-id> [--json]\n runtime forget <daemon-id>\n runtime clients list [--json]\n runtime clients revoke <grant-id>\n\nSessions:\n session fork <session-id> [--title <title>] [--json]\n\nBrowser:\n browser install|update|version|clean [...]\n browser open [url] [--session <id>] [--runtime <local|daemon-id>] [--json]\n browser status|pages|close [--session <id>] [--runtime <local|daemon-id>] [--json]\n browser endpoint [--ensure] [--session <local-id>] [--json]\n browser snapshot [--session <local-id>] [--json]\n browser navigate <url> [--session <local-id>] [--json]\n browser click (--ref <ref>|--selector <css>|--x <n> --y <n>) [--session <local-id>] [--json]\n browser type (--ref <ref>|--selector <css>) --text <text> [--session <local-id>] [--json]\n browser screenshot --output <absolute-path> [--session <local-id>] [--json]\n";
|
package/dist/usage.js
CHANGED
|
@@ -7,7 +7,7 @@ General:
|
|
|
7
7
|
Setup:
|
|
8
8
|
setup [--non-interactive] [--default-runtime <codex|traex|claude>]
|
|
9
9
|
[--host <host>] [--port <port>] [--log-level <level>]
|
|
10
|
-
[--install-browser|--skip-browser] [--json]
|
|
10
|
+
[--install-browser|--skip-browser] [--json|--result-file <path>]
|
|
11
11
|
initialize configuration and local dependencies
|
|
12
12
|
doctor read-only health check
|
|
13
13
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/cli",
|
|
3
|
-
"version": "0.1.11-beta.
|
|
3
|
+
"version": "0.1.11-beta.30",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=22"
|
|
13
|
+
"node": ">=22.16"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -51,11 +51,12 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@clack/prompts": "^1.6.0",
|
|
53
53
|
"ws": "^8.21.0",
|
|
54
|
-
"@rynx-ai/core": "0.1.11-beta.
|
|
55
|
-
"@rynx-ai/
|
|
56
|
-
"@rynx-ai/
|
|
57
|
-
"@rynx-ai/
|
|
58
|
-
"@rynx-ai/protocol": "0.1.11-beta.
|
|
54
|
+
"@rynx-ai/core": "0.1.11-beta.30",
|
|
55
|
+
"@rynx-ai/daemon": "0.1.11-beta.30",
|
|
56
|
+
"@rynx-ai/browser-cdp": "0.1.11-beta.30",
|
|
57
|
+
"@rynx-ai/emulator": "0.1.11-beta.30",
|
|
58
|
+
"@rynx-ai/protocol": "0.1.11-beta.30",
|
|
59
|
+
"@rynx-ai/tmux": "0.1.11-beta.30"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@types/ws": "^8.18.1"
|