@rynx-ai/cli 0.1.10

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 (47) hide show
  1. package/dist/agent-file.d.ts +13 -0
  2. package/dist/agent-file.js +61 -0
  3. package/dist/browser-cli-args.d.ts +28 -0
  4. package/dist/browser-cli-args.js +181 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +11 -0
  7. package/dist/client.d.ts +4 -0
  8. package/dist/client.js +2 -0
  9. package/dist/commands/agent.d.ts +1 -0
  10. package/dist/commands/agent.js +55 -0
  11. package/dist/commands/app-distribution.d.ts +6 -0
  12. package/dist/commands/app-distribution.js +98 -0
  13. package/dist/commands/browser.d.ts +1 -0
  14. package/dist/commands/browser.js +273 -0
  15. package/dist/commands/cleanup.d.ts +1 -0
  16. package/dist/commands/cleanup.js +24 -0
  17. package/dist/commands/emulator.d.ts +1 -0
  18. package/dist/commands/emulator.js +23 -0
  19. package/dist/commands/errors.d.ts +5 -0
  20. package/dist/commands/errors.js +10 -0
  21. package/dist/commands/index.d.ts +9 -0
  22. package/dist/commands/index.js +9 -0
  23. package/dist/commands/plugin.d.ts +6 -0
  24. package/dist/commands/plugin.js +289 -0
  25. package/dist/commands/runtime.d.ts +1 -0
  26. package/dist/commands/runtime.js +136 -0
  27. package/dist/commands/skills.d.ts +10 -0
  28. package/dist/commands/skills.js +80 -0
  29. package/dist/control-client.d.ts +163 -0
  30. package/dist/control-client.js +1028 -0
  31. package/dist/control-endpoint.d.ts +29 -0
  32. package/dist/control-endpoint.js +121 -0
  33. package/dist/desktop-browser-host-client.d.ts +44 -0
  34. package/dist/desktop-browser-host-client.js +430 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +2 -0
  37. package/dist/legacy-adapter.d.ts +7 -0
  38. package/dist/legacy-adapter.js +63 -0
  39. package/dist/run-cli.d.ts +1 -0
  40. package/dist/run-cli.js +62 -0
  41. package/dist/usage.d.ts +1 -0
  42. package/dist/usage.js +56 -0
  43. package/dist/version.d.ts +1 -0
  44. package/dist/version.js +8 -0
  45. package/package.json +52 -0
  46. package/skills/rynx-cli/SKILL.md +99 -0
  47. package/skills/rynx-cli/agents/openai.yaml +4 -0
@@ -0,0 +1,136 @@
1
+ import { encodePairingCode } from "@rynx-ai/protocol/direct-runtime";
2
+ import { createResidentRemoteRuntimePairingOffer, forgetResidentRuntimeTarget, listResidentRemoteRuntimeClients, listResidentRuntimeTargets, pairResidentRuntimeTarget, revokeResidentRemoteRuntimeClient, testResidentRuntimeTarget, } from "../control-client.js";
3
+ import { fail } from "./errors.js";
4
+ export async function runRuntimeCommand(args) {
5
+ const [subcommand, arg] = args;
6
+ const json = args.includes("--json");
7
+ switch (subcommand) {
8
+ case "share":
9
+ case "pair": {
10
+ const label = optionValue(args, "--label");
11
+ const address = optionValue(args, "--address");
12
+ if (!address) {
13
+ fail("runtime share: pass --address with a host or ws(s) URL reachable by the other device");
14
+ }
15
+ const offer = await createResidentRemoteRuntimePairingOffer({
16
+ ...(label ? { clientLabel: label } : {}),
17
+ address,
18
+ });
19
+ console.log(json ? JSON.stringify(offer, null, 2) : encodePairingCode(offer));
20
+ return 0;
21
+ }
22
+ case "add": {
23
+ const name = optionValue(args, "--name");
24
+ const code = optionValue(args, "--pairing-code");
25
+ if (code === undefined && process.stdin.isTTY) {
26
+ fail("runtime add: pass --pairing-code or pipe a pairing link on stdin");
27
+ }
28
+ const raw = code ?? await readStdinBounded(64 * 1024);
29
+ if (!raw.trim()) {
30
+ fail("runtime add: pass --pairing-code or pipe a pairing link on stdin");
31
+ }
32
+ let offer = raw.trim();
33
+ if (raw.trim().startsWith("{")) {
34
+ try {
35
+ offer = JSON.parse(raw);
36
+ }
37
+ catch {
38
+ fail("runtime add: stdin is not valid pairing JSON");
39
+ }
40
+ }
41
+ const result = await pairResidentRuntimeTarget(offer, name);
42
+ if (json) {
43
+ console.log(JSON.stringify(result, null, 2));
44
+ }
45
+ else {
46
+ console.log(`Paired ${result.target.displayName} (${result.target.daemonId}) ` +
47
+ `via ${result.target.endpoint}.`);
48
+ console.log(`Remote instance: ${result.status.daemonInstanceId}`);
49
+ }
50
+ return 0;
51
+ }
52
+ case "list": {
53
+ const targets = await listResidentRuntimeTargets();
54
+ if (json) {
55
+ console.log(JSON.stringify({ runtimes: targets }, null, 2));
56
+ return 0;
57
+ }
58
+ console.log("Runtime targets");
59
+ for (const target of targets) {
60
+ const route = target.binding === "local" ? "local" : target.endpoint;
61
+ console.log(` ${target.selector.padEnd(38)} ${target.displayName} ${route}`);
62
+ }
63
+ return 0;
64
+ }
65
+ case "test": {
66
+ if (!arg || arg.startsWith("--"))
67
+ fail("runtime test: missing local or daemon id");
68
+ const result = await testResidentRuntimeTarget(arg);
69
+ if (json) {
70
+ console.log(JSON.stringify(result, null, 2));
71
+ }
72
+ else {
73
+ console.log(`${result.target.displayName}: connected to ${result.status.daemonId} ` +
74
+ `(instance ${result.status.daemonInstanceId})`);
75
+ }
76
+ return 0;
77
+ }
78
+ case "forget": {
79
+ if (!arg || arg.startsWith("--"))
80
+ fail("runtime forget: missing daemon id");
81
+ await forgetResidentRuntimeTarget(arg);
82
+ console.log(`Forgot Runtime target ${arg}.`);
83
+ return 0;
84
+ }
85
+ case "clients": {
86
+ if (arg === "list") {
87
+ const clients = await listResidentRemoteRuntimeClients();
88
+ if (json) {
89
+ console.log(JSON.stringify({ clients }, null, 2));
90
+ return 0;
91
+ }
92
+ console.log("Remote Runtime clients");
93
+ if (clients.length === 0)
94
+ console.log(" (none)");
95
+ for (const client of clients) {
96
+ const state = client.revokedAt ? "revoked" : "active";
97
+ console.log(` ${client.grantId.padEnd(38)} ${client.clientLabel ?? client.clientId} ${state}`);
98
+ }
99
+ return 0;
100
+ }
101
+ if (arg === "revoke") {
102
+ const grantId = args[2];
103
+ if (!grantId || grantId.startsWith("--")) {
104
+ fail("runtime clients revoke: missing grant id");
105
+ }
106
+ const result = await revokeResidentRemoteRuntimeClient(grantId);
107
+ console.log(`Revoked ${grantId}; closed ${result.closedConnections} active connection(s).`);
108
+ return 0;
109
+ }
110
+ fail("runtime clients: expected list or revoke <grant-id>");
111
+ }
112
+ default:
113
+ fail("runtime: expected share, add, list, test, forget, or clients");
114
+ }
115
+ }
116
+ function optionValue(args, option) {
117
+ const index = args.indexOf(option);
118
+ if (index < 0)
119
+ return undefined;
120
+ const value = args[index + 1];
121
+ if (!value || value.startsWith("--"))
122
+ fail(`${option}: missing value`);
123
+ return value;
124
+ }
125
+ async function readStdinBounded(maxBytes) {
126
+ const chunks = [];
127
+ let bytes = 0;
128
+ for await (const chunk of process.stdin) {
129
+ const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
130
+ bytes += value.byteLength;
131
+ if (bytes > maxBytes)
132
+ fail(`stdin exceeds ${maxBytes} bytes`);
133
+ chunks.push(value);
134
+ }
135
+ return Buffer.concat(chunks, bytes).toString("utf8");
136
+ }
@@ -0,0 +1,10 @@
1
+ export interface BuiltinSkill {
2
+ name: string;
3
+ directory: string;
4
+ skillFile: string;
5
+ content: string;
6
+ }
7
+ export declare function runSkillsCommand(args: readonly string[]): Promise<number>;
8
+ export declare function listBuiltinSkills(): Promise<BuiltinSkill[]>;
9
+ export declare function readBuiltinSkill(name: string): Promise<BuiltinSkill | null>;
10
+ export declare function builtinSkillsDirectory(moduleUrl?: string, env?: NodeJS.ProcessEnv): string;
@@ -0,0 +1,80 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { fail } from "./errors.js";
6
+ const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
7
+ const MAX_SKILL_BYTES = 256 * 1024;
8
+ export async function runSkillsCommand(args) {
9
+ const [subcommand, name] = args;
10
+ const json = args.includes("--json");
11
+ if (subcommand === "list") {
12
+ const skills = await listBuiltinSkills();
13
+ if (json) {
14
+ console.log(JSON.stringify({ skills: skills.map(({ name: skillName }) => ({ name: skillName })) }, null, 2));
15
+ }
16
+ else {
17
+ for (const skill of skills)
18
+ console.log(skill.name);
19
+ }
20
+ return 0;
21
+ }
22
+ if (subcommand === "get") {
23
+ if (!name || name.startsWith("--")) {
24
+ fail("skills get: missing Builtin Skill name");
25
+ }
26
+ const skill = await readBuiltinSkill(name);
27
+ if (!skill)
28
+ fail(`Builtin Skill "${name}" was not found`);
29
+ if (json) {
30
+ console.log(JSON.stringify({
31
+ name: skill.name,
32
+ directory: skill.directory,
33
+ skillFile: skill.skillFile,
34
+ content: skill.content,
35
+ }, null, 2));
36
+ }
37
+ else {
38
+ process.stdout.write(skill.content);
39
+ if (!skill.content.endsWith("\n"))
40
+ process.stdout.write("\n");
41
+ }
42
+ return 0;
43
+ }
44
+ fail("skills: expected list or get <name>");
45
+ }
46
+ export async function listBuiltinSkills() {
47
+ const known = ["rynx-cli"];
48
+ const skills = await Promise.all(known.map((name) => readBuiltinSkill(name)));
49
+ return skills.filter((skill) => skill !== null);
50
+ }
51
+ export async function readBuiltinSkill(name) {
52
+ if (!SKILL_NAME_PATTERN.test(name))
53
+ return null;
54
+ const directory = path.join(builtinSkillsDirectory(), name);
55
+ const skillFile = path.join(directory, "SKILL.md");
56
+ try {
57
+ const content = await readFile(skillFile, "utf8");
58
+ if (Buffer.byteLength(content, "utf8") > MAX_SKILL_BYTES) {
59
+ throw new Error(`Builtin Skill "${name}" exceeds ${MAX_SKILL_BYTES} bytes`);
60
+ }
61
+ return { name, directory, skillFile, content };
62
+ }
63
+ catch (error) {
64
+ if (error.code === "ENOENT")
65
+ return null;
66
+ throw error;
67
+ }
68
+ }
69
+ export function builtinSkillsDirectory(moduleUrl = import.meta.url, env = process.env) {
70
+ const configured = env.RYNX_BUILTIN_SKILLS_DIR?.trim();
71
+ if (configured && path.isAbsolute(configured) && existsSync(configured)) {
72
+ return configured;
73
+ }
74
+ const packaged = fileURLToPath(new URL("../../skills/", moduleUrl));
75
+ if (existsSync(packaged))
76
+ return packaged;
77
+ // Source-tree tests run before a package build has copied the canonical
78
+ // artifact. Published/App builds always take the packaged branch above.
79
+ return fileURLToPath(new URL("../../../../skills/", moduleUrl));
80
+ }
@@ -0,0 +1,163 @@
1
+ import { type DaemonStatus } from "@rynx-ai/protocol/remote-runtime";
2
+ import { type DaemonBrowserArtifactCleanResult, type DaemonBrowserArtifactInstallInput, type DaemonBrowserArtifactInstallResult, type DaemonBrowserArtifactUpdateInput, type DaemonBrowserArtifactVersionResult, type DaemonCleanupSessionsInput, type DaemonCleanupSessionsResult, type DaemonChromeInspectionConfigureInput, type DaemonChromeInspectionStatus, type DaemonShutdownIfIdleResult } from "@rynx-ai/protocol/control";
3
+ import { type RemoteRuntimeRpcMethod, type RemoteRuntimeRpcParams, type RemoteRuntimeRpcResultFor } from "@rynx-ai/protocol/remote-runtime-rpc";
4
+ import { type PairingOffer } from "@rynx-ai/protocol/direct-runtime";
5
+ import { type RuntimeBrowserBootstrapCredential, type RuntimeBrowserEndpointDescriptor } from "@rynx-ai/protocol/runtime-browser-bootstrap";
6
+ import { type PluginInstallCommitInput, type PluginInstallCommitResult, type PluginInstallPreparation, type PluginInstallPrepareInput, type PluginManagementItem, type PluginManagementState } from "@rynx-ai/protocol/plugin-management";
7
+ export { connectResidentDesktopBrowserHost, type ResidentDesktopBrowserHostConnection, type ResidentDesktopBrowserHostCommandRequest, type ResidentDesktopBrowserHostConnectOptions, type ResidentDesktopBrowserHostFailure, } from "./desktop-browser-host-client.js";
8
+ export interface ResidentDaemon {
9
+ origin: string;
10
+ }
11
+ export interface ResidentDaemonIdentity {
12
+ installationId: string;
13
+ algorithm: "Ed25519";
14
+ publicKey: string;
15
+ }
16
+ export interface ResidentPluginCommandResult {
17
+ code: number;
18
+ stdout: string;
19
+ stderr: string;
20
+ truncated: boolean;
21
+ }
22
+ export type ResidentPluginManagementState = PluginManagementState;
23
+ export type ResidentPluginManagementItem = PluginManagementItem;
24
+ export interface ResidentRemoteRuntimeClientGrant {
25
+ grantId: string;
26
+ clientId: string;
27
+ clientLabel: string | null;
28
+ clientKeyFingerprint: string;
29
+ authorities: string[];
30
+ createdAt: string;
31
+ revokedAt: string | null;
32
+ lastUsedAt: string | null;
33
+ }
34
+ export interface ResidentRuntimeTargetView {
35
+ selector: string;
36
+ daemonId: string;
37
+ displayName: string;
38
+ binding: "local" | "direct";
39
+ endpoint?: string;
40
+ identityKeyFingerprint?: string;
41
+ createdAt?: string;
42
+ }
43
+ export interface ResidentRuntimeTargetTestResult {
44
+ target: ResidentRuntimeTargetView;
45
+ status: DaemonStatus;
46
+ }
47
+ export interface InvokeResidentPluginCommandOptions {
48
+ stdin?: string;
49
+ signal?: AbortSignal;
50
+ }
51
+ export type ResidentRuntimeCallErrorCode = "invalid_target" | "invalid_request" | "not_found" | "conflict" | "failed_precondition" | "method_not_found" | "deadline_exceeded" | "unreachable" | "tls_error" | "identity_mismatch" | "incompatible" | "authentication_failed" | "protocol_error" | "operation_failed" | "outcome_unknown" | "cancelled" | "unauthorized" | "closed" | "internal" | "internal_error";
52
+ export type ResidentRuntimeCallOutcome = "not_started" | "unknown";
53
+ /** Stable error returned by the resident daemon's typed Runtime gateway. */
54
+ export declare class ResidentRuntimeCallError extends Error {
55
+ readonly code: ResidentRuntimeCallErrorCode;
56
+ readonly status?: number | undefined;
57
+ readonly outcome?: ResidentRuntimeCallOutcome;
58
+ constructor(code: ResidentRuntimeCallErrorCode, message: string, status?: number | undefined, options?: ErrorOptions & {
59
+ outcome?: ResidentRuntimeCallOutcome;
60
+ });
61
+ }
62
+ /** Connect to the resident daemon already owned by the App or standalone supervisor. */
63
+ export declare function ensureResidentDaemon(): Promise<ResidentDaemon>;
64
+ /** Read the stable public identity of the single resident daemon. */
65
+ export declare function getResidentDaemonIdentity(): Promise<ResidentDaemonIdentity>;
66
+ /** Read the transport-independent status of the resident daemon process. */
67
+ export declare function getResidentDaemonRuntimeStatus(): Promise<DaemonStatus>;
68
+ /**
69
+ * Ask the resident daemon to perform one final activity check and stop only
70
+ * when idle. Busy is a normal result so the caller can ask the user to resolve
71
+ * the listed work and explicitly retry.
72
+ */
73
+ export declare function shutdownResidentDaemonIfIdle(): Promise<DaemonShutdownIfIdleResult>;
74
+ export declare function getResidentChromeInspectionStatus(): Promise<DaemonChromeInspectionStatus>;
75
+ export declare function configureResidentChromeInspection(input: DaemonChromeInspectionConfigureInput): Promise<DaemonChromeInspectionStatus>;
76
+ export declare function installResidentBrowserArtifact(input: DaemonBrowserArtifactInstallInput): Promise<DaemonBrowserArtifactInstallResult>;
77
+ export declare function updateResidentBrowserArtifact(input: DaemonBrowserArtifactUpdateInput): Promise<DaemonBrowserArtifactInstallResult>;
78
+ export declare function getResidentBrowserArtifactVersion(): Promise<DaemonBrowserArtifactVersionResult>;
79
+ export declare function cleanResidentBrowserArtifacts(): Promise<DaemonBrowserArtifactCleanResult>;
80
+ export declare function cleanupResidentSessions(input?: DaemonCleanupSessionsInput): Promise<DaemonCleanupSessionsResult>;
81
+ /** Create one pairing offer on the resident daemon for a selected reachable route. */
82
+ export declare function createResidentRemoteRuntimePairingOffer(input?: {
83
+ clientLabel?: string;
84
+ address?: string;
85
+ }): Promise<PairingOffer>;
86
+ /** List redacted client grants accepted by the resident daemon. */
87
+ export declare function listResidentRemoteRuntimeClients(): Promise<ResidentRemoteRuntimeClientGrant[]>;
88
+ /** Revoke one resident-daemon client grant and close its active channels. */
89
+ export declare function revokeResidentRemoteRuntimeClient(grantId: string): Promise<{
90
+ revoked: true;
91
+ closedConnections: number;
92
+ }>;
93
+ /** List local and paired Runtime targets through the resident daemon BFF. */
94
+ export declare function listResidentRuntimeTargets(): Promise<ResidentRuntimeTargetView[]>;
95
+ /** Pair a target; the offer remains inside the loopback management request. */
96
+ export declare function pairResidentRuntimeTarget(offer: unknown, displayName?: string): Promise<ResidentRuntimeTargetTestResult>;
97
+ export declare function testResidentRuntimeTarget(selector: string): Promise<ResidentRuntimeTargetTestResult>;
98
+ export declare function forgetResidentRuntimeTarget(daemonId: string): Promise<{
99
+ forgotten: true;
100
+ }>;
101
+ /**
102
+ * Invoke one typed Runtime method through the single resident daemon.
103
+ *
104
+ * The short-lived CLI process never reads Direct credentials or opens a
105
+ * remote socket. The resident daemon owns target resolution, Local/Direct
106
+ * connection reuse, authorization and no-retry outcome semantics.
107
+ */
108
+ export declare function callResidentRuntime<M extends RemoteRuntimeRpcMethod>(selectorInput: string, method: M, params: RemoteRuntimeRpcParams<M>, options?: {
109
+ signal?: AbortSignal;
110
+ }): Promise<RemoteRuntimeRpcResultFor<M>>;
111
+ /** Read the current managed Session credential without exposing it in output. */
112
+ export declare function readManagedRuntimeBrowserCredential(env?: NodeJS.ProcessEnv): Promise<RuntimeBrowserBootstrapCredential>;
113
+ /** Return undefined only when the process has no managed Session context at all. */
114
+ export declare function readOptionalManagedRuntimeBrowserCredential(env?: NodeJS.ProcessEnv): Promise<RuntimeBrowserBootstrapCredential | undefined>;
115
+ /**
116
+ * Invoke Browser control for the caller's own managed Session. Unlike the
117
+ * operator Runtime gateway, this path never reads or sends daemon management
118
+ * authority and cannot select a remote Runtime or another Session.
119
+ */
120
+ export declare function callManagedRuntimeBrowser<M extends RemoteRuntimeRpcMethod>(credential: RuntimeBrowserBootstrapCredential, method: M, params: RemoteRuntimeRpcParams<M>, options?: {
121
+ signal?: AbortSignal;
122
+ }): Promise<RemoteRuntimeRpcResultFor<M>>;
123
+ /** Resolve native CDP for the caller's own Session on this Runtime only. */
124
+ export declare function getResidentRuntimeLocalBrowserEndpoint(options?: {
125
+ env?: NodeJS.ProcessEnv;
126
+ sessionId?: string;
127
+ signal?: AbortSignal;
128
+ }): Promise<RuntimeBrowserEndpointDescriptor>;
129
+ /**
130
+ * Resolve CDP together with the Runtime-scoped MAC key used for opaque
131
+ * automation refs. Keep the key in-process; it must never be printed.
132
+ */
133
+ export declare function getResidentRuntimeLocalBrowserAutomationAccess(options?: {
134
+ env?: NodeJS.ProcessEnv;
135
+ sessionId?: string;
136
+ signal?: AbortSignal;
137
+ }): Promise<{
138
+ descriptor: RuntimeBrowserEndpointDescriptor;
139
+ referenceKey: string;
140
+ }>;
141
+ /** Invoke one command declared by an installed plugin through the resident daemon. */
142
+ export declare function invokeResidentPluginCommand(pluginId: string, args: readonly string[], options?: InvokeResidentPluginCommandOptions): Promise<ResidentPluginCommandResult>;
143
+ /** Read the daemon-owned plugin registry without exposing package paths/specs. */
144
+ export declare function listResidentPlugins(): Promise<ResidentPluginManagementItem[]>;
145
+ /** Enable or disable one installed plugin through authenticated management RPC. */
146
+ export declare function setResidentPluginEnabled(pluginId: string, enabled: boolean): Promise<ResidentPluginManagementItem>;
147
+ /** Remove one plugin registry entry through authenticated management RPC. */
148
+ export declare function uninstallResidentPlugin(pluginId: string): Promise<{
149
+ uninstalled: true;
150
+ pluginId: string;
151
+ }>;
152
+ /** Reload one plugin runtime after a durable registry mutation. */
153
+ export declare function reloadResidentPluginRuntime(pluginId: string): Promise<Record<string, unknown>>;
154
+ /** Materialize and hold one exact plugin artifact in daemon-owned staging. */
155
+ export declare function prepareResidentPluginInstallation(input: PluginInstallPrepareInput, options?: {
156
+ signal?: AbortSignal;
157
+ }): Promise<PluginInstallPreparation>;
158
+ /** Consume one preparation token and promote only its already-approved artifact. */
159
+ export declare function commitResidentPluginInstallation(token: string, input: PluginInstallCommitInput, options?: {
160
+ signal?: AbortSignal;
161
+ }): Promise<PluginInstallCommitResult>;
162
+ /** Best-effort early release when the user declines a prepared artifact. */
163
+ export declare function cancelResidentPluginInstallation(token: string): Promise<boolean>;