@runneth/cli 0.0.0-sha.3142666bf4dc.production
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/README.md +144 -0
- package/dist/build-defaults.d.ts +1 -0
- package/dist/build-defaults.js +21 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1112 -0
- package/dist/copy.d.ts +25 -0
- package/dist/copy.js +492 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +547 -0
- package/dist/oauth.d.ts +80 -0
- package/dist/oauth.js +592 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +25 -0
- package/dist/skills.d.ts +15 -0
- package/dist/skills.js +89 -0
- package/dist/ssh-stdio.d.ts +63 -0
- package/dist/ssh-stdio.js +608 -0
- package/dist/ssh.d.ts +129 -0
- package/dist/ssh.js +835 -0
- package/package.json +38 -0
- package/skills/runneth/SKILL.md +177 -0
package/dist/skills.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { cp, mkdir, readdir, readFile, rm } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
const RUNNETH_SKILL_NAME = "runneth";
|
|
7
|
+
const isRecord = (value) => {
|
|
8
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
|
+
};
|
|
10
|
+
const isErrnoCode = (error, code) => {
|
|
11
|
+
return isRecord(error) && error.code === code;
|
|
12
|
+
};
|
|
13
|
+
const currentFilePath = () => {
|
|
14
|
+
return fileURLToPath(import.meta.url);
|
|
15
|
+
};
|
|
16
|
+
export const resolveBundledRunnethSkillPath = () => {
|
|
17
|
+
return path.resolve(path.dirname(currentFilePath()), "..", "skills", RUNNETH_SKILL_NAME);
|
|
18
|
+
};
|
|
19
|
+
const resolveCodexHome = () => {
|
|
20
|
+
const configured = process.env.CODEX_HOME;
|
|
21
|
+
if (configured === undefined) {
|
|
22
|
+
return path.join(os.homedir(), ".codex");
|
|
23
|
+
}
|
|
24
|
+
const normalized = configured.trim();
|
|
25
|
+
if (normalized.length === 0) {
|
|
26
|
+
throw new Error("CODEX_HOME must be a non-empty path");
|
|
27
|
+
}
|
|
28
|
+
return normalized;
|
|
29
|
+
};
|
|
30
|
+
const resolveAgentSkillsRoot = (agent) => {
|
|
31
|
+
switch (agent) {
|
|
32
|
+
case "claude": {
|
|
33
|
+
return path.join(os.homedir(), ".claude", "skills");
|
|
34
|
+
}
|
|
35
|
+
case "codex": {
|
|
36
|
+
return path.join(resolveCodexHome(), "skills");
|
|
37
|
+
}
|
|
38
|
+
default: {
|
|
39
|
+
const exhaustiveCheck = agent;
|
|
40
|
+
return exhaustiveCheck;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const validateRunnethSkillSource = async (sourcePath) => {
|
|
45
|
+
const skillPath = path.join(sourcePath, "SKILL.md");
|
|
46
|
+
const rawSkill = await readFile(skillPath, "utf8");
|
|
47
|
+
if (!/^---\r?\n/u.test(rawSkill)) {
|
|
48
|
+
throw new Error(`Bundled Runneth skill is missing frontmatter: ${skillPath}`);
|
|
49
|
+
}
|
|
50
|
+
if (!/\r?\nname:\s*runneth\r?\n/u.test(rawSkill)) {
|
|
51
|
+
throw new Error(`Bundled Runneth skill has an invalid name: ${skillPath}`);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const assertSafeSkillDirectory = async (targetPath) => {
|
|
55
|
+
const entries = await readdir(targetPath).catch((error) => {
|
|
56
|
+
if (isErrnoCode(error, "ENOENT")) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
});
|
|
61
|
+
if (entries === null) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!entries.includes("SKILL.md")) {
|
|
65
|
+
throw new Error(`Refusing to replace non-skill directory: ${targetPath}`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export const installRunnethSkills = async (options = {}) => {
|
|
69
|
+
const agents = options.agents ?? ["claude", "codex"];
|
|
70
|
+
const sourcePath = resolveBundledRunnethSkillPath();
|
|
71
|
+
await validateRunnethSkillSource(sourcePath);
|
|
72
|
+
const targets = [];
|
|
73
|
+
for (const agent of agents) {
|
|
74
|
+
const targetPath = path.join(resolveAgentSkillsRoot(agent), RUNNETH_SKILL_NAME);
|
|
75
|
+
await assertSafeSkillDirectory(targetPath);
|
|
76
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
77
|
+
await rm(targetPath, { force: true, recursive: true });
|
|
78
|
+
await cp(sourcePath, targetPath, { recursive: true });
|
|
79
|
+
targets.push({
|
|
80
|
+
agent,
|
|
81
|
+
path: targetPath,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
skillName: RUNNETH_SKILL_NAME,
|
|
86
|
+
sourcePath,
|
|
87
|
+
targets,
|
|
88
|
+
};
|
|
89
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
import type { RunnethSshSetupResult } from "./ssh.js";
|
|
3
|
+
type RunnethSshStdioStreams = Readonly<{
|
|
4
|
+
stderr: Writable;
|
|
5
|
+
stdin: Readable;
|
|
6
|
+
stdout: Writable;
|
|
7
|
+
}>;
|
|
8
|
+
export type RunnethSshStdioOptions = Readonly<{
|
|
9
|
+
defaultTimeoutMs?: number;
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
11
|
+
masterReadyTimeoutMs?: number;
|
|
12
|
+
maxFrameBytes?: number;
|
|
13
|
+
maxProcesses?: number;
|
|
14
|
+
setup: RunnethSshSetupResult;
|
|
15
|
+
sshCommand?: string;
|
|
16
|
+
streams?: RunnethSshStdioStreams;
|
|
17
|
+
}>;
|
|
18
|
+
type ExecRequest = Readonly<{
|
|
19
|
+
id: string;
|
|
20
|
+
method: "exec";
|
|
21
|
+
params: Readonly<{
|
|
22
|
+
command: string;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}>;
|
|
25
|
+
}>;
|
|
26
|
+
type SpawnRequest = Readonly<{
|
|
27
|
+
id: string;
|
|
28
|
+
method: "spawn";
|
|
29
|
+
params: Readonly<{
|
|
30
|
+
command: string;
|
|
31
|
+
}>;
|
|
32
|
+
}>;
|
|
33
|
+
type StdinRequest = Readonly<{
|
|
34
|
+
id: string;
|
|
35
|
+
method: "stdin";
|
|
36
|
+
params: Readonly<{
|
|
37
|
+
data: string;
|
|
38
|
+
}>;
|
|
39
|
+
}>;
|
|
40
|
+
type SignalRequest = Readonly<{
|
|
41
|
+
id: string;
|
|
42
|
+
method: "signal";
|
|
43
|
+
params: Readonly<{
|
|
44
|
+
signal: ProcessSignal;
|
|
45
|
+
}>;
|
|
46
|
+
}>;
|
|
47
|
+
type CloseRequest = Readonly<{
|
|
48
|
+
id: string;
|
|
49
|
+
method: "close";
|
|
50
|
+
}>;
|
|
51
|
+
type ListRequest = Readonly<{
|
|
52
|
+
id: string;
|
|
53
|
+
method: "list";
|
|
54
|
+
}>;
|
|
55
|
+
type PingRequest = Readonly<{
|
|
56
|
+
id: string;
|
|
57
|
+
method: "ping";
|
|
58
|
+
}>;
|
|
59
|
+
type RunnethSshStdioRequest = CloseRequest | ExecRequest | ListRequest | PingRequest | SignalRequest | SpawnRequest | StdinRequest;
|
|
60
|
+
type ProcessSignal = "SIGHUP" | "SIGINT" | "SIGKILL" | "SIGTERM";
|
|
61
|
+
export declare const parseRunnethSshStdioRequest: (value: unknown) => RunnethSshStdioRequest;
|
|
62
|
+
export declare const runRunnethSshStdio: (options: RunnethSshStdioOptions) => Promise<void>;
|
|
63
|
+
export {};
|