chainlesschain 0.38.1 → 0.40.1
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/package.json +3 -2
- package/src/commands/agent.js +5 -1
- package/src/commands/ask.js +24 -9
- package/src/commands/chat.js +5 -1
- package/src/commands/cli-anything.js +266 -0
- package/src/commands/serve.js +109 -0
- package/src/constants.js +1 -0
- package/src/index.js +12 -0
- package/src/lib/cli-anything-bridge.js +379 -0
- package/src/lib/git-integration.js +1 -1
- package/src/lib/llm-providers.js +14 -1
- package/src/lib/task-model-selector.js +232 -0
- package/src/lib/ws-server.js +474 -0
- package/src/repl/agent-repl.js +25 -4
- package/src/repl/chat-repl.js +14 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chainlesschain",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.1",
|
|
4
4
|
"description": "CLI for ChainlessChain - install, configure, and manage your personal AI management system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"@chainlesschain/shared-logger": "0.1.0",
|
|
51
51
|
"@chainlesschain/core-db": "0.1.0",
|
|
52
52
|
"@chainlesschain/core-config": "0.1.0",
|
|
53
|
-
"@chainlesschain/core-infra": "0.1.0"
|
|
53
|
+
"@chainlesschain/core-infra": "0.1.0",
|
|
54
|
+
"ws": "^8.14.2"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"vitest": "^3.1.1"
|
package/src/commands/agent.js
CHANGED
|
@@ -16,7 +16,11 @@ export function registerAgentCommand(program) {
|
|
|
16
16
|
"Start an agentic AI session (reads/writes files, runs commands)",
|
|
17
17
|
)
|
|
18
18
|
.option("--model <model>", "Model name", "qwen2:7b")
|
|
19
|
-
.option(
|
|
19
|
+
.option(
|
|
20
|
+
"--provider <provider>",
|
|
21
|
+
"LLM provider (ollama, openai, volcengine, deepseek, ...)",
|
|
22
|
+
"ollama",
|
|
23
|
+
)
|
|
20
24
|
.option("--base-url <url>", "API base URL")
|
|
21
25
|
.option("--api-key <key>", "API key")
|
|
22
26
|
.option("--session <id>", "Resume a previous agent session")
|
package/src/commands/ask.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import ora from "ora";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import { logger } from "../lib/logger.js";
|
|
9
|
+
import { BUILT_IN_PROVIDERS } from "../lib/llm-providers.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Send a single question to an LLM provider
|
|
@@ -37,12 +38,24 @@ async function queryLLM(question, options = {}) {
|
|
|
37
38
|
|
|
38
39
|
const data = await response.json();
|
|
39
40
|
return data.response;
|
|
40
|
-
} else
|
|
41
|
-
|
|
41
|
+
} else {
|
|
42
|
+
// OpenAI-compatible providers (openai, volcengine, deepseek, dashscope, mistral, gemini)
|
|
43
|
+
const providerDef = BUILT_IN_PROVIDERS[provider];
|
|
44
|
+
if (!providerDef) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Unsupported provider: ${provider}. Supported: ollama, openai, volcengine, deepseek, dashscope, gemini, mistral, anthropic`,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const apiKey =
|
|
51
|
+
options.apiKey ||
|
|
52
|
+
(providerDef.apiKeyEnv ? process.env[providerDef.apiKeyEnv] : null);
|
|
42
53
|
if (!apiKey)
|
|
43
|
-
throw new Error(
|
|
54
|
+
throw new Error(
|
|
55
|
+
`API key required for ${provider} (--api-key or ${providerDef.apiKeyEnv})`,
|
|
56
|
+
);
|
|
44
57
|
|
|
45
|
-
const apiBase = options.baseUrl ||
|
|
58
|
+
const apiBase = options.baseUrl || providerDef.baseUrl;
|
|
46
59
|
const response = await fetch(`${apiBase}/chat/completions`, {
|
|
47
60
|
method: "POST",
|
|
48
61
|
headers: {
|
|
@@ -50,22 +63,20 @@ async function queryLLM(question, options = {}) {
|
|
|
50
63
|
Authorization: `Bearer ${apiKey}`,
|
|
51
64
|
},
|
|
52
65
|
body: JSON.stringify({
|
|
53
|
-
model: model ||
|
|
66
|
+
model: model || providerDef.models[0],
|
|
54
67
|
messages: [{ role: "user", content: question }],
|
|
55
68
|
}),
|
|
56
69
|
});
|
|
57
70
|
|
|
58
71
|
if (!response.ok) {
|
|
59
72
|
throw new Error(
|
|
60
|
-
|
|
73
|
+
`${provider} error: ${response.status} ${response.statusText}`,
|
|
61
74
|
);
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
const data = await response.json();
|
|
65
78
|
return data.choices[0].message.content;
|
|
66
79
|
}
|
|
67
|
-
|
|
68
|
-
throw new Error(`Unsupported provider: ${provider}`);
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
export function registerAskCommand(program) {
|
|
@@ -74,7 +85,11 @@ export function registerAskCommand(program) {
|
|
|
74
85
|
.description("Ask a question to the AI (single-shot)")
|
|
75
86
|
.argument("<question>", "The question to ask")
|
|
76
87
|
.option("--model <model>", "Model name", "qwen2:7b")
|
|
77
|
-
.option(
|
|
88
|
+
.option(
|
|
89
|
+
"--provider <provider>",
|
|
90
|
+
"LLM provider (ollama, openai, volcengine, deepseek, ...)",
|
|
91
|
+
"ollama",
|
|
92
|
+
)
|
|
78
93
|
.option("--base-url <url>", "API base URL")
|
|
79
94
|
.option("--api-key <key>", "API key")
|
|
80
95
|
.option("--json", "Output as JSON")
|
package/src/commands/chat.js
CHANGED
|
@@ -11,7 +11,11 @@ export function registerChatCommand(program) {
|
|
|
11
11
|
.command("chat")
|
|
12
12
|
.description("Start an interactive AI chat session")
|
|
13
13
|
.option("--model <model>", "Model name", "qwen2:7b")
|
|
14
|
-
.option(
|
|
14
|
+
.option(
|
|
15
|
+
"--provider <provider>",
|
|
16
|
+
"LLM provider (ollama, openai, volcengine, deepseek, ...)",
|
|
17
|
+
"ollama",
|
|
18
|
+
)
|
|
15
19
|
.option("--base-url <url>", "API base URL")
|
|
16
20
|
.option("--api-key <key>", "API key")
|
|
17
21
|
.option(
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-Anything commands — discover & register CLI-Anything generated tools
|
|
3
|
+
* chainlesschain cli-anything doctor|scan|register|list|remove
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { logger } from "../lib/logger.js";
|
|
8
|
+
import { bootstrap, shutdown } from "../runtime/bootstrap.js";
|
|
9
|
+
import {
|
|
10
|
+
ensureCliAnythingTables,
|
|
11
|
+
detectPython,
|
|
12
|
+
detectCliAnything,
|
|
13
|
+
scanPathForTools,
|
|
14
|
+
parseToolHelp,
|
|
15
|
+
registerTool,
|
|
16
|
+
removeTool,
|
|
17
|
+
listTools,
|
|
18
|
+
} from "../lib/cli-anything-bridge.js";
|
|
19
|
+
|
|
20
|
+
export function registerCliAnythingCommand(program) {
|
|
21
|
+
const cliAny = program
|
|
22
|
+
.command("cli-anything")
|
|
23
|
+
.description(
|
|
24
|
+
"CLI-Anything — discover and register Agent-native CLI tools as skills",
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/* ---- doctor ---- */
|
|
28
|
+
cliAny
|
|
29
|
+
.command("doctor")
|
|
30
|
+
.description("Check Python & CLI-Anything environment")
|
|
31
|
+
.option("--json", "Output as JSON")
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
const py = detectPython();
|
|
34
|
+
const clia = py.found ? detectCliAnything() : { installed: false };
|
|
35
|
+
const tools = scanPathForTools();
|
|
36
|
+
|
|
37
|
+
const report = {
|
|
38
|
+
python: py,
|
|
39
|
+
cliAnything: clia,
|
|
40
|
+
toolsOnPath: tools.length,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (opts.json) {
|
|
44
|
+
console.log(JSON.stringify(report, null, 2));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
logger.log("");
|
|
49
|
+
logger.log(chalk.bold(" CLI-Anything Environment"));
|
|
50
|
+
logger.log("");
|
|
51
|
+
|
|
52
|
+
// Python
|
|
53
|
+
if (py.found) {
|
|
54
|
+
logger.log(
|
|
55
|
+
` ${chalk.green("✓")} Python ${chalk.cyan(py.version)} (${py.command})`,
|
|
56
|
+
);
|
|
57
|
+
} else {
|
|
58
|
+
logger.log(` ${chalk.red("✗")} Python not found`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// CLI-Anything
|
|
62
|
+
if (clia.installed) {
|
|
63
|
+
logger.log(
|
|
64
|
+
` ${chalk.green("✓")} CLI-Anything ${chalk.cyan(clia.version)}`,
|
|
65
|
+
);
|
|
66
|
+
} else {
|
|
67
|
+
logger.log(` ${chalk.red("✗")} CLI-Anything not installed`);
|
|
68
|
+
if (py.found) {
|
|
69
|
+
logger.log(
|
|
70
|
+
` ${chalk.gray(`Install: ${py.command} -m pip install cli-anything`)}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Tools
|
|
76
|
+
logger.log(
|
|
77
|
+
` ${tools.length > 0 ? chalk.green("✓") : chalk.yellow("○")} ${tools.length} tool(s) on PATH`,
|
|
78
|
+
);
|
|
79
|
+
for (const t of tools) {
|
|
80
|
+
logger.log(
|
|
81
|
+
` ${chalk.gray(`cli-anything-${t.name}`)} → ${chalk.gray(t.path)}`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
logger.log("");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/* ---- scan ---- */
|
|
88
|
+
cliAny
|
|
89
|
+
.command("scan")
|
|
90
|
+
.description("Scan PATH for cli-anything-* tools")
|
|
91
|
+
.option("--json", "Output as JSON")
|
|
92
|
+
.action(async (opts) => {
|
|
93
|
+
const tools = scanPathForTools();
|
|
94
|
+
|
|
95
|
+
if (opts.json) {
|
|
96
|
+
console.log(JSON.stringify(tools, null, 2));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (tools.length === 0) {
|
|
101
|
+
logger.info("No cli-anything-* tools found on PATH.");
|
|
102
|
+
logger.log(
|
|
103
|
+
chalk.gray(
|
|
104
|
+
" Use CLI-Anything to generate tools first: /cli-anything <software>",
|
|
105
|
+
),
|
|
106
|
+
);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
logger.log("");
|
|
111
|
+
logger.log(chalk.bold(` Found ${tools.length} tool(s):`));
|
|
112
|
+
logger.log("");
|
|
113
|
+
for (const t of tools) {
|
|
114
|
+
const help = parseToolHelp(t.command);
|
|
115
|
+
logger.log(` ${chalk.cyan(t.name)}`);
|
|
116
|
+
logger.log(` Command: ${chalk.gray(t.command)}`);
|
|
117
|
+
logger.log(` Path: ${chalk.gray(t.path)}`);
|
|
118
|
+
if (help.description) {
|
|
119
|
+
logger.log(` Desc: ${chalk.gray(help.description)}`);
|
|
120
|
+
}
|
|
121
|
+
if (help.subcommands.length > 0) {
|
|
122
|
+
logger.log(
|
|
123
|
+
` Subs: ${chalk.gray(help.subcommands.map((s) => s.name).join(", "))}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
logger.log("");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
/* ---- register ---- */
|
|
131
|
+
cliAny
|
|
132
|
+
.command("register <name>")
|
|
133
|
+
.description("Register a cli-anything-* tool as a ChainlessChain skill")
|
|
134
|
+
.option("--force", "Overwrite existing registration")
|
|
135
|
+
.option("--json", "Output as JSON")
|
|
136
|
+
.action(async (name, opts) => {
|
|
137
|
+
try {
|
|
138
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
139
|
+
if (!ctx.db) {
|
|
140
|
+
logger.error(
|
|
141
|
+
"Database not available. Run `chainlesschain setup` first.",
|
|
142
|
+
);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
const db = ctx.db.getDatabase();
|
|
146
|
+
ensureCliAnythingTables(db);
|
|
147
|
+
|
|
148
|
+
const command = `cli-anything-${name}`;
|
|
149
|
+
const helpData = parseToolHelp(command);
|
|
150
|
+
|
|
151
|
+
const result = registerTool(db, name, {
|
|
152
|
+
command,
|
|
153
|
+
helpData,
|
|
154
|
+
force: opts.force,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await shutdown();
|
|
158
|
+
|
|
159
|
+
if (opts.json) {
|
|
160
|
+
console.log(JSON.stringify(result, null, 2));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
logger.success(
|
|
165
|
+
`Registered ${chalk.cyan(name)} as skill ${chalk.bold(result.skillName)}`,
|
|
166
|
+
);
|
|
167
|
+
logger.log(` Skill dir: ${chalk.gray(result.dir)}`);
|
|
168
|
+
if (result.subcommands.length > 0) {
|
|
169
|
+
logger.log(
|
|
170
|
+
` Subcommands: ${chalk.gray(result.subcommands.map((s) => s.name).join(", "))}`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
logger.log(
|
|
174
|
+
chalk.gray(
|
|
175
|
+
` Use in Agent: /skill ${result.skillName} <subcommand> [args]`,
|
|
176
|
+
),
|
|
177
|
+
);
|
|
178
|
+
} catch (err) {
|
|
179
|
+
logger.error(`Register failed: ${err.message}`);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/* ---- list (default) ---- */
|
|
185
|
+
cliAny
|
|
186
|
+
.command("list", { isDefault: true })
|
|
187
|
+
.description("List registered CLI-Anything tools")
|
|
188
|
+
.option("--json", "Output as JSON")
|
|
189
|
+
.action(async (opts) => {
|
|
190
|
+
try {
|
|
191
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
192
|
+
if (!ctx.db) {
|
|
193
|
+
logger.error("Database not available.");
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
const db = ctx.db.getDatabase();
|
|
197
|
+
ensureCliAnythingTables(db);
|
|
198
|
+
|
|
199
|
+
const tools = listTools(db);
|
|
200
|
+
await shutdown();
|
|
201
|
+
|
|
202
|
+
if (opts.json) {
|
|
203
|
+
console.log(JSON.stringify(tools, null, 2));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (tools.length === 0) {
|
|
208
|
+
logger.info("No CLI-Anything tools registered.");
|
|
209
|
+
logger.log(
|
|
210
|
+
chalk.gray(
|
|
211
|
+
" Run `chainlesschain cli-anything scan` to discover tools.",
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
logger.log("");
|
|
218
|
+
logger.log(chalk.bold(` ${tools.length} registered tool(s):`));
|
|
219
|
+
logger.log("");
|
|
220
|
+
for (const t of tools) {
|
|
221
|
+
const statusColor =
|
|
222
|
+
t.status === "registered" ? chalk.green : chalk.yellow;
|
|
223
|
+
logger.log(
|
|
224
|
+
` ${chalk.cyan(t.name)} ${statusColor(`[${t.status}]`)} → ${chalk.gray(t.skill_name)}`,
|
|
225
|
+
);
|
|
226
|
+
if (t.description) {
|
|
227
|
+
logger.log(` ${chalk.gray(t.description)}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
logger.log("");
|
|
231
|
+
} catch (err) {
|
|
232
|
+
logger.error(`List failed: ${err.message}`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
/* ---- remove ---- */
|
|
238
|
+
cliAny
|
|
239
|
+
.command("remove <name>")
|
|
240
|
+
.description("Remove a registered CLI-Anything tool")
|
|
241
|
+
.option("--json", "Output as JSON")
|
|
242
|
+
.action(async (name, opts) => {
|
|
243
|
+
try {
|
|
244
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
245
|
+
if (!ctx.db) {
|
|
246
|
+
logger.error("Database not available.");
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
const db = ctx.db.getDatabase();
|
|
250
|
+
ensureCliAnythingTables(db);
|
|
251
|
+
|
|
252
|
+
const result = removeTool(db, name);
|
|
253
|
+
await shutdown();
|
|
254
|
+
|
|
255
|
+
if (opts.json) {
|
|
256
|
+
console.log(JSON.stringify(result, null, 2));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
logger.success(`Removed tool ${chalk.cyan(name)}`);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
logger.error(`Remove failed: ${err.message}`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* serve command — start a WebSocket server for remote CLI access
|
|
3
|
+
* chainlesschain serve [--port] [--host] [--token] [--max-connections] [--timeout] [--allow-remote]
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { logger } from "../lib/logger.js";
|
|
8
|
+
import { ChainlessChainWSServer } from "../lib/ws-server.js";
|
|
9
|
+
|
|
10
|
+
export function registerServeCommand(program) {
|
|
11
|
+
program
|
|
12
|
+
.command("serve")
|
|
13
|
+
.description("Start WebSocket server for remote CLI access")
|
|
14
|
+
.option("-p, --port <port>", "Port number", "18800")
|
|
15
|
+
.option("-H, --host <host>", "Bind host", "127.0.0.1")
|
|
16
|
+
.option(
|
|
17
|
+
"--token <token>",
|
|
18
|
+
"Authentication token (required for remote access)",
|
|
19
|
+
)
|
|
20
|
+
.option("--max-connections <n>", "Maximum concurrent connections", "10")
|
|
21
|
+
.option(
|
|
22
|
+
"--timeout <ms>",
|
|
23
|
+
"Command execution timeout in milliseconds",
|
|
24
|
+
"30000",
|
|
25
|
+
)
|
|
26
|
+
.option(
|
|
27
|
+
"--allow-remote",
|
|
28
|
+
"Allow non-localhost connections (requires --token)",
|
|
29
|
+
)
|
|
30
|
+
.action(async (opts) => {
|
|
31
|
+
const port = parseInt(opts.port, 10);
|
|
32
|
+
const maxConnections = parseInt(opts.maxConnections, 10);
|
|
33
|
+
const timeout = parseInt(opts.timeout, 10);
|
|
34
|
+
let host = opts.host;
|
|
35
|
+
|
|
36
|
+
// Validation
|
|
37
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
38
|
+
logger.error("Invalid port number. Must be between 1 and 65535.");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (opts.allowRemote) {
|
|
43
|
+
if (!opts.token) {
|
|
44
|
+
logger.error("--allow-remote requires --token for security.");
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
host = "0.0.0.0";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const server = new ChainlessChainWSServer({
|
|
51
|
+
port,
|
|
52
|
+
host,
|
|
53
|
+
token: opts.token || null,
|
|
54
|
+
maxConnections,
|
|
55
|
+
timeout,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Event logging
|
|
59
|
+
server.on("connection", ({ clientId, ip }) => {
|
|
60
|
+
logger.log(chalk.green(` + Client connected: ${clientId} (${ip})`));
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
server.on("disconnection", ({ clientId, reason }) => {
|
|
64
|
+
const extra = reason ? ` (${reason})` : "";
|
|
65
|
+
logger.log(
|
|
66
|
+
chalk.yellow(` - Client disconnected: ${clientId}${extra}`),
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
server.on("command:start", ({ id, command }) => {
|
|
71
|
+
logger.log(chalk.cyan(` > [${id}] ${command}`));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
server.on("command:end", ({ id, exitCode }) => {
|
|
75
|
+
const color = exitCode === 0 ? chalk.green : chalk.red;
|
|
76
|
+
logger.log(color(` < [${id}] exit ${exitCode}`));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Graceful shutdown
|
|
80
|
+
const shutdown = async () => {
|
|
81
|
+
logger.log("\n" + chalk.yellow("Shutting down WebSocket server..."));
|
|
82
|
+
await server.stop();
|
|
83
|
+
process.exit(0);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
process.on("SIGINT", shutdown);
|
|
87
|
+
process.on("SIGTERM", shutdown);
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
await server.start();
|
|
91
|
+
|
|
92
|
+
logger.log("");
|
|
93
|
+
logger.log(chalk.bold(" ChainlessChain WebSocket Server"));
|
|
94
|
+
logger.log("");
|
|
95
|
+
logger.log(` Address: ${chalk.cyan(`ws://${host}:${port}`)}`);
|
|
96
|
+
logger.log(
|
|
97
|
+
` Auth: ${opts.token ? chalk.green("enabled") : chalk.yellow("disabled")}`,
|
|
98
|
+
);
|
|
99
|
+
logger.log(` Max conn: ${maxConnections}`);
|
|
100
|
+
logger.log(` Timeout: ${timeout}ms`);
|
|
101
|
+
logger.log("");
|
|
102
|
+
logger.log(chalk.dim(" Press Ctrl+C to stop"));
|
|
103
|
+
logger.log("");
|
|
104
|
+
} catch (err) {
|
|
105
|
+
logger.error(`Failed to start server: ${err.message}`);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
package/src/constants.js
CHANGED
package/src/index.js
CHANGED
|
@@ -79,6 +79,12 @@ import { registerLowcodeCommand } from "./commands/lowcode.js";
|
|
|
79
79
|
// EvoMap: Gene Exchange Protocol
|
|
80
80
|
import { registerEvoMapCommand } from "./commands/evomap.js";
|
|
81
81
|
|
|
82
|
+
// CLI-Anything: Agent-Native Software Integration
|
|
83
|
+
import { registerCliAnythingCommand } from "./commands/cli-anything.js";
|
|
84
|
+
|
|
85
|
+
// WebSocket Server Interface
|
|
86
|
+
import { registerServeCommand } from "./commands/serve.js";
|
|
87
|
+
|
|
82
88
|
export function createProgram() {
|
|
83
89
|
const program = new Command();
|
|
84
90
|
|
|
@@ -187,5 +193,11 @@ export function createProgram() {
|
|
|
187
193
|
// EvoMap: Gene Exchange Protocol
|
|
188
194
|
registerEvoMapCommand(program);
|
|
189
195
|
|
|
196
|
+
// CLI-Anything: Agent-Native Software Integration
|
|
197
|
+
registerCliAnythingCommand(program);
|
|
198
|
+
|
|
199
|
+
// WebSocket Server Interface
|
|
200
|
+
registerServeCommand(program);
|
|
201
|
+
|
|
190
202
|
return program;
|
|
191
203
|
}
|