nikou-cli 0.1.0 → 0.1.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/README.md +21 -0
- package/dist/index.js +124 -50
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -165,6 +165,19 @@ Hook 模式包含一个主节点和多个从节点:
|
|
|
165
165
|
nikou-cli hook init
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
安装后也可以用 `ai-hook` 入口完成 Hook 初始化与启动:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
NIKOU_HOOK_MASTER_HOST=203.0.113.10 ai-hook init
|
|
172
|
+
ai-hook
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
其中 `ai-hook` 默认等价于 `nikou-cli hook worker codex`;如需 Claude:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
ai-hook claude --model opus
|
|
179
|
+
```
|
|
180
|
+
|
|
168
181
|
配置默认写入:
|
|
169
182
|
|
|
170
183
|
```text
|
|
@@ -254,6 +267,14 @@ nikou-cli hook worker claude \
|
|
|
254
267
|
--max-budget-usd 5
|
|
255
268
|
```
|
|
256
269
|
|
|
270
|
+
使用 `ai-hook` 入口时,默认启动 Codex Worker;第一个参数可指定引擎:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
ai-hook
|
|
274
|
+
ai-hook claude --model sonnet
|
|
275
|
+
ai-hook gemini
|
|
276
|
+
```
|
|
277
|
+
|
|
257
278
|
也可以通过 `--` 传递底层工具参数:
|
|
258
279
|
|
|
259
280
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -460,17 +460,17 @@ var TOOL_CONFIG = {
|
|
|
460
460
|
gemini: { filePath: join6(homedir(), ".gemini", "settings.json"), format: "json", jsonPath: ["mcpServers"] },
|
|
461
461
|
opencode: { filePath: join6(homedir(), ".config", "opencode", "opencode.json"), format: "json", jsonPath: ["mcp"] }
|
|
462
462
|
};
|
|
463
|
-
function readJsonFile(
|
|
464
|
-
if (!existsSync5(
|
|
463
|
+
function readJsonFile(path30) {
|
|
464
|
+
if (!existsSync5(path30)) return {};
|
|
465
465
|
try {
|
|
466
|
-
return JSON.parse(readFileSync4(
|
|
466
|
+
return JSON.parse(readFileSync4(path30, "utf-8"));
|
|
467
467
|
} catch {
|
|
468
468
|
return {};
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
function writeJsonFile(
|
|
472
|
-
mkdirSync4(dirname2(
|
|
473
|
-
writeFileSync3(
|
|
471
|
+
function writeJsonFile(path30, data) {
|
|
472
|
+
mkdirSync4(dirname2(path30), { recursive: true });
|
|
473
|
+
writeFileSync3(path30, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
474
474
|
}
|
|
475
475
|
function getNestedObj(root, keys) {
|
|
476
476
|
let cur = root;
|
|
@@ -497,10 +497,10 @@ function extractServerFromContent(content, jsonPath) {
|
|
|
497
497
|
return null;
|
|
498
498
|
}
|
|
499
499
|
}
|
|
500
|
-
function readTomlFile(
|
|
501
|
-
if (!existsSync5(
|
|
500
|
+
function readTomlFile(path30) {
|
|
501
|
+
if (!existsSync5(path30)) return "";
|
|
502
502
|
try {
|
|
503
|
-
return readFileSync4(
|
|
503
|
+
return readFileSync4(path30, "utf-8");
|
|
504
504
|
} catch {
|
|
505
505
|
return "";
|
|
506
506
|
}
|
|
@@ -546,9 +546,9 @@ function tomlListServers(toml) {
|
|
|
546
546
|
}
|
|
547
547
|
return results;
|
|
548
548
|
}
|
|
549
|
-
function backupFile(
|
|
550
|
-
if (existsSync5(
|
|
551
|
-
copyFileSync(
|
|
549
|
+
function backupFile(path30) {
|
|
550
|
+
if (existsSync5(path30)) {
|
|
551
|
+
copyFileSync(path30, path30 + ".bak");
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
function writeMcpToTool(toolId, serverName, variantContent, force) {
|
|
@@ -14361,6 +14361,88 @@ function countObjectKeys(value) {
|
|
|
14361
14361
|
return Object.keys(value).length;
|
|
14362
14362
|
}
|
|
14363
14363
|
|
|
14364
|
+
// src/hook/init/hook-init-normalizer.ts
|
|
14365
|
+
var DEFAULT_MASTER_HOST_ENV = "NIKOU_HOOK_MASTER_HOST";
|
|
14366
|
+
function resolveHookSection2(config) {
|
|
14367
|
+
return config.hook ?? config.ai_hook ?? config.aiHook ?? {};
|
|
14368
|
+
}
|
|
14369
|
+
function resolveContextConfigFromHook(hook2) {
|
|
14370
|
+
return {
|
|
14371
|
+
enabled: parseBoolean(
|
|
14372
|
+
hook2.context_enabled ?? hook2.contextEnabled,
|
|
14373
|
+
DEFAULT_CONTEXT_CONFIG.enabled
|
|
14374
|
+
),
|
|
14375
|
+
timeoutMs: parsePositiveInt(
|
|
14376
|
+
hook2.context_timeout_ms ?? hook2.contextTimeoutMs,
|
|
14377
|
+
DEFAULT_CONTEXT_CONFIG.timeoutMs
|
|
14378
|
+
),
|
|
14379
|
+
threadMax: parsePositiveInt(
|
|
14380
|
+
hook2.context_thread_max ?? hook2.contextThreadMax,
|
|
14381
|
+
DEFAULT_CONTEXT_CONFIG.threadMax
|
|
14382
|
+
),
|
|
14383
|
+
chatRecentMax: parsePositiveInt(
|
|
14384
|
+
hook2.context_chat_recent_max ?? hook2.contextChatRecentMax,
|
|
14385
|
+
DEFAULT_CONTEXT_CONFIG.chatRecentMax
|
|
14386
|
+
),
|
|
14387
|
+
userRecentMax: parsePositiveInt(
|
|
14388
|
+
hook2.context_user_recent_max ?? hook2.contextUserRecentMax,
|
|
14389
|
+
DEFAULT_CONTEXT_CONFIG.userRecentMax
|
|
14390
|
+
),
|
|
14391
|
+
userRecentWindowMin: parsePositiveInt(
|
|
14392
|
+
hook2.context_user_recent_window_min ?? hook2.contextUserRecentWindowMin,
|
|
14393
|
+
DEFAULT_CONTEXT_CONFIG.userRecentWindowMin
|
|
14394
|
+
),
|
|
14395
|
+
maxChars: parsePositiveInt(
|
|
14396
|
+
hook2.context_max_chars ?? hook2.contextMaxChars,
|
|
14397
|
+
DEFAULT_CONTEXT_CONFIG.maxChars
|
|
14398
|
+
),
|
|
14399
|
+
logVerbose: parseBoolean(
|
|
14400
|
+
hook2.context_log_verbose ?? hook2.contextLogVerbose,
|
|
14401
|
+
DEFAULT_CONTEXT_CONFIG.logVerbose
|
|
14402
|
+
)
|
|
14403
|
+
};
|
|
14404
|
+
}
|
|
14405
|
+
function resolveDefaultMasterHost(env = process.env) {
|
|
14406
|
+
return String(env[DEFAULT_MASTER_HOST_ENV] || "").trim();
|
|
14407
|
+
}
|
|
14408
|
+
function normalizeHookInitConfig(config, defaults = {}) {
|
|
14409
|
+
const hook2 = resolveHookSection2(config);
|
|
14410
|
+
const appId = String(config.feishu?.app_id || config.feishu?.appId || config.feishu?.appid || "").trim();
|
|
14411
|
+
const appSecret = String(
|
|
14412
|
+
config.feishu?.app_secret || config.feishu?.appSecret || config.feishu?.appsecret || ""
|
|
14413
|
+
).trim();
|
|
14414
|
+
const masterHost = String(hook2.master_host || hook2.masterHost || defaults.defaultMasterHost || "").trim();
|
|
14415
|
+
const masterPort = parsePositiveInt(hook2.master_port ?? hook2.masterPort, DEFAULT_MASTER_PORT);
|
|
14416
|
+
const sharedSecret = String(hook2.shared_secret || hook2.sharedSecret || appSecret || "").trim();
|
|
14417
|
+
const bindAllowedUserIds = parseUserIdList(hook2.bind_allowed_user_ids ?? hook2.bindAllowedUserIds);
|
|
14418
|
+
const missing = [];
|
|
14419
|
+
if (!appId) missing.push("feishu.app_id");
|
|
14420
|
+
if (!appSecret) missing.push("feishu.app_secret");
|
|
14421
|
+
if (!masterHost) missing.push(`hook.master_host \u6216 ${DEFAULT_MASTER_HOST_ENV}`);
|
|
14422
|
+
if (!sharedSecret) missing.push("hook.shared_secret");
|
|
14423
|
+
if (bindAllowedUserIds.length === 0) missing.push("hook.bind_allowed_user_ids");
|
|
14424
|
+
if (missing.length > 0) {
|
|
14425
|
+
throw new Error(`\u521D\u59CB\u5316\u6240\u9700\u914D\u7F6E\u7F3A\u5931: ${missing.join(", ")}`);
|
|
14426
|
+
}
|
|
14427
|
+
return {
|
|
14428
|
+
feishuAppId: appId,
|
|
14429
|
+
feishuAppSecret: appSecret,
|
|
14430
|
+
masterHost,
|
|
14431
|
+
masterPort,
|
|
14432
|
+
sharedSecret,
|
|
14433
|
+
bindAllowedUserIds,
|
|
14434
|
+
botName: String(hook2.bot_name || hook2.botName || "").trim() || void 0,
|
|
14435
|
+
claimTimeoutMs: parsePositiveInt(hook2.claim_timeout_ms ?? hook2.claimTimeoutMs, 1e4),
|
|
14436
|
+
relayHeartbeatIntervalMs: parsePositiveInt(hook2.relay_heartbeat_interval_ms ?? hook2.relayHeartbeatIntervalMs, 3e4),
|
|
14437
|
+
relayHeartbeatTimeoutMs: parsePositiveInt(hook2.relay_heartbeat_timeout_ms ?? hook2.relayHeartbeatTimeoutMs, 9e4),
|
|
14438
|
+
slaveConnectTimeoutMs: parsePositiveInt(hook2.slave_connect_timeout_ms ?? hook2.slaveConnectTimeoutMs, 5e3),
|
|
14439
|
+
reconnectIntervalMs: parsePositiveInt(hook2.reconnect_interval_ms ?? hook2.reconnectIntervalMs, 3e3),
|
|
14440
|
+
authCliAuthSecret: String(config.auth?.cli_auth_secret || "").trim() || void 0,
|
|
14441
|
+
authApiUrl: String(config.auth?.api_url || "").trim() || void 0,
|
|
14442
|
+
contextConfig: resolveContextConfigFromHook(hook2)
|
|
14443
|
+
};
|
|
14444
|
+
}
|
|
14445
|
+
|
|
14364
14446
|
// src/hook/init/hook-init-command.ts
|
|
14365
14447
|
var BOT_OPTIONS = [{ label: "\u59AE\u853B", value: "\u59AE\u853B" }];
|
|
14366
14448
|
var DEPLOYMENT_OPTIONS = [
|
|
@@ -14452,44 +14534,9 @@ var HookInitCommand = class {
|
|
|
14452
14534
|
throw new Error(`\u672A\u627E\u5230\u53EF\u521D\u59CB\u5316\u7684\u914D\u7F6E\u6E90\uFF0C\u8BF7\u5148\u51C6\u5907 ${LEGACY_CONFIG_PATH}\u3001${DEFAULT_CONFIG_PATH} \u6216\u89D2\u8272\u914D\u7F6E\u6587\u4EF6`);
|
|
14453
14535
|
}
|
|
14454
14536
|
normalizeSourceConfig(config) {
|
|
14455
|
-
|
|
14456
|
-
|
|
14457
|
-
|
|
14458
|
-
config.feishu?.app_secret || config.feishu?.appSecret || config.feishu?.appsecret || ""
|
|
14459
|
-
).trim();
|
|
14460
|
-
const masterHost = String(hook2.master_host || hook2.masterHost || "").trim();
|
|
14461
|
-
const masterPort = parsePositiveInt(hook2.master_port ?? hook2.masterPort, 19732);
|
|
14462
|
-
const sharedSecret = String(hook2.shared_secret || hook2.sharedSecret || appSecret || "").trim();
|
|
14463
|
-
const bindAllowedUserIds = parseUserIdList(hook2.bind_allowed_user_ids ?? hook2.bindAllowedUserIds);
|
|
14464
|
-
const missing = [];
|
|
14465
|
-
if (!appId) missing.push("feishu.app_id");
|
|
14466
|
-
if (!appSecret) missing.push("feishu.app_secret");
|
|
14467
|
-
if (!masterHost) missing.push("hook.master_host");
|
|
14468
|
-
if (!sharedSecret) missing.push("hook.shared_secret");
|
|
14469
|
-
if (bindAllowedUserIds.length === 0) missing.push("hook.bind_allowed_user_ids");
|
|
14470
|
-
if (missing.length > 0) {
|
|
14471
|
-
throw new Error(`\u521D\u59CB\u5316\u6240\u9700\u914D\u7F6E\u7F3A\u5931: ${missing.join(", ")}`);
|
|
14472
|
-
}
|
|
14473
|
-
return {
|
|
14474
|
-
feishuAppId: appId,
|
|
14475
|
-
feishuAppSecret: appSecret,
|
|
14476
|
-
masterHost,
|
|
14477
|
-
masterPort,
|
|
14478
|
-
sharedSecret,
|
|
14479
|
-
bindAllowedUserIds,
|
|
14480
|
-
botName: String(hook2.bot_name || hook2.botName || "").trim() || void 0,
|
|
14481
|
-
claimTimeoutMs: parsePositiveInt(hook2.claim_timeout_ms ?? hook2.claimTimeoutMs, 1e4),
|
|
14482
|
-
relayHeartbeatIntervalMs: parsePositiveInt(hook2.relay_heartbeat_interval_ms ?? hook2.relayHeartbeatIntervalMs, 3e4),
|
|
14483
|
-
relayHeartbeatTimeoutMs: parsePositiveInt(hook2.relay_heartbeat_timeout_ms ?? hook2.relayHeartbeatTimeoutMs, 9e4),
|
|
14484
|
-
slaveConnectTimeoutMs: parsePositiveInt(hook2.slave_connect_timeout_ms ?? hook2.slaveConnectTimeoutMs, 5e3),
|
|
14485
|
-
reconnectIntervalMs: parsePositiveInt(hook2.reconnect_interval_ms ?? hook2.reconnectIntervalMs, 3e3),
|
|
14486
|
-
authCliAuthSecret: String(config.auth?.cli_auth_secret || "").trim() || void 0,
|
|
14487
|
-
authApiUrl: String(config.auth?.api_url || "").trim() || void 0,
|
|
14488
|
-
contextConfig: resolveContextConfig(config)
|
|
14489
|
-
};
|
|
14490
|
-
}
|
|
14491
|
-
resolveHookSection(config) {
|
|
14492
|
-
return config.hook ?? config.ai_hook ?? config.aiHook ?? {};
|
|
14537
|
+
return normalizeHookInitConfig(config, {
|
|
14538
|
+
defaultMasterHost: resolveDefaultMasterHost()
|
|
14539
|
+
});
|
|
14493
14540
|
}
|
|
14494
14541
|
printEnvironmentSummary(sourcePath, existingConfig, migrationSummary) {
|
|
14495
14542
|
console.log(chalk9.bold("\nHook \u521D\u59CB\u5316\u5411\u5BFC\n"));
|
|
@@ -15042,6 +15089,28 @@ async function hookLogAction(query = "", options = {}) {
|
|
|
15042
15089
|
}
|
|
15043
15090
|
}
|
|
15044
15091
|
|
|
15092
|
+
// src/cli-entry.ts
|
|
15093
|
+
import path29 from "path";
|
|
15094
|
+
var AI_HOOK_COMMAND_NAMES = /* @__PURE__ */ new Set(["ai-hook", "ai-hook.cmd", "ai-hook.exe"]);
|
|
15095
|
+
var HOOK_SUBCOMMANDS = /* @__PURE__ */ new Set(["master", "init", "worker", "log", "help"]);
|
|
15096
|
+
function normalizeCliArgs(commandPath, args) {
|
|
15097
|
+
const commandName = path29.basename(commandPath || "");
|
|
15098
|
+
if (!AI_HOOK_COMMAND_NAMES.has(commandName)) {
|
|
15099
|
+
return args;
|
|
15100
|
+
}
|
|
15101
|
+
const [firstArg = "", ...restArgs] = args;
|
|
15102
|
+
if (firstArg === "hook") {
|
|
15103
|
+
return args;
|
|
15104
|
+
}
|
|
15105
|
+
if (HOOK_SUBCOMMANDS.has(firstArg)) {
|
|
15106
|
+
return ["hook", ...args];
|
|
15107
|
+
}
|
|
15108
|
+
if (!firstArg || firstArg.startsWith("-")) {
|
|
15109
|
+
return ["hook", "worker", "codex", ...args];
|
|
15110
|
+
}
|
|
15111
|
+
return ["hook", "worker", firstArg, ...restArgs];
|
|
15112
|
+
}
|
|
15113
|
+
|
|
15045
15114
|
// src/index.ts
|
|
15046
15115
|
var DEFAULT_DEST = ".agents/skills";
|
|
15047
15116
|
var WORKER_BOOLEAN_OPTIONS = /* @__PURE__ */ new Set([
|
|
@@ -15139,4 +15208,9 @@ hook.command("worker").argument("[engine]", "codex|gemini|claude", "codex").desc
|
|
|
15139
15208
|
hook.command("log").argument("[query]", "\u53EF\u9009\uFF0CtraceId / messageId / \u5173\u952E\u5B57").description("\u67E5\u770B\u672C\u673A agent-block hook master/worker \u65E5\u5FD7").option("--worker", "\u53EA\u770B worker \u65E5\u5FD7", false).option("--slave", "\u53EA\u770B worker \u65E5\u5FD7\uFF08\u517C\u5BB9\u65E7 ai-hook \u4E60\u60EF\uFF09", false).option("--master", "\u53EA\u770B master \u65E5\u5FD7", false).option("-n, --lines <lines>", "\u9ED8\u8BA4\u8FD4\u56DE\u6700\u8FD1\u591A\u5C11\u884C\uFF0C\u9ED8\u8BA4 200").option("-f, --follow", "\u6301\u7EED\u8DDF\u968F\u65E5\u5FD7\u8F93\u51FA\uFF0C\u7B49\u4EF7 tail -f", false).option("-c, --context <lines>", "\u5E26 query \u65F6\u8FD4\u56DE\u524D\u540E\u6587\uFF0C\u9ED8\u8BA4 20").action(async (query, options) => {
|
|
15140
15209
|
await hookLogAction(query, options);
|
|
15141
15210
|
});
|
|
15211
|
+
process.argv = [
|
|
15212
|
+
process.argv[0],
|
|
15213
|
+
process.argv[1],
|
|
15214
|
+
...normalizeCliArgs(process.argv[1], process.argv.slice(2))
|
|
15215
|
+
];
|
|
15142
15216
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nikou-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Install Agent Skills and MCP servers, and run distributed AI hook workers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"nikou-cli": "dist/index.js"
|
|
7
|
+
"nikou-cli": "dist/index.js",
|
|
8
|
+
"ai-hook": "dist/index.js"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"dist"
|