@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.
Files changed (89) hide show
  1. package/dist/browser-cli-args.d.ts +20 -0
  2. package/dist/browser-cli-args.js +100 -0
  3. package/dist/browser-runner-session-context.d.ts +24 -0
  4. package/dist/browser-runner-session-context.js +113 -0
  5. package/dist/cdp-keyboard-input.d.ts +6 -0
  6. package/dist/cdp-keyboard-input.js +209 -0
  7. package/dist/channel-store.d.ts +0 -6
  8. package/dist/channel-store.js +2 -18
  9. package/dist/chrome-for-testing-release-resolver.d.ts +34 -0
  10. package/dist/chrome-for-testing-release-resolver.js +214 -0
  11. package/dist/chrome-for-testing-store.d.ts +85 -0
  12. package/dist/chrome-for-testing-store.js +836 -0
  13. package/dist/cli.js +467 -30
  14. package/dist/control-client.d.ts +113 -0
  15. package/dist/control-client.js +792 -0
  16. package/dist/control-deps.js +37 -6
  17. package/dist/control-endpoint.d.ts +14 -0
  18. package/dist/control-endpoint.js +124 -0
  19. package/dist/control-link-store.d.ts +16 -0
  20. package/dist/control-link-store.js +53 -0
  21. package/dist/daemon-owner.d.ts +14 -0
  22. package/dist/daemon-owner.js +104 -0
  23. package/dist/daemon-server.d.ts +12 -2
  24. package/dist/daemon-server.js +559 -28
  25. package/dist/db.js +140 -10
  26. package/dist/desktop-browser-host-client.d.ts +34 -0
  27. package/dist/desktop-browser-host-client.js +413 -0
  28. package/dist/direct-runtime-authenticator.d.ts +13 -0
  29. package/dist/direct-runtime-authenticator.js +127 -0
  30. package/dist/direct-runtime-config.d.ts +20 -0
  31. package/dist/direct-runtime-config.js +101 -0
  32. package/dist/embedded-browser-profile-cleanup.d.ts +58 -0
  33. package/dist/embedded-browser-profile-cleanup.js +338 -0
  34. package/dist/headless-browser-host.d.ts +14 -0
  35. package/dist/headless-browser-host.js +2156 -0
  36. package/dist/index-daemon.js +28 -5
  37. package/dist/installation-id.d.ts +33 -0
  38. package/dist/installation-id.js +692 -0
  39. package/dist/migrations/cleanup-legacy-sessions.d.ts +0 -3
  40. package/dist/migrations/cleanup-legacy-sessions.js +10 -28
  41. package/dist/plugin-cli.d.ts +30 -0
  42. package/dist/plugin-cli.js +270 -0
  43. package/dist/plugin-host-rpc.d.ts +85 -0
  44. package/dist/plugin-host-rpc.js +878 -0
  45. package/dist/plugin-install-restart.d.ts +13 -0
  46. package/dist/plugin-install-restart.js +24 -0
  47. package/dist/plugin-installer.d.ts +36 -15
  48. package/dist/plugin-installer.js +420 -155
  49. package/dist/plugin-package.d.ts +38 -0
  50. package/dist/plugin-package.js +553 -0
  51. package/dist/plugin-runtime-control.d.ts +2 -0
  52. package/dist/plugin-runtime-control.js +37 -0
  53. package/dist/plugin-store.d.ts +37 -8
  54. package/dist/plugin-store.js +80 -15
  55. package/dist/plugin-supervisor.d.ts +160 -0
  56. package/dist/plugin-supervisor.js +1143 -0
  57. package/dist/pm2.d.ts +3 -1
  58. package/dist/pm2.js +55 -13
  59. package/dist/provider-cli-service.d.ts +46 -0
  60. package/dist/provider-cli-service.js +510 -0
  61. package/dist/registry.d.ts +6 -19
  62. package/dist/registry.js +22 -87
  63. package/dist/remote-runtime-access-store.d.ts +61 -0
  64. package/dist/remote-runtime-access-store.js +386 -0
  65. package/dist/remote-runtime-admin.d.ts +32 -0
  66. package/dist/remote-runtime-admin.js +107 -0
  67. package/dist/remote-runtime-connection-manager.d.ts +92 -0
  68. package/dist/remote-runtime-connection-manager.js +1409 -0
  69. package/dist/remote-runtime-credential-store.d.ts +45 -0
  70. package/dist/remote-runtime-credential-store.js +639 -0
  71. package/dist/remote-runtime-target-control.d.ts +47 -0
  72. package/dist/remote-runtime-target-control.js +433 -0
  73. package/dist/remote-runtime-target-store.d.ts +53 -0
  74. package/dist/remote-runtime-target-store.js +307 -0
  75. package/dist/runtime-share-addresses.d.ts +21 -0
  76. package/dist/runtime-share-addresses.js +50 -0
  77. package/dist/session-browser-capability-store.d.ts +13 -0
  78. package/dist/session-browser-capability-store.js +58 -0
  79. package/dist/session-emulator-binding-store.d.ts +10 -0
  80. package/dist/session-emulator-binding-store.js +61 -0
  81. package/dist/session-launch-operations.d.ts +41 -0
  82. package/dist/session-launch-operations.js +124 -0
  83. package/dist/session-meta-store.d.ts +3 -2
  84. package/dist/session-meta-store.js +57 -7
  85. package/dist/setup.js +9 -4
  86. package/dist/skills-catalog.js +8 -4
  87. package/dist/update.d.ts +11 -2
  88. package/dist/update.js +0 -27
  89. package/package.json +18 -10
@@ -2,29 +2,24 @@
2
2
  * Self-healing cleanup of legacy, origin-encoded sessions.
3
3
  *
4
4
  * Sessions now carry an opaque `sess_<uuid>` id. Any session keyed by a legacy id
5
- * (`session_<uuid>` console, `lark:…:session:<uuid>` / `lark:…` channel) is simply
6
- * discarded — not migrated — so the system stays clean and every channel re-mints
7
- * a fresh `sess_` session on its next message.
5
+ * is discarded rather than migrated.
8
6
  *
9
7
  * Deletes:
10
8
  * - canonical-log rows (`session_items`) and identity rows (`sessions`) whose
11
9
  * id is not an opaque `sess_` id,
12
- * - the runtime thread→rollout bindings `.codex-proxy/sessions.json` and the
13
- * channel routing maps `.codex-proxy/lark-sessions*.json` entries that point
14
- * at a legacy id (the externalKey KEYS go too, so the next message bootstraps
15
- * a fresh session).
10
+ * - the daemon-owned runtime thread→rollout bindings in
11
+ * `.codex-proxy/sessions.json` that use a legacy id.
16
12
  *
17
13
  * Runs on every daemon boot (not marker-gated): on a healthy system it deletes
18
14
  * nothing and writes nothing, so it is cheap; if a legacy session ever appears
19
- * (e.g. an old channel plugin produced one), the next boot removes it. The
20
- * `sess_` filter means it can never touch a current session.
15
+ * the next boot removes it. The `sess_` filter means it can never touch a
16
+ * current session. Plugin-private routing stores are deliberately not read.
21
17
  */
22
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
18
+ import { mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
23
19
  import path from "node:path";
24
20
  import { isMachineSessionId } from "@rynx-ai/core";
25
21
  import { db } from "../db.js";
26
- /** Mirrors the channel stores' own resolution (`<cwd>/.codex-proxy`). Kept local
27
- * so the daemon needn't depend on `@rynx-ai/runtime` / the lark plugin. */
22
+ /** Mirrors the daemon runtime store's default resolution. */
28
23
  function defaultProxyDir() {
29
24
  return path.join(process.cwd(), ".codex-proxy");
30
25
  }
@@ -37,13 +32,10 @@ export function cleanupLegacySessions(opts = {}) {
37
32
  const dryRun = Boolean(opts.dryRun);
38
33
  const conn = db();
39
34
  const codexStorePath = opts.codexStorePath ?? path.join(defaultProxyDir(), "sessions.json");
40
- const channelStoreDir = opts.channelStoreDir ?? defaultProxyDir();
41
- const larkFiles = listLarkStoreFiles(channelStoreDir);
42
35
  if (dryRun) {
43
36
  const deletedLogRows = countRows(conn, `SELECT COUNT(*) AS n FROM session_items WHERE ${LEGACY_LOG}`);
44
37
  const deletedSessions = countRows(conn, `SELECT COUNT(*) AS n FROM sessions WHERE ${LEGACY_META}`);
45
- const prunedStoreEntries = countLegacyStoreEntries(readJsonStore(codexStorePath), (key) => key) +
46
- larkFiles.reduce((sum, file) => sum + countLegacyStoreEntries(readJsonStore(file), (_k, rec) => rec.sessionId), 0);
38
+ const prunedStoreEntries = countLegacyStoreEntries(readJsonStore(codexStorePath), (key) => key);
47
39
  log({ event: "cleanup.dry_run", deletedLogRows, deletedSessions, prunedStoreEntries });
48
40
  return { dryRun: true, deletedLogRows, deletedSessions, prunedStoreEntries };
49
41
  }
@@ -54,12 +46,9 @@ export function cleanupLegacySessions(opts = {}) {
54
46
  deletedLogRows = conn.prepare(`DELETE FROM session_items WHERE ${LEGACY_LOG}`).run().changes;
55
47
  deletedSessions = conn.prepare(`DELETE FROM sessions WHERE ${LEGACY_META}`).run().changes;
56
48
  })();
57
- // Prune the JSON stores: a codex entry keyed by a legacy id, or a routing entry
58
- // whose value points at one. Removing the routing entry makes the next message
59
- // bootstrap a fresh `sess_` session for that conversation.
49
+ // The runtime store is daemon-owned. Plugin routing stores remain private to
50
+ // their plugins and are never inspected by this migration.
60
51
  prunedStoreEntries += pruneStore(codexStorePath, (key) => key);
61
- for (const file of larkFiles)
62
- prunedStoreEntries += pruneStore(file, (_k, rec) => rec.sessionId);
63
52
  if (deletedLogRows || deletedSessions || prunedStoreEntries) {
64
53
  log({ event: "cleanup.done", deletedLogRows, deletedSessions, prunedStoreEntries });
65
54
  }
@@ -99,13 +88,6 @@ function pruneStore(file, idOf) {
99
88
  }
100
89
  return pruned;
101
90
  }
102
- function listLarkStoreFiles(dir) {
103
- if (!existsSync(dir))
104
- return [];
105
- return readdirSync(dir)
106
- .filter((name) => /^lark-sessions.*\.json$/.test(name))
107
- .map((name) => path.join(dir, name));
108
- }
109
91
  function readJsonStore(file) {
110
92
  try {
111
93
  const parsed = JSON.parse(readFileSync(file, "utf8"));
@@ -0,0 +1,30 @@
1
+ import { type PluginCliHostEffect } from "@rynx-ai/plugin-sdk";
2
+ import { type RunnablePluginRecord } from "./plugin-store.js";
3
+ export interface RunPluginCliOptions {
4
+ stdio?: "inherit" | "pipe";
5
+ env?: NodeJS.ProcessEnv;
6
+ /** Text piped to the child without ever being logged or copied to its argv. */
7
+ stdin?: string;
8
+ /** Capture at most this many bytes from each output stream; excess is drained. */
9
+ captureOutputBytes?: number;
10
+ /** Abort the child command; the host escalates from SIGTERM to SIGKILL. */
11
+ signal?: AbortSignal;
12
+ /** Test seam for the bounded SIGTERM grace period. */
13
+ terminationGraceMs?: number;
14
+ }
15
+ export interface PluginCliCommandResult {
16
+ code: number;
17
+ effects: PluginCliHostEffect[];
18
+ output?: {
19
+ stdout: string;
20
+ stderr: string;
21
+ stdoutTruncated: boolean;
22
+ stderrTruncated: boolean;
23
+ };
24
+ }
25
+ /** Execute one statically declared plugin command in a separate Node process. */
26
+ export declare function runPluginCliCommand(pluginId: string, args: readonly string[], options?: RunPluginCliOptions): Promise<PluginCliCommandResult>;
27
+ export declare function pluginCommandUsage(record: RunnablePluginRecord): string;
28
+ export declare class PluginCliUsageError extends Error {
29
+ constructor(message: string);
30
+ }
@@ -0,0 +1,270 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdirSync, realpathSync, statSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { rynxHome } from "@rynx-ai/core";
5
+ import { createPluginCliInvocationLeaseId, parsePluginCliHostEffect, removePluginRuntimeLease, writePluginRuntimeLease, } from "@rynx-ai/plugin-sdk";
6
+ import { db } from "./db.js";
7
+ import { getPlugin, isRunnablePluginRecord } from "./plugin-store.js";
8
+ import { loadOrCreateDaemonInstallationIdentitySync } from "./installation-id.js";
9
+ const DEFAULT_TERMINATION_GRACE_MS = 2_000;
10
+ const MAX_TERMINATION_GRACE_MS = 30_000;
11
+ /** Execute one statically declared plugin command in a separate Node process. */
12
+ export async function runPluginCliCommand(pluginId, args, options = {}) {
13
+ const hostEnv = options.env ?? process.env;
14
+ const terminationGraceMs = options.terminationGraceMs ?? DEFAULT_TERMINATION_GRACE_MS;
15
+ let child;
16
+ let completion;
17
+ let dataDir;
18
+ let leaseId;
19
+ let stdout;
20
+ let stderr;
21
+ let terminationReason;
22
+ let forceKillTimer;
23
+ let abortListener;
24
+ const effects = new Map();
25
+ if (options.stdin !== undefined && options.stdio !== "pipe") {
26
+ throw new Error("plugin CLI stdin requires piped stdio");
27
+ }
28
+ if (options.captureOutputBytes !== undefined &&
29
+ (!Number.isSafeInteger(options.captureOutputBytes) || options.captureOutputBytes < 0)) {
30
+ throw new Error("plugin CLI output limit must be a non-negative safe integer");
31
+ }
32
+ if (!Number.isSafeInteger(terminationGraceMs) ||
33
+ terminationGraceMs < 0 ||
34
+ terminationGraceMs > MAX_TERMINATION_GRACE_MS) {
35
+ throw new Error(`plugin CLI termination grace must be between 0 and ${MAX_TERMINATION_GRACE_MS}ms`);
36
+ }
37
+ if (options.signal?.aborted)
38
+ throw pluginCliAbortError(options.signal.reason);
39
+ const installationIdentity = loadOrCreateDaemonInstallationIdentitySync(hostEnv);
40
+ const clearForceKill = () => {
41
+ if (forceKillTimer)
42
+ clearTimeout(forceKillTimer);
43
+ forceKillTimer = undefined;
44
+ };
45
+ const childIsRunning = () => Boolean(child && typeof child.pid === "number" && child.exitCode === null && child.signalCode === null);
46
+ const terminateChild = (reason) => {
47
+ terminationReason ??= reason;
48
+ if (!childIsRunning())
49
+ return;
50
+ try {
51
+ child.kill("SIGTERM");
52
+ }
53
+ catch {
54
+ // The close/error event remains authoritative for cleanup.
55
+ }
56
+ if (forceKillTimer)
57
+ return;
58
+ forceKillTimer = setTimeout(() => {
59
+ forceKillTimer = undefined;
60
+ if (!childIsRunning())
61
+ return;
62
+ try {
63
+ child.kill("SIGKILL");
64
+ }
65
+ catch {
66
+ // Completion still waits for close/error; no lease is removed early.
67
+ }
68
+ }, terminationGraceMs);
69
+ forceKillTimer.unref?.();
70
+ };
71
+ const cleanup = () => {
72
+ clearForceKill();
73
+ if (abortListener)
74
+ options.signal?.removeEventListener("abort", abortListener);
75
+ abortListener = undefined;
76
+ if (dataDir && leaseId)
77
+ removePluginRuntimeLease(dataDir, leaseId);
78
+ };
79
+ try {
80
+ db().transaction(() => {
81
+ const record = getPlugin(pluginId);
82
+ if (!record)
83
+ throw new Error(`plugin "${pluginId}" is not installed`);
84
+ if (!isRunnablePluginRecord(record)) {
85
+ throw new Error(`plugin "${pluginId}" uses the removed legacy format; reinstall it`);
86
+ }
87
+ // `enabled` controls daemon runtime contributions, not explicit CLI calls.
88
+ // Keeping commands available lets a user stop/status a managed service before
89
+ // uninstalling a disabled plugin.
90
+ const command = args[0];
91
+ const declared = record.manifest.contributions?.commands?.find((entry) => entry.id === command);
92
+ if (!command ||
93
+ command === "--help" ||
94
+ command === "-h" ||
95
+ (command === "help" && !declared)) {
96
+ throw new PluginCliUsageError(pluginCommandUsage(record));
97
+ }
98
+ if (!declared) {
99
+ throw new PluginCliUsageError(`plugin "${pluginId}" does not declare command "${command}"\n\n${pluginCommandUsage(record)}`);
100
+ }
101
+ if (!record.manifest.cliEntry) {
102
+ throw new Error(`plugin "${pluginId}" declares commands but has no cliEntry`);
103
+ }
104
+ const packageRoot = realpathSync(record.installPath);
105
+ const cliEntry = realpathSync(path.resolve(packageRoot, record.manifest.cliEntry));
106
+ if (!isPathInside(packageRoot, cliEntry) || !statSync(cliEntry).isFile()) {
107
+ throw new Error(`plugin "${pluginId}" cliEntry resolves outside its package`);
108
+ }
109
+ dataDir = path.join(rynxHome(), "plugin-data", record.name);
110
+ mkdirSync(dataDir, { recursive: true, mode: 0o700 });
111
+ child = spawn(process.execPath, [cliEntry, ...args], {
112
+ cwd: dataDir,
113
+ env: {
114
+ ...hostEnv,
115
+ RYNX_HOST_INSTALLATION_ID: installationIdentity.installationId,
116
+ RYNX_HOST_INSTALLATION_PROOF_ALGORITHM: installationIdentity.algorithm,
117
+ RYNX_HOST_INSTALLATION_PUBLIC_KEY: installationIdentity.publicKey,
118
+ RYNX_PLUGIN_ID: record.name,
119
+ RYNX_PLUGIN_PACKAGE_ROOT: packageRoot,
120
+ RYNX_PLUGIN_DATA_DIR: dataDir,
121
+ },
122
+ stdio: options.stdio === "pipe"
123
+ ? ["pipe", "pipe", "pipe", "ipc"]
124
+ : ["inherit", "inherit", "inherit", "ipc"],
125
+ });
126
+ completion = new Promise((resolve, reject) => {
127
+ child.on("message", (message) => {
128
+ try {
129
+ const effect = parsePluginCliHostEffect(message);
130
+ effects.set(effect.effect, effect);
131
+ }
132
+ catch (error) {
133
+ terminateChild(error instanceof Error ? error : new Error(String(error)));
134
+ }
135
+ });
136
+ child.once("error", (error) => {
137
+ if (!childIsRunning()) {
138
+ reject(error);
139
+ return;
140
+ }
141
+ terminateChild(error);
142
+ });
143
+ child.once("close", (code, signal) => {
144
+ clearForceKill();
145
+ if (terminationReason) {
146
+ reject(terminationReason);
147
+ return;
148
+ }
149
+ if (signal) {
150
+ reject(new Error(`plugin command terminated by ${signal}`));
151
+ return;
152
+ }
153
+ resolve(code ?? 1);
154
+ });
155
+ });
156
+ if (options.stdio === "pipe") {
157
+ stdout = captureStream(child.stdout, options.captureOutputBytes);
158
+ stderr = captureStream(child.stderr, options.captureOutputBytes);
159
+ child.stdin.on("error", () => {
160
+ // A command may intentionally exit without reading all input. The
161
+ // exit status remains the authoritative invocation result.
162
+ });
163
+ child.stdin.end(options.stdin ?? "", "utf8");
164
+ }
165
+ if (options.signal) {
166
+ abortListener = () => terminateChild(pluginCliAbortError(options.signal.reason));
167
+ if (options.signal.aborted)
168
+ abortListener();
169
+ else
170
+ options.signal.addEventListener("abort", abortListener, { once: true });
171
+ }
172
+ leaseId = createPluginCliInvocationLeaseId(child.pid ?? process.pid);
173
+ writePluginRuntimeLease({
174
+ dataDir,
175
+ pluginId: record.name,
176
+ leaseId,
177
+ installPath: packageRoot,
178
+ });
179
+ }).immediate();
180
+ }
181
+ catch (error) {
182
+ if (completion && childIsRunning()) {
183
+ terminateChild(error instanceof Error ? error : new Error(String(error)));
184
+ await completion.catch(() => undefined);
185
+ }
186
+ else if (completion) {
187
+ await completion.catch(() => undefined);
188
+ }
189
+ cleanup();
190
+ throw error;
191
+ }
192
+ try {
193
+ const code = await completion;
194
+ return {
195
+ code,
196
+ effects: code === 0 ? [...effects.values()] : [],
197
+ ...(options.captureOutputBytes !== undefined && stdout && stderr
198
+ ? {
199
+ output: {
200
+ stdout: stdout.text(),
201
+ stderr: stderr.text(),
202
+ stdoutTruncated: stdout.truncated(),
203
+ stderrTruncated: stderr.truncated(),
204
+ },
205
+ }
206
+ : {}),
207
+ };
208
+ }
209
+ finally {
210
+ cleanup();
211
+ }
212
+ }
213
+ function pluginCliAbortError(reason) {
214
+ const error = new Error(reason instanceof Error && reason.message ? reason.message : "plugin CLI command aborted");
215
+ error.name = reason instanceof Error && reason.name === "TimeoutError"
216
+ ? "TimeoutError"
217
+ : "AbortError";
218
+ return error;
219
+ }
220
+ function captureStream(stream, limit) {
221
+ const chunks = [];
222
+ let captured = 0;
223
+ let dropped = false;
224
+ stream.on("data", (chunk) => {
225
+ const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
226
+ if (limit === undefined)
227
+ return;
228
+ const remaining = limit - captured;
229
+ if (remaining <= 0) {
230
+ if (data.byteLength > 0)
231
+ dropped = true;
232
+ return;
233
+ }
234
+ if (data.byteLength <= remaining) {
235
+ chunks.push(data);
236
+ captured += data.byteLength;
237
+ return;
238
+ }
239
+ chunks.push(data.subarray(0, remaining));
240
+ captured += remaining;
241
+ dropped = true;
242
+ });
243
+ return {
244
+ text: () => Buffer.concat(chunks, captured).toString("utf8"),
245
+ truncated: () => dropped,
246
+ };
247
+ }
248
+ export function pluginCommandUsage(record) {
249
+ const commands = record.manifest.contributions?.commands ?? [];
250
+ const lines = [`Usage: rynx plugin ${record.name} <command> [args...]`];
251
+ if (commands.length === 0)
252
+ return [...lines, "", "This plugin declares no CLI commands."].join("\n");
253
+ lines.push("", "Commands:");
254
+ for (const command of commands) {
255
+ lines.push(` ${command.id.padEnd(16)} ${command.description}`);
256
+ if (command.usage)
257
+ lines.push(` ${"".padEnd(16)} ${command.usage}`);
258
+ }
259
+ return lines.join("\n");
260
+ }
261
+ export class PluginCliUsageError extends Error {
262
+ constructor(message) {
263
+ super(message);
264
+ this.name = "PluginCliUsageError";
265
+ }
266
+ }
267
+ function isPathInside(root, candidate) {
268
+ const relative = path.relative(root, candidate);
269
+ return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative));
270
+ }
@@ -0,0 +1,85 @@
1
+ import { type AgentCapabilities, type AgentSessionStore, type ConversationRuntime, type SessionRegistry } from "@rynx-ai/core";
2
+ import { type PluginAgentSummary, type PluginCapability, type PluginHostEvent, type PluginResolvedSessionExecution, type PluginSessionExecutionSnapshot, type PluginSessionInteractionResolveDisposition } from "@rynx-ai/plugin-sdk";
3
+ import type { SessionInteractionResolution } from "@rynx-ai/protocol";
4
+ import { PluginRunnerError } from "@rynx-ai/plugin-runner";
5
+ /** Leaves ample room for the RPC envelope below the runner's 1 MiB line cap. */
6
+ export declare const MAX_PLUGIN_HOST_EVENT_BYTES: number;
7
+ export interface PluginAgentCatalogHost {
8
+ list(): Promise<PluginAgentSummary[]>;
9
+ get(id: string): Promise<PluginAgentSummary | null>;
10
+ resolveExecution(input: {
11
+ defaultAgent?: string;
12
+ session: PluginSessionExecutionSnapshot;
13
+ }): Promise<PluginResolvedSessionExecution>;
14
+ }
15
+ export interface PluginHostServices {
16
+ installationId: string;
17
+ installationProof: {
18
+ algorithm: "Ed25519";
19
+ publicKey: string;
20
+ sign(pluginId: string, challenge: string): string;
21
+ };
22
+ conversationRuntime: ConversationRuntime;
23
+ capabilities: AgentCapabilities;
24
+ sessionStore: AgentSessionStore;
25
+ sessionRegistry: SessionRegistry;
26
+ agentCatalog: PluginAgentCatalogHost;
27
+ interruptSession?(sessionId: string): Promise<boolean>;
28
+ resolveSessionInteraction?(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
29
+ disposition: PluginSessionInteractionResolveDisposition;
30
+ }>;
31
+ }
32
+ export interface PluginHostRpcOptions {
33
+ pluginId: string;
34
+ daemonInstanceId: string;
35
+ grants: readonly PluginCapability[];
36
+ services: PluginHostServices;
37
+ /** Resolving this promise is the stream's backpressure acknowledgement. */
38
+ emit(event: PluginHostEvent): void | Promise<void>;
39
+ }
40
+ /**
41
+ * One authenticated plugin's capability-gated Host RPC surface.
42
+ *
43
+ * This adapter is deliberately the only place that maps public string methods
44
+ * to trusted runtime objects. The runner receives neither this class nor its
45
+ * dependencies; it receives JSON responses and canonical session events.
46
+ */
47
+ export declare class PluginHostRpc {
48
+ private readonly pluginId;
49
+ private readonly daemonInstanceId;
50
+ private readonly grants;
51
+ private readonly services;
52
+ private readonly emit;
53
+ private readonly activeRuns;
54
+ private readonly activeSessionRuns;
55
+ private readonly activeRunsByOperation;
56
+ private disposed;
57
+ constructor(options: PluginHostRpcOptions);
58
+ call(method: string, params: unknown): Promise<unknown>;
59
+ dispose(): Promise<void>;
60
+ private ensureSession;
61
+ private runSession;
62
+ private pumpRun;
63
+ private releaseRun;
64
+ private steerSession;
65
+ private interruptRun;
66
+ private interruptWon;
67
+ private activeRun;
68
+ private activeRunByIdentity;
69
+ private getBinding;
70
+ private listBindings;
71
+ private findBinding;
72
+ private withOwnedSession;
73
+ private resolveSessionInteraction;
74
+ private forkSession;
75
+ private setSessionTitle;
76
+ private resolveAgentExecution;
77
+ private issueControlLink;
78
+ private ownedSession;
79
+ private isOwned;
80
+ }
81
+ export declare class PluginHostCallError extends PluginRunnerError {
82
+ readonly retryable: boolean;
83
+ readonly data?: unknown | undefined;
84
+ constructor(code: string, message: string, retryable?: boolean, data?: unknown | undefined);
85
+ }