@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
package/dist/db.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `~/.rynx/rynx.db` — the daemon's SQLite store. Concerns kept apart:
|
|
3
|
-
* - `
|
|
4
|
-
* - `
|
|
5
|
-
* enforced by a UNIQUE channel_id). This is what the daemon mounts.
|
|
6
|
-
* - `plugins` — static manifests, grants and immutable install locations.
|
|
3
|
+
* - `plugin_installations` — source-qualified manifests, capabilities, and immutable packages.
|
|
4
|
+
* - `plugin_marketplaces` — catalog registrations; catalog data is never executable.
|
|
7
5
|
* - `plugin_session_launch_operations` — durable idempotency/tombstones.
|
|
8
6
|
* - `control_links` — generic, one-use links to the local session console.
|
|
9
7
|
* - `runtime_pairing_claims` / `runtime_client_grants` — one-use enrollment
|
|
@@ -16,15 +14,18 @@
|
|
|
16
14
|
* Connections are cached per resolved path so tests can point `RYNX_DB` /
|
|
17
15
|
* `RYNX_HOME` at a temp dir. Override with `RYNX_DB` (full path) or `RYNX_HOME`.
|
|
18
16
|
*/
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import { dirname, join } from "node:path";
|
|
17
|
+
import { chmodSync, mkdirSync } from "node:fs";
|
|
18
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
19
|
+
import { rynxHome } from "@rynx-ai/core";
|
|
23
20
|
import Database from "better-sqlite3";
|
|
24
21
|
const connections = new Map();
|
|
25
22
|
/** Absolute path to the SQLite file (override via `RYNX_DB`, else `~/.rynx/rynx.db`). */
|
|
26
23
|
export function dbPath() {
|
|
27
|
-
|
|
24
|
+
const configured = process.env.RYNX_DB?.trim();
|
|
25
|
+
if (configured && !isAbsolute(configured)) {
|
|
26
|
+
throw new Error("RYNX_DB must be an absolute path");
|
|
27
|
+
}
|
|
28
|
+
return configured ? resolve(configured) : join(rynxHome(), "rynx.db");
|
|
28
29
|
}
|
|
29
30
|
/** Open (or reuse) the database at the current path, migrating + importing on first open. */
|
|
30
31
|
export function db() {
|
|
@@ -37,7 +38,7 @@ export function db() {
|
|
|
37
38
|
conn.pragma("busy_timeout = 5000");
|
|
38
39
|
conn.pragma("foreign_keys = ON");
|
|
39
40
|
migrate(conn);
|
|
40
|
-
//
|
|
41
|
+
// Plugin state and daemon credentials are private.
|
|
41
42
|
try {
|
|
42
43
|
chmodSync(path, 0o600);
|
|
43
44
|
}
|
|
@@ -49,34 +50,46 @@ export function db() {
|
|
|
49
50
|
}
|
|
50
51
|
function migrate(conn) {
|
|
51
52
|
conn.exec(`
|
|
52
|
-
CREATE TABLE IF NOT EXISTS
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
integrity TEXT,
|
|
63
|
-
grants TEXT
|
|
53
|
+
CREATE TABLE IF NOT EXISTS plugin_marketplaces (
|
|
54
|
+
marketplace_id TEXT PRIMARY KEY,
|
|
55
|
+
source_type TEXT NOT NULL CHECK(source_type IN ('git', 'local')),
|
|
56
|
+
requested_source TEXT NOT NULL,
|
|
57
|
+
resolved_revision TEXT NOT NULL,
|
|
58
|
+
source_fingerprint TEXT NOT NULL,
|
|
59
|
+
built_in INTEGER NOT NULL DEFAULT 0,
|
|
60
|
+
catalog TEXT NOT NULL,
|
|
61
|
+
created_at TEXT NOT NULL,
|
|
62
|
+
refreshed_at TEXT NOT NULL
|
|
64
63
|
);
|
|
65
|
-
CREATE TABLE IF NOT EXISTS
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
options TEXT,
|
|
70
|
-
created_at TEXT NOT NULL,
|
|
71
|
-
updated_at TEXT NOT NULL
|
|
64
|
+
CREATE TABLE IF NOT EXISTS plugin_marketplace_bindings (
|
|
65
|
+
marketplace_id TEXT PRIMARY KEY,
|
|
66
|
+
source_fingerprint TEXT NOT NULL,
|
|
67
|
+
created_at TEXT NOT NULL
|
|
72
68
|
);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
INSERT OR IGNORE INTO plugin_marketplace_bindings (
|
|
70
|
+
marketplace_id, source_fingerprint, created_at
|
|
71
|
+
)
|
|
72
|
+
SELECT marketplace_id, source_fingerprint, created_at
|
|
73
|
+
FROM plugin_marketplaces;
|
|
74
|
+
CREATE TABLE IF NOT EXISTS plugin_installations (
|
|
75
|
+
canonical_id TEXT PRIMARY KEY,
|
|
76
|
+
marketplace_id TEXT NOT NULL,
|
|
77
|
+
plugin_id TEXT NOT NULL,
|
|
78
|
+
source_type TEXT NOT NULL CHECK(source_type IN ('git', 'local')),
|
|
79
|
+
requested_source TEXT NOT NULL,
|
|
80
|
+
resolved_revision TEXT NOT NULL,
|
|
81
|
+
source_fingerprint TEXT NOT NULL,
|
|
82
|
+
version TEXT NOT NULL,
|
|
83
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
84
|
+
installed_at TEXT NOT NULL,
|
|
85
|
+
updated_at TEXT NOT NULL,
|
|
86
|
+
install_path TEXT NOT NULL,
|
|
87
|
+
manifest TEXT NOT NULL,
|
|
88
|
+
integrity TEXT NOT NULL,
|
|
89
|
+
capabilities TEXT NOT NULL,
|
|
90
|
+
runtime_state TEXT,
|
|
91
|
+
runtime_error TEXT,
|
|
92
|
+
UNIQUE(marketplace_id, plugin_id)
|
|
80
93
|
);
|
|
81
94
|
CREATE TABLE IF NOT EXISTS session_items (
|
|
82
95
|
id TEXT PRIMARY KEY,
|
|
@@ -142,16 +155,25 @@ function migrate(conn) {
|
|
|
142
155
|
ON DELETE CASCADE
|
|
143
156
|
);
|
|
144
157
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
158
|
+
id TEXT PRIMARY KEY,
|
|
159
|
+
workspace TEXT NOT NULL,
|
|
160
|
+
execution TEXT NOT NULL,
|
|
161
|
+
title TEXT,
|
|
162
|
+
forked_from_session_id TEXT,
|
|
163
|
+
source TEXT NOT NULL,
|
|
164
|
+
created_at TEXT NOT NULL,
|
|
165
|
+
updated_at TEXT
|
|
166
|
+
);
|
|
167
|
+
CREATE TABLE IF NOT EXISTS session_snapshot_cleanup (
|
|
168
|
+
session_id TEXT PRIMARY KEY
|
|
169
|
+
);
|
|
170
|
+
CREATE TABLE IF NOT EXISTS runtime_projects (
|
|
145
171
|
id TEXT PRIMARY KEY,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
model TEXT,
|
|
150
|
-
reasoning_effort TEXT,
|
|
151
|
-
title TEXT,
|
|
152
|
-
source TEXT,
|
|
172
|
+
name TEXT NOT NULL,
|
|
173
|
+
directories_json TEXT NOT NULL,
|
|
174
|
+
primary_dir TEXT NOT NULL,
|
|
153
175
|
created_at TEXT NOT NULL,
|
|
154
|
-
updated_at TEXT
|
|
176
|
+
updated_at TEXT NOT NULL
|
|
155
177
|
);
|
|
156
178
|
CREATE TABLE IF NOT EXISTS session_pending_messages (
|
|
157
179
|
session_id TEXT PRIMARY KEY REFERENCES sessions(id) ON DELETE CASCADE,
|
|
@@ -187,6 +209,31 @@ function migrate(conn) {
|
|
|
187
209
|
);
|
|
188
210
|
CREATE INDEX IF NOT EXISTS idx_plugin_session_launch_operations_session
|
|
189
211
|
ON plugin_session_launch_operations(session_id);
|
|
212
|
+
CREATE TABLE IF NOT EXISTS session_fork_operations (
|
|
213
|
+
operation_id TEXT PRIMARY KEY,
|
|
214
|
+
request_hash TEXT NOT NULL,
|
|
215
|
+
source_session_id TEXT NOT NULL,
|
|
216
|
+
target_session_id TEXT NOT NULL UNIQUE,
|
|
217
|
+
title TEXT,
|
|
218
|
+
fork_position INTEGER,
|
|
219
|
+
state TEXT NOT NULL DEFAULT 'reserved'
|
|
220
|
+
CHECK(state IN ('reserved', 'completed', 'target_deleted')),
|
|
221
|
+
error TEXT,
|
|
222
|
+
created_at TEXT NOT NULL,
|
|
223
|
+
updated_at TEXT NOT NULL,
|
|
224
|
+
completed_at TEXT,
|
|
225
|
+
deleted_at TEXT,
|
|
226
|
+
CHECK(
|
|
227
|
+
(state = 'reserved' AND completed_at IS NULL AND deleted_at IS NULL)
|
|
228
|
+
OR (state = 'completed' AND completed_at IS NOT NULL AND deleted_at IS NULL)
|
|
229
|
+
OR (state = 'target_deleted' AND deleted_at IS NOT NULL)
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
CREATE INDEX IF NOT EXISTS idx_session_fork_operations_source
|
|
233
|
+
ON session_fork_operations(source_session_id, state);
|
|
234
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_session_fork_operations_reserved_source
|
|
235
|
+
ON session_fork_operations(source_session_id)
|
|
236
|
+
WHERE state = 'reserved';
|
|
190
237
|
CREATE TABLE IF NOT EXISTS control_links (
|
|
191
238
|
token TEXT PRIMARY KEY,
|
|
192
239
|
plugin_id TEXT NOT NULL,
|
|
@@ -260,97 +307,71 @@ function migrate(conn) {
|
|
|
260
307
|
CREATE INDEX IF NOT EXISTS idx_runtime_pending_enrollments_expires
|
|
261
308
|
ON runtime_pending_enrollments(expires_at);
|
|
262
309
|
`);
|
|
310
|
+
migratePluginCapabilities(conn);
|
|
311
|
+
migrateSessionSnapshots(conn);
|
|
263
312
|
// Breaking plugin-runtime cutover: remove obsolete core-owned state.
|
|
264
313
|
conn.exec(`
|
|
265
314
|
DROP TABLE IF EXISTS control_sessions;
|
|
266
315
|
DROP TABLE IF EXISTS plugin_daemon_worker_settings;
|
|
267
316
|
`);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// ADD COLUMN IF NOT EXISTS) and backfill the origin of rows written before
|
|
271
|
-
// this change — they were all console sessions.
|
|
272
|
-
addColumnIfMissing(conn, "sessions", "source", "TEXT");
|
|
273
|
-
addColumnIfMissing(conn, "sessions", "updated_at", "TEXT");
|
|
274
|
-
addColumnIfMissing(conn, "sessions", "provider", "TEXT");
|
|
275
|
-
const sessionColumns = conn.prepare("PRAGMA table_info(sessions)").all();
|
|
276
|
-
if (sessionColumns.some((column) => column.name === "executor")) {
|
|
277
|
-
conn.exec("UPDATE sessions SET provider = executor WHERE provider IS NULL AND executor IS NOT NULL");
|
|
278
|
-
}
|
|
279
|
-
addColumnIfMissing(conn, "plugins", "updated_at", "TEXT");
|
|
280
|
-
addColumnIfMissing(conn, "plugins", "install_path", "TEXT");
|
|
281
|
-
addColumnIfMissing(conn, "plugins", "manifest", "TEXT");
|
|
282
|
-
addColumnIfMissing(conn, "plugins", "integrity", "TEXT");
|
|
283
|
-
addColumnIfMissing(conn, "plugins", "grants", "TEXT");
|
|
284
|
-
conn.exec("UPDATE sessions SET source = 'console' WHERE source IS NULL");
|
|
285
|
-
conn.exec("UPDATE plugins SET updated_at = installed_at WHERE updated_at IS NULL");
|
|
286
|
-
importLegacyConfig(conn);
|
|
287
|
-
}
|
|
288
|
-
/** Idempotently add a column to an existing table (no-op if already present). */
|
|
289
|
-
function addColumnIfMissing(conn, table, column, ddl) {
|
|
290
|
-
const cols = conn.prepare(`PRAGMA table_info(${table})`).all();
|
|
291
|
-
if (cols.some((c) => c.name === column))
|
|
292
|
-
return;
|
|
293
|
-
conn.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddl}`);
|
|
317
|
+
addColumnIfMissing(conn, "plugin_marketplaces", "built_in", "INTEGER NOT NULL DEFAULT 0");
|
|
318
|
+
addColumnIfMissing(conn, "sessions", "forked_from_session_id", "TEXT");
|
|
294
319
|
}
|
|
295
320
|
/**
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* (keyed by instanceId) stays intact. Runs only when empty; the file is renamed
|
|
301
|
-
* afterwards so it's never read — or hand-edited — again.
|
|
321
|
+
* Breaking Session cutover: the previous rows contain mutable Agent/Provider
|
|
322
|
+
* references and no immutable workspace/execution snapshots, so they cannot be
|
|
323
|
+
* migrated faithfully. Remove every database-owned Session artifact and create
|
|
324
|
+
* the new snapshot-only table. User workspace directories are never touched.
|
|
302
325
|
*/
|
|
303
|
-
function
|
|
304
|
-
const
|
|
305
|
-
|
|
326
|
+
function migrateSessionSnapshots(conn) {
|
|
327
|
+
const columns = conn.prepare("PRAGMA table_info(sessions)").all();
|
|
328
|
+
const names = new Set(columns.map((column) => column.name));
|
|
329
|
+
if (names.has("workspace") && names.has("execution"))
|
|
306
330
|
return;
|
|
307
|
-
|
|
308
|
-
|
|
331
|
+
conn.transaction(() => {
|
|
332
|
+
conn.exec(`
|
|
333
|
+
INSERT OR IGNORE INTO session_snapshot_cleanup (session_id)
|
|
334
|
+
SELECT id FROM sessions;
|
|
335
|
+
DELETE FROM session_message_operation_resources;
|
|
336
|
+
DELETE FROM session_message_operations;
|
|
337
|
+
DELETE FROM session_resources;
|
|
338
|
+
DELETE FROM session_items;
|
|
339
|
+
DELETE FROM session_pending_messages;
|
|
340
|
+
DELETE FROM session_emulator_bindings;
|
|
341
|
+
DELETE FROM plugin_session_launch_operations;
|
|
342
|
+
DELETE FROM session_fork_operations;
|
|
343
|
+
DELETE FROM control_links;
|
|
344
|
+
DELETE FROM sessions;
|
|
345
|
+
DROP TABLE sessions;
|
|
346
|
+
CREATE TABLE sessions (
|
|
347
|
+
id TEXT PRIMARY KEY,
|
|
348
|
+
workspace TEXT NOT NULL,
|
|
349
|
+
execution TEXT NOT NULL,
|
|
350
|
+
title TEXT,
|
|
351
|
+
forked_from_session_id TEXT,
|
|
352
|
+
source TEXT NOT NULL,
|
|
353
|
+
created_at TEXT NOT NULL,
|
|
354
|
+
updated_at TEXT
|
|
355
|
+
);
|
|
356
|
+
`);
|
|
357
|
+
}).immediate();
|
|
358
|
+
}
|
|
359
|
+
function migratePluginCapabilities(conn) {
|
|
360
|
+
const columns = conn
|
|
361
|
+
.prepare("PRAGMA table_info(plugin_installations)")
|
|
362
|
+
.all();
|
|
363
|
+
if (columns.some((column) => column.name === "capabilities"))
|
|
309
364
|
return;
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const parsed = JSON.parse(readFileSync(legacy, "utf8"));
|
|
313
|
-
if (parsed.channels && typeof parsed.channels === "object") {
|
|
314
|
-
channels = parsed.channels;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
catch {
|
|
318
|
-
return; // malformed legacy file — leave it alone, start empty
|
|
319
|
-
}
|
|
320
|
-
if (!channels)
|
|
365
|
+
if (columns.some((column) => column.name === "grants")) {
|
|
366
|
+
conn.exec("ALTER TABLE plugin_installations RENAME COLUMN grants TO capabilities");
|
|
321
367
|
return;
|
|
322
|
-
const now = new Date().toISOString();
|
|
323
|
-
const insertChannel = conn.prepare(`INSERT OR IGNORE INTO channels (id, name, type, options, created_at, updated_at)
|
|
324
|
-
VALUES (@id, @name, @type, @options, @now, @now)`);
|
|
325
|
-
const insertInstance = conn.prepare(`INSERT OR IGNORE INTO instances (id, channel_id, agent, enabled, created_at, updated_at)
|
|
326
|
-
VALUES (@id, @channelId, @agent, @enabled, @now, @now)`);
|
|
327
|
-
const tx = conn.transaction(() => {
|
|
328
|
-
for (const [key, entry] of Object.entries(channels)) {
|
|
329
|
-
const channelId = randomUUID();
|
|
330
|
-
insertChannel.run({
|
|
331
|
-
id: channelId,
|
|
332
|
-
name: key,
|
|
333
|
-
type: entry.type ?? key,
|
|
334
|
-
options: entry.options ? JSON.stringify(entry.options) : null,
|
|
335
|
-
now,
|
|
336
|
-
});
|
|
337
|
-
insertInstance.run({
|
|
338
|
-
id: key, // preserve the old key as the runtime instanceId
|
|
339
|
-
channelId,
|
|
340
|
-
agent: entry.agent ?? null,
|
|
341
|
-
enabled: entry.enabled === false ? 0 : 1,
|
|
342
|
-
now,
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
tx();
|
|
347
|
-
try {
|
|
348
|
-
renameSync(legacy, `${legacy}.imported`);
|
|
349
|
-
}
|
|
350
|
-
catch {
|
|
351
|
-
/* leave the source in place if it can't be renamed */
|
|
352
368
|
}
|
|
369
|
+
conn.exec("ALTER TABLE plugin_installations ADD COLUMN capabilities TEXT NOT NULL DEFAULT '[]'");
|
|
353
370
|
}
|
|
354
|
-
|
|
355
|
-
|
|
371
|
+
/** Idempotently add a column to an existing table (no-op if already present). */
|
|
372
|
+
function addColumnIfMissing(conn, table, column, ddl) {
|
|
373
|
+
const cols = conn.prepare(`PRAGMA table_info(${table})`).all();
|
|
374
|
+
if (cols.some((c) => c.name === column))
|
|
375
|
+
return;
|
|
376
|
+
conn.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddl}`);
|
|
356
377
|
}
|
package/dist/index-daemon.js
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
* The resident daemon entry — this is what pm2 keeps alive.
|
|
4
4
|
*
|
|
5
5
|
* Boot order matters: install the EPIPE guard first (we're a pm2 child).
|
|
6
|
-
* The composition root reads static plugin manifests
|
|
7
|
-
*
|
|
8
|
-
* plugin
|
|
6
|
+
* The composition root reads static plugin manifests and supervises one runtime
|
|
7
|
+
* process for each enabled runtime plugin. Installed plugin code is loaded only
|
|
8
|
+
* in child processes; plugin-owned channel instances stay inside that process.
|
|
9
9
|
*/
|
|
10
10
|
import { startRynxDaemonServer } from "./daemon-server.js";
|
|
11
|
+
import { ensureBundledOfficialPlugins } from "./bundled-plugins.js";
|
|
11
12
|
import { installStdioEpipeGuard } from "./stdio-epipe-guard.js";
|
|
12
13
|
installStdioEpipeGuard();
|
|
13
14
|
async function main() {
|
|
@@ -18,9 +19,29 @@ async function main() {
|
|
|
18
19
|
};
|
|
19
20
|
if (followsApp)
|
|
20
21
|
process.once("disconnect", recordParentDisconnect);
|
|
22
|
+
const preparePlugins = async () => {
|
|
23
|
+
try {
|
|
24
|
+
const bundled = await ensureBundledOfficialPlugins({ reclaimHostLeases: true });
|
|
25
|
+
if (bundled.status === "ready") {
|
|
26
|
+
console.log(JSON.stringify({
|
|
27
|
+
level: "info",
|
|
28
|
+
type: "bundled_plugins_ready",
|
|
29
|
+
installed: bundled.installed,
|
|
30
|
+
updated: bundled.updated,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error(JSON.stringify({
|
|
36
|
+
level: "error",
|
|
37
|
+
type: "bundled_plugins_failed",
|
|
38
|
+
error: error instanceof Error ? error.message : String(error),
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
21
42
|
let server;
|
|
22
43
|
try {
|
|
23
|
-
server = await startRynxDaemonServer();
|
|
44
|
+
server = await startRynxDaemonServer({ preparePlugins });
|
|
24
45
|
}
|
|
25
46
|
catch (error) {
|
|
26
47
|
process.off("disconnect", recordParentDisconnect);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface CleanupOptions {
|
|
2
|
-
/** CodexSessionStore JSON path; defaults to
|
|
2
|
+
/** CodexSessionStore JSON path; defaults to `{RYNX_HOME}/.codex-proxy/sessions.json`. */
|
|
3
3
|
codexStorePath?: string;
|
|
4
4
|
/** Report what would be removed without deleting anything. */
|
|
5
5
|
dryRun?: boolean;
|
|
@@ -8,20 +8,21 @@
|
|
|
8
8
|
* - canonical-log rows (`session_items`) and identity rows (`sessions`) whose
|
|
9
9
|
* id is not an opaque `sess_` id,
|
|
10
10
|
* - the daemon-owned runtime thread→rollout bindings in
|
|
11
|
-
* `.codex-proxy/sessions.json` that
|
|
11
|
+
* `.codex-proxy/sessions.json` that no longer have a Session row. This also
|
|
12
|
+
* removes opaque bindings left behind by the snapshot-schema cutover.
|
|
12
13
|
*
|
|
13
14
|
* Runs on every daemon boot (not marker-gated): on a healthy system it deletes
|
|
14
15
|
* nothing and writes nothing, so it is cheap; if a legacy session ever appears
|
|
15
|
-
* the next boot removes it.
|
|
16
|
-
*
|
|
16
|
+
* the next boot removes it. Plugin-private routing stores are deliberately not
|
|
17
|
+
* read.
|
|
17
18
|
*/
|
|
18
19
|
import { mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
19
20
|
import path from "node:path";
|
|
20
|
-
import {
|
|
21
|
+
import { rynxHome } from "@rynx-ai/core";
|
|
21
22
|
import { db } from "../db.js";
|
|
22
23
|
/** Mirrors the daemon runtime store's default resolution. */
|
|
23
24
|
function defaultProxyDir() {
|
|
24
|
-
return path.join(
|
|
25
|
+
return path.join(rynxHome(), ".codex-proxy");
|
|
25
26
|
}
|
|
26
27
|
// Anything whose id isn't an opaque `sess_` id is legacy. GLOB treats `_` as a
|
|
27
28
|
// literal (unlike LIKE), so `sess_*` matches exactly the new id shape.
|
|
@@ -31,11 +32,14 @@ export function cleanupLegacySessions(opts = {}) {
|
|
|
31
32
|
const log = opts.log ?? (() => { });
|
|
32
33
|
const dryRun = Boolean(opts.dryRun);
|
|
33
34
|
const conn = db();
|
|
34
|
-
const
|
|
35
|
+
const liveSessionIds = new Set(conn.prepare("SELECT id FROM sessions").all().map((row) => row.id));
|
|
36
|
+
const codexStorePath = opts.codexStorePath
|
|
37
|
+
? path.resolve(rynxHome(), opts.codexStorePath)
|
|
38
|
+
: path.join(defaultProxyDir(), "sessions.json");
|
|
35
39
|
if (dryRun) {
|
|
36
40
|
const deletedLogRows = countRows(conn, `SELECT COUNT(*) AS n FROM session_items WHERE ${LEGACY_LOG}`);
|
|
37
41
|
const deletedSessions = countRows(conn, `SELECT COUNT(*) AS n FROM sessions WHERE ${LEGACY_META}`);
|
|
38
|
-
const prunedStoreEntries =
|
|
42
|
+
const prunedStoreEntries = countOrphanedStoreEntries(readJsonStore(codexStorePath), (key) => key, liveSessionIds);
|
|
39
43
|
log({ event: "cleanup.dry_run", deletedLogRows, deletedSessions, prunedStoreEntries });
|
|
40
44
|
return { dryRun: true, deletedLogRows, deletedSessions, prunedStoreEntries };
|
|
41
45
|
}
|
|
@@ -48,7 +52,7 @@ export function cleanupLegacySessions(opts = {}) {
|
|
|
48
52
|
})();
|
|
49
53
|
// The runtime store is daemon-owned. Plugin routing stores remain private to
|
|
50
54
|
// their plugins and are never inspected by this migration.
|
|
51
|
-
prunedStoreEntries += pruneStore(codexStorePath, (key) => key);
|
|
55
|
+
prunedStoreEntries += pruneStore(codexStorePath, (key) => key, liveSessionIds);
|
|
52
56
|
if (deletedLogRows || deletedSessions || prunedStoreEntries) {
|
|
53
57
|
log({ event: "cleanup.done", deletedLogRows, deletedSessions, prunedStoreEntries });
|
|
54
58
|
}
|
|
@@ -57,31 +61,45 @@ export function cleanupLegacySessions(opts = {}) {
|
|
|
57
61
|
function countRows(conn, sql) {
|
|
58
62
|
return conn.prepare(sql).get().n;
|
|
59
63
|
}
|
|
60
|
-
function
|
|
64
|
+
function countOrphanedStoreEntries(data, idOf, liveSessionIds) {
|
|
61
65
|
let n = 0;
|
|
62
66
|
for (const [key, record] of Object.entries(data.sessions ?? {})) {
|
|
63
67
|
const id = idOf(key, record);
|
|
64
|
-
if (typeof id === "string" && !
|
|
68
|
+
if (typeof id === "string" && !liveSessionIds.has(id))
|
|
69
|
+
n += 1;
|
|
70
|
+
}
|
|
71
|
+
for (const key of Object.keys(data.claudeForkIntents ?? {})) {
|
|
72
|
+
if (!liveSessionIds.has(key))
|
|
65
73
|
n += 1;
|
|
66
74
|
}
|
|
67
75
|
return n;
|
|
68
76
|
}
|
|
69
|
-
/** Drop every
|
|
70
|
-
function pruneStore(file, idOf) {
|
|
77
|
+
/** Drop every binding whose owning Session no longer exists. */
|
|
78
|
+
function pruneStore(file, idOf, liveSessionIds) {
|
|
71
79
|
const data = readJsonStore(file);
|
|
72
|
-
if (!data.sessions)
|
|
80
|
+
if (!data.sessions && !data.claudeForkIntents)
|
|
73
81
|
return 0;
|
|
74
82
|
let pruned = 0;
|
|
75
83
|
const kept = {};
|
|
76
|
-
for (const [key, record] of Object.entries(data.sessions)) {
|
|
84
|
+
for (const [key, record] of Object.entries(data.sessions ?? {})) {
|
|
77
85
|
const id = idOf(key, record);
|
|
78
|
-
if (typeof id === "string" && !
|
|
86
|
+
if (typeof id === "string" && !liveSessionIds.has(id)) {
|
|
79
87
|
pruned += 1;
|
|
80
88
|
}
|
|
81
89
|
else {
|
|
82
90
|
kept[key] = record;
|
|
83
91
|
}
|
|
84
92
|
}
|
|
93
|
+
if (data.claudeForkIntents) {
|
|
94
|
+
const keptIntents = {};
|
|
95
|
+
for (const [targetSessionId, intent] of Object.entries(data.claudeForkIntents)) {
|
|
96
|
+
if (liveSessionIds.has(targetSessionId))
|
|
97
|
+
keptIntents[targetSessionId] = intent;
|
|
98
|
+
else
|
|
99
|
+
pruned += 1;
|
|
100
|
+
}
|
|
101
|
+
data.claudeForkIntents = keptIntents;
|
|
102
|
+
}
|
|
85
103
|
if (pruned > 0) {
|
|
86
104
|
data.sessions = kept;
|
|
87
105
|
writeJsonStore(file, data);
|
package/dist/plugin-cli.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type PluginCliHostEffect } from "@rynx-ai/plugin-sdk";
|
|
2
1
|
import { type RunnablePluginRecord } from "./plugin-store.js";
|
|
3
2
|
export interface RunPluginCliOptions {
|
|
4
3
|
stdio?: "inherit" | "pipe";
|
|
@@ -14,7 +13,6 @@ export interface RunPluginCliOptions {
|
|
|
14
13
|
}
|
|
15
14
|
export interface PluginCliCommandResult {
|
|
16
15
|
code: number;
|
|
17
|
-
effects: PluginCliHostEffect[];
|
|
18
16
|
output?: {
|
|
19
17
|
stdout: string;
|
|
20
18
|
stderr: string;
|
|
@@ -22,7 +20,7 @@ export interface PluginCliCommandResult {
|
|
|
22
20
|
stderrTruncated: boolean;
|
|
23
21
|
};
|
|
24
22
|
}
|
|
25
|
-
/** Execute one statically declared plugin command
|
|
23
|
+
/** Execute one statically declared, language-neutral plugin command. */
|
|
26
24
|
export declare function runPluginCliCommand(pluginId: string, args: readonly string[], options?: RunPluginCliOptions): Promise<PluginCliCommandResult>;
|
|
27
25
|
export declare function pluginCommandUsage(record: RunnablePluginRecord): string;
|
|
28
26
|
export declare class PluginCliUsageError extends Error {
|