@rynx-ai/daemon 0.1.10 → 0.1.11-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-plugins/.rynx-plugin/marketplace.json +10 -0
- package/bundled-plugins/plugins/lark/.rynx-plugin/plugin.json +37 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.d.ts +48 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.js +54 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.d.ts +85 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-mirror.js +333 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.d.ts +109 -0
- package/bundled-plugins/plugins/lark/dist/cli-mirror/rollout-watcher.js +347 -0
- package/bundled-plugins/plugins/lark/dist/host-adapters.d.ts +95 -0
- package/bundled-plugins/plugins/lark/dist/host-adapters.js +504 -0
- package/bundled-plugins/plugins/lark/dist/index.d.ts +7 -0
- package/bundled-plugins/plugins/lark/dist/index.js +7 -0
- package/bundled-plugins/plugins/lark/dist/lark-card-stream.d.ts +363 -0
- package/bundled-plugins/plugins/lark/dist/lark-card-stream.js +1335 -0
- package/bundled-plugins/plugins/lark/dist/lark-config-store.d.ts +30 -0
- package/bundled-plugins/plugins/lark/dist/lark-config-store.js +135 -0
- package/bundled-plugins/plugins/lark/dist/lark-content.d.ts +30 -0
- package/bundled-plugins/plugins/lark/dist/lark-content.js +138 -0
- package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.d.ts +65 -0
- package/bundled-plugins/plugins/lark/dist/lark-conversation-directory.js +106 -0
- package/bundled-plugins/plugins/lark/dist/lark-diff-card.d.ts +25 -0
- package/bundled-plugins/plugins/lark/dist/lark-diff-card.js +58 -0
- package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.d.ts +16 -0
- package/bundled-plugins/plugins/lark/dist/lark-fork-transcript.js +141 -0
- package/bundled-plugins/plugins/lark/dist/lark-resume-card.d.ts +31 -0
- package/bundled-plugins/plugins/lark/dist/lark-resume-card.js +105 -0
- package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.d.ts +18 -0
- package/bundled-plugins/plugins/lark/dist/lark-runtime-state-store.js +95 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/client.d.ts +8 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/client.js +32 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/index.d.ts +1 -0
- package/bundled-plugins/plugins/lark/dist/lark-sdk/index.js +1 -0
- package/bundled-plugins/plugins/lark/dist/lark-sender.d.ts +114 -0
- package/bundled-plugins/plugins/lark/dist/lark-sender.js +323 -0
- package/bundled-plugins/plugins/lark/dist/lark-session-store.d.ts +13 -0
- package/bundled-plugins/plugins/lark/dist/lark-session-store.js +14 -0
- package/bundled-plugins/plugins/lark/dist/lark-settings-card.d.ts +55 -0
- package/bundled-plugins/plugins/lark/dist/lark-settings-card.js +158 -0
- package/bundled-plugins/plugins/lark/dist/lark-setup.d.ts +39 -0
- package/bundled-plugins/plugins/lark/dist/lark-setup.js +103 -0
- package/bundled-plugins/plugins/lark/dist/lark.d.ts +507 -0
- package/bundled-plugins/plugins/lark/dist/lark.js +1977 -0
- package/bundled-plugins/plugins/lark/dist/runtime.d.ts +13 -0
- package/bundled-plugins/plugins/lark/dist/runtime.js +131316 -0
- package/bundled-plugins/plugins/lark/dist/settings.d.ts +7 -0
- package/bundled-plugins/plugins/lark/dist/settings.js +126958 -0
- package/bundled-plugins/plugins/lark/package.json +57 -0
- package/bundled-plugins/plugins/lark/ui/assets/index-B2dhMlMU.css +1 -0
- package/bundled-plugins/plugins/lark/ui/assets/index-D9N-AkLX.js +201 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/bundled-plugins/plugins/lark/ui/index.html +13 -0
- package/dist/bundled-plugins.d.ts +15 -0
- package/dist/bundled-plugins.js +134 -0
- package/dist/cli.js +26 -208
- package/dist/control-deps.js +2 -79
- package/dist/daemon-server.d.ts +4 -1
- package/dist/daemon-server.js +167 -57
- package/dist/db.js +145 -124
- package/dist/index-daemon.js +25 -4
- package/dist/migrations/cleanup-legacy-sessions.d.ts +1 -1
- package/dist/migrations/cleanup-legacy-sessions.js +33 -15
- package/dist/official-plugins.d.ts +2 -0
- package/dist/official-plugins.js +2 -0
- package/dist/plugin-cli.d.ts +1 -3
- package/dist/plugin-cli.js +56 -45
- package/dist/plugin-host-leases.d.ts +4 -0
- package/dist/plugin-host-leases.js +7 -0
- package/dist/plugin-host-rpc.d.ts +42 -4
- package/dist/plugin-host-rpc.js +144 -34
- package/dist/plugin-installer.d.ts +24 -55
- package/dist/plugin-installer.js +202 -415
- package/dist/plugin-management-service.d.ts +30 -23
- package/dist/plugin-management-service.js +290 -105
- package/dist/plugin-marketplace.d.ts +35 -0
- package/dist/plugin-marketplace.js +299 -0
- package/dist/plugin-package.d.ts +22 -24
- package/dist/plugin-package.js +520 -571
- package/dist/plugin-skill-context.d.ts +4 -0
- package/dist/plugin-skill-context.js +35 -0
- package/dist/plugin-store.d.ts +36 -37
- package/dist/plugin-store.js +140 -92
- package/dist/plugin-supervisor.d.ts +45 -125
- package/dist/plugin-supervisor.js +516 -1053
- package/dist/pm2.js +15 -10
- package/dist/runtime-project-store.d.ts +9 -0
- package/dist/runtime-project-store.js +83 -0
- package/dist/session-fallback-workspace.d.ts +22 -0
- package/dist/session-fallback-workspace.js +120 -0
- package/dist/session-fork-store.d.ts +41 -0
- package/dist/session-fork-store.js +288 -0
- package/dist/session-launch-operations.d.ts +14 -2
- package/dist/session-launch-operations.js +34 -2
- package/dist/session-meta-store.d.ts +7 -9
- package/dist/session-meta-store.js +28 -49
- package/dist/setup.js +26 -14
- package/package.json +14 -11
- package/dist/channel-store.d.ts +0 -22
- package/dist/channel-store.js +0 -65
- package/dist/instance-store.d.ts +0 -38
- package/dist/instance-store.js +0 -85
- package/dist/plugin-install-restart.d.ts +0 -13
- package/dist/plugin-install-restart.js +0 -24
- package/dist/plugin-runtime-control.d.ts +0 -2
- package/dist/plugin-runtime-control.js +0 -37
- package/dist/registry.d.ts +0 -10
- package/dist/registry.js +0 -52
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2
ADDED
|
Binary file
|
package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2
ADDED
|
Binary file
|
package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2
ADDED
|
Binary file
|
package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2
ADDED
|
Binary file
|
package/bundled-plugins/plugins/lark/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2
ADDED
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Lark settings</title>
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-D9N-AkLX.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B2dhMlMU.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface EnsureBundledPluginsResult {
|
|
2
|
+
status: "ready" | "unavailable";
|
|
3
|
+
installed: string[];
|
|
4
|
+
updated: string[];
|
|
5
|
+
unchanged: string[];
|
|
6
|
+
marketplacePath?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function ensureBundledOfficialPlugins(options?: {
|
|
9
|
+
bundleDirectory?: string;
|
|
10
|
+
defaultPlugins?: readonly string[];
|
|
11
|
+
onProgress?: (message: string) => void;
|
|
12
|
+
/** Reclaim supervisor leases left by a prior daemon process. The caller
|
|
13
|
+
* must already hold the exclusive RYNX_HOME daemon-owner lock. */
|
|
14
|
+
reclaimHostLeases?: boolean;
|
|
15
|
+
}): Promise<EnsureBundledPluginsResult>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, renameSync, rmSync, } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { isAbsolute, join } from "node:path";
|
|
4
|
+
import { rynxHome } from "@rynx-ai/core";
|
|
5
|
+
import { removePluginRuntimeLease } from "@rynx-ai/plugin-sdk";
|
|
6
|
+
import { pluginDataDir, preparePluginInstallation, } from "./plugin-installer.js";
|
|
7
|
+
import { PLUGIN_HOST_RUNTIME_LEASE_IDS } from "./plugin-host-leases.js";
|
|
8
|
+
import { addPluginMarketplace, resolveMarketplacePlugin, } from "./plugin-marketplace.js";
|
|
9
|
+
import { DEFAULT_BUNDLED_PLUGINS, OFFICIAL_MARKETPLACE_ID, } from "./official-plugins.js";
|
|
10
|
+
import { getPlugin, setPluginEnabled } from "./plugin-store.js";
|
|
11
|
+
export async function ensureBundledOfficialPlugins(options = {}) {
|
|
12
|
+
const configuredBundle = options.bundleDirectory ?? process.env.RYNX_BUNDLED_PLUGINS_DIR?.trim();
|
|
13
|
+
const bundleDirectory = configuredBundle ?? fileURLToPath(new URL("../bundled-plugins", import.meta.url));
|
|
14
|
+
if (!isAbsolute(bundleDirectory)) {
|
|
15
|
+
throw new Error("bundled plugin directory must be an absolute path");
|
|
16
|
+
}
|
|
17
|
+
if (!existsSync(bundleDirectory)) {
|
|
18
|
+
if (configuredBundle) {
|
|
19
|
+
throw new Error(`bundled plugin directory not found: ${bundleDirectory}`);
|
|
20
|
+
}
|
|
21
|
+
return emptyResult("unavailable");
|
|
22
|
+
}
|
|
23
|
+
if (!lstatSync(bundleDirectory).isDirectory()) {
|
|
24
|
+
throw new Error(`bundled plugin path is not a directory: ${bundleDirectory}`);
|
|
25
|
+
}
|
|
26
|
+
const marketplacePath = syncBundledMarketplace(bundleDirectory);
|
|
27
|
+
await addPluginMarketplace(marketplacePath, {
|
|
28
|
+
allowSourceRebind: true,
|
|
29
|
+
builtIn: true,
|
|
30
|
+
onProgress: options.onProgress,
|
|
31
|
+
});
|
|
32
|
+
const result = {
|
|
33
|
+
...emptyResult("ready"),
|
|
34
|
+
marketplacePath,
|
|
35
|
+
};
|
|
36
|
+
for (const identity of options.defaultPlugins ?? DEFAULT_BUNDLED_PLUGINS) {
|
|
37
|
+
if (options.reclaimHostLeases)
|
|
38
|
+
reclaimPluginHostLeases(identity);
|
|
39
|
+
const resolved = resolveMarketplacePlugin(identity);
|
|
40
|
+
const prepared = await preparePluginInstallation(resolved.spec, options.onProgress, {
|
|
41
|
+
marketplaceId: OFFICIAL_MARKETPLACE_ID,
|
|
42
|
+
expectedId: resolved.pluginId,
|
|
43
|
+
expectedIdentity: identity,
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
if (prepared.existing?.integrity === prepared.integrity) {
|
|
47
|
+
result.unchanged.push(identity);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const updating = Boolean(prepared.existing);
|
|
51
|
+
await prepared.commit({ expectedDigest: prepared.integrity });
|
|
52
|
+
if (!updating)
|
|
53
|
+
setPluginEnabled(identity, false);
|
|
54
|
+
(updating ? result.updated : result.installed).push(identity);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
prepared.discard();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
function reclaimPluginHostLeases(identity) {
|
|
63
|
+
const installed = getPlugin(identity);
|
|
64
|
+
if (!installed)
|
|
65
|
+
return;
|
|
66
|
+
const dataDir = pluginDataDir(installed.marketplaceId, installed.pluginId);
|
|
67
|
+
for (const leaseId of PLUGIN_HOST_RUNTIME_LEASE_IDS) {
|
|
68
|
+
removePluginRuntimeLease(dataDir, leaseId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function syncBundledMarketplace(bundleDirectory) {
|
|
72
|
+
const distributionRoot = join(rynxHome(), "distribution");
|
|
73
|
+
const marketplacePath = join(distributionRoot, "official-market");
|
|
74
|
+
mkdirSync(distributionRoot, { recursive: true, mode: 0o700 });
|
|
75
|
+
const transactionDirectory = mkdtempSync(join(distributionRoot, "official-market-stage-"));
|
|
76
|
+
const stagedMarketplace = join(transactionDirectory, "market");
|
|
77
|
+
const backupPath = join(distributionRoot, `official-market-backup-${process.pid}-${Date.now()}`);
|
|
78
|
+
let backedUp = false;
|
|
79
|
+
try {
|
|
80
|
+
copyBundledTree(bundleDirectory, stagedMarketplace);
|
|
81
|
+
if (existsSync(marketplacePath)) {
|
|
82
|
+
renameSync(marketplacePath, backupPath);
|
|
83
|
+
backedUp = true;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
renameSync(stagedMarketplace, marketplacePath);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (backedUp && !existsSync(marketplacePath)) {
|
|
90
|
+
renameSync(backupPath, marketplacePath);
|
|
91
|
+
backedUp = false;
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
if (backedUp) {
|
|
96
|
+
rmSync(backupPath, { recursive: true, force: true });
|
|
97
|
+
backedUp = false;
|
|
98
|
+
}
|
|
99
|
+
return marketplacePath;
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
rmSync(transactionDirectory, { recursive: true, force: true });
|
|
103
|
+
if (backedUp && !existsSync(marketplacePath) && existsSync(backupPath)) {
|
|
104
|
+
renameSync(backupPath, marketplacePath);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function copyBundledTree(source, destination) {
|
|
109
|
+
const info = lstatSync(source);
|
|
110
|
+
const mode = info.mode & 0o777;
|
|
111
|
+
if (info.isSymbolicLink()) {
|
|
112
|
+
throw new Error(`bundled plugin tree must not contain symbolic links: ${source}`);
|
|
113
|
+
}
|
|
114
|
+
if (info.isDirectory()) {
|
|
115
|
+
mkdirSync(destination, { recursive: true, mode: 0o700 });
|
|
116
|
+
for (const entry of readdirSync(source)) {
|
|
117
|
+
copyBundledTree(join(source, entry), join(destination, entry));
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!info.isFile()) {
|
|
122
|
+
throw new Error(`bundled plugin tree contains an unsupported entry: ${source}`);
|
|
123
|
+
}
|
|
124
|
+
copyFileSync(source, destination);
|
|
125
|
+
chmodSync(destination, mode);
|
|
126
|
+
}
|
|
127
|
+
function emptyResult(status) {
|
|
128
|
+
return {
|
|
129
|
+
status,
|
|
130
|
+
installed: [],
|
|
131
|
+
updated: [],
|
|
132
|
+
unchanged: [],
|
|
133
|
+
};
|
|
134
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* `rynx` — the daemon CLI.
|
|
4
4
|
*
|
|
5
5
|
* rynx start | stop | restart | status | logs process lifecycle (pm2)
|
|
6
|
-
* rynx
|
|
7
|
-
* rynx plugin
|
|
6
|
+
* rynx market add|list|remove|refresh ...
|
|
7
|
+
* rynx plugin install|list|update|uninstall|enable|disable ...
|
|
8
|
+
* rynx plugin <plugin-id>@<marketplace-id> <plugin-command> ...
|
|
8
9
|
* rynx agent list | show <name> | add <name> | rm <name>
|
|
9
10
|
*
|
|
10
|
-
* The CLI owns process lifecycle
|
|
11
|
-
*
|
|
12
|
-
* configured in the web control console (`rynx start`, then open it).
|
|
11
|
+
* The CLI owns process lifecycle and file-based declarative agent specs.
|
|
12
|
+
* Plugin and Market mutations go through the resident daemon management API.
|
|
13
13
|
*
|
|
14
14
|
* Hand-rolled arg dispatch (no arg-parser dep) to match the repo's zero-dep CLI
|
|
15
15
|
* style.
|
|
@@ -18,21 +18,15 @@ import { spawn } from "node:child_process";
|
|
|
18
18
|
import { existsSync } from "node:fs";
|
|
19
19
|
import { createRequire } from "node:module";
|
|
20
20
|
import path from "node:path";
|
|
21
|
-
import {
|
|
21
|
+
import { runCli as runModernCli } from "@rynx-ai/cli";
|
|
22
22
|
import { listAgentSpecs, loadAgentSpec, loadConfig, rynxAgentsDir } from "@rynx-ai/core";
|
|
23
23
|
import { encodePairingCode } from "@rynx-ai/protocol/direct-runtime";
|
|
24
24
|
import { agentSpecPath, removeAgentSpec, scaffoldAgentSpec } from "./agent-file.js";
|
|
25
25
|
import { parseBrowserCliArgs, resolveBrowserCliTarget, } from "./browser-cli-args.js";
|
|
26
26
|
import { resolveChromeForTestingRelease } from "./chrome-for-testing-release-resolver.js";
|
|
27
27
|
import { createChromeForTestingArtifactStore } from "./chrome-for-testing-store.js";
|
|
28
|
-
import { dbPath } from "./db.js";
|
|
29
28
|
import { cleanupLegacySessions } from "./migrations/cleanup-legacy-sessions.js";
|
|
30
|
-
import {
|
|
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";
|
|
29
|
+
import { startDaemon, statusDaemon, stopDaemon, streamLogs } from "./pm2.js";
|
|
36
30
|
import { runDoctor, runSetup } from "./setup.js";
|
|
37
31
|
import { runUpdate } from "./update.js";
|
|
38
32
|
import { createResidentRemoteRuntimePairingOffer, callManagedRuntimeBrowser, callResidentRuntime, forgetResidentRuntimeTarget, getResidentRuntimeLocalBrowserEndpoint, listResidentRemoteRuntimeClients, listResidentRuntimeTargets, pairResidentRuntimeTarget, revokeResidentRemoteRuntimeClient, readOptionalManagedRuntimeBrowserCredential, testResidentRuntimeTarget, } from "./control-client.js";
|
|
@@ -50,15 +44,19 @@ Lifecycle:
|
|
|
50
44
|
logs tail the server logs
|
|
51
45
|
update [version] upgrade @rynx-ai/daemon (npm) + restart (--check: report only)
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
plugin
|
|
61
|
-
|
|
47
|
+
Plugin marketplaces:
|
|
48
|
+
market add <git|path> [--alias <id>]
|
|
49
|
+
market list
|
|
50
|
+
market refresh [id]
|
|
51
|
+
market remove <id>
|
|
52
|
+
|
|
53
|
+
Plugins:
|
|
54
|
+
plugin list
|
|
55
|
+
plugin install <git|path|plugin@market> [--force]
|
|
56
|
+
plugin update <plugin@market>
|
|
57
|
+
plugin uninstall <plugin@market>
|
|
58
|
+
plugin enable|disable <plugin@market>
|
|
59
|
+
plugin <plugin@market> <command> [args...]
|
|
62
60
|
|
|
63
61
|
Agents (~/.rynx/agents/<id>/agent.json — dir name is the id):
|
|
64
62
|
agent list list agents (id · runtime · model · [display name])
|
|
@@ -115,189 +113,13 @@ Browser (one Browser per Runtime Session):
|
|
|
115
113
|
browser close [--session <id>] [--runtime <local|daemon-id>] [--json]
|
|
116
114
|
close the current Browser generation
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
Plugin-owned settings and channel instances are configured from each plugin's
|
|
117
|
+
management interface (run \`rynx start\`, then open the printed URL).
|
|
120
118
|
`;
|
|
121
119
|
function fail(message) {
|
|
122
120
|
console.error(message);
|
|
123
121
|
process.exit(2);
|
|
124
122
|
}
|
|
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
123
|
async function agentCommand(sub, name) {
|
|
302
124
|
switch (sub) {
|
|
303
125
|
case "list": {
|
|
@@ -645,13 +467,6 @@ function optionValue(args, option) {
|
|
|
645
467
|
fail(`${option}: missing value`);
|
|
646
468
|
return value;
|
|
647
469
|
}
|
|
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
470
|
async function readStdinBounded(maxBytes) {
|
|
656
471
|
const chunks = [];
|
|
657
472
|
let bytes = 0;
|
|
@@ -699,7 +514,10 @@ async function main() {
|
|
|
699
514
|
streamLogs();
|
|
700
515
|
break;
|
|
701
516
|
case "plugin":
|
|
702
|
-
await
|
|
517
|
+
process.exitCode = await runModernCli(["plugin", ...process.argv.slice(3)]);
|
|
518
|
+
break;
|
|
519
|
+
case "market":
|
|
520
|
+
process.exitCode = await runModernCli(["market", ...process.argv.slice(3)]);
|
|
703
521
|
break;
|
|
704
522
|
case "agent":
|
|
705
523
|
await agentCommand(sub, arg);
|
package/dist/control-deps.js
CHANGED
|
@@ -1,89 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Assemble the daemon-side {@link ControlPlaneDeps} the server needs to serve
|
|
3
|
-
* the control console:
|
|
4
|
-
*
|
|
5
|
-
* managed via the CLI, not here. Keeps `~/.rynx` knowledge in the daemon (the
|
|
3
|
+
* the control console: file-backed agent specs, skills, sessions, and a log
|
|
4
|
+
* tail. Plugin-private configuration is served by each plugin. Keeps `~/.rynx` knowledge in the daemon (the
|
|
6
5
|
* composition root); the server stays storage-agnostic.
|
|
7
6
|
*/
|
|
8
7
|
import { readFile } from "node:fs/promises";
|
|
9
8
|
import { join } from "node:path";
|
|
10
9
|
import { listAgentSpecs, loadAgentSpec, rynxHome } from "@rynx-ai/core";
|
|
11
10
|
import { createEmulatorControlDeps } from "@rynx-ai/emulator";
|
|
12
|
-
import { normalizePluginConfig } from "@rynx-ai/plugin-sdk";
|
|
13
11
|
import { removeAgentSpec, writeAgentSpec } from "./agent-file.js";
|
|
14
12
|
import { getCatalogSkill, installCatalogSkill, listCatalogSkills, readCatalogSkillFile, removeCatalogSkill, } from "./skills-catalog.js";
|
|
15
|
-
import { createChannel, getChannel, listChannels, removeChannel, renameChannel, setChannelOptions, } from "./channel-store.js";
|
|
16
|
-
import { createInstance, listInstances, removeInstance, setInstanceAgent, setInstanceEnabled, } from "./instance-store.js";
|
|
17
|
-
import { getChannelType, listChannelTypes } from "./registry.js";
|
|
18
13
|
import { createSessionMeta, getSessionMeta, listSessionMetas, removeSessionMeta, setSessionTitle, } from "./session-meta-store.js";
|
|
19
14
|
import { consumeControlLink } from "./control-link-store.js";
|
|
20
15
|
export function buildControlDeps() {
|
|
21
16
|
return {
|
|
22
|
-
// ── channel types (from loaded plugins) ──────────────────────────────
|
|
23
|
-
listChannelTypes: () => listChannelTypes().map((descriptor) => ({
|
|
24
|
-
type: descriptor.type,
|
|
25
|
-
configSchema: descriptor.configSchema,
|
|
26
|
-
authorize: Boolean(descriptor.authorize),
|
|
27
|
-
})),
|
|
28
|
-
// ── channels (config + credentials) ──────────────────────────────────
|
|
29
|
-
listChannels: () => listChannels(),
|
|
30
|
-
createChannel: (input) => {
|
|
31
|
-
if (!getChannelType(input.type))
|
|
32
|
-
throw new Error(`unknown chat channel type: ${input.type}`);
|
|
33
|
-
return {
|
|
34
|
-
id: createChannel({
|
|
35
|
-
...input,
|
|
36
|
-
...(input.options !== undefined
|
|
37
|
-
? { options: normalizeChannelOptions(input.type, input.options) }
|
|
38
|
-
: {}),
|
|
39
|
-
}).id,
|
|
40
|
-
};
|
|
41
|
-
},
|
|
42
|
-
setChannel: (id, patch) => {
|
|
43
|
-
let normalizedOptions;
|
|
44
|
-
if (patch.options !== undefined) {
|
|
45
|
-
const current = getChannel(id);
|
|
46
|
-
if (!current)
|
|
47
|
-
throw new Error(`channel not found: ${id}`);
|
|
48
|
-
normalizedOptions = normalizeChannelOptions(current.type, {
|
|
49
|
-
...(current.options ?? {}),
|
|
50
|
-
...patch.options,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
if (patch.name !== undefined)
|
|
54
|
-
renameChannel(id, patch.name);
|
|
55
|
-
if (normalizedOptions !== undefined)
|
|
56
|
-
setChannelOptions(id, normalizedOptions);
|
|
57
|
-
},
|
|
58
|
-
removeChannel: (id) => {
|
|
59
|
-
removeChannel(id);
|
|
60
|
-
},
|
|
61
|
-
authorizeChannel: (type, context, emit, signal) => {
|
|
62
|
-
const descriptor = getChannelType(type);
|
|
63
|
-
if (!descriptor?.authorize) {
|
|
64
|
-
throw new Error(`channel type "${type}" has no authorize flow`);
|
|
65
|
-
}
|
|
66
|
-
return descriptor.authorize(emit, signal, context);
|
|
67
|
-
},
|
|
68
|
-
// ── instances (channel + agent binding) ──────────────────────────────
|
|
69
|
-
listInstancesConfig: () => listInstances().map((i) => ({
|
|
70
|
-
id: i.id,
|
|
71
|
-
channelId: i.channelId,
|
|
72
|
-
channelName: i.channelName,
|
|
73
|
-
type: i.type,
|
|
74
|
-
agent: i.agent,
|
|
75
|
-
enabled: i.enabled,
|
|
76
|
-
})),
|
|
77
|
-
createInstance: (input) => ({ id: createInstance(input).id }),
|
|
78
|
-
setInstance: (id, patch) => {
|
|
79
|
-
if (patch.agent !== undefined)
|
|
80
|
-
setInstanceAgent(id, patch.agent);
|
|
81
|
-
if (patch.enabled !== undefined)
|
|
82
|
-
setInstanceEnabled(id, patch.enabled);
|
|
83
|
-
},
|
|
84
|
-
removeInstance: (id) => {
|
|
85
|
-
removeInstance(id);
|
|
86
|
-
},
|
|
87
17
|
// ── declarative agents ───────────────────────────────────────────────
|
|
88
18
|
listAgents: async () => (await listAgentSpecs()).map((spec) => ({
|
|
89
19
|
id: spec.id,
|
|
@@ -114,13 +44,6 @@ export function buildControlDeps() {
|
|
|
114
44
|
tailLogs: (instanceId, lines) => tailLogs(instanceId, lines),
|
|
115
45
|
};
|
|
116
46
|
}
|
|
117
|
-
function normalizeChannelOptions(type, options) {
|
|
118
|
-
const descriptor = getChannelType(type);
|
|
119
|
-
if (!descriptor)
|
|
120
|
-
throw new Error(`unknown chat channel type: ${type}`);
|
|
121
|
-
const schema = descriptor.configSchema ?? [];
|
|
122
|
-
return schema.length > 0 ? normalizePluginConfig(schema, options) : { ...options };
|
|
123
|
-
}
|
|
124
47
|
/** Tail the daemon's merged pm2 logs, best-effort filtered by instance id. */
|
|
125
48
|
async function tailLogs(instanceId, lines) {
|
|
126
49
|
const dir = join(rynxHome(), "logs");
|
package/dist/daemon-server.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface StartRynxDaemonServerOptions {
|
|
|
13
13
|
writeEndpoint?: (config: AppConfig, managementToken: string) => Promise<void>;
|
|
14
14
|
/** Test seam for owner-lock failure injection. Production always uses the RYNX_HOME lease. */
|
|
15
15
|
acquireOwner?: () => Promise<DaemonOwnerLease>;
|
|
16
|
+
/** Runs after the exclusive daemon-owner lock is acquired and before plugin
|
|
17
|
+
* records are loaded or runners are started. */
|
|
18
|
+
preparePlugins?: () => Promise<void>;
|
|
16
19
|
/** Test/deployment seam for the always-available Direct Runtime socket. */
|
|
17
20
|
loadDirectConfig?: () => Promise<DirectRuntimeConfig>;
|
|
18
21
|
/** Test seam for listener lifecycle and bind failures. */
|
|
@@ -22,7 +25,7 @@ export interface StartRynxDaemonServerOptions {
|
|
|
22
25
|
/** Test seam for the App-only embedded Chromium process supervisor. */
|
|
23
26
|
createBrowserHostSupervisor?: (options: AppBrowserHostSupervisorOptions) => Pick<AppBrowserHostSupervisor, "ensureConnected" | "restart" | "stop">;
|
|
24
27
|
}
|
|
25
|
-
export declare function startRynxDaemonServer({ config, warn, writeEndpoint, acquireOwner, loadDirectConfig, startDirectServer, createChromeInspectionManager, createBrowserHostSupervisor, }?: StartRynxDaemonServerOptions): Promise<Awaited<ReturnType<typeof startServer>>>;
|
|
28
|
+
export declare function startRynxDaemonServer({ config, warn, writeEndpoint, acquireOwner, preparePlugins, loadDirectConfig, startDirectServer, createChromeInspectionManager, createBrowserHostSupervisor, }?: StartRynxDaemonServerOptions): Promise<Awaited<ReturnType<typeof startServer>>>;
|
|
26
29
|
export declare function createSupervisedAppSessionBrowserHost(desktop: SessionBrowserHost, supervisor: Pick<AppBrowserHostSupervisor, "ensureConnected" | "restart">): SessionBrowserHost;
|
|
27
30
|
/**
|
|
28
31
|
* Resolve the authenticated semantic target inside its owning Runtime and
|