@launchchair/agent 0.4.0
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/AGENTS.md +248 -0
- package/LICENSE +8 -0
- package/README.md +188 -0
- package/chatgpt-runner.mjs +239 -0
- package/claude-code-runner.mjs +141 -0
- package/claude-runner.mjs +218 -0
- package/codex-runner.mjs +123 -0
- package/launchchair-cli.mjs +1013 -0
- package/local-bridge.mjs +540 -0
- package/mcp-bridge-server.mjs +1101 -0
- package/package.json +43 -0
- package/runner-command.mjs +96 -0
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@launchchair/agent",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "LaunchChair Agent CLI, MCP bridge, local bridge, and runners for Codex, Claude Code, ChatGPT, Claude, and Hermes workflows.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"launchchair": "./launchchair-cli.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"AGENTS.md",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"launchchair-cli.mjs",
|
|
14
|
+
"local-bridge.mjs",
|
|
15
|
+
"mcp-bridge-server.mjs",
|
|
16
|
+
"runner-command.mjs",
|
|
17
|
+
"codex-runner.mjs",
|
|
18
|
+
"claude-code-runner.mjs",
|
|
19
|
+
"chatgpt-runner.mjs",
|
|
20
|
+
"claude-runner.mjs"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20.0.0"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"launchchair",
|
|
27
|
+
"mcp",
|
|
28
|
+
"agent",
|
|
29
|
+
"codex",
|
|
30
|
+
"claude",
|
|
31
|
+
"startup",
|
|
32
|
+
"mvp",
|
|
33
|
+
"product"
|
|
34
|
+
],
|
|
35
|
+
"homepage": "https://www.launchchair.io/docs/cli",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://www.launchchair.io/docs/cli"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"license": "SEE LICENSE IN LICENSE"
|
|
43
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
function isWhitespace(char) {
|
|
2
|
+
return /\s/.test(char);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parse a command template into argv tokens without invoking a shell.
|
|
7
|
+
* Supports single/double quotes and backslash escaping.
|
|
8
|
+
*/
|
|
9
|
+
export function parseRunnerCommand(command) {
|
|
10
|
+
const input = String(command ?? "").trim();
|
|
11
|
+
if (!input) {
|
|
12
|
+
throw new Error("Runner command is empty.");
|
|
13
|
+
}
|
|
14
|
+
if (input.includes("\n") || input.includes("\r")) {
|
|
15
|
+
throw new Error("Runner command must be a single line.");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const tokens = [];
|
|
19
|
+
let current = "";
|
|
20
|
+
let quote = null;
|
|
21
|
+
let escaped = false;
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
24
|
+
const ch = input[i];
|
|
25
|
+
|
|
26
|
+
if (escaped) {
|
|
27
|
+
current += ch;
|
|
28
|
+
escaped = false;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (ch === "\\") {
|
|
33
|
+
escaped = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (quote) {
|
|
38
|
+
if (ch === quote) {
|
|
39
|
+
quote = null;
|
|
40
|
+
} else {
|
|
41
|
+
current += ch;
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (ch === "'" || ch === '"') {
|
|
47
|
+
quote = ch;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (isWhitespace(ch)) {
|
|
52
|
+
if (current.length > 0) {
|
|
53
|
+
tokens.push(current);
|
|
54
|
+
current = "";
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
current += ch;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (escaped) {
|
|
63
|
+
throw new Error("Runner command has trailing escape.");
|
|
64
|
+
}
|
|
65
|
+
if (quote) {
|
|
66
|
+
throw new Error("Runner command has an unterminated quote.");
|
|
67
|
+
}
|
|
68
|
+
if (current.length > 0) {
|
|
69
|
+
tokens.push(current);
|
|
70
|
+
}
|
|
71
|
+
if (tokens.length === 0) {
|
|
72
|
+
throw new Error("Runner command is empty after parsing.");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
file: tokens[0],
|
|
77
|
+
args: tokens.slice(1),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function quoteForToken(value) {
|
|
82
|
+
return JSON.stringify(String(value ?? ""));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function buildRunnerCommand(commandTemplate, run) {
|
|
86
|
+
const prompt = String(run?.prompt ?? "");
|
|
87
|
+
const promptB64 = Buffer.from(prompt, "utf8").toString("base64");
|
|
88
|
+
let cmd = String(commandTemplate ?? "").trim();
|
|
89
|
+
if (!cmd) return "";
|
|
90
|
+
|
|
91
|
+
cmd = cmd.replaceAll("{{PROMPT_B64}}", promptB64);
|
|
92
|
+
cmd = cmd.replaceAll("{{PROMPT}}", quoteForToken(prompt));
|
|
93
|
+
cmd = cmd.replaceAll("{{RUN_ID}}", String(run?.id ?? ""));
|
|
94
|
+
cmd = cmd.replaceAll("{{PROJECT_ID}}", String(run?.projectId ?? ""));
|
|
95
|
+
return cmd;
|
|
96
|
+
}
|