@rynx-ai/daemon 0.1.10 → 0.1.11-beta.10

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.
Files changed (156) hide show
  1. package/bundled-plugins/.rynx-plugin/marketplace.json +10 -0
  2. package/bundled-plugins/plugins/lark/.rynx-plugin/plugin.json +25 -0
  3. package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.d.ts +48 -0
  4. package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.js +56 -0
  5. package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.d.ts +85 -0
  6. package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.js +333 -0
  7. package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.d.ts +109 -0
  8. package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.js +347 -0
  9. package/bundled-plugins/plugins/lark/dist/host-adapters.d.ts +95 -0
  10. package/bundled-plugins/plugins/lark/dist/host-adapters.js +506 -0
  11. package/bundled-plugins/plugins/lark/dist/index.d.ts +7 -0
  12. package/bundled-plugins/plugins/lark/dist/index.js +7 -0
  13. package/bundled-plugins/plugins/lark/dist/lark-card-stream.d.ts +363 -0
  14. package/bundled-plugins/plugins/lark/dist/lark-card-stream.js +1335 -0
  15. package/bundled-plugins/plugins/lark/dist/lark-config-store.d.ts +30 -0
  16. package/bundled-plugins/plugins/lark/dist/lark-config-store.js +135 -0
  17. package/bundled-plugins/plugins/lark/dist/lark-content.d.ts +30 -0
  18. package/bundled-plugins/plugins/lark/dist/lark-content.js +138 -0
  19. package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.d.ts +65 -0
  20. package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.js +106 -0
  21. package/bundled-plugins/plugins/lark/dist/lark-diff-card.d.ts +25 -0
  22. package/bundled-plugins/plugins/lark/dist/lark-diff-card.js +58 -0
  23. package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.d.ts +16 -0
  24. package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.js +141 -0
  25. package/bundled-plugins/plugins/lark/dist/lark-resume-card.d.ts +31 -0
  26. package/bundled-plugins/plugins/lark/dist/lark-resume-card.js +105 -0
  27. package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.d.ts +18 -0
  28. package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.js +95 -0
  29. package/bundled-plugins/plugins/lark/dist/lark-sdk/client.d.ts +8 -0
  30. package/bundled-plugins/plugins/lark/dist/lark-sdk/client.js +32 -0
  31. package/bundled-plugins/plugins/lark/dist/lark-sdk/index.d.ts +1 -0
  32. package/bundled-plugins/plugins/lark/dist/lark-sdk/index.js +1 -0
  33. package/bundled-plugins/plugins/lark/dist/lark-sender.d.ts +114 -0
  34. package/bundled-plugins/plugins/lark/dist/lark-sender.js +323 -0
  35. package/bundled-plugins/plugins/lark/dist/lark-session-store.d.ts +13 -0
  36. package/bundled-plugins/plugins/lark/dist/lark-session-store.js +14 -0
  37. package/bundled-plugins/plugins/lark/dist/lark-settings-card.d.ts +55 -0
  38. package/bundled-plugins/plugins/lark/dist/lark-settings-card.js +158 -0
  39. package/bundled-plugins/plugins/lark/dist/lark-setup.d.ts +39 -0
  40. package/bundled-plugins/plugins/lark/dist/lark-setup.js +103 -0
  41. package/bundled-plugins/plugins/lark/dist/lark.d.ts +507 -0
  42. package/bundled-plugins/plugins/lark/dist/lark.js +1975 -0
  43. package/bundled-plugins/plugins/lark/dist/runtime.d.ts +13 -0
  44. package/bundled-plugins/plugins/lark/dist/runtime.js +131328 -0
  45. package/bundled-plugins/plugins/lark/dist/settings.d.ts +7 -0
  46. package/bundled-plugins/plugins/lark/dist/settings.js +126971 -0
  47. package/bundled-plugins/plugins/lark/package.json +57 -0
  48. package/bundled-plugins/plugins/lark/ui/assets/index-CGUVAMsv.css +1 -0
  49. package/bundled-plugins/plugins/lark/ui/assets/index-D8Amoe6a.js +201 -0
  50. package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  51. package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  52. package/bundled-plugins/plugins/lark/ui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  53. package/bundled-plugins/plugins/lark/ui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  54. package/bundled-plugins/plugins/lark/ui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  55. package/bundled-plugins/plugins/lark/ui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  56. package/bundled-plugins/plugins/lark/ui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  57. package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  58. package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  59. package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  60. package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  61. package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  62. package/bundled-plugins/plugins/lark/ui/index.html +13 -0
  63. package/dist/agent-file.js +0 -1
  64. package/dist/browser-artifact-management.d.ts +4 -1
  65. package/dist/browser-artifact-management.js +18 -10
  66. package/dist/browser-artifacts.d.ts +1 -0
  67. package/dist/browser-artifacts.js +1 -0
  68. package/dist/bundled-plugins.d.ts +15 -0
  69. package/dist/bundled-plugins.js +134 -0
  70. package/dist/chrome-for-testing-runtime.d.ts +27 -0
  71. package/dist/chrome-for-testing-runtime.js +193 -0
  72. package/dist/chrome-for-testing-store.d.ts +2 -0
  73. package/dist/chrome-for-testing-store.js +9 -0
  74. package/dist/control-deps.d.ts +6 -2
  75. package/dist/control-deps.js +88 -82
  76. package/dist/daemon-server.d.ts +7 -1
  77. package/dist/daemon-server.js +310 -87
  78. package/dist/db.js +181 -124
  79. package/dist/entry-path.d.ts +3 -0
  80. package/dist/entry-path.js +12 -0
  81. package/dist/index-daemon.js +3 -66
  82. package/dist/lifecycle.d.ts +12 -0
  83. package/dist/lifecycle.js +16 -0
  84. package/dist/maintenance-lease.d.ts +39 -0
  85. package/dist/maintenance-lease.js +250 -0
  86. package/dist/migrations/cleanup-legacy-sessions.d.ts +1 -1
  87. package/dist/migrations/cleanup-legacy-sessions.js +33 -15
  88. package/dist/official-plugins.d.ts +2 -0
  89. package/dist/official-plugins.js +2 -0
  90. package/dist/plugin-cli.d.ts +1 -3
  91. package/dist/plugin-cli.js +56 -45
  92. package/dist/plugin-host-leases.d.ts +4 -0
  93. package/dist/plugin-host-leases.js +7 -0
  94. package/dist/plugin-host-rpc.d.ts +73 -6
  95. package/dist/plugin-host-rpc.js +354 -81
  96. package/dist/plugin-installer.d.ts +24 -55
  97. package/dist/plugin-installer.js +258 -412
  98. package/dist/plugin-management-service.d.ts +30 -23
  99. package/dist/plugin-management-service.js +288 -105
  100. package/dist/plugin-marketplace.d.ts +35 -0
  101. package/dist/plugin-marketplace.js +299 -0
  102. package/dist/plugin-package.d.ts +22 -24
  103. package/dist/plugin-package.js +520 -571
  104. package/dist/plugin-skill-context.d.ts +4 -0
  105. package/dist/plugin-skill-context.js +35 -0
  106. package/dist/plugin-store.d.ts +36 -37
  107. package/dist/plugin-store.js +138 -92
  108. package/dist/plugin-supervisor.d.ts +50 -125
  109. package/dist/plugin-supervisor.js +678 -1030
  110. package/dist/pm2.d.ts +11 -2
  111. package/dist/pm2.js +130 -28
  112. package/dist/process.d.ts +12 -0
  113. package/dist/process.js +91 -0
  114. package/dist/runtime-project-store.d.ts +9 -0
  115. package/dist/runtime-project-store.js +83 -0
  116. package/dist/session-fallback-workspace.d.ts +22 -0
  117. package/dist/session-fallback-workspace.js +120 -0
  118. package/dist/session-fork-store.d.ts +41 -0
  119. package/dist/session-fork-store.js +288 -0
  120. package/dist/session-launch-operations.d.ts +23 -2
  121. package/dist/session-launch-operations.js +48 -7
  122. package/dist/session-meta-store.d.ts +12 -9
  123. package/dist/session-meta-store.js +50 -49
  124. package/dist/session-portal-grant-store.d.ts +29 -0
  125. package/dist/session-portal-grant-store.js +84 -0
  126. package/dist/setup-service.d.ts +21 -0
  127. package/dist/setup-service.js +39 -0
  128. package/dist/skills-catalog.d.ts +11 -2
  129. package/dist/skills-catalog.js +307 -7
  130. package/dist/system-dependencies.d.ts +26 -0
  131. package/dist/system-dependencies.js +149 -0
  132. package/package.json +36 -20
  133. package/dist/browser-cli-args.d.ts +0 -20
  134. package/dist/browser-cli-args.js +0 -100
  135. package/dist/channel-store.d.ts +0 -22
  136. package/dist/channel-store.js +0 -65
  137. package/dist/cli.d.ts +0 -2
  138. package/dist/cli.js +0 -732
  139. package/dist/control-client.d.ts +0 -122
  140. package/dist/control-client.js +0 -855
  141. package/dist/control-endpoint.d.ts +0 -14
  142. package/dist/control-endpoint.js +0 -124
  143. package/dist/desktop-browser-host-client.d.ts +0 -35
  144. package/dist/desktop-browser-host-client.js +0 -415
  145. package/dist/instance-store.d.ts +0 -38
  146. package/dist/instance-store.js +0 -85
  147. package/dist/plugin-install-restart.d.ts +0 -13
  148. package/dist/plugin-install-restart.js +0 -24
  149. package/dist/plugin-runtime-control.d.ts +0 -2
  150. package/dist/plugin-runtime-control.js +0 -37
  151. package/dist/registry.d.ts +0 -10
  152. package/dist/registry.js +0 -52
  153. package/dist/setup.d.ts +0 -20
  154. package/dist/setup.js +0 -374
  155. package/dist/update.d.ts +0 -25
  156. package/dist/update.js +0 -133
package/dist/cli.js DELETED
@@ -1,732 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * `rynx` — the daemon CLI.
4
- *
5
- * rynx start | stop | restart | status | logs process lifecycle (pm2)
6
- * rynx plugin manage install|list|uninstall|enable|disable ...
7
- * rynx plugin <plugin-id> <plugin-command> ...
8
- * rynx agent list | show <name> | add <name> | rm <name>
9
- *
10
- * The CLI owns process lifecycle, plugin install/registry, and the file-based
11
- * declarative agent specs. Channel instances (a channel + an agent) are
12
- * configured in the web control console (`rynx start`, then open it).
13
- *
14
- * Hand-rolled arg dispatch (no arg-parser dep) to match the repo's zero-dep CLI
15
- * style.
16
- */
17
- import { spawn } from "node:child_process";
18
- import { existsSync } from "node:fs";
19
- import { createRequire } from "node:module";
20
- import path from "node:path";
21
- import { confirm, isCancel } from "@clack/prompts";
22
- import { listAgentSpecs, loadAgentSpec, loadConfig, rynxAgentsDir } from "@rynx-ai/core";
23
- import { encodePairingCode } from "@rynx-ai/protocol/direct-runtime";
24
- import { agentSpecPath, removeAgentSpec, scaffoldAgentSpec } from "./agent-file.js";
25
- import { parseBrowserCliArgs, resolveBrowserCliTarget, } from "./browser-cli-args.js";
26
- import { resolveChromeForTestingRelease } from "./chrome-for-testing-release-resolver.js";
27
- import { createChromeForTestingArtifactStore } from "./chrome-for-testing-store.js";
28
- import { dbPath } from "./db.js";
29
- import { cleanupLegacySessions } from "./migrations/cleanup-legacy-sessions.js";
30
- import { PluginCliUsageError, runPluginCliCommand } from "./plugin-cli.js";
31
- import { installPlugin, uninstallPlugin } from "./plugin-installer.js";
32
- import { restartAfterPluginInstall } from "./plugin-install-restart.js";
33
- import { getPlugin, isRunnablePluginRecord, listPlugins, setPluginEnabled } from "./plugin-store.js";
34
- import { ensureResidentPluginRuntime, reloadResidentPluginRuntime, } from "./plugin-runtime-control.js";
35
- import { isPm2DaemonOnline, startDaemon, statusDaemon, stopDaemon, streamLogs } from "./pm2.js";
36
- import { runDoctor, runSetup } from "./setup.js";
37
- import { runUpdate } from "./update.js";
38
- import { createResidentRemoteRuntimePairingOffer, callManagedRuntimeBrowser, callResidentRuntime, forgetResidentRuntimeTarget, getResidentRuntimeLocalBrowserEndpoint, listResidentRemoteRuntimeClients, listResidentRuntimeTargets, pairResidentRuntimeTarget, revokeResidentRemoteRuntimeClient, readOptionalManagedRuntimeBrowserCredential, testResidentRuntimeTarget, } from "./control-client.js";
39
- const USAGE = `Usage: rynx <command>
40
-
41
- Setup:
42
- setup interactive wizard — configure ~/.rynx/config.json step by step
43
- doctor read-only health check (creates nothing; non-zero on failure)
44
-
45
- Lifecycle:
46
- start start the resident server (pm2-supervised)
47
- restart reload the running server
48
- stop stop and remove the server
49
- status print whether the server is running
50
- logs tail the server logs
51
- update [version] upgrade @rynx-ai/daemon (npm) + restart (--check: report only)
52
-
53
- Plugins (static manifest + isolated runner):
54
- plugin manage list
55
- plugin manage install <npm|path|git|url> [...] [--expect-digest <sha256-...>]
56
- plugin manage update <id> [...] [--expect-digest <sha256-...>]
57
- plugin manage uninstall <id>
58
- plugin manage enable|disable <id>
59
- manage arbitrary installed plugins
60
- plugin <id> <command> run a command declared by that plugin
61
- (\`manage\` is a reserved plugin id)
62
-
63
- Agents (~/.rynx/agents/<id>/agent.json — dir name is the id):
64
- agent list list agents (id · runtime · model · [display name])
65
- agent show <id> print a parsed + validated agent spec
66
- agent add <id> scaffold an agent dir + starter spec, then edit it
67
- agent rm <id> remove an agent (its whole config dir)
68
- (select an agent in a chat with \`/agent <id>\`;
69
- set a fleet default via the RYNX_DEFAULT_AGENT env var)
70
-
71
- Maintenance:
72
- cleanup sessions [--dry-run]
73
- delete legacy (pre-uuid) sessions so the system starts
74
- clean on opaque ids (runs once at boot too). Stop the
75
- daemon before running manually.
76
-
77
- Emulator:
78
- emulator <args…> passthrough to the bundled \`rynx-emulator\` CLI
79
- (use --runtime <local|daemon-id> for bounded unary
80
- remote control; run \`rynx emulator\` for its help)
81
-
82
- Remote Runtime:
83
- runtime share --address <host|ws-url> [--label <label>] [--json]
84
- on the remote host, print one revocable pairing link
85
- runtime pair [...] compatibility alias for runtime share
86
- runtime add --pairing-code <rynx://...> [--name <name>]
87
- pair, verify and save a remote daemon
88
- (stdin remains supported for scripts)
89
- runtime list [--json] list the synthetic local target and paired daemons
90
- runtime test <local|daemon-id> [--json]
91
- authenticate and read the selected daemon status
92
- runtime forget <daemon-id>
93
- remove one local target and its client credential
94
- runtime clients list [--json]
95
- runtime clients revoke <grant-id>
96
- inspect/revoke clients authorized by this daemon
97
-
98
- Browser (one Browser per Runtime Session):
99
- browser install [--channel <stable|beta|dev|canary> | --version <x.x.x.x>] [--json]
100
- install and activate managed Chrome for Testing
101
- browser update [--channel <stable|beta|dev|canary>] [--json]
102
- resolve and activate the current channel build
103
- browser version [--json]
104
- show the active managed Browser engine
105
- browser clean [--json] remove inactive managed builds while retaining active,
106
- rollback, and live Headless Browser builds
107
- browser open [url] [--session <id>] [--runtime <local|daemon-id>] [--json]
108
- open the selected Runtime Session's managed Browser
109
- browser status [--session <id>] [--runtime <local|daemon-id>] [--json]
110
- show Browser generation, state and active Page
111
- browser pages [--session <id>] [--runtime <local|daemon-id>] [--json]
112
- list the Browser's opaque Pages
113
- browser endpoint [--ensure] [--session <local-id>] [--json]
114
- print Runtime-local CDP; --ensure opens it when absent
115
- browser close [--session <id>] [--runtime <local|daemon-id>] [--json]
116
- close the current Browser generation
117
-
118
- Channel instances (a channel + an agent) are configured in the web control
119
- console (run \`rynx start\`, then open the printed URL).
120
- `;
121
- function fail(message) {
122
- console.error(message);
123
- process.exit(2);
124
- }
125
- async function pluginManageCommand(sub, arg) {
126
- switch (sub) {
127
- case "list": {
128
- const plugins = listPlugins();
129
- console.log(`Plugins (db: ${dbPath()})`);
130
- if (plugins.length === 0) {
131
- console.log(" (none)");
132
- return;
133
- }
134
- for (const p of plugins) {
135
- const state = !isRunnablePluginRecord(p)
136
- ? "reinstall-required"
137
- : p.enabled
138
- ? "enabled"
139
- : "disabled";
140
- console.log(` ${p.name.padEnd(16)} ${(p.version ?? "-").padEnd(10)} ${p.source.padEnd(6)} ${state}`);
141
- }
142
- return;
143
- }
144
- case "install": {
145
- if (!arg)
146
- fail("plugin manage install: missing npm/path/git/url source");
147
- const force = process.argv.includes("--force");
148
- const grantAll = process.argv.includes("--grant-all");
149
- const allowScripts = process.argv.includes("--allow-scripts");
150
- const expectedDigest = digestOption(process.argv);
151
- const result = await installPlugin(arg, (line) => console.log(line), {
152
- allowScripts,
153
- ...(expectedDigest ? { expectedDigest } : {}),
154
- onConflict: async (existing) => {
155
- if (force)
156
- return true;
157
- const desc = `${existing.source}${existing.version ? ` @${existing.version}` : ""}`;
158
- if (!process.stdin.isTTY) {
159
- fail(`plugin "${existing.name}" already installed (${desc}). ` +
160
- `Re-run with --force, or \`rynx plugin manage uninstall ${existing.name}\` first.`);
161
- }
162
- const yes = await confirm({
163
- message: `插件 "${existing.name}" 已存在(${desc}),覆盖吗?`,
164
- initialValue: false,
165
- });
166
- return !isCancel(yes) && yes === true;
167
- },
168
- approveCapabilities: (manifest, existing) => approvePluginCapabilities(manifest, existing?.grants ?? [], grantAll),
169
- });
170
- if (result.skipped) {
171
- console.log(`已取消,保留现有插件 "${result.name}"。`);
172
- }
173
- else {
174
- console.log(`Plugin "${result.name}" (${result.source}${result.version ? ` @${result.version}` : ""}) installed.`);
175
- await restartAfterPluginInstall({
176
- restart: process.argv.includes("--restart"),
177
- interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
178
- }, {
179
- isDaemonOnline: isPm2DaemonOnline,
180
- confirmRestart: async () => {
181
- const answer = await confirm({
182
- message: "Restart Rynx now to apply the plugin?",
183
- initialValue: true,
184
- });
185
- return !isCancel(answer) && answer === true;
186
- },
187
- restartDaemon: () => startDaemon({ force: true }),
188
- log: (message) => console.log(message),
189
- });
190
- }
191
- return;
192
- }
193
- case "update": {
194
- if (!arg)
195
- fail("plugin manage update: missing plugin id");
196
- const existing = getPlugin(arg);
197
- if (!existing)
198
- fail(`plugin "${arg}" not found`);
199
- if (!isRunnablePluginRecord(existing)) {
200
- fail(`plugin "${arg}" uses the removed legacy format; reinstall it from an explicit source`);
201
- }
202
- const expectedDigest = digestOption(process.argv);
203
- const result = await installPlugin(existing.spec, (line) => console.log(line), {
204
- expectedId: existing.name,
205
- allowScripts: process.argv.includes("--allow-scripts"),
206
- ...(expectedDigest ? { expectedDigest } : {}),
207
- onConflict: () => true,
208
- approveCapabilities: (manifest, current) => approvePluginCapabilities(manifest, current?.grants ?? [], process.argv.includes("--grant-all")),
209
- });
210
- console.log(`Plugin "${result.name}" updated${result.version ? ` to ${result.version}` : ""}. Run \`rynx restart\` to apply.`);
211
- return;
212
- }
213
- case "uninstall": {
214
- if (!arg)
215
- fail("plugin manage uninstall: missing plugin id");
216
- if (!(await uninstallPlugin(arg, (line) => console.log(line))))
217
- fail(`plugin "${arg}" not found`);
218
- console.log(`Plugin "${arg}" uninstalled. Run \`rynx restart\` to apply.`);
219
- return;
220
- }
221
- case "enable":
222
- case "disable": {
223
- if (!arg)
224
- fail(`plugin manage ${sub}: missing plugin id`);
225
- const plugin = getPlugin(arg);
226
- if (!plugin)
227
- fail(`plugin "${arg}" not found`);
228
- if (!isRunnablePluginRecord(plugin))
229
- fail(`plugin "${arg}" must be reinstalled before it can be enabled`);
230
- setPluginEnabled(arg, sub === "enable");
231
- console.log(`Plugin "${arg}" ${sub}d. Run \`rynx restart\` to apply.`);
232
- return;
233
- }
234
- default:
235
- fail(USAGE);
236
- }
237
- }
238
- async function pluginCommand(args) {
239
- const [pluginId, command] = args;
240
- if (pluginId === "manage") {
241
- await pluginManageCommand(command, args[2]);
242
- return;
243
- }
244
- if (!pluginId)
245
- fail(USAGE);
246
- try {
247
- const result = await runPluginCliCommand(pluginId, args.slice(1));
248
- if (result.code !== 0) {
249
- process.exitCode = result.code;
250
- return;
251
- }
252
- const reload = result.effects.some((effect) => effect.effect === "runtime.reload");
253
- const ensure = result.effects.some((effect) => effect.effect === "runtime.ensure");
254
- if (reload || ensure) {
255
- try {
256
- if (reload)
257
- await reloadResidentPluginRuntime(pluginId);
258
- else
259
- await ensureResidentPluginRuntime(pluginId);
260
- }
261
- catch (error) {
262
- const detail = error instanceof Error ? error.message : String(error);
263
- throw new Error(reload
264
- ? `Plugin "${pluginId}" configuration was saved, but its runtime did not become ready: ${detail}`
265
- : `Plugin "${pluginId}" runtime did not become ready: ${detail}`);
266
- }
267
- if (!args.includes("--json"))
268
- console.log(`Plugin "${pluginId}" runtime is ready.`);
269
- }
270
- }
271
- catch (error) {
272
- if (error instanceof PluginCliUsageError) {
273
- console.log(error.message);
274
- return;
275
- }
276
- throw error;
277
- }
278
- }
279
- async function approvePluginCapabilities(manifest, existing, grantAll) {
280
- const requested = manifest.requestedCapabilities;
281
- const existingSet = new Set(existing);
282
- const newCapabilities = requested.filter((capability) => !existingSet.has(capability));
283
- if (newCapabilities.length === 0)
284
- return requested.filter((capability) => existingSet.has(capability));
285
- if (grantAll)
286
- return requested;
287
- console.log(`Plugin "${manifest.id}" requests host capabilities:`);
288
- for (const capability of newCapabilities)
289
- console.log(` - ${capability}`);
290
- if (!process.stdin.isTTY) {
291
- throw new Error("capability approval required; inspect the list and re-run with --grant-all");
292
- }
293
- const approved = await confirm({
294
- message: `Grant these ${newCapabilities.length} capability/capabilities to "${manifest.id}"?`,
295
- initialValue: false,
296
- });
297
- if (isCancel(approved) || approved !== true)
298
- throw new Error("plugin installation cancelled");
299
- return requested;
300
- }
301
- async function agentCommand(sub, name) {
302
- switch (sub) {
303
- case "list": {
304
- const specs = await listAgentSpecs();
305
- console.log(`Agents (dir: ${rynxAgentsDir()})`);
306
- if (specs.length === 0) {
307
- console.log(" (none)");
308
- return;
309
- }
310
- for (const spec of specs) {
311
- const runtime = spec.executor?.runtime ?? "(default)";
312
- const model = spec.executor?.model ?? "(default)";
313
- const display = spec.name && spec.name !== spec.id ? ` (${spec.name})` : "";
314
- console.log(` ${spec.id.padEnd(16)} ${runtime.padEnd(8)} ${model}${display}`);
315
- }
316
- return;
317
- }
318
- case "show": {
319
- if (!name)
320
- fail("agent show: missing agent name");
321
- const spec = await loadAgentSpec(name);
322
- if (!spec)
323
- fail(`agent "${name}" not found at ${agentSpecPath(name)}`);
324
- console.log(JSON.stringify(spec, null, 2));
325
- return;
326
- }
327
- case "add": {
328
- if (!name)
329
- fail("agent add: missing agent name");
330
- if (existsSync(agentSpecPath(name)))
331
- fail(`agent "${name}" already exists at ${agentSpecPath(name)}`);
332
- scaffoldAgentSpec(name);
333
- console.log(`Agent "${name}" created at ${agentSpecPath(name)}. Edit it, then select it in a chat with \`/agent ${name}\`.`);
334
- return;
335
- }
336
- case "rm":
337
- case "remove": {
338
- if (!name)
339
- fail("agent rm: missing agent name");
340
- if (!removeAgentSpec(name))
341
- fail(`agent "${name}" not found`);
342
- console.log(`Agent "${name}" removed.`);
343
- return;
344
- }
345
- default:
346
- fail(USAGE);
347
- }
348
- }
349
- async function cleanupCommand(sub) {
350
- if (sub !== "sessions")
351
- fail("cleanup: only `cleanup sessions` is supported");
352
- const dryRun = process.argv.includes("--dry-run");
353
- const result = cleanupLegacySessions({
354
- codexStorePath: loadConfig().AGENT_SESSION_STORE_PATH,
355
- dryRun,
356
- log: (entry) => console.log(JSON.stringify(entry)),
357
- });
358
- const summary = `${result.deletedSessions} session(s), ${result.deletedLogRows} log row(s), ${result.prunedStoreEntries} store entr(ies)`;
359
- console.log(dryRun ? `Dry run: would delete ${summary}.` : `Deleted ${summary}.`);
360
- }
361
- /** Pass `rynx emulator <args…>` through to the dependency's own CLI, verbatim.
362
- * Resolved from @rynx-ai/emulator (dist/cli.js sits beside the main entry), so it
363
- * runs the exact locked version — no PATH or npx involved. Stdio is inherited
364
- * so interactive flows (the skill install agent picker) work. */
365
- function emulatorPassthrough(args) {
366
- const require = createRequire(import.meta.url);
367
- const cliPath = path.join(path.dirname(require.resolve("@rynx-ai/emulator")), "cli.js");
368
- const child = spawn(process.execPath, [cliPath, ...args], { stdio: "inherit" });
369
- child.on("exit", (code) => process.exit(code ?? 1));
370
- child.on("error", (error) => {
371
- console.error(`rynx emulator: failed to launch the bundled CLI: ${error.message}`);
372
- process.exit(1);
373
- });
374
- }
375
- async function runtimeCommand(args) {
376
- const [sub, arg] = args;
377
- const json = args.includes("--json");
378
- switch (sub) {
379
- case "share":
380
- case "pair": {
381
- const label = optionValue(args, "--label");
382
- const address = optionValue(args, "--address");
383
- if (!address) {
384
- fail("runtime share: pass --address with a host or ws(s) URL reachable by the other device");
385
- }
386
- const offer = await createResidentRemoteRuntimePairingOffer({
387
- ...(label ? { clientLabel: label } : {}),
388
- address,
389
- });
390
- console.log(json ? JSON.stringify(offer, null, 2) : encodePairingCode(offer));
391
- return;
392
- }
393
- case "add": {
394
- const name = optionValue(args, "--name");
395
- const code = optionValue(args, "--pairing-code");
396
- if (code === undefined && process.stdin.isTTY) {
397
- fail("runtime add: pass --pairing-code or pipe a pairing link on stdin");
398
- }
399
- const raw = code ?? await readStdinBounded(64 * 1024);
400
- if (!raw.trim()) {
401
- fail("runtime add: pass --pairing-code or pipe a pairing link on stdin");
402
- }
403
- let offer = raw.trim();
404
- if (raw.trim().startsWith("{")) {
405
- try {
406
- offer = JSON.parse(raw);
407
- }
408
- catch {
409
- fail("runtime add: stdin is not valid pairing JSON");
410
- }
411
- }
412
- const result = await pairResidentRuntimeTarget(offer, name);
413
- if (json)
414
- console.log(JSON.stringify(result, null, 2));
415
- else {
416
- console.log(`Paired ${result.target.displayName} (${result.target.daemonId}) via ${result.target.endpoint}.`);
417
- console.log(`Remote instance: ${result.status.daemonInstanceId}`);
418
- }
419
- return;
420
- }
421
- case "list": {
422
- const targets = await listResidentRuntimeTargets();
423
- if (json) {
424
- console.log(JSON.stringify({ runtimes: targets }, null, 2));
425
- return;
426
- }
427
- console.log("Runtime targets");
428
- for (const target of targets) {
429
- const route = target.binding === "local" ? "local" : target.endpoint;
430
- console.log(` ${target.selector.padEnd(38)} ${target.displayName} ${route}`);
431
- }
432
- return;
433
- }
434
- case "test": {
435
- if (!arg || arg.startsWith("--"))
436
- fail("runtime test: missing local or daemon id");
437
- const result = await testResidentRuntimeTarget(arg);
438
- if (json)
439
- console.log(JSON.stringify(result, null, 2));
440
- else {
441
- console.log(`${result.target.displayName}: connected to ${result.status.daemonId} ` +
442
- `(instance ${result.status.daemonInstanceId})`);
443
- }
444
- return;
445
- }
446
- case "forget": {
447
- if (!arg || arg.startsWith("--"))
448
- fail("runtime forget: missing daemon id");
449
- await forgetResidentRuntimeTarget(arg);
450
- console.log(`Forgot Runtime target ${arg}.`);
451
- return;
452
- }
453
- case "clients": {
454
- const action = arg;
455
- if (action === "list") {
456
- const clients = await listResidentRemoteRuntimeClients();
457
- if (json) {
458
- console.log(JSON.stringify({ clients }, null, 2));
459
- return;
460
- }
461
- console.log("Remote Runtime clients");
462
- if (clients.length === 0)
463
- console.log(" (none)");
464
- for (const client of clients) {
465
- const state = client.revokedAt ? "revoked" : "active";
466
- console.log(` ${client.grantId.padEnd(38)} ${client.clientLabel ?? client.clientId} ${state}`);
467
- }
468
- return;
469
- }
470
- if (action === "revoke") {
471
- const grantId = args[2];
472
- if (!grantId || grantId.startsWith("--")) {
473
- fail("runtime clients revoke: missing grant id");
474
- }
475
- const result = await revokeResidentRemoteRuntimeClient(grantId);
476
- console.log(`Revoked ${grantId}; closed ${result.closedConnections} active connection(s).`);
477
- return;
478
- }
479
- fail("runtime clients: expected list or revoke <grant-id>");
480
- }
481
- default:
482
- fail(USAGE);
483
- }
484
- }
485
- async function browserCommand(args) {
486
- let parsed;
487
- try {
488
- parsed = parseBrowserCliArgs(args);
489
- }
490
- catch (error) {
491
- fail(error instanceof Error ? error.message : String(error));
492
- }
493
- const sub = parsed.subcommand;
494
- const json = parsed.json;
495
- if (sub === "install" || sub === "update") {
496
- const version = parsed.version;
497
- const channelValue = parsed.channel;
498
- if (version && channelValue) {
499
- fail("browser install: choose either --version or --channel");
500
- }
501
- if (sub === "update" && version) {
502
- fail("browser update: use --channel, or browser install --version for a pinned build");
503
- }
504
- const selector = version
505
- ? { kind: "version", version }
506
- : { kind: "channel", channel: browserReleaseChannel(channelValue) };
507
- const resolved = await resolveChromeForTestingRelease(selector);
508
- const installed = await createChromeForTestingArtifactStore().installResolved(resolved, {
509
- ...(json ? {} : { onProgress: (message) => console.log(message) }),
510
- });
511
- if (json)
512
- console.log(JSON.stringify({ resolved, installed }, null, 2));
513
- else
514
- console.log(`Active Browser engine: Chrome for Testing ${installed.version}.`);
515
- return;
516
- }
517
- if (sub === "version") {
518
- const installed = createChromeForTestingArtifactStore().readActive();
519
- if (json)
520
- console.log(JSON.stringify({ installed: installed ?? null }, null, 2));
521
- else if (installed) {
522
- console.log(`Chrome for Testing ${installed.version} · ${installed.hostPlatform} · ${installed.sha256}`);
523
- }
524
- else {
525
- console.log("No managed Chrome for Testing build is installed.");
526
- }
527
- return;
528
- }
529
- if (sub === "clean") {
530
- const result = createChromeForTestingArtifactStore().pruneBuilds();
531
- if (json)
532
- console.log(JSON.stringify(result, null, 2));
533
- else if (result.removedBuilds.length === 0) {
534
- console.log("No inactive Chrome for Testing builds were eligible for removal.");
535
- }
536
- else {
537
- console.log(`Removed ${result.removedBuilds.length} inactive Chrome for Testing build(s).`);
538
- }
539
- return;
540
- }
541
- if (sub === "endpoint") {
542
- const target = await resolveBrowserTarget(parsed);
543
- if (parsed.ensure) {
544
- await callBrowserRuntime(target, "browser.open", { sessionId: target.sessionId });
545
- }
546
- const descriptor = await getResidentRuntimeLocalBrowserEndpoint({
547
- ...(target.credential ? {} : { sessionId: target.sessionId }),
548
- });
549
- console.log(json ? JSON.stringify(descriptor, null, 2) : descriptor.endpoint);
550
- return;
551
- }
552
- const target = await resolveBrowserTarget(parsed);
553
- const sessionId = target.sessionId;
554
- if (sub === "open") {
555
- const state = await callBrowserRuntime(target, "browser.open", {
556
- sessionId,
557
- ...(parsed.url ? { url: parsed.url } : {}),
558
- });
559
- printBrowserState(state, json);
560
- return;
561
- }
562
- const state = await callBrowserRuntime(target, "browser.state.get", { sessionId });
563
- if (sub === "status") {
564
- printBrowserState(state, json);
565
- return;
566
- }
567
- if (sub === "pages") {
568
- if (json)
569
- console.log(JSON.stringify({ pages: state?.pages ?? [] }, null, 2));
570
- else
571
- printBrowserPages(state);
572
- return;
573
- }
574
- if (!state) {
575
- if (json)
576
- console.log(JSON.stringify({ closed: false, browser: null }, null, 2));
577
- else
578
- console.log(`No Browser is open for Session ${sessionId}.`);
579
- return;
580
- }
581
- const result = await callBrowserRuntime(target, "browser.close", {
582
- sessionId,
583
- browserGeneration: state.browserGeneration,
584
- });
585
- console.log(json
586
- ? JSON.stringify(result, null, 2)
587
- : `Closed Browser generation ${result.browserGeneration} for Session ${sessionId}.`);
588
- }
589
- function browserReleaseChannel(value) {
590
- const normalized = value === undefined
591
- ? "Stable"
592
- : `${value.slice(0, 1).toUpperCase()}${value.slice(1).toLowerCase()}`;
593
- if (normalized !== "Stable" &&
594
- normalized !== "Beta" &&
595
- normalized !== "Dev" &&
596
- normalized !== "Canary") {
597
- fail("browser: --channel must be stable, beta, dev, or canary");
598
- }
599
- return normalized;
600
- }
601
- async function resolveBrowserTarget(args) {
602
- const credential = await readOptionalManagedRuntimeBrowserCredential();
603
- try {
604
- return resolveBrowserCliTarget(args, credential);
605
- }
606
- catch (error) {
607
- fail(error instanceof Error ? error.message : String(error));
608
- }
609
- }
610
- async function callBrowserRuntime(target, method, params) {
611
- if (target.credential) {
612
- return callManagedRuntimeBrowser(target.credential, method, params);
613
- }
614
- return callResidentRuntime(target.runtimeSelector, method, params);
615
- }
616
- function printBrowserState(state, json) {
617
- if (json) {
618
- console.log(JSON.stringify({ browser: state }, null, 2));
619
- return;
620
- }
621
- if (!state) {
622
- console.log("No Browser is open for this Session.");
623
- return;
624
- }
625
- console.log(`Browser ${state.status} · ${state.executionBackend} · generation ${state.browserGeneration}`);
626
- printBrowserPages(state);
627
- }
628
- function printBrowserPages(state) {
629
- if (!state || state.pages.length === 0) {
630
- console.log(" (no Pages)");
631
- return;
632
- }
633
- for (const page of state.pages) {
634
- const marker = page.pageId === state.activePageId ? "*" : " ";
635
- const title = page.title ? ` ${page.title}` : "";
636
- console.log(`${marker} ${page.pageId} ${page.url}${title}`);
637
- }
638
- }
639
- function optionValue(args, option) {
640
- const index = args.indexOf(option);
641
- if (index < 0)
642
- return undefined;
643
- const value = args[index + 1];
644
- if (!value || value.startsWith("--"))
645
- fail(`${option}: missing value`);
646
- return value;
647
- }
648
- function digestOption(args) {
649
- const expected = optionValue(args, "--expect-digest");
650
- const legacyAlias = optionValue(args, "--expected-digest");
651
- if (expected && legacyAlias)
652
- fail("pass only one digest expectation option");
653
- return expected ?? legacyAlias;
654
- }
655
- async function readStdinBounded(maxBytes) {
656
- const chunks = [];
657
- let bytes = 0;
658
- for await (const chunk of process.stdin) {
659
- const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
660
- bytes += value.byteLength;
661
- if (bytes > maxBytes)
662
- fail(`stdin exceeds ${maxBytes} bytes`);
663
- chunks.push(value);
664
- }
665
- return Buffer.concat(chunks, bytes).toString("utf8");
666
- }
667
- async function main() {
668
- const [command, sub, arg] = process.argv.slice(2);
669
- switch (command) {
670
- case "setup":
671
- process.exit(await runSetup());
672
- break;
673
- case "doctor":
674
- process.exit(await runDoctor());
675
- break;
676
- case "update": {
677
- const rest = process.argv.slice(3);
678
- const version = rest.find((a) => !a.startsWith("--"));
679
- process.exit(await runUpdate({
680
- check: rest.includes("--check"),
681
- json: rest.includes("--json"),
682
- version,
683
- }));
684
- break;
685
- }
686
- case "start":
687
- process.exit(startDaemon({ force: false }));
688
- break;
689
- case "restart":
690
- process.exit(startDaemon({ force: true }));
691
- break;
692
- case "stop":
693
- process.exit(stopDaemon());
694
- break;
695
- case "status":
696
- process.exit(statusDaemon());
697
- break;
698
- case "logs":
699
- streamLogs();
700
- break;
701
- case "plugin":
702
- await pluginCommand(process.argv.slice(3));
703
- break;
704
- case "agent":
705
- await agentCommand(sub, arg);
706
- break;
707
- case "cleanup":
708
- await cleanupCommand(sub);
709
- break;
710
- case "emulator":
711
- emulatorPassthrough(process.argv.slice(3));
712
- break;
713
- case "runtime":
714
- await runtimeCommand(process.argv.slice(3));
715
- break;
716
- case "browser":
717
- await browserCommand(process.argv.slice(3));
718
- break;
719
- case undefined:
720
- case "help":
721
- case "-h":
722
- case "--help":
723
- console.log(USAGE);
724
- break;
725
- default:
726
- fail(`Unknown command: ${command}\n\n${USAGE}`);
727
- }
728
- }
729
- main().catch((err) => {
730
- console.error(err instanceof Error ? err.message : String(err));
731
- process.exit(1);
732
- });