kinstra-neko 1.0.0 → 1.0.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 +7 -4
- package/installer/bin/kinstra-neko-init.mjs +2 -2
- package/installer/linux/install.sh +113 -34
- package/installer/windows/install.ps1 +12 -6
- package/lib/index.js +10 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,14 +89,17 @@ irm https://raw.githubusercontent.com/EROQIN/kinstra-neko/main/installer/windows
|
|
|
89
89
|
|
|
90
90
|
### 🧑💻 已有 Node 环境,只想装插件
|
|
91
91
|
|
|
92
|
+
DSH 是 pnpm 生态(依赖多为 alpha 预发布版本,npm 的严格 peer 校验会报 ERESOLVE),请用 pnpm:
|
|
93
|
+
|
|
92
94
|
```bash
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
npm i -g pnpm # 若还没有 pnpm
|
|
96
|
+
pnpm dlx kinstra-neko@latest init # 建 profile、装 bundle、引导写凭据
|
|
97
|
+
dsh --profile kinstra-neko --port 3090 # 控制台会自动打开带一次性 token 的页面
|
|
95
98
|
```
|
|
96
99
|
|
|
97
100
|
### 装完之后 · 3 分钟向导
|
|
98
101
|
|
|
99
|
-
1.
|
|
102
|
+
1. 打开控制台:Windows 双击桌面图标会自动用带一次性 token 的链接打开;Linux 服务器从安装结尾输出或 `journalctl -u kinstra-neko -n 30 | grep -o 'http://.*token=.*' | tail -1` 取带 token 的地址(裸 `http://<IP>:3090` 会被令牌门挡住,云服务器记得安全组放行 3090)。
|
|
100
103
|
2. 按向导填:**猫娘小号 QQ**、**你的 QQ(主人)**。
|
|
101
104
|
3. 在「连接」页点「生成 OneBot 配置」再点「启动 NapCat」,用猫娘小号扫弹出窗口里的二维码登录;插件会自动核对登录号与配置是否一致。
|
|
102
105
|
4. 在 DSH 设置里配置模型服务商与 API Key(DeepSeek 官方或任意 OpenAI 兼容端点)。
|
|
@@ -219,7 +222,7 @@ npm run build # tsdown 双入口:lib/index.js + lib/clien
|
|
|
219
222
|
# 装进本地 DSH 调试:
|
|
220
223
|
dsh kinstra-neko --from-default-profile web --dump-config >/dev/null # 仅首次
|
|
221
224
|
dsh plugin --profile kinstra-neko add "link:$PWD"
|
|
222
|
-
dsh --profile kinstra-neko
|
|
225
|
+
dsh --profile kinstra-neko --port 3090 # 控制台会自动打开带一次性 token 的页面
|
|
223
226
|
```
|
|
224
227
|
|
|
225
228
|
无真实 QQ 环境时,决策、消息解析、记忆、回复拆条均为纯函数,直接跑单测即可;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Kinstra Neko 初始化器:创建独立 DSH profile、装入猫娘 bundle、引导最小配置。
|
|
3
3
|
// 用法:
|
|
4
|
-
//
|
|
4
|
+
// pnpm dlx kinstra-neko init # 从 npm 装插件(推荐;npm/npx 会因 alpha 严格 peer 报 ERESOLVE)
|
|
5
5
|
// node kinstra-neko-init.mjs init --link /path/to/kinstra-neko # 开发/离线本地装
|
|
6
6
|
// node kinstra-neko-init.mjs doctor # 环境自检
|
|
7
7
|
// node kinstra-neko-init.mjs set-napcat-dir <NapCat Shell 目录> # 安装器种协议端目录
|
|
@@ -157,7 +157,7 @@ function cmdInit(options) {
|
|
|
157
157
|
console.log()
|
|
158
158
|
say('初始化完成!接下来:')
|
|
159
159
|
console.log(` 1. 确保 QQ 协议端在跑(NapCat:先执行平台安装脚本;或自行准备 OneBot v11)`)
|
|
160
|
-
console.log(` 2. 启动控制台: ${c.bold}dsh --profile ${PROFILE}
|
|
160
|
+
console.log(` 2. 启动控制台: ${c.bold}dsh --profile ${PROFILE} --port ${port} --no-open${c.reset}`)
|
|
161
161
|
console.log(` 3. 浏览器打开 http://127.0.0.1:${port} ,按猫娘向导填小号 QQ、你的 QQ、白名单`)
|
|
162
162
|
console.log(` 默认是试运行:她只会在面板记录“本来会说什么”,确认对味后再关试运行\n`)
|
|
163
163
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# 2. Node.js 22(缺失时用 NodeSource;国内可用 CN_MIRROR=1 走镜像)
|
|
7
7
|
# 3. 全局安装 DeepSeek Harness
|
|
8
8
|
# 4. 调 kinstra-neko init 建 profile、装猫娘 bundle
|
|
9
|
-
# 5. 装 NapCat(官方 NapCat-Installer
|
|
9
|
+
# 5. 装 NapCat(官方 NapCat-Installer · rootless Shell:Xvfb 里跑 QQNT,扫码走 NapCat 内置 WebUI)并生成 OneBot 配置
|
|
10
10
|
# 6. 注册 systemd 服务 kinstra-neko(开机自启、崩溃重启、Node 内存上限)
|
|
11
11
|
#
|
|
12
12
|
# 用法:
|
|
@@ -14,13 +14,19 @@
|
|
|
14
14
|
# # 或下载后:sudo CN_MIRROR=1 bash install.sh
|
|
15
15
|
#
|
|
16
16
|
# 可覆盖变量:DSH_VERSION、KINSTRA_NEKO_SPEC(本地/自定义插件源)、WEB_PORT(默认 3090)、
|
|
17
|
-
#
|
|
17
|
+
# WEB_HOST(默认主网卡 IP 供远程访问;设 127.0.0.1 只本机)、
|
|
18
|
+
# NAPCAT_INSTALL_URL、NAPCAT_PROXY(官方脚本 GitHub 加速选项,0=直连;默认 0)、SKIP_NAPCAT=1
|
|
18
19
|
|
|
19
20
|
set -euo pipefail
|
|
20
21
|
|
|
21
22
|
WEB_PORT="${WEB_PORT:-3090}"
|
|
23
|
+
# 远程(云服务器)浏览器访问需绑到网卡上的具体 IP(DSH 拒绝 0.0.0.0 通配)。
|
|
24
|
+
# 默认取主网卡首个 IPv4;只想本机访问可 WEB_HOST=127.0.0.1。
|
|
25
|
+
WEB_HOST="${WEB_HOST:-$(hostname -I 2>/dev/null | awk '{print $1}')}"
|
|
22
26
|
DSH_VERSION="${DSH_VERSION:-0.2.1-rc.3}"
|
|
23
|
-
|
|
27
|
+
# 官方脚本源在 GitHub(NapNeko/NapCat-Installer);旧默认域名 nclatest.znin.net 已不可达,可用 NAPCAT_INSTALL_URL 覆盖。
|
|
28
|
+
NAPCAT_INSTALL_URL="${NAPCAT_INSTALL_URL:-https://raw.githubusercontent.com/NapNeko/NapCat-Installer/main/script/install.sh}"
|
|
29
|
+
NAPCAT_PROXY="${NAPCAT_PROXY:-0}"
|
|
24
30
|
RUN_USER="${SUDO_USER:-$USER}"
|
|
25
31
|
RUN_HOME="$(eval echo "~$RUN_USER")"
|
|
26
32
|
|
|
@@ -83,54 +89,106 @@ if [ "$need_node" = 1 ]; then
|
|
|
83
89
|
fi
|
|
84
90
|
|
|
85
91
|
# ---------- 3. DSH ----------
|
|
86
|
-
|
|
92
|
+
# 系统级 node(NodeSource)的全局 prefix 是 /usr,/usr/lib/node_modules 归 root,
|
|
93
|
+
# 因此全局包必须以 root 身份装(bin 链到 /usr/bin/dsh,普通用户也能调用)。
|
|
94
|
+
# 切勿 su 到普通用户执行 npm -g:写不进 root 目录会 EACCES。
|
|
95
|
+
if ! command -v dsh >/dev/null 2>&1; then
|
|
87
96
|
say "全局安装 DeepSeek Harness @$DSH_VERSION…"
|
|
88
|
-
|
|
97
|
+
npm install -g "@deepseek-ai/dsh@$DSH_VERSION" --no-audit --no-fund
|
|
89
98
|
fi
|
|
90
|
-
ok "DSH:$(
|
|
99
|
+
ok "DSH:$(dsh --version 2>/dev/null || echo 已安装)"
|
|
100
|
+
|
|
101
|
+
# pnpm:DSH 的 `dsh plugin add` 用 pnpm 装插件,且本生态全是 alpha 预发布版本,
|
|
102
|
+
# npm 的严格 peer 解析会因版本范围(精确 alpha vs ~x.y.z)报 ERESOLVE,pnpm 只告警不阻断。
|
|
103
|
+
if ! command -v pnpm >/dev/null 2>&1; then
|
|
104
|
+
say '安装 pnpm(DSH 插件管理器依赖)…'
|
|
105
|
+
npm install -g pnpm --no-audit --no-fund
|
|
106
|
+
fi
|
|
107
|
+
ok "pnpm $(pnpm -v)"
|
|
91
108
|
|
|
92
109
|
# ---------- 4. Kinstra Neko 插件 ----------
|
|
93
110
|
say '初始化 Kinstra Neko profile 与插件…'
|
|
94
111
|
INIT_ARGS='init'
|
|
95
112
|
[ -n "${KINSTRA_NEKO_SPEC:-}" ] && INIT_ARGS="init --link $KINSTRA_NEKO_SPEC"
|
|
96
|
-
|
|
113
|
+
# init 的 stdin 一律接 /dev/null:唯一交互是可跳过的模型 API Key(EOF 自动取空),
|
|
114
|
+
# 密钥本就改在装完后的面板向导里填,curl|bash 过程中不该卡在输入。
|
|
115
|
+
# 切勿在此重定向 /dev/tty:root 脚本里探测到的控制终端,在 `su - <user>` 经 PAM/setsid
|
|
116
|
+
# 起 login shell 后可能已不可达(交互式 ssh 下 curl|sudo bash 必现),反而让整条 su 失败。
|
|
117
|
+
su - "$RUN_USER" -c "DSH_VERSION=$DSH_VERSION pnpm dlx kinstra-neko@latest $INIT_ARGS </dev/null" || \
|
|
97
118
|
die '插件初始化失败(网络问题可重试;开发版可设 KINSTRA_NEKO_SPEC=本地目录)'
|
|
98
119
|
ok '猫娘插件已装入 profile'
|
|
99
120
|
|
|
100
121
|
# ---------- 5. NapCat(可跳过)----------
|
|
122
|
+
# 真机确认的官方 NapCat Shell(rootless) 布局(NapCat-Installer --docker n):
|
|
123
|
+
# $RUN_HOME/Napcat/opt/QQ/qq QQNT 可执行
|
|
124
|
+
# $RUN_HOME/Napcat/opt/QQ/resources/app/app_launcher/napcat/ NapCat 插件目录(config/ 在此)
|
|
125
|
+
# 启动是 `xvfb-run -a <qq> --no-sandbox`(无头自动起 Xvfb);官方【不】注册 systemd 服务、
|
|
126
|
+
# 也【不】装 x11vnc,headless 扫码走 NapCat 内置 WebUI(首启后 config/webui.json 出 token,默认 6099)。
|
|
101
127
|
if [ "${SKIP_NAPCAT:-0}" != 1 ]; then
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
NAPCAT_HOME="$RUN_HOME/Napcat"
|
|
129
|
+
NAPCAT_QQ="$NAPCAT_HOME/opt/QQ"
|
|
130
|
+
NAPCAT_DIR="$NAPCAT_QQ/resources/app/app_launcher/napcat" # config 与 run-napcat.sh 所在,种给插件
|
|
131
|
+
NAPCAT_QQ_BIN="$NAPCAT_QQ/qq"
|
|
132
|
+
|
|
133
|
+
if [ -x "$NAPCAT_QQ_BIN" ] && [ -f "$NAPCAT_DIR/napcat.mjs" ]; then
|
|
134
|
+
# 幂等:已装好就别再下载/重跑官方安装器(重跑几百 MB 且易因 /tmp 残留触发 curl 写错误)。
|
|
135
|
+
ok "NapCat 已安装:$NAPCAT_HOME(跳过官方安装器)"
|
|
136
|
+
else
|
|
137
|
+
say '安装 NapCat(官方 NapCat-Installer · rootless Shell:QQNT + NapCat + Xvfb,约几百 MB)…'
|
|
138
|
+
# 下到唯一临时文件再执行:curl -o 直接覆盖一个属主为普通用户的 /tmp 残留会报 write error 23
|
|
139
|
+
# (真机实测),mktemp 新文件可规避;下载失败只跳过 NapCat、不阻断已就绪的核心服务。
|
|
140
|
+
napcat_inst="$(mktemp /tmp/napcat-installer.XXXXXX.sh)"
|
|
141
|
+
# --retry 让瞬态网络/写错误就地自愈(curl 23 在真机出现过一次),尽量一次装成;
|
|
142
|
+
# 最终仍失败才降级为跳过 NapCat,不阻断核心控制台。
|
|
143
|
+
if curl -fsSL --retry 3 --retry-delay 2 --connect-timeout 20 "$NAPCAT_INSTALL_URL" -o "$napcat_inst"; then
|
|
144
|
+
# 以 root 跑(apt 装 Xvfb/依赖免密),但 HOME 指向普通用户家目录:rootless 安装器按
|
|
145
|
+
# $HOME/Napcat 落文件,这样 QQ/NapCat 落在运行用户名下;后面再 chown 兜底归属。
|
|
146
|
+
# 显式参数跳过交互菜单:--docker n 走 Shell、--cli y 装 napcat 命令、--proxy 直连。
|
|
147
|
+
HOME="$RUN_HOME" bash "$napcat_inst" --docker n --cli y --proxy "$NAPCAT_PROXY" \
|
|
148
|
+
|| warn 'NapCat 安装器返回非零(多为网络/版本差异)。可稍后重跑本脚本,或面板「连接」改接任意 OneBot v11。'
|
|
149
|
+
else
|
|
150
|
+
warn "下载 NapCat 官方安装器失败(网络受限可设 NAPCAT_INSTALL_URL 指向可达镜像)。跳过 NapCat,核心控制台仍可用。"
|
|
151
|
+
fi
|
|
152
|
+
rm -f "$napcat_inst"
|
|
105
153
|
fi
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
cat > "$NAPCAT_DIR/run-napcat.sh" <<'RUNEOF'
|
|
154
|
+
|
|
155
|
+
if [ -x "$NAPCAT_QQ_BIN" ] && [ -d "$NAPCAT_DIR" ]; then
|
|
156
|
+
# root 跑安装器可能在用户家目录留下 root 属主文件;插件以普通用户 spawn,要能写
|
|
157
|
+
# config(onebot11_*.json),NapCat 首启也要写 webui.json/登录态,故整目录归普通用户。
|
|
158
|
+
chown -R "$RUN_USER":"$RUN_USER" "$NAPCAT_HOME"
|
|
159
|
+
install -d -o "$RUN_USER" -g "$RUN_USER" "$NAPCAT_DIR/config"
|
|
160
|
+
cat > "$NAPCAT_DIR/run-napcat.sh" <<'RUNEOF'
|
|
114
161
|
#!/usr/bin/env bash
|
|
115
|
-
# Kinstra Neko 调起的 NapCat
|
|
116
|
-
#
|
|
162
|
+
# Kinstra Neko 调起的 NapCat 启动脚本(安装器生成)。
|
|
163
|
+
# 官方 rootless Shell 形态:没有 systemd 服务、没有 x11vnc;在 Xvfb 虚拟显示里前台跑 QQNT,
|
|
164
|
+
# 扫码/登录管理走 NapCat 内置 WebUI(token 见同目录 config/webui.json,默认端口 6099)。
|
|
165
|
+
# 插件以普通用户 spawn 本脚本(cwd=本目录);exec 让 QQ 顶替本壳,信号可直达。
|
|
117
166
|
set -e
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
fi
|
|
167
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
168
|
+
# 本脚本在 resources/app/app_launcher/napcat 下,上溯四级到 opt/QQ,QQ 本体在那。
|
|
169
|
+
QQ="$(cd "$DIR/../../../.." && pwd)/qq"
|
|
170
|
+
[ -x "$QQ" ] || QQ="$HOME/Napcat/opt/QQ/qq"
|
|
171
|
+
exec xvfb-run -a "$QQ" --no-sandbox "$@"
|
|
124
172
|
RUNEOF
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
173
|
+
chmod 755 "$NAPCAT_DIR/run-napcat.sh"
|
|
174
|
+
chown "$RUN_USER":"$RUN_USER" "$NAPCAT_DIR/run-napcat.sh"
|
|
175
|
+
# 关键:把 NapCat 插件目录(config 所在)种进插件配置,否则 detect() 回落到
|
|
176
|
+
# ~/.dsh/plugins-data/kinstra-neko/napcat,与真实安装目录不一致而判“未安装”。
|
|
177
|
+
su - "$RUN_USER" -c "pnpm dlx kinstra-neko@latest set-napcat-dir '$NAPCAT_DIR' </dev/null" \
|
|
178
|
+
|| warn '未能把 NapCat 目录写入插件配置,可在面板「连接」页手填:'"$NAPCAT_DIR"
|
|
179
|
+
ok "NapCat 就绪:$NAPCAT_HOME(首次启动后经 SSH 隧道开 WebUI 扫码,见下方上线步骤)"
|
|
180
|
+
else
|
|
181
|
+
warn "NapCat 似乎没装完整(缺 $NAPCAT_QQ_BIN 或 $NAPCAT_DIR,多为下载失败)。可重跑本脚本,或面板「连接」改接 OneBot。"
|
|
182
|
+
fi
|
|
128
183
|
fi
|
|
129
184
|
|
|
130
185
|
# ---------- 6. systemd 服务 ----------
|
|
131
186
|
say '注册 systemd 服务 kinstra-neko…'
|
|
132
187
|
NODE_BIN="$(su - "$RUN_USER" -c 'command -v node')"
|
|
133
188
|
DSH_BIN="$(su - "$RUN_USER" -c 'command -v dsh')"
|
|
189
|
+
# --host 只接受具体本机 IP(拒绝通配);取不到就不传给 DSH(回落其默认 loopback)。
|
|
190
|
+
BIND_ARGS="--port $WEB_PORT --no-open"
|
|
191
|
+
[ -n "$WEB_HOST" ] && BIND_ARGS="--host $WEB_HOST $BIND_ARGS"
|
|
134
192
|
cat > /etc/systemd/system/kinstra-neko.service <<SVCEOF
|
|
135
193
|
[Unit]
|
|
136
194
|
Description=Kinstra Neko — DSH web with QQ catgirl
|
|
@@ -143,7 +201,7 @@ User=$RUN_USER
|
|
|
143
201
|
Environment=NODE_ENV=production
|
|
144
202
|
# 2H2G 内存上限:给 NapCat/系统留足,DSH 侧压缩到 ~700MB 老生代
|
|
145
203
|
Environment=NODE_OPTIONS=--max-old-space-size=700
|
|
146
|
-
ExecStart=$DSH_BIN --profile kinstra-neko
|
|
204
|
+
ExecStart=$DSH_BIN --profile kinstra-neko $BIND_ARGS
|
|
147
205
|
Restart=on-failure
|
|
148
206
|
RestartSec=5
|
|
149
207
|
WorkingDirectory=$RUN_HOME
|
|
@@ -157,20 +215,41 @@ systemctl enable kinstra-neko >/dev/null 2>&1
|
|
|
157
215
|
systemctl restart kinstra-neko
|
|
158
216
|
ok '服务已启动并设为开机自启'
|
|
159
217
|
|
|
160
|
-
|
|
161
|
-
|
|
218
|
+
# web 首次挂载插件要十几秒,等到 active 且端口起来(最多 ~40s)
|
|
219
|
+
BIND_IP="${WEB_HOST:-127.0.0.1}"
|
|
220
|
+
for _ in $(seq 1 20); do
|
|
221
|
+
systemctl is-active --quiet kinstra-neko || { warn '服务没起来:journalctl -u kinstra-neko -n 50 看日志'; break; }
|
|
222
|
+
curl -s -o /dev/null --max-time 2 "http://$BIND_IP:$WEB_PORT/" && break
|
|
223
|
+
sleep 2
|
|
224
|
+
done
|
|
225
|
+
systemctl is-active --quiet kinstra-neko && ok "kinstra-neko 正在运行(监听 $BIND_IP:$WEB_PORT)"
|
|
226
|
+
|
|
227
|
+
# DSH web 默认带一次性 token 门,从日志取带 token 的直达 URL
|
|
228
|
+
TOKEN_URL="$(journalctl -u kinstra-neko --no-pager 2>/dev/null | grep -oE 'http://[^ ]*\?token=[^ ]+' | tail -1)"
|
|
229
|
+
if [ -n "$TOKEN_URL" ]; then
|
|
230
|
+
TOKEN_URL="${TOKEN_URL/127.0.0.1/$BIND_IP}"
|
|
231
|
+
TOKEN_URL="${TOKEN_URL/localhost/$BIND_IP}"
|
|
232
|
+
else
|
|
233
|
+
TOKEN_URL="http://$BIND_IP:$WEB_PORT/(按页面提示取 token:journalctl -u kinstra-neko -n 30)"
|
|
234
|
+
fi
|
|
162
235
|
|
|
163
236
|
echo
|
|
164
237
|
say '安装完成!'
|
|
165
238
|
cat <<TIPS
|
|
166
239
|
|
|
167
|
-
|
|
240
|
+
控制台(带免输 token 的直达地址):
|
|
241
|
+
$TOKEN_URL
|
|
242
|
+
(也可运行: journalctl -u kinstra-neko -n 30 | grep -o 'http://.*token=.*' | tail -1)
|
|
243
|
+
云服务器:确认安全组/防火墙放行 $WEB_PORT/tcp;只想本机访问用 WEB_HOST=127.0.0.1 重装。
|
|
168
244
|
服务管理: sudo systemctl {status|restart|stop} kinstra-neko
|
|
169
245
|
实时日志: journalctl -u kinstra-neko -f
|
|
170
246
|
|
|
171
247
|
上线步骤:
|
|
172
248
|
1. 控制台按猫娘向导填「猫娘小号 QQ」和「你的 QQ」
|
|
173
|
-
2. 扫码登录 NapCat
|
|
249
|
+
2. 扫码登录 NapCat 里的小号(headless 服务器走 SSH 隧道,勿对公网开放 6099):
|
|
250
|
+
本机执行 ssh -L 6099:127.0.0.1:6099 $RUN_USER@<服务器 IP>
|
|
251
|
+
浏览器开 http://127.0.0.1:6099 ,token 见服务器上
|
|
252
|
+
$NAPCAT_DIR/config/webui.json 的 "token" 字段
|
|
174
253
|
3. 在 DSH 设置里配置模型服务商与 API Key
|
|
175
254
|
4. 把要养她的群加进白名单
|
|
176
255
|
5. 出厂是试运行:先在「试运行」页确认她会说什么,再关试运行开麦
|
|
@@ -49,22 +49,28 @@ try { dsh --version | Out-Null; Ok "DSH $(dsh --version)" } catch {
|
|
|
49
49
|
npm install -g "@deepseek-ai/dsh@$DshVersion" --no-audit --no-fund
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
#
|
|
52
|
+
# 2.5 pnpm:DSH 插件管理器用 pnpm;本生态全是 alpha 预发布版本,npm 严格 peer 会 ERESOLVE,pnpm 只告警。
|
|
53
|
+
try { pnpm --version | Out-Null; Ok "pnpm $(pnpm --version)" } catch {
|
|
54
|
+
Say '全局安装 pnpm(DSH 插件管理器依赖)…'
|
|
55
|
+
npm install -g pnpm --no-audit --no-fund
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# 3. 插件初始化(用 pnpm dlx,不用 npx:避开 npm 对 alpha peer 的 ERESOLVE)
|
|
53
59
|
Say '初始化 Kinstra Neko …'
|
|
54
60
|
$initArgs = @('init')
|
|
55
61
|
if ($env:KINSTRA_NEKO_SPEC) { $initArgs = @('init', '--link', $env:KINSTRA_NEKO_SPEC) }
|
|
56
62
|
$env:DSH_VERSION = $DshVersion
|
|
57
|
-
|
|
63
|
+
pnpm dlx kinstra-neko@latest @initArgs
|
|
58
64
|
if ($LASTEXITCODE -ne 0) { Die '插件初始化失败,检查网络后重试(开发版设 KINSTRA_NEKO_SPEC=本地目录)。' }
|
|
59
65
|
Ok '猫娘插件已装入 profile'
|
|
60
66
|
|
|
61
|
-
# 调用本包 CLI(
|
|
67
|
+
# 调用本包 CLI(pnpm 源或本地 --link 源),用于把探测到的 NapCat 目录种入插件配置。
|
|
62
68
|
function Invoke-KinstraCli([string[]]$CliArgs) {
|
|
63
69
|
if ($env:KINSTRA_NEKO_SPEC) {
|
|
64
70
|
$scriptPath = Join-Path $env:KINSTRA_NEKO_SPEC 'installer\bin\kinstra-neko-init.mjs'
|
|
65
71
|
node $scriptPath @CliArgs
|
|
66
72
|
} else {
|
|
67
|
-
|
|
73
|
+
pnpm dlx kinstra-neko@latest @CliArgs
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -177,8 +183,8 @@ $startBat = Join-Path $appData 'start-kinstra.bat'
|
|
|
177
183
|
REM Kinstra Neko 启动脚本(安装器生成)
|
|
178
184
|
title Kinstra Neko
|
|
179
185
|
echo Starting Kinstra Neko on http://127.0.0.1:$WebPort ...
|
|
180
|
-
|
|
181
|
-
dsh --profile $ProfileName
|
|
186
|
+
echo 浏览器会自动打开带一次性 token 的控制台;若没弹出,复制本窗口日志里 http://...?token=... 的链接。
|
|
187
|
+
dsh --profile $ProfileName --port $WebPort
|
|
182
188
|
pause
|
|
183
189
|
"@ | Set-Content -Encoding UTF8 $startBat
|
|
184
190
|
Ok "启动脚本:$startBat(已在桌面放快捷方式)"
|
package/lib/index.js
CHANGED
|
@@ -727,7 +727,7 @@ function createNapCatManager(opts) {
|
|
|
727
727
|
child = spawn(script, [], {
|
|
728
728
|
cwd: installDir(),
|
|
729
729
|
windowsHide: process.platform !== "win32",
|
|
730
|
-
detached:
|
|
730
|
+
detached: process.platform !== "win32",
|
|
731
731
|
stdio: [
|
|
732
732
|
"ignore",
|
|
733
733
|
"pipe",
|
|
@@ -756,8 +756,11 @@ function createNapCatManager(opts) {
|
|
|
756
756
|
message: "已启动"
|
|
757
757
|
};
|
|
758
758
|
}
|
|
759
|
-
/** 结束 NapCat 进程。
|
|
760
|
-
*
|
|
759
|
+
/** 结束 NapCat 进程。
|
|
760
|
+
* Windows 下 spawn(.bat, shell:true) 的 pid 是 cmd.exe,只 kill 它会孤儿化
|
|
761
|
+
* NapCat/QQ,必须 taskkill /T 连整棵进程树一起结束。
|
|
762
|
+
* POSIX 下 start() 用 detached:true 建了新进程组,对负 pid 发 SIGTERM 即可连同
|
|
763
|
+
* xvfb-run → Xvfb + QQ(+zygote) 整组结束;进程组已不在(ESRCH)时兜底 kill 直接子。 */
|
|
761
764
|
function killTree(me) {
|
|
762
765
|
if (process.platform === "win32") try {
|
|
763
766
|
execFileSync("taskkill", [
|
|
@@ -768,6 +771,10 @@ function createNapCatManager(opts) {
|
|
|
768
771
|
], { stdio: "ignore" });
|
|
769
772
|
return;
|
|
770
773
|
} catch {}
|
|
774
|
+
if (typeof me.pid === "number") try {
|
|
775
|
+
process.kill(-me.pid, "SIGTERM");
|
|
776
|
+
return;
|
|
777
|
+
} catch {}
|
|
771
778
|
try {
|
|
772
779
|
me.kill();
|
|
773
780
|
} catch {}
|