@rynx-ai/daemon 0.1.0 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-cli-args.d.ts +20 -0
- package/dist/browser-cli-args.js +100 -0
- package/dist/browser-runner-session-context.d.ts +24 -0
- package/dist/browser-runner-session-context.js +113 -0
- package/dist/cdp-keyboard-input.d.ts +6 -0
- package/dist/cdp-keyboard-input.js +209 -0
- package/dist/channel-store.d.ts +0 -6
- package/dist/channel-store.js +2 -18
- package/dist/chrome-for-testing-release-resolver.d.ts +34 -0
- package/dist/chrome-for-testing-release-resolver.js +214 -0
- package/dist/chrome-for-testing-store.d.ts +85 -0
- package/dist/chrome-for-testing-store.js +836 -0
- package/dist/cli.js +467 -30
- package/dist/control-client.d.ts +113 -0
- package/dist/control-client.js +792 -0
- package/dist/control-deps.js +37 -6
- package/dist/control-endpoint.d.ts +14 -0
- package/dist/control-endpoint.js +124 -0
- package/dist/control-link-store.d.ts +16 -0
- package/dist/control-link-store.js +53 -0
- package/dist/daemon-owner.d.ts +14 -0
- package/dist/daemon-owner.js +104 -0
- package/dist/daemon-server.d.ts +12 -2
- package/dist/daemon-server.js +559 -28
- package/dist/db.js +140 -10
- package/dist/desktop-browser-host-client.d.ts +34 -0
- package/dist/desktop-browser-host-client.js +413 -0
- package/dist/direct-runtime-authenticator.d.ts +13 -0
- package/dist/direct-runtime-authenticator.js +127 -0
- package/dist/direct-runtime-config.d.ts +20 -0
- package/dist/direct-runtime-config.js +101 -0
- package/dist/embedded-browser-profile-cleanup.d.ts +58 -0
- package/dist/embedded-browser-profile-cleanup.js +338 -0
- package/dist/headless-browser-host.d.ts +14 -0
- package/dist/headless-browser-host.js +2156 -0
- package/dist/index-daemon.js +28 -5
- package/dist/installation-id.d.ts +33 -0
- package/dist/installation-id.js +692 -0
- package/dist/migrations/cleanup-legacy-sessions.d.ts +0 -3
- package/dist/migrations/cleanup-legacy-sessions.js +10 -28
- package/dist/plugin-cli.d.ts +30 -0
- package/dist/plugin-cli.js +270 -0
- package/dist/plugin-host-rpc.d.ts +85 -0
- package/dist/plugin-host-rpc.js +878 -0
- package/dist/plugin-install-restart.d.ts +13 -0
- package/dist/plugin-install-restart.js +24 -0
- package/dist/plugin-installer.d.ts +36 -15
- package/dist/plugin-installer.js +420 -155
- package/dist/plugin-package.d.ts +38 -0
- package/dist/plugin-package.js +553 -0
- package/dist/plugin-runtime-control.d.ts +2 -0
- package/dist/plugin-runtime-control.js +37 -0
- package/dist/plugin-store.d.ts +37 -8
- package/dist/plugin-store.js +80 -15
- package/dist/plugin-supervisor.d.ts +160 -0
- package/dist/plugin-supervisor.js +1143 -0
- package/dist/pm2.d.ts +3 -1
- package/dist/pm2.js +55 -13
- package/dist/provider-cli-service.d.ts +46 -0
- package/dist/provider-cli-service.js +510 -0
- package/dist/registry.d.ts +6 -19
- package/dist/registry.js +22 -87
- package/dist/remote-runtime-access-store.d.ts +61 -0
- package/dist/remote-runtime-access-store.js +386 -0
- package/dist/remote-runtime-admin.d.ts +32 -0
- package/dist/remote-runtime-admin.js +107 -0
- package/dist/remote-runtime-connection-manager.d.ts +92 -0
- package/dist/remote-runtime-connection-manager.js +1409 -0
- package/dist/remote-runtime-credential-store.d.ts +45 -0
- package/dist/remote-runtime-credential-store.js +639 -0
- package/dist/remote-runtime-target-control.d.ts +47 -0
- package/dist/remote-runtime-target-control.js +433 -0
- package/dist/remote-runtime-target-store.d.ts +53 -0
- package/dist/remote-runtime-target-store.js +307 -0
- package/dist/runtime-share-addresses.d.ts +21 -0
- package/dist/runtime-share-addresses.js +50 -0
- package/dist/session-browser-capability-store.d.ts +13 -0
- package/dist/session-browser-capability-store.js +58 -0
- package/dist/session-emulator-binding-store.d.ts +10 -0
- package/dist/session-emulator-binding-store.js +61 -0
- package/dist/session-launch-operations.d.ts +41 -0
- package/dist/session-launch-operations.js +124 -0
- package/dist/session-meta-store.d.ts +3 -2
- package/dist/session-meta-store.js +57 -7
- package/dist/setup.js +9 -4
- package/dist/skills-catalog.js +8 -4
- package/dist/update.d.ts +11 -2
- package/dist/update.js +0 -27
- package/package.json +18 -10
package/dist/plugin-store.js
CHANGED
|
@@ -1,56 +1,121 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Durable inventory of installed plugin packages.
|
|
3
|
+
*
|
|
4
|
+
* The registry stores only static, validated manifest data and a host-owned
|
|
5
|
+
* installation path. Runtime modules are never imported while reading this
|
|
6
|
+
* table. Rows from the pre-v1 executable-manifest format remain visible to the
|
|
7
|
+
* CLI, but are not runnable and must be reinstalled.
|
|
6
8
|
*/
|
|
9
|
+
import { parsePluginManifest, } from "@rynx-ai/plugin-sdk";
|
|
7
10
|
import { db } from "./db.js";
|
|
8
11
|
function toRecord(row) {
|
|
12
|
+
const manifest = parseStoredManifest(row.manifest);
|
|
9
13
|
return {
|
|
10
14
|
name: row.name,
|
|
11
15
|
spec: row.spec,
|
|
12
|
-
source: row.source,
|
|
16
|
+
source: parseSource(row.source),
|
|
13
17
|
version: row.version ?? undefined,
|
|
14
18
|
enabled: row.enabled !== 0,
|
|
15
19
|
installedAt: row.installed_at,
|
|
20
|
+
updatedAt: row.updated_at ?? row.installed_at,
|
|
21
|
+
installPath: row.install_path ?? undefined,
|
|
22
|
+
manifest,
|
|
23
|
+
integrity: row.integrity ?? undefined,
|
|
24
|
+
grants: parseStoredGrants(row.grants, manifest),
|
|
16
25
|
};
|
|
17
26
|
}
|
|
18
|
-
/** All installed plugins,
|
|
27
|
+
/** All installed plugins, including incompatible legacy rows. */
|
|
19
28
|
export function listPlugins() {
|
|
20
29
|
const rows = db().prepare("SELECT * FROM plugins ORDER BY name").all();
|
|
21
30
|
return rows.map(toRecord);
|
|
22
31
|
}
|
|
23
|
-
/**
|
|
32
|
+
/** Enabled v1 installations that are safe for the runner to consider. */
|
|
24
33
|
export function listEnabledPlugins() {
|
|
25
|
-
return listPlugins().filter((
|
|
34
|
+
return listPlugins().filter(isRunnablePluginRecord).filter((plugin) => plugin.enabled);
|
|
26
35
|
}
|
|
27
36
|
export function getPlugin(name) {
|
|
28
37
|
const row = db().prepare("SELECT * FROM plugins WHERE name = ?").get(name);
|
|
29
38
|
return row ? toRecord(row) : undefined;
|
|
30
39
|
}
|
|
31
|
-
/**
|
|
40
|
+
/** Atomically point a plugin id at a completely materialized installation. */
|
|
32
41
|
export function upsertPlugin(rec) {
|
|
42
|
+
if (rec.name !== rec.manifest.id) {
|
|
43
|
+
throw new Error(`plugin registry id mismatch: ${rec.name} != ${rec.manifest.id}`);
|
|
44
|
+
}
|
|
45
|
+
const requested = new Set(rec.manifest.requestedCapabilities);
|
|
46
|
+
for (const grant of rec.grants) {
|
|
47
|
+
if (!requested.has(grant))
|
|
48
|
+
throw new Error(`plugin grant was not requested: ${grant}`);
|
|
49
|
+
}
|
|
50
|
+
const now = new Date().toISOString();
|
|
33
51
|
db()
|
|
34
|
-
.prepare(`INSERT INTO plugins (
|
|
35
|
-
|
|
52
|
+
.prepare(`INSERT INTO plugins (
|
|
53
|
+
name, spec, source, version, enabled, installed_at, updated_at,
|
|
54
|
+
install_path, manifest, integrity, grants
|
|
55
|
+
) VALUES (
|
|
56
|
+
@name, @spec, @source, @version, @enabled, @now, @now,
|
|
57
|
+
@installPath, @manifest, @integrity, @grants
|
|
58
|
+
)
|
|
36
59
|
ON CONFLICT(name) DO UPDATE SET
|
|
37
60
|
spec = excluded.spec,
|
|
38
61
|
source = excluded.source,
|
|
39
62
|
version = excluded.version,
|
|
40
|
-
enabled = excluded.enabled
|
|
63
|
+
enabled = excluded.enabled,
|
|
64
|
+
installed_at = excluded.installed_at,
|
|
65
|
+
updated_at = excluded.updated_at,
|
|
66
|
+
install_path = excluded.install_path,
|
|
67
|
+
manifest = excluded.manifest,
|
|
68
|
+
integrity = excluded.integrity,
|
|
69
|
+
grants = excluded.grants`)
|
|
41
70
|
.run({
|
|
42
71
|
name: rec.name,
|
|
43
72
|
spec: rec.spec,
|
|
44
73
|
source: rec.source,
|
|
45
74
|
version: rec.version ?? null,
|
|
46
75
|
enabled: rec.enabled === false ? 0 : 1,
|
|
47
|
-
|
|
76
|
+
now,
|
|
77
|
+
installPath: rec.installPath,
|
|
78
|
+
manifest: JSON.stringify(rec.manifest),
|
|
79
|
+
integrity: rec.integrity,
|
|
80
|
+
grants: JSON.stringify([...rec.grants]),
|
|
48
81
|
});
|
|
49
82
|
}
|
|
50
83
|
export function setPluginEnabled(name, enabled) {
|
|
51
|
-
db()
|
|
84
|
+
db()
|
|
85
|
+
.prepare("UPDATE plugins SET enabled = ?, updated_at = ? WHERE name = ?")
|
|
86
|
+
.run(enabled ? 1 : 0, new Date().toISOString(), name);
|
|
52
87
|
}
|
|
53
|
-
/** Remove
|
|
88
|
+
/** Remove only the registry row. Package deletion is owned by the installer. */
|
|
54
89
|
export function removePlugin(name) {
|
|
55
90
|
return db().prepare("DELETE FROM plugins WHERE name = ?").run(name).changes > 0;
|
|
56
91
|
}
|
|
92
|
+
export function isRunnablePluginRecord(record) {
|
|
93
|
+
return Boolean(record.installPath && record.manifest && record.integrity);
|
|
94
|
+
}
|
|
95
|
+
function parseStoredManifest(raw) {
|
|
96
|
+
if (!raw)
|
|
97
|
+
return undefined;
|
|
98
|
+
try {
|
|
99
|
+
return parsePluginManifest(JSON.parse(raw));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function parseStoredGrants(raw, manifest) {
|
|
106
|
+
if (!raw || !manifest)
|
|
107
|
+
return [];
|
|
108
|
+
try {
|
|
109
|
+
const values = JSON.parse(raw);
|
|
110
|
+
if (!Array.isArray(values))
|
|
111
|
+
return [];
|
|
112
|
+
const requested = new Set(manifest.requestedCapabilities);
|
|
113
|
+
return values.filter((value) => typeof value === "string" && requested.has(value));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function parseSource(value) {
|
|
120
|
+
return value === "local" || value === "git" || value === "url" ? value : "npm";
|
|
121
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { type ChannelTypeDescriptor } from "@rynx-ai/core";
|
|
2
|
+
import { type SpawnPluginRunnerOptions } from "@rynx-ai/plugin-runner";
|
|
3
|
+
import { type PluginAuthMaterial, type PluginContributionStatus, type PluginContributionTarget, type PluginJsonValue, type PluginRunnerHandshake, type PluginRuntimeStatus, type PluginStartContributionRequest } from "@rynx-ai/plugin-sdk";
|
|
4
|
+
import { type PluginHostServices } from "./plugin-host-rpc.js";
|
|
5
|
+
import type { RunnablePluginRecord } from "./plugin-store.js";
|
|
6
|
+
export interface PluginRunnerClientHandle {
|
|
7
|
+
startContribution(request: PluginStartContributionRequest): Promise<void>;
|
|
8
|
+
stopContribution(target: PluginContributionTarget): Promise<void>;
|
|
9
|
+
status(target: PluginContributionTarget): Promise<PluginContributionStatus>;
|
|
10
|
+
runtimeStatus(): Promise<PluginRuntimeStatus>;
|
|
11
|
+
authorize(request: {
|
|
12
|
+
kind: "chat-channel";
|
|
13
|
+
contributionId: string;
|
|
14
|
+
instanceId?: string;
|
|
15
|
+
config: Readonly<Record<string, PluginJsonValue>>;
|
|
16
|
+
}, onMaterial: (material: PluginAuthMaterial) => void, options?: {
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
}): Promise<Record<string, PluginJsonValue>>;
|
|
20
|
+
emitHostEvent(event: string, payload?: unknown): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** The subset of a spawned runner the supervisor owns. Kept structural for tests. */
|
|
23
|
+
export interface SupervisedPluginRunner {
|
|
24
|
+
readonly client: PluginRunnerClientHandle;
|
|
25
|
+
readonly handshake: PluginRunnerHandshake;
|
|
26
|
+
readonly completion: Promise<{
|
|
27
|
+
code: number | null;
|
|
28
|
+
signal: NodeJS.Signals | null;
|
|
29
|
+
}>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export type PluginRunnerSpawnFactory = (options: SpawnPluginRunnerOptions) => Promise<SupervisedPluginRunner>;
|
|
33
|
+
export interface PluginSupervisorLogEntry {
|
|
34
|
+
level: "info" | "warn" | "error";
|
|
35
|
+
event: string;
|
|
36
|
+
pluginId: string;
|
|
37
|
+
message?: string;
|
|
38
|
+
delayMs?: number;
|
|
39
|
+
code?: number | null;
|
|
40
|
+
signal?: NodeJS.Signals | null;
|
|
41
|
+
}
|
|
42
|
+
export interface PluginSupervisorOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Trusted daemon-owned services. May be bound later because the composition
|
|
45
|
+
* root needs the static channel catalog before startServer constructs them.
|
|
46
|
+
*/
|
|
47
|
+
services?: PluginHostServices;
|
|
48
|
+
spawnRunner?: PluginRunnerSpawnFactory;
|
|
49
|
+
log?: (entry: PluginSupervisorLogEntry) => void;
|
|
50
|
+
/** Test knobs; production restart delay is always capped at 30 seconds. */
|
|
51
|
+
restartBaseMs?: number;
|
|
52
|
+
restartMaxMs?: number;
|
|
53
|
+
stableResetMs?: number;
|
|
54
|
+
/** Test override. Production generates one identity per supervisor process lifetime. */
|
|
55
|
+
daemonInstanceId?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface PluginContributionRuntimeSnapshot {
|
|
58
|
+
key: string;
|
|
59
|
+
target: PluginContributionTarget;
|
|
60
|
+
desired: boolean;
|
|
61
|
+
generation?: number;
|
|
62
|
+
failureCount: number;
|
|
63
|
+
status: PluginContributionStatus;
|
|
64
|
+
}
|
|
65
|
+
export interface PluginRunnerRuntimeSnapshot {
|
|
66
|
+
state: "stopped" | "starting" | "running" | "backoff" | "failed";
|
|
67
|
+
generation: number;
|
|
68
|
+
failureCount: number;
|
|
69
|
+
lastError?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface PluginRuntimeStatusSnapshot {
|
|
72
|
+
capturedAt: string;
|
|
73
|
+
plugins: Array<{
|
|
74
|
+
pluginId: string;
|
|
75
|
+
runner: PluginRunnerRuntimeSnapshot;
|
|
76
|
+
runtimeStatus: PluginRuntimeStatus;
|
|
77
|
+
contributions: PluginContributionRuntimeSnapshot[];
|
|
78
|
+
}>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Owns isolated plugin child processes and projects their static chat-channel
|
|
82
|
+
* declarations onto trusted host-side ChannelManager handles.
|
|
83
|
+
*
|
|
84
|
+
* There is at most one resident child per enabled plugin. Chat-channel
|
|
85
|
+
* instances are independent desired-state entries inside that child, so
|
|
86
|
+
* stopping the final channel does not tear down the plugin runtime itself.
|
|
87
|
+
*/
|
|
88
|
+
export declare class PluginSupervisor {
|
|
89
|
+
private readonly states;
|
|
90
|
+
private services?;
|
|
91
|
+
private readonly spawnRunner;
|
|
92
|
+
private readonly logger?;
|
|
93
|
+
private readonly restartBaseMs;
|
|
94
|
+
private readonly restartMaxMs;
|
|
95
|
+
private readonly stableResetMs;
|
|
96
|
+
private readonly daemonInstanceId;
|
|
97
|
+
private readonly runtimeOperations;
|
|
98
|
+
private disposed;
|
|
99
|
+
constructor(plugins: readonly RunnablePluginRecord[], options: PluginSupervisorOptions);
|
|
100
|
+
/** Static channel catalog. Calling this never loads or executes plugin code. */
|
|
101
|
+
createChannelTypeDescriptors(): ChannelTypeDescriptor[];
|
|
102
|
+
/** Bind the trusted host once, after the server composition root constructs it. */
|
|
103
|
+
bindHostServices(services: PluginHostServices): this;
|
|
104
|
+
/** Cached, non-blocking runner/contribution health for the generic control API. */
|
|
105
|
+
statusSnapshot(): PluginRuntimeStatusSnapshot;
|
|
106
|
+
/** Start one resident runner for every enabled runtime plugin. */
|
|
107
|
+
startPluginRuntimes(): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Atomically replace or add one plugin runtime, preserving its live chat
|
|
110
|
+
* desired state. Concurrent reloads of the same plugin are applied in call
|
|
111
|
+
* order; other plugins continue running independently.
|
|
112
|
+
*/
|
|
113
|
+
reloadPluginRuntime(record: RunnablePluginRecord, { readyTimeoutMs }?: {
|
|
114
|
+
readyTimeoutMs?: number;
|
|
115
|
+
}): Promise<PluginRuntimeStatus>;
|
|
116
|
+
/**
|
|
117
|
+
* Make one enabled plugin runtime ready without replacing an already healthy
|
|
118
|
+
* runner. This is the idempotent operation plugin CLIs use when their durable
|
|
119
|
+
* configuration has not changed.
|
|
120
|
+
*/
|
|
121
|
+
ensurePluginRuntime(record: RunnablePluginRecord, { readyTimeoutMs }?: {
|
|
122
|
+
readyTimeoutMs?: number;
|
|
123
|
+
}): Promise<PluginRuntimeStatus>;
|
|
124
|
+
private enqueueRuntimeOperation;
|
|
125
|
+
private performPluginRuntimeEnsure;
|
|
126
|
+
private performPluginRuntimeReload;
|
|
127
|
+
/** Permanently stop all children and cancel every pending automatic restart. */
|
|
128
|
+
dispose(): Promise<void>;
|
|
129
|
+
private channelDescriptor;
|
|
130
|
+
private createRemoteChannel;
|
|
131
|
+
private authorize;
|
|
132
|
+
private rememberDesired;
|
|
133
|
+
private ensureDesiredStarted;
|
|
134
|
+
private startDesiredOnRunner;
|
|
135
|
+
private stopDesired;
|
|
136
|
+
private refreshContributionStatus;
|
|
137
|
+
private refreshRuntimeStatus;
|
|
138
|
+
private waitForRuntimeReady;
|
|
139
|
+
private runtimeReadyTimeoutError;
|
|
140
|
+
private ensureRunner;
|
|
141
|
+
private spawnAndBind;
|
|
142
|
+
private trackRunnerExit;
|
|
143
|
+
private runnerExited;
|
|
144
|
+
private joinExitTransition;
|
|
145
|
+
private scheduleRestart;
|
|
146
|
+
private restart;
|
|
147
|
+
private restoreDesiredContributions;
|
|
148
|
+
private closeRunner;
|
|
149
|
+
private disposeState;
|
|
150
|
+
private cancelRestart;
|
|
151
|
+
private markRunnerUnavailable;
|
|
152
|
+
private markContributionFailed;
|
|
153
|
+
private stderrSink;
|
|
154
|
+
private writeLog;
|
|
155
|
+
private assertOpen;
|
|
156
|
+
private assertReady;
|
|
157
|
+
private requireHostServices;
|
|
158
|
+
}
|
|
159
|
+
/** Convenience export for composition roots that only need the static catalog. */
|
|
160
|
+
export declare function createChannelTypeDescriptors(supervisor: PluginSupervisor): ChannelTypeDescriptor[];
|