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.
Files changed (3) hide show
  1. package/README.md +21 -0
  2. package/dist/index.js +124 -50
  3. 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(path29) {
464
- if (!existsSync5(path29)) return {};
463
+ function readJsonFile(path30) {
464
+ if (!existsSync5(path30)) return {};
465
465
  try {
466
- return JSON.parse(readFileSync4(path29, "utf-8"));
466
+ return JSON.parse(readFileSync4(path30, "utf-8"));
467
467
  } catch {
468
468
  return {};
469
469
  }
470
470
  }
471
- function writeJsonFile(path29, data) {
472
- mkdirSync4(dirname2(path29), { recursive: true });
473
- writeFileSync3(path29, JSON.stringify(data, null, 2) + "\n", "utf-8");
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(path29) {
501
- if (!existsSync5(path29)) return "";
500
+ function readTomlFile(path30) {
501
+ if (!existsSync5(path30)) return "";
502
502
  try {
503
- return readFileSync4(path29, "utf-8");
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(path29) {
550
- if (existsSync5(path29)) {
551
- copyFileSync(path29, path29 + ".bak");
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
- const hook2 = this.resolveHookSection(config);
14456
- const appId = String(config.feishu?.app_id || config.feishu?.appId || config.feishu?.appid || "").trim();
14457
- const appSecret = String(
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.0",
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"