@cordfuse/llmux 0.10.5 → 0.12.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/dist/index.js +3743 -91
- package/package.json +17 -4
- package/src/cli.ts +100 -0
- package/src/client/client.ts +674 -0
- package/src/daemon/agents.ts +193 -0
- package/src/daemon/auth-store.ts +85 -0
- package/src/daemon/config.ts +77 -0
- package/src/daemon/handlers.ts +414 -0
- package/src/daemon/net.ts +113 -0
- package/src/daemon/state.ts +78 -0
- package/src/daemon/tmux.ts +117 -0
- package/src/daemon/token.ts +13 -0
- package/src/daemon/web/server.ts +2277 -0
- package/src/index.ts +386 -37
- package/src/client.ts +0 -110
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cordfuse/llmux",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "tmux-based AI agent dispatcher — REST/WS daemon + CLI client in one binary",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -20,16 +20,29 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"start": "tsx src/index.ts",
|
|
23
|
-
"build": "tsup src/index.ts --target node20 --format esm --out-dir dist --clean",
|
|
23
|
+
"build": "tsup src/index.ts --target node20 --format esm --out-dir dist --external node-pty --external ws --external yaml --external qrcode-terminal --clean",
|
|
24
24
|
"prepublishOnly": "cp ../../README.md ../../LICENSE . && npm run build",
|
|
25
25
|
"postpublish": "rm -f README.md LICENSE",
|
|
26
26
|
"typecheck": "tsc --noEmit"
|
|
27
27
|
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@types/ws": "^8.18.1",
|
|
30
|
+
"node-pty": "^1.1.0",
|
|
31
|
+
"qrcode-terminal": "^0.12.0",
|
|
32
|
+
"ws": "^8.21.0",
|
|
33
|
+
"yaml": "^2.5.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/qrcode-terminal": "^0.12.2"
|
|
37
|
+
},
|
|
28
38
|
"keywords": [
|
|
29
39
|
"tmux",
|
|
30
40
|
"ai",
|
|
31
41
|
"agent",
|
|
32
|
-
"
|
|
42
|
+
"claude",
|
|
43
|
+
"codex",
|
|
44
|
+
"session-manager",
|
|
45
|
+
"llm",
|
|
33
46
|
"cordfuse"
|
|
34
47
|
],
|
|
35
48
|
"repository": {
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export type FlagKind = 'boolean' | 'string';
|
|
2
|
+
|
|
3
|
+
export interface FlagSpec {
|
|
4
|
+
kind: FlagKind;
|
|
5
|
+
alias?: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type FlagSpecs = Record<string, FlagSpec>;
|
|
10
|
+
|
|
11
|
+
export interface ParsedArgs {
|
|
12
|
+
positional: string[];
|
|
13
|
+
flags: Record<string, string | boolean>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function parseArgs(argv: readonly string[], specs: FlagSpecs): ParsedArgs {
|
|
17
|
+
const aliasMap = new Map<string, string>();
|
|
18
|
+
for (const [name, spec] of Object.entries(specs)) {
|
|
19
|
+
if (spec.alias) aliasMap.set(spec.alias, name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const resolveName = (raw: string): string => aliasMap.get(raw) ?? raw;
|
|
23
|
+
|
|
24
|
+
const positional: string[] = [];
|
|
25
|
+
const flags: Record<string, string | boolean> = {};
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < argv.length; i++) {
|
|
28
|
+
const token = argv[i]!;
|
|
29
|
+
|
|
30
|
+
if (token === '--') {
|
|
31
|
+
positional.push(...argv.slice(i + 1));
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (token.startsWith('--')) {
|
|
36
|
+
const body = token.slice(2);
|
|
37
|
+
const eq = body.indexOf('=');
|
|
38
|
+
const rawName = eq >= 0 ? body.slice(0, eq) : body;
|
|
39
|
+
const name = resolveName(rawName);
|
|
40
|
+
const spec = specs[name];
|
|
41
|
+
if (!spec) {
|
|
42
|
+
throw new Error(`unknown flag --${rawName}`);
|
|
43
|
+
}
|
|
44
|
+
if (spec.kind === 'boolean') {
|
|
45
|
+
flags[name] = eq >= 0 ? body.slice(eq + 1) !== 'false' : true;
|
|
46
|
+
} else {
|
|
47
|
+
if (eq >= 0) {
|
|
48
|
+
flags[name] = body.slice(eq + 1);
|
|
49
|
+
} else {
|
|
50
|
+
const next = argv[i + 1];
|
|
51
|
+
if (next === undefined || next.startsWith('-')) {
|
|
52
|
+
throw new Error(`--${rawName} requires a value`);
|
|
53
|
+
}
|
|
54
|
+
flags[name] = next;
|
|
55
|
+
i++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (token.startsWith('-') && token.length > 1) {
|
|
62
|
+
const body = token.slice(1);
|
|
63
|
+
const name = resolveName(body);
|
|
64
|
+
const spec = specs[name];
|
|
65
|
+
if (!spec) {
|
|
66
|
+
throw new Error(`unknown flag -${body}`);
|
|
67
|
+
}
|
|
68
|
+
if (spec.kind === 'boolean') {
|
|
69
|
+
flags[name] = true;
|
|
70
|
+
} else {
|
|
71
|
+
const next = argv[i + 1];
|
|
72
|
+
if (next === undefined || next.startsWith('-')) {
|
|
73
|
+
throw new Error(`-${body} requires a value`);
|
|
74
|
+
}
|
|
75
|
+
flags[name] = next;
|
|
76
|
+
i++;
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
positional.push(token);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { positional, flags };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function renderFlagHelp(specs: FlagSpecs): string {
|
|
88
|
+
const lines: string[] = [];
|
|
89
|
+
for (const [name, spec] of Object.entries(specs)) {
|
|
90
|
+
const lead = spec.alias ? `-${spec.alias}, --${name}` : ` --${name}`;
|
|
91
|
+
const value = spec.kind === 'string' ? ' <value>' : '';
|
|
92
|
+
lines.push(` ${(lead + value).padEnd(28)}${spec.description}`);
|
|
93
|
+
}
|
|
94
|
+
return lines.join('\n');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function notImplemented(commandPath: string): never {
|
|
98
|
+
console.error(`llmuxd ${commandPath}: not yet implemented (scaffold)`);
|
|
99
|
+
process.exit(70);
|
|
100
|
+
}
|