nikou-cli 0.1.6 → 0.1.7

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 +2 -0
  2. package/dist/index.js +89 -74
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -177,6 +177,8 @@ ai-hook local
177
177
 
178
178
  初始化时会提示部署方式和主节点地址。没有远端主节点配置时默认选择本机一体,并使用 `127.0.0.1`;如果旧配置里已有非本机主节点地址,默认选择从节点并沿用该地址。
179
179
 
180
+ 单独从节点连接已有主节点时,不要求配置主节点专用的 `hook.bind_allowed_user_ids`。本机一体或单独启动主节点时,仍必须至少配置一个允许绑定的飞书 `user_id`。
181
+
180
182
  `ai-hook` 裸命令为兼容旧习惯,仍默认等价于 `nikou-cli hook worker codex`;如需只启动 Claude Worker:
181
183
 
182
184
  ```bash
package/dist/index.js CHANGED
@@ -912,7 +912,7 @@ function pad3(str, width) {
912
912
 
913
913
  // src/hook/master/master-command.ts
914
914
  import * as lark2 from "@larksuiteoapi/node-sdk";
915
- import fs8 from "fs";
915
+ import fs7 from "fs";
916
916
  import path8 from "path";
917
917
  import process4 from "process";
918
918
 
@@ -975,7 +975,7 @@ var CARD_STREAM_STDOUT_MAX_LENGTH = 12e3;
975
975
  var BIND_WHITELIST_REFRESH_MS = 5e3;
976
976
 
977
977
  // src/hook/utils.ts
978
- import fs2 from "fs";
978
+ import fs from "fs";
979
979
  import os2 from "os";
980
980
  import path2 from "path";
981
981
  import process2 from "process";
@@ -1029,9 +1029,9 @@ function resolveAiHookGuestPath() {
1029
1029
  }
1030
1030
  function resolveOpsUserName() {
1031
1031
  const propsPath = path2.join(os2.homedir(), "ops", "ops_global.properties");
1032
- if (!fs2.existsSync(propsPath)) return "\u672A\u77E5";
1032
+ if (!fs.existsSync(propsPath)) return "\u672A\u77E5";
1033
1033
  try {
1034
- const lines = fs2.readFileSync(propsPath, "utf-8").split(/\r?\n/);
1034
+ const lines = fs.readFileSync(propsPath, "utf-8").split(/\r?\n/);
1035
1035
  for (const line of lines) {
1036
1036
  const trimmed = line.trim();
1037
1037
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -1056,8 +1056,8 @@ function resolveCardPathDisplay(dirPath) {
1056
1056
  return `${segments[segments.length - 2]}\\${segments[segments.length - 1]}`;
1057
1057
  }
1058
1058
  function ensureDirExists(dirPath) {
1059
- if (!fs2.existsSync(dirPath)) {
1060
- fs2.mkdirSync(dirPath, { recursive: true });
1059
+ if (!fs.existsSync(dirPath)) {
1060
+ fs.mkdirSync(dirPath, { recursive: true });
1061
1061
  }
1062
1062
  }
1063
1063
  function normalizeHost(value) {
@@ -1369,7 +1369,7 @@ function formatCompactTokenCount(value) {
1369
1369
  }
1370
1370
 
1371
1371
  // src/hook/config-loader.ts
1372
- import fs3 from "fs";
1372
+ import fs2 from "fs";
1373
1373
 
1374
1374
  // src/hook/json-config.ts
1375
1375
  function stripJsonLineComments(content) {
@@ -1413,7 +1413,7 @@ function parseJsonWithLineComments(content, filePath = "JSON \u914D\u7F6E") {
1413
1413
  // src/hook/config-loader.ts
1414
1414
  function resolveConfigPath(role = "worker") {
1415
1415
  const configPath = role === "master" ? MASTER_CONFIG_PATH : WORKER_CONFIG_PATH;
1416
- return fs3.existsSync(configPath) ? configPath : null;
1416
+ return fs2.existsSync(configPath) ? configPath : null;
1417
1417
  }
1418
1418
  function loadRoleConfig(role) {
1419
1419
  const configPath = resolveConfigPath(role);
@@ -1427,7 +1427,7 @@ function loadRoleConfig(role) {
1427
1427
  ` + sampleBody + "}"
1428
1428
  );
1429
1429
  }
1430
- const raw = fs3.readFileSync(configPath, "utf-8");
1430
+ const raw = fs2.readFileSync(configPath, "utf-8");
1431
1431
  const config = parseJsonWithLineComments(raw, configPath);
1432
1432
  return { config, configPath };
1433
1433
  }
@@ -1597,7 +1597,7 @@ function resolveAuthConfig(config) {
1597
1597
  }
1598
1598
 
1599
1599
  // src/hook/state-manager.ts
1600
- import fs4 from "fs";
1600
+ import fs3 from "fs";
1601
1601
  import path3 from "path";
1602
1602
  import process3 from "process";
1603
1603
  var StateManager = class {
@@ -1609,13 +1609,13 @@ var StateManager = class {
1609
1609
  this.logger = logger3;
1610
1610
  }
1611
1611
  read() {
1612
- if (!fs4.existsSync(this.statePath)) {
1612
+ if (!fs3.existsSync(this.statePath)) {
1613
1613
  this.state = null;
1614
1614
  return null;
1615
1615
  }
1616
1616
  for (let attempt = 0; attempt < 2; attempt++) {
1617
1617
  try {
1618
- const raw = fs4.readFileSync(this.statePath, "utf-8");
1618
+ const raw = fs3.readFileSync(this.statePath, "utf-8");
1619
1619
  this.state = JSON.parse(raw);
1620
1620
  return this.state;
1621
1621
  } catch (error) {
@@ -1634,13 +1634,13 @@ var StateManager = class {
1634
1634
  const tempPath = `${this.statePath}.tmp.${process3.pid}`;
1635
1635
  try {
1636
1636
  ensureDirExists(path3.dirname(this.statePath));
1637
- fs4.writeFileSync(tempPath, JSON.stringify(nextState, null, 4));
1638
- fs4.renameSync(tempPath, this.statePath);
1637
+ fs3.writeFileSync(tempPath, JSON.stringify(nextState, null, 4));
1638
+ fs3.renameSync(tempPath, this.statePath);
1639
1639
  } catch (error) {
1640
1640
  const msg = error instanceof Error ? error.message : String(error);
1641
1641
  this.logger.warn(`\u5199\u5165\u72B6\u6001\u6587\u4EF6\u5931\u8D25: ${msg}`);
1642
1642
  try {
1643
- if (fs4.existsSync(tempPath)) fs4.unlinkSync(tempPath);
1643
+ if (fs3.existsSync(tempPath)) fs3.unlinkSync(tempPath);
1644
1644
  } catch (cleanupError) {
1645
1645
  const cmsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
1646
1646
  this.logger.warn(`\u6E05\u7406\u4E34\u65F6\u72B6\u6001\u6587\u4EF6\u5931\u8D25: ${cmsg}`);
@@ -3909,7 +3909,7 @@ var DirectWorkerRegistry = class {
3909
3909
  };
3910
3910
 
3911
3911
  // src/hook/master/routing/chat-binding-registry.ts
3912
- import fs5 from "fs";
3912
+ import fs4 from "fs";
3913
3913
  import path4 from "path";
3914
3914
  function normalize2(value) {
3915
3915
  return String(value || "").trim();
@@ -3970,12 +3970,12 @@ var ChatBindingRegistry = class {
3970
3970
  }
3971
3971
  load() {
3972
3972
  this.bindings.clear();
3973
- if (!fs5.existsSync(this.filePath)) {
3973
+ if (!fs4.existsSync(this.filePath)) {
3974
3974
  this.save();
3975
3975
  return;
3976
3976
  }
3977
3977
  try {
3978
- const parsed = JSON.parse(fs5.readFileSync(this.filePath, "utf-8") || "{}");
3978
+ const parsed = JSON.parse(fs4.readFileSync(this.filePath, "utf-8") || "{}");
3979
3979
  for (const [chatId, value] of Object.entries(parsed.bindings || {})) {
3980
3980
  const normalizedChatId = normalize2(chatId);
3981
3981
  if (!normalizedChatId || !value || typeof value !== "object") {
@@ -4003,7 +4003,7 @@ var ChatBindingRegistry = class {
4003
4003
  }
4004
4004
  }
4005
4005
  save() {
4006
- fs5.mkdirSync(path4.dirname(this.filePath), { recursive: true });
4006
+ fs4.mkdirSync(path4.dirname(this.filePath), { recursive: true });
4007
4007
  const bindings = {};
4008
4008
  for (const [chatId, chatMap] of this.bindings.entries()) {
4009
4009
  const serialized = {};
@@ -4012,7 +4012,7 @@ var ChatBindingRegistry = class {
4012
4012
  }
4013
4013
  bindings[chatId] = serialized;
4014
4014
  }
4015
- fs5.writeFileSync(
4015
+ fs4.writeFileSync(
4016
4016
  this.filePath,
4017
4017
  `${JSON.stringify({ version: 2, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), bindings }, null, 2)}
4018
4018
  `,
@@ -4136,7 +4136,7 @@ var ChatBindingRegistry = class {
4136
4136
  };
4137
4137
 
4138
4138
  // src/hook/master/routing/worker-diagnostics-registry.ts
4139
- import fs6 from "fs";
4139
+ import fs5 from "fs";
4140
4140
  import path5 from "path";
4141
4141
  function normalize3(value) {
4142
4142
  return String(value || "").trim();
@@ -4161,12 +4161,12 @@ var WorkerDiagnosticsRegistry = class {
4161
4161
  }
4162
4162
  load() {
4163
4163
  this.workers.clear();
4164
- if (!fs6.existsSync(this.filePath)) {
4164
+ if (!fs5.existsSync(this.filePath)) {
4165
4165
  this.save();
4166
4166
  return;
4167
4167
  }
4168
4168
  try {
4169
- const parsed = JSON.parse(fs6.readFileSync(this.filePath, "utf-8") || "{}");
4169
+ const parsed = JSON.parse(fs5.readFileSync(this.filePath, "utf-8") || "{}");
4170
4170
  for (const [workerId, diagnostics] of Object.entries(safeObject(parsed.workers))) {
4171
4171
  const normalizedWorkerId = normalize3(diagnostics.workerId || workerId);
4172
4172
  const registryKey = buildRegistryKey({
@@ -4198,12 +4198,12 @@ var WorkerDiagnosticsRegistry = class {
4198
4198
  }
4199
4199
  }
4200
4200
  save() {
4201
- fs6.mkdirSync(path5.dirname(this.filePath), { recursive: true });
4201
+ fs5.mkdirSync(path5.dirname(this.filePath), { recursive: true });
4202
4202
  const workers = {};
4203
4203
  for (const [key, diagnostics] of this.workers.entries()) {
4204
4204
  workers[key] = diagnostics;
4205
4205
  }
4206
- fs6.writeFileSync(
4206
+ fs5.writeFileSync(
4207
4207
  this.filePath,
4208
4208
  `${JSON.stringify({ version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), workers }, null, 2)}
4209
4209
  `,
@@ -4252,7 +4252,7 @@ var WorkerDiagnosticsRegistry = class {
4252
4252
  };
4253
4253
 
4254
4254
  // src/hook/master/master-event-utils.ts
4255
- import fs7 from "fs";
4255
+ import fs6 from "fs";
4256
4256
  import os3 from "os";
4257
4257
  import path6 from "path";
4258
4258
  var VOPS_USER_CACHE_PATH = path6.join(os3.homedir(), "ops", "vops_user.json");
@@ -4339,11 +4339,11 @@ function isTaskOperatorMatched(task, operatorUserId, operatorOpenId) {
4339
4339
  function resolveSenderNameFromCache(senderUserId, senderOpenId = "") {
4340
4340
  const targetUserId = String(senderUserId || "").trim();
4341
4341
  const targetOpenId = String(senderOpenId || "").trim();
4342
- if (!targetUserId && !targetOpenId || !fs7.existsSync(VOPS_USER_CACHE_PATH)) {
4342
+ if (!targetUserId && !targetOpenId || !fs6.existsSync(VOPS_USER_CACHE_PATH)) {
4343
4343
  return "";
4344
4344
  }
4345
4345
  try {
4346
- const parsed = JSON.parse(fs7.readFileSync(VOPS_USER_CACHE_PATH, "utf-8"));
4346
+ const parsed = JSON.parse(fs6.readFileSync(VOPS_USER_CACHE_PATH, "utf-8"));
4347
4347
  const entries = Array.isArray(parsed) ? parsed : [];
4348
4348
  const matched = entries.find((item) => {
4349
4349
  if (!item || typeof item !== "object" || item.__cacheType) {
@@ -5231,7 +5231,7 @@ var HookMasterCommand = class {
5231
5231
  if (masterConfig.botName) {
5232
5232
  this.botName = masterConfig.botName;
5233
5233
  }
5234
- const configStat = fs8.statSync(configPath);
5234
+ const configStat = fs7.statSync(configPath);
5235
5235
  this.bindWhitelistConfigMtimeMs = Number(configStat.mtimeMs || 0);
5236
5236
  this.chatBindingRegistry.load();
5237
5237
  this.workerDiagnosticsRegistry.load();
@@ -5753,8 +5753,8 @@ var HookMasterCommand = class {
5753
5753
  }
5754
5754
  refreshBindWhitelistIfNeeded() {
5755
5755
  try {
5756
- if (!this.configPath || !fs8.existsSync(this.configPath)) return;
5757
- const stat = fs8.statSync(this.configPath);
5756
+ if (!this.configPath || !fs7.existsSync(this.configPath)) return;
5757
+ const stat = fs7.statSync(this.configPath);
5758
5758
  const mtimeMs = Number(stat.mtimeMs || 0);
5759
5759
  if (!mtimeMs || mtimeMs <= this.bindWhitelistConfigMtimeMs) return;
5760
5760
  const { config } = loadMasterHstMcpConfig();
@@ -5836,11 +5836,11 @@ var HookMasterCommand = class {
5836
5836
  };
5837
5837
 
5838
5838
  // src/hook/logger.ts
5839
- import fs9 from "fs";
5839
+ import fs8 from "fs";
5840
5840
  import path9 from "path";
5841
5841
  function ensureLogsDir() {
5842
- if (!fs9.existsSync(LOGS_DIR)) {
5843
- fs9.mkdirSync(LOGS_DIR, { recursive: true });
5842
+ if (!fs8.existsSync(LOGS_DIR)) {
5843
+ fs8.mkdirSync(LOGS_DIR, { recursive: true });
5844
5844
  }
5845
5845
  }
5846
5846
  function todaySuffix() {
@@ -5851,8 +5851,8 @@ function timestamp() {
5851
5851
  }
5852
5852
  function appendLine(filePath, line) {
5853
5853
  try {
5854
- fs9.mkdirSync(path9.dirname(filePath), { recursive: true });
5855
- fs9.appendFileSync(filePath, line + "\n", "utf-8");
5854
+ fs8.mkdirSync(path9.dirname(filePath), { recursive: true });
5855
+ fs8.appendFileSync(filePath, line + "\n", "utf-8");
5856
5856
  } catch {
5857
5857
  }
5858
5858
  }
@@ -5877,22 +5877,22 @@ function resolveServiceLogName(role) {
5877
5877
  }
5878
5878
  function ensureCurrentLogLink(currentPath, dailyPath) {
5879
5879
  try {
5880
- fs9.mkdirSync(path9.dirname(currentPath), { recursive: true });
5881
- fs9.mkdirSync(path9.dirname(dailyPath), { recursive: true });
5882
- fs9.writeFileSync(dailyPath, "", { flag: "a" });
5883
- if (fs9.existsSync(currentPath)) {
5884
- const stat = fs9.lstatSync(currentPath);
5880
+ fs8.mkdirSync(path9.dirname(currentPath), { recursive: true });
5881
+ fs8.mkdirSync(path9.dirname(dailyPath), { recursive: true });
5882
+ fs8.writeFileSync(dailyPath, "", { flag: "a" });
5883
+ if (fs8.existsSync(currentPath)) {
5884
+ const stat = fs8.lstatSync(currentPath);
5885
5885
  if (!stat.isSymbolicLink()) {
5886
5886
  const legacyDir = path9.join(path9.dirname(currentPath), "logs", "legacy");
5887
- fs9.mkdirSync(legacyDir, { recursive: true });
5887
+ fs8.mkdirSync(legacyDir, { recursive: true });
5888
5888
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5889
- fs9.renameSync(currentPath, path9.join(legacyDir, `${path9.basename(currentPath)}.${stamp}`));
5889
+ fs8.renameSync(currentPath, path9.join(legacyDir, `${path9.basename(currentPath)}.${stamp}`));
5890
5890
  }
5891
5891
  }
5892
- fs9.rmSync(currentPath, { force: true });
5893
- fs9.symlinkSync(dailyPath, currentPath);
5892
+ fs8.rmSync(currentPath, { force: true });
5893
+ fs8.symlinkSync(dailyPath, currentPath);
5894
5894
  } catch {
5895
- fs9.writeFileSync(currentPath, "", { flag: "a" });
5895
+ fs8.writeFileSync(currentPath, "", { flag: "a" });
5896
5896
  }
5897
5897
  }
5898
5898
  function createLogger(name, verbose = false) {
@@ -5957,12 +5957,15 @@ import os17 from "os";
5957
5957
  import path27 from "path";
5958
5958
  import * as lark3 from "@larksuiteoapi/node-sdk";
5959
5959
 
5960
+ // src/hook/worker/message-strategy.ts
5961
+ import fs14 from "fs";
5962
+
5960
5963
  // src/hook/worker/runners/codex-runner.ts
5961
5964
  import process7 from "process";
5962
5965
  import { spawn, spawnSync as spawnSync4 } from "child_process";
5963
5966
 
5964
5967
  // src/hook/runtime-env.ts
5965
- import fs10 from "fs";
5968
+ import fs9 from "fs";
5966
5969
  import process5 from "process";
5967
5970
  import { spawnSync as spawnSync2 } from "child_process";
5968
5971
  var HST_MCP_DISABLED_MODULES_ENV_KEY = "HST_MCP_DISABLED_MODULES";
@@ -6007,11 +6010,11 @@ function parseEnvFileContent(content = "") {
6007
6010
  return env;
6008
6011
  }
6009
6012
  function loadRuntimeEnvFile(filePath = RUNTIME_ENV_PATH) {
6010
- if (!filePath || !fs10.existsSync(filePath)) {
6013
+ if (!filePath || !fs9.existsSync(filePath)) {
6011
6014
  return {};
6012
6015
  }
6013
6016
  try {
6014
- return parseEnvFileContent(fs10.readFileSync(filePath, "utf-8"));
6017
+ return parseEnvFileContent(fs9.readFileSync(filePath, "utf-8"));
6015
6018
  } catch {
6016
6019
  return {};
6017
6020
  }
@@ -6023,7 +6026,7 @@ function resolveUnixShell(baseEnv = process5.env) {
6023
6026
  "/bin/bash",
6024
6027
  "/bin/sh"
6025
6028
  ].filter(Boolean);
6026
- return candidates.find((item) => fs10.existsSync(item)) || "/bin/sh";
6029
+ return candidates.find((item) => fs9.existsSync(item)) || "/bin/sh";
6027
6030
  }
6028
6031
  function parseNullSeparatedEnv(output = "") {
6029
6032
  const env = {};
@@ -6144,23 +6147,23 @@ function buildHookRuntimeEnv(baseEnv = process5.env, {
6144
6147
  }
6145
6148
 
6146
6149
  // src/hook/worker/runners/command-resolver.ts
6147
- import fs11 from "fs";
6150
+ import fs10 from "fs";
6148
6151
  import path10 from "path";
6149
6152
  import process6 from "process";
6150
6153
  import { spawnSync as spawnSync3 } from "child_process";
6151
6154
  function isExecutableFile(filePath) {
6152
- if (!filePath || !fs11.existsSync(filePath)) {
6155
+ if (!filePath || !fs10.existsSync(filePath)) {
6153
6156
  return false;
6154
6157
  }
6155
6158
  try {
6156
- const stat = fs11.statSync(filePath);
6159
+ const stat = fs10.statSync(filePath);
6157
6160
  if (!stat.isFile()) {
6158
6161
  return false;
6159
6162
  }
6160
6163
  if (process6.platform === "win32") {
6161
6164
  return true;
6162
6165
  }
6163
- fs11.accessSync(filePath, fs11.constants.X_OK);
6166
+ fs10.accessSync(filePath, fs10.constants.X_OK);
6164
6167
  return true;
6165
6168
  } catch {
6166
6169
  return false;
@@ -6705,7 +6708,7 @@ command=${execConfig.displayCommand}`));
6705
6708
  };
6706
6709
 
6707
6710
  // src/hook/context/identity-resolver.ts
6708
- import fs12 from "fs";
6711
+ import fs11 from "fs";
6709
6712
  import os5 from "os";
6710
6713
  import path11 from "path";
6711
6714
 
@@ -6910,12 +6913,12 @@ var IdentityResolver = class {
6910
6913
  if (Array.isArray(this.cache)) {
6911
6914
  return this.cache;
6912
6915
  }
6913
- if (!fs12.existsSync(this.cachePath)) {
6916
+ if (!fs11.existsSync(this.cachePath)) {
6914
6917
  this.cache = [];
6915
6918
  return this.cache;
6916
6919
  }
6917
6920
  try {
6918
- const parsed = JSON.parse(fs12.readFileSync(this.cachePath, "utf-8"));
6921
+ const parsed = JSON.parse(fs11.readFileSync(this.cachePath, "utf-8"));
6919
6922
  const input = Array.isArray(parsed) ? parsed : [];
6920
6923
  this.cache = this.dedupeCacheEntries(input);
6921
6924
  if (this.cache.length !== input.length) {
@@ -6932,7 +6935,7 @@ var IdentityResolver = class {
6932
6935
  saveCache() {
6933
6936
  try {
6934
6937
  this.cache = this.dedupeCacheEntries(this.cache || []);
6935
- fs12.writeFileSync(this.cachePath, JSON.stringify(this.cache, null, 2));
6938
+ fs11.writeFileSync(this.cachePath, JSON.stringify(this.cache, null, 2));
6936
6939
  } catch (error) {
6937
6940
  const message = error instanceof Error ? error.message : String(error);
6938
6941
  this.logger.warn(`\u5199\u5165 vops_user.json \u5931\u8D25: ${message}`);
@@ -7265,7 +7268,7 @@ var IdentityResolver = class {
7265
7268
  };
7266
7269
 
7267
7270
  // src/hook/prompt/nikou-prompt-store.ts
7268
- import fs13 from "fs";
7271
+ import fs12 from "fs";
7269
7272
  import os6 from "os";
7270
7273
  import path12 from "path";
7271
7274
 
@@ -7320,7 +7323,7 @@ function normalizeText2(value) {
7320
7323
  return String(value || "").trim();
7321
7324
  }
7322
7325
  function ensureDir(dirPath) {
7323
- fs13.mkdirSync(dirPath, { recursive: true });
7326
+ fs12.mkdirSync(dirPath, { recursive: true });
7324
7327
  }
7325
7328
  function parseFrontmatter(content) {
7326
7329
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
@@ -7367,18 +7370,18 @@ ${body}
7367
7370
  ` : "\n"}`;
7368
7371
  }
7369
7372
  function readTextFile(filePath) {
7370
- if (!fs13.existsSync(filePath)) {
7373
+ if (!fs12.existsSync(filePath)) {
7371
7374
  return "";
7372
7375
  }
7373
7376
  try {
7374
- return fs13.readFileSync(filePath, "utf-8").trim();
7377
+ return fs12.readFileSync(filePath, "utf-8").trim();
7375
7378
  } catch {
7376
7379
  return "";
7377
7380
  }
7378
7381
  }
7379
7382
  function writeTextFile(filePath, content) {
7380
7383
  ensureDir(path12.dirname(filePath));
7381
- fs13.writeFileSync(filePath, content, "utf-8");
7384
+ fs12.writeFileSync(filePath, content, "utf-8");
7382
7385
  }
7383
7386
  function buildPromptDefinitions() {
7384
7387
  const roleDefinitions = Object.entries(REQUESTER_PERSONA_RULES.roles).map(([roleKey, roleConfig]) => ({
@@ -7439,7 +7442,7 @@ var NikouPromptStore = class {
7439
7442
  return definition.defaultContent.trim();
7440
7443
  }
7441
7444
  readPromptFile(definition) {
7442
- if (!fs13.existsSync(definition.path)) {
7445
+ if (!fs12.existsSync(definition.path)) {
7443
7446
  const content = this.resolveBootstrapContent(definition);
7444
7447
  const file = {
7445
7448
  title: definition.title,
@@ -7450,7 +7453,7 @@ var NikouPromptStore = class {
7450
7453
  this.syncLegacyFiles(definition, file);
7451
7454
  return file;
7452
7455
  }
7453
- return parseFrontmatter(fs13.readFileSync(definition.path, "utf-8"));
7456
+ return parseFrontmatter(fs12.readFileSync(definition.path, "utf-8"));
7454
7457
  }
7455
7458
  syncLegacyFiles(definition, file) {
7456
7459
  if (!definition.legacyPaths.length) {
@@ -7463,7 +7466,7 @@ var NikouPromptStore = class {
7463
7466
  }
7464
7467
  }
7465
7468
  toSummary(definition, file) {
7466
- const stat = fs13.existsSync(definition.path) ? fs13.statSync(definition.path) : null;
7469
+ const stat = fs12.existsSync(definition.path) ? fs12.statSync(definition.path) : null;
7467
7470
  return {
7468
7471
  id: definition.id,
7469
7472
  kind: definition.kind,
@@ -7544,7 +7547,7 @@ var NikouPromptStore = class {
7544
7547
  };
7545
7548
 
7546
7549
  // src/hook/worker/task-route-binding.ts
7547
- import fs14 from "fs";
7550
+ import fs13 from "fs";
7548
7551
  import path13 from "path";
7549
7552
  function resolveTaskRouteDir(routeBinding, fallbackDir) {
7550
7553
  if (routeBinding) {
@@ -7553,7 +7556,7 @@ function resolveTaskRouteDir(routeBinding, fallbackDir) {
7553
7556
  return { dirPath: "", reason: "invalid_route_dir" };
7554
7557
  }
7555
7558
  try {
7556
- if (!fs14.statSync(dirPath2).isDirectory()) {
7559
+ if (!fs13.statSync(dirPath2).isDirectory()) {
7557
7560
  return { dirPath: "", reason: "invalid_route_dir" };
7558
7561
  }
7559
7562
  } catch {
@@ -8323,7 +8326,7 @@ ${question}` : question;
8323
8326
  if (!bindTarget) {
8324
8327
  return { ...baseTask, canHandle: true, type: "quick_result", quickResult: "\u8BF7\u6307\u5B9A\u7ED1\u5B9A\u8DEF\u5F84\uFF0C\u683C\u5F0F: \u7ED1\u5B9A:/path/to/project" };
8325
8328
  }
8326
- if (!fs.existsSync(bindTarget)) {
8329
+ if (!fs14.existsSync(bindTarget)) {
8327
8330
  return { ...baseTask, canHandle: true, type: "quick_result", quickResult: `\u8DEF\u5F84\u4E0D\u5B58\u5728: ${bindTarget}` };
8328
8331
  }
8329
8332
  this.stateManager.rebindChatToDir(message.chatId, bindTarget);
@@ -9759,7 +9762,15 @@ var SlaveRelayClient = class {
9759
9762
  this.resolvePendingClaim(packet.task_id, false);
9760
9763
  break;
9761
9764
  case "task_offer":
9762
- this.handleTaskOffer(packet);
9765
+ void this.handleTaskOffer(packet).catch((error) => {
9766
+ const taskId = String(packet.task_id || "").trim();
9767
+ const traceId = resolveTraceId(taskId);
9768
+ const message = error instanceof Error ? error.message : String(error);
9769
+ this.logger.error(formatTraceLog(
9770
+ traceId,
9771
+ `\u5904\u7406\u4EFB\u52A1 offer \u5931\u8D25: task_id=${taskId || "-"}, error=${message}`
9772
+ ));
9773
+ });
9763
9774
  break;
9764
9775
  case "task_cancel": {
9765
9776
  const cancelResult = this.taskExecutor.cancelTask(packet.task_id);
@@ -14839,7 +14850,9 @@ function normalizeHookInitConfig(config, defaults = {}) {
14839
14850
  if (!appSecret) missing.push("feishu.app_secret");
14840
14851
  if (!masterHost) missing.push(`hook.master_host \u6216 ${DEFAULT_MASTER_HOST_ENV}`);
14841
14852
  if (!sharedSecret) missing.push("hook.shared_secret");
14842
- if (bindAllowedUserIds.length === 0) missing.push("hook.bind_allowed_user_ids");
14853
+ if (defaults.deploymentMode !== "slave" && bindAllowedUserIds.length === 0) {
14854
+ missing.push("hook.bind_allowed_user_ids");
14855
+ }
14843
14856
  if (missing.length > 0) {
14844
14857
  throw new Error(`\u521D\u59CB\u5316\u6240\u9700\u914D\u7F6E\u7F3A\u5931: ${missing.join(", ")}`);
14845
14858
  }
@@ -14897,7 +14910,8 @@ var HookInitCommand = class {
14897
14910
  const defaultMasterHost = deploymentMode === "local" ? LOCAL_MASTER_HOST : deploymentDefaults.masterHost;
14898
14911
  const masterHost = await this.askMasterHost(rl, source.config, defaultMasterHost);
14899
14912
  const normalized = this.normalizeSourceConfig(
14900
- mergeHookInitMasterHost(source.config, masterHost)
14913
+ mergeHookInitMasterHost(source.config, masterHost),
14914
+ deploymentMode
14901
14915
  );
14902
14916
  const nextMasterConfig = this.buildMasterConfigPayload(normalized, botName);
14903
14917
  const nextWorkerConfig = this.buildWorkerConfigPayload(normalized, botName);
@@ -14969,9 +14983,10 @@ var HookInitCommand = class {
14969
14983
  }
14970
14984
  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`);
14971
14985
  }
14972
- normalizeSourceConfig(config) {
14986
+ normalizeSourceConfig(config, deploymentMode) {
14973
14987
  return normalizeHookInitConfig(config, {
14974
- defaultMasterHost: resolveDefaultMasterHost()
14988
+ defaultMasterHost: resolveDefaultMasterHost(),
14989
+ deploymentMode
14975
14990
  });
14976
14991
  }
14977
14992
  printEnvironmentSummary(sourcePath, existingConfig, migrationSummary) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nikou-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Install Agent Skills and MCP servers, and run distributed AI hook workers.",
5
5
  "type": "module",
6
6
  "bin": {