@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
|
@@ -31,12 +31,44 @@ export class SessionLaunchOperationTargetDeletedError extends Error {
|
|
|
31
31
|
this.name = "SessionLaunchOperationTargetDeletedError";
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Read the durable idempotency fence before resolving mutable launch selectors
|
|
36
|
+
* such as a Project or Agent. A replay must not fail merely because the
|
|
37
|
+
* original template was edited or deleted after the Session snapshot existed.
|
|
38
|
+
*
|
|
39
|
+
* `undefined` means the caller must resolve snapshots and proceed through
|
|
40
|
+
* {@link ensurePluginSessionLaunch}; that function remains the atomic race
|
|
41
|
+
* winner when two first attempts arrive concurrently.
|
|
42
|
+
*/
|
|
43
|
+
export function replayPluginSessionLaunch(input) {
|
|
44
|
+
const pluginId = requiredId(input.pluginId, "pluginId");
|
|
45
|
+
const scopeId = requiredId(input.scopeId, "scopeId");
|
|
46
|
+
const operationId = requiredId(input.operationId, "operationId");
|
|
47
|
+
const requestHash = requiredRequestHash(input.requestHash);
|
|
48
|
+
const existing = readOperation(pluginId, scopeId, operationId);
|
|
49
|
+
if (!existing)
|
|
50
|
+
return undefined;
|
|
51
|
+
if (existing.request_hash !== requestHash) {
|
|
52
|
+
throw new SessionLaunchOperationConflictError(pluginId, scopeId, operationId);
|
|
53
|
+
}
|
|
54
|
+
if (existing.state === "deleted") {
|
|
55
|
+
throw new SessionLaunchOperationTargetDeletedError(pluginId, scopeId, operationId, existing.session_id);
|
|
56
|
+
}
|
|
57
|
+
if (!sessionExists(existing.session_id)) {
|
|
58
|
+
db().transaction(() => {
|
|
59
|
+
tombstoneOperations(existing.session_id, new Date().toISOString());
|
|
60
|
+
}).immediate();
|
|
61
|
+
throw new SessionLaunchOperationTargetDeletedError(pluginId, scopeId, operationId, existing.session_id);
|
|
62
|
+
}
|
|
63
|
+
return { disposition: "replayed", sessionId: existing.session_id };
|
|
64
|
+
}
|
|
34
65
|
/**
|
|
35
66
|
* Atomically allocate a persisted machine session for one plugin operation.
|
|
36
67
|
*
|
|
37
68
|
* The durable operation row is the idempotency boundary across runner crashes,
|
|
38
|
-
* daemon restarts, and remote lease re-delivery.
|
|
39
|
-
*
|
|
69
|
+
* daemon restarts, and remote lease re-delivery. `scopeId` and `operationId`
|
|
70
|
+
* remain opaque; the Session row stores only the already-resolved workspace
|
|
71
|
+
* snapshot, never a Project identity.
|
|
40
72
|
*/
|
|
41
73
|
export function ensurePluginSessionLaunch(input) {
|
|
42
74
|
const pluginId = requiredId(input.pluginId, "pluginId");
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The unified machine-session record (SQLite) — one row per session regardless
|
|
3
|
-
* of origin (the web console AND every channel). Holds
|
|
4
|
-
*
|
|
5
|
-
* daemon restart
|
|
3
|
+
* of origin (the web console AND every channel). Holds immutable workspace /
|
|
4
|
+
* execution snapshots plus display metadata so the **session list survives a
|
|
5
|
+
* daemon restart** without re-reading a Project or Agent; the transcript lives
|
|
6
|
+
* in `session_items` (see
|
|
6
7
|
* {@link import("./session-log-store.js")}). Runtime `status` is intentionally
|
|
7
8
|
* not stored — it is reconstructed as `idle` after a restart.
|
|
8
9
|
*
|
|
9
10
|
* Exposes both the standalone functions the control-plane deps wire in and a
|
|
10
|
-
* {@link SessionRegistry} adapter ({@link sessionRegistry})
|
|
11
|
-
*
|
|
12
|
-
* console does.
|
|
11
|
+
* {@link SessionRegistry} adapter ({@link sessionRegistry}) used by daemon
|
|
12
|
+
* session services and capability-checked plugin Host RPC.
|
|
13
13
|
*/
|
|
14
14
|
import { type MachineSessionRecord, type SessionRegistry } from "@rynx-ai/core";
|
|
15
15
|
/** Back-compat alias for the unified record. */
|
|
@@ -17,9 +17,7 @@ export type StoredSessionMeta = MachineSessionRecord;
|
|
|
17
17
|
export declare function listSessionMetas(): StoredSessionMeta[];
|
|
18
18
|
export declare function getSessionMeta(id: string): StoredSessionMeta | undefined;
|
|
19
19
|
export declare function createSessionMeta(meta: StoredSessionMeta): void;
|
|
20
|
-
export declare function updateSessionMeta(meta: StoredSessionMeta): void;
|
|
21
20
|
export declare function setSessionTitle(id: string, title: string): void;
|
|
22
21
|
export declare function removeSessionMeta(id: string): void;
|
|
23
|
-
/** {@link SessionRegistry} over the same `sessions` table
|
|
24
|
-
* receive through their `ChannelContext`. */
|
|
22
|
+
/** {@link SessionRegistry} over the same `sessions` table. */
|
|
25
23
|
export declare const sessionRegistry: SessionRegistry;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The unified machine-session record (SQLite) — one row per session regardless
|
|
3
|
-
* of origin (the web console AND every channel). Holds
|
|
4
|
-
*
|
|
5
|
-
* daemon restart
|
|
3
|
+
* of origin (the web console AND every channel). Holds immutable workspace /
|
|
4
|
+
* execution snapshots plus display metadata so the **session list survives a
|
|
5
|
+
* daemon restart** without re-reading a Project or Agent; the transcript lives
|
|
6
|
+
* in `session_items` (see
|
|
6
7
|
* {@link import("./session-log-store.js")}). Runtime `status` is intentionally
|
|
7
8
|
* not stored — it is reconstructed as `idle` after a restart.
|
|
8
9
|
*
|
|
9
10
|
* Exposes both the standalone functions the control-plane deps wire in and a
|
|
10
|
-
* {@link SessionRegistry} adapter ({@link sessionRegistry})
|
|
11
|
-
*
|
|
12
|
-
* console does.
|
|
11
|
+
* {@link SessionRegistry} adapter ({@link sessionRegistry}) used by daemon
|
|
12
|
+
* session services and capability-checked plugin Host RPC.
|
|
13
13
|
*/
|
|
14
|
-
import { normalizeSessionTitle, } from "@rynx-ai/core";
|
|
14
|
+
import { normalizeSessionTitle, resolvedExecutionSnapshotSchema, sessionWorkspaceSnapshotSchema, } from "@rynx-ai/core";
|
|
15
15
|
import { db } from "./db.js";
|
|
16
|
-
const COLS = "id,
|
|
16
|
+
const COLS = "id, workspace, execution, title, forked_from_session_id, source, created_at, updated_at";
|
|
17
17
|
export function listSessionMetas() {
|
|
18
18
|
return db()
|
|
19
19
|
.prepare(`SELECT ${COLS} FROM sessions ORDER BY created_at`)
|
|
@@ -27,45 +27,22 @@ export function getSessionMeta(id) {
|
|
|
27
27
|
export function createSessionMeta(meta) {
|
|
28
28
|
db()
|
|
29
29
|
.prepare(`INSERT OR IGNORE INTO sessions
|
|
30
|
-
(id,
|
|
31
|
-
VALUES (
|
|
30
|
+
(id, workspace, execution, title, forked_from_session_id, source, created_at, updated_at)
|
|
31
|
+
VALUES (
|
|
32
|
+
@id, @workspace, @execution, @title, @forked_from_session_id,
|
|
33
|
+
@source, @created_at, @updated_at
|
|
34
|
+
)`)
|
|
32
35
|
.run({
|
|
33
36
|
id: meta.id,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
config: meta.config ? JSON.stringify(meta.config) : null,
|
|
37
|
-
model: meta.model ?? null,
|
|
38
|
-
reasoning_effort: meta.reasoningEffort ?? null,
|
|
37
|
+
workspace: JSON.stringify(sessionWorkspaceSnapshotSchema.parse(meta.workspace)),
|
|
38
|
+
execution: JSON.stringify(resolvedExecutionSnapshotSchema.parse(meta.execution)),
|
|
39
39
|
title: normalizeSessionTitle(meta.title) ?? null,
|
|
40
|
+
forked_from_session_id: meta.forkedFromSessionId ?? null,
|
|
40
41
|
source: meta.source,
|
|
41
42
|
created_at: meta.createdAt,
|
|
42
43
|
updated_at: meta.updatedAt ?? meta.createdAt,
|
|
43
44
|
});
|
|
44
45
|
}
|
|
45
|
-
export function updateSessionMeta(meta) {
|
|
46
|
-
db()
|
|
47
|
-
.prepare(`UPDATE sessions
|
|
48
|
-
SET provider = @provider,
|
|
49
|
-
agent = @agent,
|
|
50
|
-
config = @config,
|
|
51
|
-
model = @model,
|
|
52
|
-
reasoning_effort = @reasoning_effort,
|
|
53
|
-
title = @title,
|
|
54
|
-
source = @source,
|
|
55
|
-
updated_at = @updated_at
|
|
56
|
-
WHERE id = @id`)
|
|
57
|
-
.run({
|
|
58
|
-
id: meta.id,
|
|
59
|
-
provider: meta.provider ?? null,
|
|
60
|
-
agent: meta.agent ?? null,
|
|
61
|
-
config: meta.config ? JSON.stringify(meta.config) : null,
|
|
62
|
-
model: meta.model ?? null,
|
|
63
|
-
reasoning_effort: meta.reasoningEffort ?? null,
|
|
64
|
-
title: normalizeSessionTitle(meta.title) ?? null,
|
|
65
|
-
source: meta.source,
|
|
66
|
-
updated_at: meta.updatedAt ?? new Date().toISOString(),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
46
|
export function setSessionTitle(id, title) {
|
|
70
47
|
db()
|
|
71
48
|
.prepare("UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?")
|
|
@@ -79,11 +56,15 @@ export function removeSessionMeta(id) {
|
|
|
79
56
|
SET state = 'deleted', updated_at = ?, deleted_at = ?
|
|
80
57
|
WHERE session_id = ? AND state = 'active'`)
|
|
81
58
|
.run(now, now, id);
|
|
59
|
+
db()
|
|
60
|
+
.prepare(`UPDATE session_fork_operations
|
|
61
|
+
SET state = 'target_deleted', updated_at = ?, deleted_at = ?
|
|
62
|
+
WHERE target_session_id = ? AND state IN ('reserved', 'completed')`)
|
|
63
|
+
.run(now, now, id);
|
|
82
64
|
db().prepare("DELETE FROM sessions WHERE id = ?").run(id);
|
|
83
65
|
}).immediate();
|
|
84
66
|
}
|
|
85
|
-
/** {@link SessionRegistry} over the same `sessions` table
|
|
86
|
-
* receive through their `ChannelContext`. */
|
|
67
|
+
/** {@link SessionRegistry} over the same `sessions` table. */
|
|
87
68
|
export const sessionRegistry = {
|
|
88
69
|
create: createSessionMeta,
|
|
89
70
|
get: getSessionMeta,
|
|
@@ -94,17 +75,15 @@ export const sessionRegistry = {
|
|
|
94
75
|
function rowToMeta(row) {
|
|
95
76
|
return {
|
|
96
77
|
id: row.id,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
: undefined,
|
|
100
|
-
agent: row.agent ?? undefined,
|
|
101
|
-
config: row.config ? JSON.parse(row.config) : undefined,
|
|
102
|
-
model: row.model ?? undefined,
|
|
103
|
-
reasoningEffort: (row.reasoning_effort ?? undefined),
|
|
78
|
+
workspace: sessionWorkspaceSnapshotSchema.parse(JSON.parse(row.workspace)),
|
|
79
|
+
execution: resolvedExecutionSnapshotSchema.parse(JSON.parse(row.execution)),
|
|
104
80
|
// Normalize on read as well so pre-boundary database rows cannot poison an
|
|
105
81
|
// entire Remote Session list page after upgrading the daemon.
|
|
106
82
|
title: normalizeSessionTitle(row.title ?? undefined),
|
|
107
|
-
|
|
83
|
+
...(row.forked_from_session_id
|
|
84
|
+
? { forkedFromSessionId: row.forked_from_session_id }
|
|
85
|
+
: {}),
|
|
86
|
+
source: row.source,
|
|
108
87
|
createdAt: row.created_at,
|
|
109
88
|
updatedAt: row.updated_at ?? row.created_at,
|
|
110
89
|
};
|
package/dist/setup.js
CHANGED
|
@@ -14,12 +14,11 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "n
|
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import * as p from "@clack/prompts";
|
|
16
16
|
import { AGENT_RUNTIME_IDS, getRuntimeProfile, listAgentSpecs, loadConfig, resolveRuntimeHome, rynxAgentsDir, rynxConfigFile, rynxHome, } from "@rynx-ai/core";
|
|
17
|
-
import { listChannels } from "./channel-store.js";
|
|
18
17
|
import { resolveChromeForTestingRelease } from "./chrome-for-testing-release-resolver.js";
|
|
19
18
|
import { createChromeForTestingArtifactStore, isChromeForTestingHostSupported, } from "./chrome-for-testing-store.js";
|
|
19
|
+
import { ensureBundledOfficialPlugins } from "./bundled-plugins.js";
|
|
20
20
|
import { dbPath } from "./db.js";
|
|
21
|
-
import {
|
|
22
|
-
import { isRunnablePluginRecord, listPlugins } from "./plugin-store.js";
|
|
21
|
+
import { listPlugins } from "./plugin-store.js";
|
|
23
22
|
import { formatControlUrl } from "./pm2.js";
|
|
24
23
|
const MIN_NODE_MAJOR = 20;
|
|
25
24
|
export function controlListenModeFromHost(host) {
|
|
@@ -49,11 +48,13 @@ export async function runSetup() {
|
|
|
49
48
|
if (!existsSync(rynxConfigFile()))
|
|
50
49
|
writeConfig({ HOST: "127.0.0.1", PORT: 3000, LOG_LEVEL: "info" });
|
|
51
50
|
const browser = inspectManagedBrowser();
|
|
51
|
+
const bundledMessage = await setupBundledPlugins();
|
|
52
52
|
console.log(`非交互环境:已确保 ${rynxConfigFile()} 存在(默认值)。` +
|
|
53
53
|
"在终端(TTY)下重跑 `rynx setup` 可分步配置,或直接编辑该文件。" +
|
|
54
54
|
(browser.supported && !browser.installed
|
|
55
55
|
? "\nSession Browser 尚未安装;需要时运行 `rynx browser install`。"
|
|
56
|
-
: "")
|
|
56
|
+
: "") +
|
|
57
|
+
bundledMessage);
|
|
57
58
|
return 0;
|
|
58
59
|
}
|
|
59
60
|
p.intro("rynx setup · 配置 ~/.rynx");
|
|
@@ -182,6 +183,9 @@ export async function runSetup() {
|
|
|
182
183
|
else if (browserPlan.kind === "offer") {
|
|
183
184
|
p.log.info("已跳过 Browser 安装;需要时运行 `rynx browser install`。");
|
|
184
185
|
}
|
|
186
|
+
const bundledMessage = await setupBundledPlugins();
|
|
187
|
+
if (bundledMessage)
|
|
188
|
+
p.log.info(bundledMessage.trim());
|
|
185
189
|
const url = formatControlUrl(String(cfg.HOST ?? "127.0.0.1"), Number(cfg.PORT ?? 3000));
|
|
186
190
|
p.note([
|
|
187
191
|
`启动常驻服务 rynx start`,
|
|
@@ -195,6 +199,24 @@ export async function runSetup() {
|
|
|
195
199
|
p.outro("配置完成 🎉");
|
|
196
200
|
return 0;
|
|
197
201
|
}
|
|
202
|
+
async function setupBundledPlugins() {
|
|
203
|
+
try {
|
|
204
|
+
const result = await ensureBundledOfficialPlugins();
|
|
205
|
+
if (result.status === "unavailable")
|
|
206
|
+
return "";
|
|
207
|
+
const changed = [...result.installed, ...result.updated];
|
|
208
|
+
if (changed.length > 0) {
|
|
209
|
+
return `\n已准备官方插件: ${changed.join(", ")}。`;
|
|
210
|
+
}
|
|
211
|
+
if (result.unchanged.length > 0) {
|
|
212
|
+
return `\n官方插件已就绪: ${result.unchanged.join(", ")}。`;
|
|
213
|
+
}
|
|
214
|
+
return "";
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
return `\n官方插件准备失败: ${error instanceof Error ? error.message : String(error)}`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
198
220
|
// ── rynx doctor — read-only health check ────────────────────────────────────
|
|
199
221
|
/** Read-only diagnostics. Returns a process exit code (0 ok, 1 on any failure). */
|
|
200
222
|
export async function runDoctor() {
|
|
@@ -245,16 +267,6 @@ export async function runDoctor() {
|
|
|
245
267
|
else {
|
|
246
268
|
const plugins = listPlugins();
|
|
247
269
|
p.log.info(`插件:${plugins.length} 个${plugins.length ? `(${plugins.map((pl) => pl.name).join(", ")})` : ""}`);
|
|
248
|
-
const legacyPlugins = plugins.filter((plugin) => !isRunnablePluginRecord(plugin));
|
|
249
|
-
if (legacyPlugins.length > 0) {
|
|
250
|
-
p.log.warn(`需重新安装的旧插件:${legacyPlugins.map((plugin) => plugin.name).join(", ")}`);
|
|
251
|
-
warn++;
|
|
252
|
-
}
|
|
253
|
-
const channels = listChannels();
|
|
254
|
-
const configured = channels.filter((c) => c.options && Object.keys(c.options).length > 0).length;
|
|
255
|
-
p.log.info(`channel:${channels.length} 个(${configured} 已配置凭据) · instance:${listInstances().length} 个`);
|
|
256
|
-
if (channels.length === 0)
|
|
257
|
-
(p.log.warn("还没有 channel —— 在 Web 控制台新建并授权"), warn++);
|
|
258
270
|
}
|
|
259
271
|
p.log.info(`agent:${(await listAgentSpecs()).length} 个(${rynxAgentsDir()})`);
|
|
260
272
|
const browser = inspectManagedBrowser();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/daemon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11-beta.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"bundled-plugins"
|
|
17
18
|
],
|
|
18
19
|
"bin": {
|
|
19
20
|
"rynx": "./dist/cli.js"
|
|
@@ -32,19 +33,21 @@
|
|
|
32
33
|
"pm2": "^6.0.0",
|
|
33
34
|
"tar": "^7.5.19",
|
|
34
35
|
"ws": "^8.21.0",
|
|
35
|
-
"@rynx-ai/
|
|
36
|
-
"@rynx-ai/
|
|
37
|
-
"@rynx-ai/
|
|
38
|
-
"@rynx-ai/
|
|
39
|
-
"@rynx-ai/
|
|
40
|
-
"@rynx-ai/
|
|
41
|
-
"@rynx-ai/
|
|
36
|
+
"@rynx-ai/cli": "0.1.11-beta.2",
|
|
37
|
+
"@rynx-ai/core": "0.1.11-beta.2",
|
|
38
|
+
"@rynx-ai/emulator": "0.1.11-beta.2",
|
|
39
|
+
"@rynx-ai/plugin-runner": "0.1.11-beta.2",
|
|
40
|
+
"@rynx-ai/plugin-sdk": "0.1.11-beta.2",
|
|
41
|
+
"@rynx-ai/protocol": "0.1.11-beta.2",
|
|
42
|
+
"@rynx-ai/remote-runtime-client": "0.1.11-beta.2",
|
|
43
|
+
"@rynx-ai/server": "0.1.11-beta.2"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
|
-
"@types/ws": "^8.18.1"
|
|
46
|
+
"@types/ws": "^8.18.1",
|
|
47
|
+
"@rynx-ai/plugin-channel-lark": "0.1.11"
|
|
45
48
|
},
|
|
46
49
|
"scripts": {
|
|
47
|
-
"build": "rm -rf dist && tsc -p tsconfig.json && chmod +x dist/cli.js dist/index-daemon.js",
|
|
50
|
+
"build": "rm -rf dist bundled-plugins && tsc -p tsconfig.json && chmod +x dist/cli.js dist/index-daemon.js && node ../../scripts/stage-bundled-plugins.mjs",
|
|
48
51
|
"dev": "tsx watch --tsconfig ../../tsconfig.json src/index-daemon.ts"
|
|
49
52
|
}
|
|
50
53
|
}
|
package/dist/channel-store.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface ChannelConfig {
|
|
2
|
-
/** Stable system-assigned id (never changes). */
|
|
3
|
-
id: string;
|
|
4
|
-
/** Human-visible, unique, editable label. */
|
|
5
|
-
name: string;
|
|
6
|
-
/** Channel type (which plugin-contributed factory). */
|
|
7
|
-
type: string;
|
|
8
|
-
options?: Record<string, unknown>;
|
|
9
|
-
}
|
|
10
|
-
export declare function listChannels(): ChannelConfig[];
|
|
11
|
-
export declare function getChannel(id: string): ChannelConfig | undefined;
|
|
12
|
-
/** Create a channel with a system-assigned id and a unique `name` label. */
|
|
13
|
-
export declare function createChannel(input: {
|
|
14
|
-
name: string;
|
|
15
|
-
type: string;
|
|
16
|
-
options?: Record<string, unknown>;
|
|
17
|
-
}): ChannelConfig;
|
|
18
|
-
export declare function renameChannel(id: string, name: string): void;
|
|
19
|
-
/** Merge credentials/options into a channel (e.g. the result of an authorize flow). */
|
|
20
|
-
export declare function setChannelOptions(id: string, options: Record<string, unknown>): void;
|
|
21
|
-
/** Remove a channel; its bound instance (if any) cascades away (FK ON DELETE CASCADE). */
|
|
22
|
-
export declare function removeChannel(id: string): void;
|
package/dist/channel-store.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `channels` table CRUD — a channel is a plugin type + its config/credentials
|
|
3
|
-
* (`options`), configured and authorized on its own. No agent binding here;
|
|
4
|
-
* that lives on an {@link import("./instance-store.js")} instance.
|
|
5
|
-
*
|
|
6
|
-
* Credentials stay in each channel's `options` and are sent only to that
|
|
7
|
-
* plugin runner instance; they are never copied into the daemon environment.
|
|
8
|
-
*/
|
|
9
|
-
import { randomUUID } from "node:crypto";
|
|
10
|
-
import { db } from "./db.js";
|
|
11
|
-
function parseOptions(raw) {
|
|
12
|
-
if (!raw)
|
|
13
|
-
return undefined;
|
|
14
|
-
try {
|
|
15
|
-
const parsed = JSON.parse(raw);
|
|
16
|
-
return parsed && typeof parsed === "object" ? parsed : undefined;
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function toConfig(row) {
|
|
23
|
-
return { id: row.id, name: row.name, type: row.type, options: parseOptions(row.options) };
|
|
24
|
-
}
|
|
25
|
-
export function listChannels() {
|
|
26
|
-
const rows = db().prepare("SELECT * FROM channels ORDER BY name").all();
|
|
27
|
-
return rows.map(toConfig);
|
|
28
|
-
}
|
|
29
|
-
export function getChannel(id) {
|
|
30
|
-
const row = db().prepare("SELECT * FROM channels WHERE id = ?").get(id);
|
|
31
|
-
return row ? toConfig(row) : undefined;
|
|
32
|
-
}
|
|
33
|
-
/** Create a channel with a system-assigned id and a unique `name` label. */
|
|
34
|
-
export function createChannel(input) {
|
|
35
|
-
const id = randomUUID();
|
|
36
|
-
const now = new Date().toISOString();
|
|
37
|
-
db()
|
|
38
|
-
.prepare(`INSERT INTO channels (id, name, type, options, created_at, updated_at)
|
|
39
|
-
VALUES (@id, @name, @type, @options, @now, @now)`)
|
|
40
|
-
.run({
|
|
41
|
-
id,
|
|
42
|
-
name: input.name,
|
|
43
|
-
type: input.type,
|
|
44
|
-
options: input.options ? JSON.stringify(input.options) : null,
|
|
45
|
-
now,
|
|
46
|
-
});
|
|
47
|
-
return getChannel(id);
|
|
48
|
-
}
|
|
49
|
-
export function renameChannel(id, name) {
|
|
50
|
-
db().prepare("UPDATE channels SET name = ?, updated_at = ? WHERE id = ?").run(name, new Date().toISOString(), id);
|
|
51
|
-
}
|
|
52
|
-
/** Merge credentials/options into a channel (e.g. the result of an authorize flow). */
|
|
53
|
-
export function setChannelOptions(id, options) {
|
|
54
|
-
const current = getChannel(id);
|
|
55
|
-
if (!current)
|
|
56
|
-
return;
|
|
57
|
-
const merged = { ...(current.options ?? {}), ...options };
|
|
58
|
-
db()
|
|
59
|
-
.prepare("UPDATE channels SET options = ?, updated_at = ? WHERE id = ?")
|
|
60
|
-
.run(JSON.stringify(merged), new Date().toISOString(), id);
|
|
61
|
-
}
|
|
62
|
-
/** Remove a channel; its bound instance (if any) cascades away (FK ON DELETE CASCADE). */
|
|
63
|
-
export function removeChannel(id) {
|
|
64
|
-
db().prepare("DELETE FROM channels WHERE id = ?").run(id);
|
|
65
|
-
}
|
package/dist/instance-store.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export interface InstanceConfig {
|
|
2
|
-
id: string;
|
|
3
|
-
channelId: string;
|
|
4
|
-
agent?: string;
|
|
5
|
-
enabled: boolean;
|
|
6
|
-
}
|
|
7
|
-
/** An instance joined with its channel — the shape the control plane lists. */
|
|
8
|
-
export interface InstanceView {
|
|
9
|
-
id: string;
|
|
10
|
-
channelId: string;
|
|
11
|
-
channelName: string;
|
|
12
|
-
type: string;
|
|
13
|
-
agent?: string;
|
|
14
|
-
enabled: boolean;
|
|
15
|
-
options?: Record<string, unknown>;
|
|
16
|
-
}
|
|
17
|
-
/** A mountable binding: instance id + its channel's type/options + bound agent. */
|
|
18
|
-
export interface InstanceDescriptor {
|
|
19
|
-
instanceId: string;
|
|
20
|
-
type: string;
|
|
21
|
-
options?: Record<string, unknown>;
|
|
22
|
-
agent?: string;
|
|
23
|
-
}
|
|
24
|
-
export declare function listInstances(): InstanceView[];
|
|
25
|
-
export declare function getInstance(id: string): InstanceView | undefined;
|
|
26
|
-
/** Mountable descriptors for every enabled instance (joined with its channel). */
|
|
27
|
-
export declare function listEnabledDescriptors(): InstanceDescriptor[];
|
|
28
|
-
/** Bind a channel to an agent. Throws if the channel already has an instance. */
|
|
29
|
-
export declare function createInstance(input: {
|
|
30
|
-
channelId: string;
|
|
31
|
-
agent?: string;
|
|
32
|
-
enabled?: boolean;
|
|
33
|
-
}): InstanceConfig;
|
|
34
|
-
export declare function setInstanceAgent(id: string, agent: string | undefined): void;
|
|
35
|
-
export declare function setInstanceEnabled(id: string, enabled: boolean): void;
|
|
36
|
-
export declare function removeInstance(id: string): void;
|
|
37
|
-
/** The instance bound to a channel, if any (1:1). */
|
|
38
|
-
export declare function getInstanceByChannel(channelId: string): InstanceView | undefined;
|
package/dist/instance-store.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `instances` table CRUD — a runnable binding of a channel to an agent (1:1 with
|
|
3
|
-
* a channel, enforced by a UNIQUE channel_id). The daemon mounts enabled
|
|
4
|
-
* instances; each resolves to its channel's type + options plus the bound agent.
|
|
5
|
-
*/
|
|
6
|
-
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { db } from "./db.js";
|
|
8
|
-
function parseOptions(raw) {
|
|
9
|
-
if (!raw)
|
|
10
|
-
return undefined;
|
|
11
|
-
try {
|
|
12
|
-
const parsed = JSON.parse(raw);
|
|
13
|
-
return parsed && typeof parsed === "object" ? parsed : undefined;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const JOIN_SELECT = `
|
|
20
|
-
SELECT i.id, i.channel_id, i.agent, i.enabled,
|
|
21
|
-
c.name AS channel_name, c.type AS type, c.options AS options
|
|
22
|
-
FROM instances i JOIN channels c ON c.id = i.channel_id`;
|
|
23
|
-
function toView(row) {
|
|
24
|
-
return {
|
|
25
|
-
id: row.id,
|
|
26
|
-
channelId: row.channel_id,
|
|
27
|
-
channelName: row.channel_name,
|
|
28
|
-
type: row.type,
|
|
29
|
-
agent: row.agent ?? undefined,
|
|
30
|
-
enabled: row.enabled !== 0,
|
|
31
|
-
options: parseOptions(row.options),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
export function listInstances() {
|
|
35
|
-
const rows = db().prepare(`${JOIN_SELECT} ORDER BY c.name`).all();
|
|
36
|
-
return rows.map(toView);
|
|
37
|
-
}
|
|
38
|
-
export function getInstance(id) {
|
|
39
|
-
const row = db().prepare(`${JOIN_SELECT} WHERE i.id = ?`).get(id);
|
|
40
|
-
return row ? toView(row) : undefined;
|
|
41
|
-
}
|
|
42
|
-
/** Mountable descriptors for every enabled instance (joined with its channel). */
|
|
43
|
-
export function listEnabledDescriptors() {
|
|
44
|
-
const rows = db().prepare(`${JOIN_SELECT} WHERE i.enabled = 1`).all();
|
|
45
|
-
return rows.map((row) => ({
|
|
46
|
-
instanceId: row.id,
|
|
47
|
-
type: row.type,
|
|
48
|
-
options: parseOptions(row.options),
|
|
49
|
-
agent: row.agent ?? undefined,
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
/** Bind a channel to an agent. Throws if the channel already has an instance. */
|
|
53
|
-
export function createInstance(input) {
|
|
54
|
-
const id = randomUUID();
|
|
55
|
-
const now = new Date().toISOString();
|
|
56
|
-
db()
|
|
57
|
-
.prepare(`INSERT INTO instances (id, channel_id, agent, enabled, created_at, updated_at)
|
|
58
|
-
VALUES (@id, @channelId, @agent, @enabled, @now, @now)`)
|
|
59
|
-
.run({
|
|
60
|
-
id,
|
|
61
|
-
channelId: input.channelId,
|
|
62
|
-
agent: input.agent ?? null,
|
|
63
|
-
enabled: input.enabled === false ? 0 : 1,
|
|
64
|
-
now,
|
|
65
|
-
});
|
|
66
|
-
return { id, channelId: input.channelId, agent: input.agent, enabled: input.enabled !== false };
|
|
67
|
-
}
|
|
68
|
-
export function setInstanceAgent(id, agent) {
|
|
69
|
-
db()
|
|
70
|
-
.prepare("UPDATE instances SET agent = ?, updated_at = ? WHERE id = ?")
|
|
71
|
-
.run(agent ?? null, new Date().toISOString(), id);
|
|
72
|
-
}
|
|
73
|
-
export function setInstanceEnabled(id, enabled) {
|
|
74
|
-
db()
|
|
75
|
-
.prepare("UPDATE instances SET enabled = ?, updated_at = ? WHERE id = ?")
|
|
76
|
-
.run(enabled ? 1 : 0, new Date().toISOString(), id);
|
|
77
|
-
}
|
|
78
|
-
export function removeInstance(id) {
|
|
79
|
-
db().prepare("DELETE FROM instances WHERE id = ?").run(id);
|
|
80
|
-
}
|
|
81
|
-
/** The instance bound to a channel, if any (1:1). */
|
|
82
|
-
export function getInstanceByChannel(channelId) {
|
|
83
|
-
const row = db().prepare(`${JOIN_SELECT} WHERE i.channel_id = ?`).get(channelId);
|
|
84
|
-
return row ? toView(row) : undefined;
|
|
85
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export type PluginInstallRestartResult = "restarted" | "declined" | "not-running";
|
|
2
|
-
export interface PluginInstallRestartOptions {
|
|
3
|
-
restart: boolean;
|
|
4
|
-
interactive: boolean;
|
|
5
|
-
}
|
|
6
|
-
export interface PluginInstallRestartDeps {
|
|
7
|
-
isDaemonOnline(): boolean;
|
|
8
|
-
confirmRestart(): Promise<boolean>;
|
|
9
|
-
restartDaemon(): number;
|
|
10
|
-
log(message: string): void;
|
|
11
|
-
}
|
|
12
|
-
/** Apply an installed plugin immediately without unexpectedly starting a stopped daemon. */
|
|
13
|
-
export declare function restartAfterPluginInstall(options: PluginInstallRestartOptions, deps: PluginInstallRestartDeps): Promise<PluginInstallRestartResult>;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/** Apply an installed plugin immediately without unexpectedly starting a stopped daemon. */
|
|
2
|
-
export async function restartAfterPluginInstall(options, deps) {
|
|
3
|
-
if (!options.interactive && !options.restart) {
|
|
4
|
-
deps.log("Rynx was not restarted in non-interactive mode. Pass `--restart` to apply the plugin immediately.");
|
|
5
|
-
return "declined";
|
|
6
|
-
}
|
|
7
|
-
if (!deps.isDaemonOnline()) {
|
|
8
|
-
deps.log("Rynx is not running under PM2; the plugin will load when its owning service next starts or restarts.");
|
|
9
|
-
return "not-running";
|
|
10
|
-
}
|
|
11
|
-
const shouldRestart = options.restart
|
|
12
|
-
? true
|
|
13
|
-
: options.interactive
|
|
14
|
-
? await deps.confirmRestart()
|
|
15
|
-
: false;
|
|
16
|
-
if (!shouldRestart) {
|
|
17
|
-
deps.log("Rynx restart skipped. Run `rynx restart` when you are ready to apply the plugin.");
|
|
18
|
-
return "declined";
|
|
19
|
-
}
|
|
20
|
-
if (deps.restartDaemon() !== 0) {
|
|
21
|
-
throw new Error("Plugin installed, but Rynx failed to restart. Run `rynx restart` manually.");
|
|
22
|
-
}
|
|
23
|
-
return "restarted";
|
|
24
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { ensureDaemonControlEndpoint } from "./control-endpoint.js";
|
|
2
|
-
const RELOAD_TIMEOUT_MS = 30_000;
|
|
3
|
-
export async function reloadResidentPluginRuntime(pluginId) {
|
|
4
|
-
return requestResidentPluginRuntime(pluginId, "reload");
|
|
5
|
-
}
|
|
6
|
-
export async function ensureResidentPluginRuntime(pluginId) {
|
|
7
|
-
return requestResidentPluginRuntime(pluginId, "ensure");
|
|
8
|
-
}
|
|
9
|
-
async function requestResidentPluginRuntime(pluginId, operation) {
|
|
10
|
-
if (!/^[a-z][a-z0-9-]{0,62}$/.test(pluginId))
|
|
11
|
-
throw new Error("invalid plugin id");
|
|
12
|
-
const endpoint = await ensureDaemonControlEndpoint();
|
|
13
|
-
const response = await fetch(`${endpoint.origin}/api/internal/plugin-runtimes/${encodeURIComponent(pluginId)}/${operation}`, {
|
|
14
|
-
method: "POST",
|
|
15
|
-
headers: { "x-rynx-management-token": endpoint.managementToken },
|
|
16
|
-
signal: AbortSignal.timeout(RELOAD_TIMEOUT_MS),
|
|
17
|
-
});
|
|
18
|
-
const body = await response.text();
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
throw new Error(readError(body) || `plugin runtime refresh failed (${response.status})`);
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(body);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
throw new Error("daemon returned an invalid plugin runtime refresh response");
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function readError(body) {
|
|
30
|
-
try {
|
|
31
|
-
const parsed = JSON.parse(body);
|
|
32
|
-
return typeof parsed.error === "string" ? parsed.error : undefined;
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return body.trim().slice(0, 2_000) || undefined;
|
|
36
|
-
}
|
|
37
|
-
}
|
package/dist/registry.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ChannelInstanceDescriptor, type ChannelTypeDescriptor } from "@rynx-ai/core";
|
|
2
|
-
import type { PluginSupervisor } from "./plugin-supervisor.js";
|
|
3
|
-
/** Directory plugin packages and staging data live under. */
|
|
4
|
-
export declare function pluginsDir(): string;
|
|
5
|
-
export declare function listChannelTypes(): ChannelTypeDescriptor[];
|
|
6
|
-
export declare function getChannelType(type: string): ChannelTypeDescriptor | undefined;
|
|
7
|
-
/** Rebuild the catalog from static manifests projected by the supervisor. */
|
|
8
|
-
export declare function loadPlugins(supervisor: PluginSupervisor, warn?: (message: string) => void): Promise<void>;
|
|
9
|
-
/** Join enabled channel instances to their remote runner-backed factories. */
|
|
10
|
-
export declare function resolveChannelInstances(warn?: (message: string) => void): Promise<ChannelInstanceDescriptor[]>;
|