wezard 0.3.3 → 1.1.0
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +3 -3
- package/CLAUDE.md +14 -14
- package/LICENSE +1 -1
- package/README.md +38 -38
- package/cli/{weclaude.sh → wezard.sh} +40 -35
- package/commands/audit.md +2 -2
- package/commands/wrc.md +2 -2
- package/config.example.jsonc +24 -11
- package/dist/cli/audit.js +2 -2
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/init.js +97 -24
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/migrate.js +213 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/sync.js +34 -26
- package/dist/cli/sync.js.map +1 -1
- package/dist/daemon/approval.js +45 -21
- package/dist/daemon/approval.js.map +1 -1
- package/dist/daemon/audit.js +1 -1
- package/dist/daemon/audit.js.map +1 -1
- package/dist/daemon/cc-bridge.js +1 -1
- package/dist/daemon/cc-bridge.js.map +1 -1
- package/dist/daemon/cfg-sync.js +4 -4
- package/dist/daemon/cfg-sync.js.map +1 -1
- package/dist/daemon/claim.js +2 -2
- package/dist/daemon/claim.js.map +1 -1
- package/dist/daemon/danger.js +102 -0
- package/dist/daemon/danger.js.map +1 -0
- package/dist/daemon/inbound.js +42 -40
- package/dist/daemon/inbound.js.map +1 -1
- package/dist/daemon/index.js +7 -7
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/mirror-bridge.js +40 -15
- package/dist/daemon/mirror-bridge.js.map +1 -1
- package/dist/daemon/pending.js +4 -0
- package/dist/daemon/pending.js.map +1 -1
- package/dist/daemon/quota.js +1 -1
- package/dist/daemon/quota.js.map +1 -1
- package/dist/daemon/session-scan.js +88 -26
- package/dist/daemon/session-scan.js.map +1 -1
- package/dist/daemon/spawn-tmux.js +5 -5
- package/dist/daemon/spawn-tmux.js.map +1 -1
- package/dist/daemon/usage.js +1 -1
- package/dist/daemon/usage.js.map +1 -1
- package/dist/daemon/wedoc.js +2 -2
- package/dist/daemon/wedoc.js.map +1 -1
- package/dist/mcp/server.js +4 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/shared/config-writer.js +1 -1
- package/dist/shared/config-writer.js.map +1 -1
- package/dist/shared/config.js +32 -19
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/detail-render.js +21 -1
- package/dist/shared/detail-render.js.map +1 -1
- package/dist/shared/detail-store.js +6 -0
- package/dist/shared/detail-store.js.map +1 -1
- package/dist/shared/svr-token.js +22 -0
- package/dist/shared/svr-token.js.map +1 -0
- package/dist/svr/index.js +16 -31
- package/dist/svr/index.js.map +1 -1
- package/hooks/pre-tool-use.sh +24 -24
- package/launchd/{com.weclaude.daemon.plist.template → com.wezard.daemon.plist.template} +3 -3
- package/package.json +17 -14
- package/scripts/install.sh +15 -8
- package/scripts/postinstall.sh +2 -2
- package/scripts/uninstall.sh +35 -27
- package/systemd/{weclaude.service.template → wezard.service.template} +3 -3
- package/web/chat.css +19 -5
package/dist/svr/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
2
|
+
// wezard svr — 独立的 detail 中转服务。部署到 chat + cli 都可达的网络机器上,
|
|
3
3
|
// cli/daemon 端把 tool/approval 详情 POST 过来, chat 用户点卡片链接直连本机浏览。
|
|
4
4
|
//
|
|
5
5
|
// 只有两条业务路由:
|
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
// 存储直接复用 daemon 的 createDetailStore (append-only JSONL + LRU + 24h TTL)。
|
|
11
11
|
// 信任模型: token 相同 = 可写; 读端不签名 (拿到 id 即可读)。id 是 uuid, 不可枚举。
|
|
12
12
|
import { createServer } from "node:http";
|
|
13
|
-
import {
|
|
14
|
-
import { randomBytes } from "node:crypto";
|
|
15
|
-
import { dirname } from "node:path";
|
|
13
|
+
import { mkdirSync } from "node:fs";
|
|
16
14
|
import pino from "pino";
|
|
17
15
|
import { expandHome } from "../shared/paths.js";
|
|
16
|
+
import { loadOrCreateSvrToken } from "../shared/svr-token.js";
|
|
18
17
|
import { createDetailStore } from "../shared/detail-store.js";
|
|
19
18
|
import { renderDetailPage, renderNotFound } from "../shared/detail-render.js";
|
|
20
19
|
import { createChatRoutes, chatRouteTable } from "../shared/chat-http.js";
|
|
@@ -26,8 +25,8 @@ const buildDefaults = () => {
|
|
|
26
25
|
const fallback = {
|
|
27
26
|
host: "0.0.0.0",
|
|
28
27
|
port: 17891,
|
|
29
|
-
stateDir: "~/.
|
|
30
|
-
tokenFile: "~/.
|
|
28
|
+
stateDir: "~/.wezard/svr",
|
|
29
|
+
tokenFile: "~/.wezard/svr-token",
|
|
31
30
|
logLevel: "info",
|
|
32
31
|
};
|
|
33
32
|
try {
|
|
@@ -86,32 +85,18 @@ const parseArgs = (argv) => {
|
|
|
86
85
|
};
|
|
87
86
|
const printHelp = () => {
|
|
88
87
|
// eslint-disable-next-line no-console
|
|
89
|
-
console.log(`
|
|
88
|
+
console.log(`wezard svr — standalone detail relay
|
|
90
89
|
|
|
91
|
-
Defaults come from ~/.
|
|
90
|
+
Defaults come from ~/.wezard/config.jsonc (svr.*) when present; CLI overrides.
|
|
92
91
|
|
|
93
92
|
--host <ip> bind address (default 0.0.0.0)
|
|
94
93
|
--port <n> listen port (default 17891)
|
|
95
|
-
--state <dir> state dir (default ~/.
|
|
94
|
+
--state <dir> state dir (default ~/.wezard/svr)
|
|
96
95
|
--token <t> bearer token (default: generate + persist to --token-file)
|
|
97
|
-
--token-file <p> token persist path (default ~/.
|
|
96
|
+
--token-file <p> token persist path (default ~/.wezard/svr-token)
|
|
98
97
|
--log-level <lvl> pino level (default info)
|
|
99
98
|
`);
|
|
100
99
|
};
|
|
101
|
-
const loadOrCreateToken = (explicit, tokenFile) => {
|
|
102
|
-
if (explicit && explicit.length > 0)
|
|
103
|
-
return explicit;
|
|
104
|
-
const abs = expandHome(tokenFile);
|
|
105
|
-
if (existsSync(abs)) {
|
|
106
|
-
const t = readFileSync(abs, "utf8").trim();
|
|
107
|
-
if (t.length > 0)
|
|
108
|
-
return t;
|
|
109
|
-
}
|
|
110
|
-
const t = randomBytes(24).toString("hex");
|
|
111
|
-
mkdirSync(dirname(abs), { recursive: true });
|
|
112
|
-
writeFileSync(abs, `${t}\n`, { mode: 0o600 });
|
|
113
|
-
return t;
|
|
114
|
-
};
|
|
115
100
|
const readBody = async (req) => {
|
|
116
101
|
const chunks = [];
|
|
117
102
|
for await (const c of req)
|
|
@@ -137,10 +122,10 @@ const isDetailRecord = (v) => {
|
|
|
137
122
|
};
|
|
138
123
|
const main = async () => {
|
|
139
124
|
const args = parseArgs(process.argv.slice(2));
|
|
140
|
-
const log = pino({ level: args.logLevel, name: "
|
|
125
|
+
const log = pino({ level: args.logLevel, name: "wezard-svr" });
|
|
141
126
|
const stateDir = expandHome(args.stateDir);
|
|
142
127
|
mkdirSync(stateDir, { recursive: true });
|
|
143
|
-
const token =
|
|
128
|
+
const token = loadOrCreateSvrToken(args.tokenFile, args.token);
|
|
144
129
|
const store = createDetailStore({ stateDir, log });
|
|
145
130
|
// Chat 视图 (SPA + JSON API + SSE) 与 daemon 完全同源 —— svr 侧的记录是 POST /d
|
|
146
131
|
// 推过来的, store.subscribe 一样会触发, 所以远端浏览也是实时的。
|
|
@@ -217,13 +202,13 @@ const main = async () => {
|
|
|
217
202
|
const displayHost = resolvePublicHost(args.host);
|
|
218
203
|
const base = `http://${displayHost}:${args.port}`;
|
|
219
204
|
// eslint-disable-next-line no-console
|
|
220
|
-
console.log(`[
|
|
205
|
+
console.log(`[wezard-svr] listening on ${args.host}:${args.port}`);
|
|
221
206
|
// eslint-disable-next-line no-console
|
|
222
|
-
console.log(`[
|
|
207
|
+
console.log(`[wezard-svr] base URL: ${base}`);
|
|
223
208
|
// eslint-disable-next-line no-console
|
|
224
|
-
console.log(`[
|
|
209
|
+
console.log(`[wezard-svr] token: ${token}`);
|
|
225
210
|
// eslint-disable-next-line no-console
|
|
226
|
-
console.log(`\nAdd to ~/.
|
|
211
|
+
console.log(`\nAdd to ~/.wezard/config.jsonc on every daemon host:
|
|
227
212
|
"daemon": {
|
|
228
213
|
"detailRemoteBase": "${base}",
|
|
229
214
|
"detailRemoteToken": "${token}"
|
|
@@ -240,7 +225,7 @@ const main = async () => {
|
|
|
240
225
|
};
|
|
241
226
|
main().catch((e) => {
|
|
242
227
|
// eslint-disable-next-line no-console
|
|
243
|
-
console.error("[
|
|
228
|
+
console.error("[wezard-svr] fatal:", e);
|
|
244
229
|
process.exit(1);
|
|
245
230
|
});
|
|
246
231
|
//# sourceMappingURL=index.js.map
|
package/dist/svr/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../svr/index.ts"],"names":[],"mappings":";AACA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../svr/index.ts"],"names":[],"mappings":"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"}
|
package/hooks/pre-tool-use.sh
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# wezard PreToolUse hook: forward to local daemon → long-poll → emit decision.
|
|
3
3
|
# Any failure → ask (never break workflow).
|
|
4
4
|
set -uo pipefail
|
|
5
5
|
|
|
6
|
-
DAEMON_URL="${
|
|
6
|
+
DAEMON_URL="${WEZARD_DAEMON_URL:-http://127.0.0.1:17890/approve}"
|
|
7
7
|
# 必须严格大于 daemon 的 approval.longPollSec (默认 43200) 且小于 hooks.json
|
|
8
8
|
# 的 timeout, 否则卡在 WeCom 里挂 >30min 后 curl 先死, 用户的点击写进死 socket。
|
|
9
|
-
HOOK_TIMEOUT="${
|
|
10
|
-
STATE_DIR="${
|
|
9
|
+
HOOK_TIMEOUT="${WEZARD_HOOK_TIMEOUT:-43210}"
|
|
10
|
+
STATE_DIR="${WEZARD_STATE_DIR:-$HOME/.wezard/state}"
|
|
11
11
|
# Fallback policy when the daemon is unreachable / replies garbage. ask|allow|deny.
|
|
12
12
|
# Default keeps the safe behavior; set to `allow` in trusted local-only setups.
|
|
13
|
-
FALLBACK="${
|
|
13
|
+
FALLBACK="${WEZARD_HOOK_FALLBACK:-ask}"
|
|
14
14
|
|
|
15
15
|
emit() {
|
|
16
16
|
local decision="$1" reason="${2:-}"
|
|
@@ -18,12 +18,12 @@ emit() {
|
|
|
18
18
|
# printf 直接拼会漏出内层 " 把 JSON 撕烂, Claude Code 解析失败 fallback
|
|
19
19
|
# 弹原生 picker → askq 失效。
|
|
20
20
|
if command -v jq >/dev/null 2>&1; then
|
|
21
|
-
jq -cn --arg d "$decision" --arg r "
|
|
21
|
+
jq -cn --arg d "$decision" --arg r "wezard: $reason" \
|
|
22
22
|
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$d,permissionDecisionReason:$r}}'
|
|
23
23
|
else
|
|
24
24
|
# jq 缺失兜底: 手动转义 \ 和 " (足够覆盖 reason 里的字面引号)。
|
|
25
25
|
local esc="${reason//\\/\\\\}"; esc="${esc//\"/\\\"}"
|
|
26
|
-
printf '%s\n' "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"${decision}\",\"permissionDecisionReason\":\"
|
|
26
|
+
printf '%s\n' "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"${decision}\",\"permissionDecisionReason\":\"wezard: ${esc}\"}}"
|
|
27
27
|
fi
|
|
28
28
|
exit 0
|
|
29
29
|
}
|
|
@@ -61,17 +61,17 @@ TRANSCRIPT_PATH=$(printf '%s' "$PAYLOAD" | jq -r '.transcript_path // ""')
|
|
|
61
61
|
PERMISSION_MODE=$(printf '%s' "$PAYLOAD" | jq -r '.permission_mode // ""')
|
|
62
62
|
|
|
63
63
|
# 权限模式短路: 只对用户主动选的"完全跳过"模式放掉, 其它一律走 daemon 发 IM
|
|
64
|
-
# 卡, 让
|
|
64
|
+
# 卡, 让 wezard 远端用户能在 IM 上点决策。
|
|
65
65
|
# - bypassPermissions: 用户已经主动选了"全跳", emit allow 直接放, 不打 daemon。
|
|
66
66
|
# - auto: 不在此短路。第一次发卡用户点 10min 后, daemon 的 isAutoWindowActive
|
|
67
67
|
# 会接管, 后续 tool 自动放行不再发卡, 既不丢 IM 控制权也不会变成"卡刷屏"。
|
|
68
68
|
# 若 emit "ask" 让 Claude 自己处理, 不安全 tool 会弹本地 CLI picker, 远端用户
|
|
69
69
|
# 完全看不见也答不了 — 那是 v0.1.35 的回退原因。
|
|
70
|
-
# - dontAsk: Claude 默认拒, 但
|
|
70
|
+
# - dontAsk: Claude 默认拒, 但 wezard 用户可能希望从 IM 端覆盖, 不在此短路。
|
|
71
71
|
# acceptEdits / default / plan 不在此列, 维持 daemon 流程。AskUserQuestion 始终
|
|
72
72
|
# 走卡 (远端用户的主动决策), 故任何 mode 都不在此短路。
|
|
73
|
-
#
|
|
74
|
-
if [[ "$TOOL_NAME" != "AskUserQuestion" ]] && [[ "${
|
|
73
|
+
# WEZARD_HONOR_AUTO_MODE=0 关掉本段对齐行为。
|
|
74
|
+
if [[ "$TOOL_NAME" != "AskUserQuestion" ]] && [[ "${WEZARD_HONOR_AUTO_MODE:-1}" != "0" ]]; then
|
|
75
75
|
case "$PERMISSION_MODE" in
|
|
76
76
|
bypassPermissions)
|
|
77
77
|
emit "allow" "bypass-mode passthrough" ;;
|
|
@@ -84,22 +84,22 @@ if [[ "$TOOL_NAME" == "ExitPlanMode" ]]; then
|
|
|
84
84
|
emit "allow" "ExitPlanMode passthrough"
|
|
85
85
|
fi
|
|
86
86
|
|
|
87
|
-
#
|
|
87
|
+
# wezard 自家 MCP 工具全部走 loopback 到本 daemon, 自审会把 /wrc 首次绑定卡死
|
|
88
88
|
# (还没 defaultChat, 卡片无处可推 → 鸡生蛋), 直接放行。
|
|
89
89
|
# 命名两条路径:
|
|
90
|
-
# 1. cli/sync.ts (legacy claude-internal):
|
|
91
|
-
# 2. .claude-plugin/plugin.json:
|
|
92
|
-
# 用 *
|
|
93
|
-
if [[ "$TOOL_NAME" == mcp__*
|
|
94
|
-
emit "allow" "
|
|
90
|
+
# 1. cli/sync.ts (legacy claude-internal): mcp__wezard__<tool>
|
|
91
|
+
# 2. .claude-plugin/plugin.json: mcp__plugin_wezard_wezard__<tool>
|
|
92
|
+
# 用 *wezard__* 同时覆盖两种前缀。
|
|
93
|
+
if [[ "$TOOL_NAME" == mcp__*wezard__* ]]; then
|
|
94
|
+
emit "allow" "wezard mcp self-call bypass"
|
|
95
95
|
fi
|
|
96
96
|
|
|
97
|
-
#
|
|
98
|
-
# tool_input.skill 形如 "
|
|
97
|
+
# wezard 自家 Skill (slash commands like /wrc) 也是本地插件代码, 无须审批。
|
|
98
|
+
# tool_input.skill 形如 "wezard:wrc"; plugin 命名空间用冒号分隔。
|
|
99
99
|
if [[ "$TOOL_NAME" == "Skill" ]]; then
|
|
100
100
|
SKILL_NAME=$(printf '%s' "$TOOL_INPUT" | jq -r '.skill // ""')
|
|
101
|
-
if [[ "$SKILL_NAME" ==
|
|
102
|
-
emit "allow" "
|
|
101
|
+
if [[ "$SKILL_NAME" == wezard:* ]]; then
|
|
102
|
+
emit "allow" "wezard skill self-call bypass"
|
|
103
103
|
fi
|
|
104
104
|
fi
|
|
105
105
|
|
|
@@ -110,10 +110,10 @@ if [[ "$TOOL_NAME" == "Bash" ]]; then
|
|
|
110
110
|
&& [[ ! "$CMD" =~ [\;\|\&\>\<\`\$\(] ]]; then
|
|
111
111
|
emit "allow" "read-only bypass"
|
|
112
112
|
fi
|
|
113
|
-
#
|
|
113
|
+
# wezard CLI 同理: /wrc /cd 这些 slash command 的 ! bash 都打到本 daemon,
|
|
114
114
|
# 自己审自己没意义, 也避免首次绑定时无处推卡。
|
|
115
|
-
if [[ "$CMD" =~ (^|/|[[:space:]])
|
|
116
|
-
emit "allow" "
|
|
115
|
+
if [[ "$CMD" =~ (^|/|[[:space:]])wezard(\.sh)?([[:space:]]|$) ]]; then
|
|
116
|
+
emit "allow" "wezard self-call bypass"
|
|
117
117
|
fi
|
|
118
118
|
fi
|
|
119
119
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<plist version="1.0">
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Label</key>
|
|
8
|
-
<string>com.
|
|
8
|
+
<string>com.wezard.daemon</string>
|
|
9
9
|
|
|
10
10
|
<key>ProgramArguments</key>
|
|
11
11
|
<array>
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
<integer>10</integer>
|
|
39
39
|
|
|
40
40
|
<key>StandardOutPath</key>
|
|
41
|
-
<string>__HOME__/.
|
|
41
|
+
<string>__HOME__/.wezard/daemon.stdout.log</string>
|
|
42
42
|
<key>StandardErrorPath</key>
|
|
43
|
-
<string>__HOME__/.
|
|
43
|
+
<string>__HOME__/.wezard/daemon.stderr.log</string>
|
|
44
44
|
</dict>
|
|
45
45
|
</plist>
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wezard",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Bridge Claude Code and WeCom: PreToolUse approval cards + bidirectional tmux session mirror with image paste",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/guxi11/
|
|
9
|
+
"url": "git+https://github.com/guxi11/wezard.git"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/guxi11/
|
|
11
|
+
"homepage": "https://github.com/guxi11/wezard#readme",
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/guxi11/
|
|
13
|
+
"url": "https://github.com/guxi11/wezard/issues"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
16
|
"claude",
|
|
@@ -22,18 +22,21 @@
|
|
|
22
22
|
"mcp"
|
|
23
23
|
],
|
|
24
24
|
"bin": {
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
25
|
+
"wezard": "./cli/wezard.sh",
|
|
26
|
+
"wezard-daemon": "./dist/daemon/index.js",
|
|
27
|
+
"wezard-mcp": "./dist/mcp/server.js",
|
|
28
|
+
"wezard-init": "./dist/cli/init.js",
|
|
29
|
+
"wezard-migrate": "./dist/cli/migrate.js",
|
|
30
|
+
"wezard-svr": "./dist/svr/index.js"
|
|
30
31
|
},
|
|
31
32
|
"files": [
|
|
32
33
|
".claude-plugin/marketplace.json",
|
|
33
34
|
".claude-plugin/plugin.json",
|
|
34
|
-
"cli/
|
|
35
|
+
"cli/wezard.sh",
|
|
35
36
|
"dist/cli/init.js",
|
|
36
37
|
"dist/cli/init.js.map",
|
|
38
|
+
"dist/cli/migrate.js",
|
|
39
|
+
"dist/cli/migrate.js.map",
|
|
37
40
|
"dist/cli/sync.js",
|
|
38
41
|
"dist/cli/sync.js.map",
|
|
39
42
|
"dist/cli/audit.js",
|
|
@@ -53,8 +56,8 @@
|
|
|
53
56
|
"scripts/install.sh",
|
|
54
57
|
"scripts/uninstall.sh",
|
|
55
58
|
"scripts/postinstall.sh",
|
|
56
|
-
"launchd/com.
|
|
57
|
-
"systemd/
|
|
59
|
+
"launchd/com.wezard.daemon.plist.template",
|
|
60
|
+
"systemd/wezard.service.template",
|
|
58
61
|
"config.example.jsonc",
|
|
59
62
|
"commands/wrc.md",
|
|
60
63
|
"commands/audit.md",
|
|
@@ -63,9 +66,9 @@
|
|
|
63
66
|
"LICENSE"
|
|
64
67
|
],
|
|
65
68
|
"scripts": {
|
|
66
|
-
"build": "tsc -p tsconfig.json && chmod +x dist/cli/init.js dist/cli/audit.js dist/daemon/index.js dist/mcp/server.js dist/svr/index.js",
|
|
69
|
+
"build": "tsc -p tsconfig.json && chmod +x dist/cli/init.js dist/cli/migrate.js dist/cli/audit.js dist/daemon/index.js dist/mcp/server.js dist/svr/index.js",
|
|
67
70
|
"dev:daemon": "tsx daemon/index.ts",
|
|
68
|
-
"dev:cli": "tsx cli/
|
|
71
|
+
"dev:cli": "tsx cli/init.ts",
|
|
69
72
|
"typecheck": "tsc --noEmit",
|
|
70
73
|
"prepare": "test -f dist/daemon/index.js || npm run build",
|
|
71
74
|
"prepublishOnly": "rm -rf dist && npm run build",
|
package/scripts/install.sh
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Install resident
|
|
2
|
+
# Install a resident wezard service. Auto-detects macOS (launchd) vs Linux (systemd --user).
|
|
3
|
+
# install.sh [daemon|svr] (default: daemon)
|
|
3
4
|
set -euo pipefail
|
|
4
5
|
|
|
5
6
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
6
7
|
NODE="$(command -v node)"
|
|
7
8
|
HOME_DIR="$HOME"
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
COMPONENT="${1:-daemon}"
|
|
11
|
+
case "$COMPONENT" in
|
|
12
|
+
daemon) LABEL="com.wezard.daemon"; UNIT="wezard.service"; ENTRY="dist/daemon/index.js" ;;
|
|
13
|
+
svr) LABEL="com.wezard.svr"; UNIT="wezard-svr.service"; ENTRY="dist/svr/index.js" ;;
|
|
14
|
+
*) echo "usage: install.sh [daemon|svr]"; exit 2 ;;
|
|
15
|
+
esac
|
|
9
16
|
|
|
10
17
|
[[ -x "$NODE" ]] || { echo "node not found in PATH"; exit 1; }
|
|
11
18
|
|
|
12
19
|
# Build if missing
|
|
13
|
-
if [[ ! -f "$REPO
|
|
20
|
+
if [[ ! -f "$REPO/$ENTRY" ]]; then
|
|
14
21
|
echo "[install] building..."
|
|
15
22
|
(cd "$REPO" && npm install --silent && npx tsc -p tsconfig.json)
|
|
16
23
|
fi
|
|
17
24
|
|
|
18
|
-
mkdir -p "$HOME_DIR/.
|
|
25
|
+
mkdir -p "$HOME_DIR/.wezard"
|
|
19
26
|
|
|
20
27
|
OS="$(uname -s)"
|
|
21
28
|
case "$OS" in
|
|
@@ -56,18 +63,18 @@ case "$OS" in
|
|
|
56
63
|
Linux)
|
|
57
64
|
UNIT_DIR="$HOME_DIR/.config/systemd/user"
|
|
58
65
|
mkdir -p "$UNIT_DIR"
|
|
59
|
-
UNIT_DST="$UNIT_DIR
|
|
66
|
+
UNIT_DST="$UNIT_DIR/$UNIT"
|
|
60
67
|
sed \
|
|
61
68
|
-e "s|__NODE__|$NODE|g" \
|
|
62
69
|
-e "s|__REPO__|$REPO|g" \
|
|
63
70
|
-e "s|__HOME__|$HOME_DIR|g" \
|
|
64
|
-
"$REPO/systemd
|
|
71
|
+
"$REPO/systemd/${UNIT}.template" > "$UNIT_DST"
|
|
65
72
|
systemctl --user daemon-reload
|
|
66
|
-
systemctl --user enable --now
|
|
73
|
+
systemctl --user enable --now "$UNIT"
|
|
67
74
|
echo "[install] systemd unit enabled: $UNIT_DST"
|
|
68
75
|
;;
|
|
69
76
|
*)
|
|
70
77
|
echo "unsupported OS: $OS"; exit 1 ;;
|
|
71
78
|
esac
|
|
72
79
|
|
|
73
|
-
echo "[install] done. Logs at $HOME_DIR/.
|
|
80
|
+
echo "[install] $COMPONENT done. Logs at $HOME_DIR/.wezard/"
|
package/scripts/postinstall.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# Refresh the Claude Code plugin clone after `npm install -g` so the
|
|
3
|
-
# marketplace copy at ~/.claude/plugins/marketplaces/
|
|
3
|
+
# marketplace copy at ~/.claude/plugins/marketplaces/wezard-local/ stays
|
|
4
4
|
# in lockstep with the npm global install. Silent no-op in any irrelevant
|
|
5
5
|
# context (local dev install, claude not on PATH, marketplace never added).
|
|
6
6
|
# Must never fail npm install.
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
[ "$npm_config_global" = "true" ] || exit 0
|
|
9
9
|
command -v claude >/dev/null 2>&1 || exit 0
|
|
10
10
|
|
|
11
|
-
claude plugin marketplace update
|
|
11
|
+
claude plugin marketplace update wezard-local >/dev/null 2>&1 || true
|
|
12
12
|
exit 0
|
package/scripts/uninstall.sh
CHANGED
|
@@ -1,44 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -uo pipefail
|
|
3
|
-
LABEL="com.weclaude.daemon"
|
|
4
3
|
HOME_DIR="$HOME"
|
|
5
4
|
OS="$(uname -s)"
|
|
6
5
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
7
6
|
|
|
7
|
+
# label | systemd unit | entry script (for the pkill sweep)
|
|
8
|
+
SERVICES=(
|
|
9
|
+
"com.wezard.daemon|wezard.service|dist/daemon/index.js"
|
|
10
|
+
"com.wezard.svr|wezard-svr.service|dist/svr/index.js"
|
|
11
|
+
)
|
|
12
|
+
|
|
8
13
|
# Best-effort: drop the Claude Code plugin + marketplace registration installed
|
|
9
|
-
# by `
|
|
14
|
+
# by `wezard init`. Tries both `claude` and `claude-internal` since either
|
|
10
15
|
# could have been used at install time. All failures are non-fatal — uninstall
|
|
11
16
|
# must keep going even if claude binaries are gone.
|
|
12
17
|
for bin in claude claude-internal; do
|
|
13
18
|
command -v "$bin" >/dev/null 2>&1 || continue
|
|
14
|
-
"$bin" plugin uninstall
|
|
19
|
+
"$bin" plugin uninstall wezard@wezard-local 2>/dev/null && \
|
|
15
20
|
echo "[uninstall] $bin: plugin uninstalled" || true
|
|
16
21
|
"$bin" plugin marketplace remove "$REPO" 2>/dev/null && \
|
|
17
22
|
echo "[uninstall] $bin: marketplace removed" || true
|
|
18
23
|
done
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
for svc in "${SERVICES[@]}"; do
|
|
26
|
+
IFS='|' read -r LABEL UNIT ENTRY <<< "$svc"
|
|
27
|
+
case "$OS" in
|
|
28
|
+
Darwin)
|
|
29
|
+
PLIST="$HOME_DIR/Library/LaunchAgents/${LABEL}.plist"
|
|
30
|
+
if [[ -f "$PLIST" ]]; then
|
|
31
|
+
launchctl unload "$PLIST" 2>/dev/null || true
|
|
32
|
+
rm -f "$PLIST"
|
|
33
|
+
echo "[uninstall] removed $PLIST"
|
|
34
|
+
fi
|
|
35
|
+
# Belt-and-braces: launchctl unload can leave a stray process if the plist
|
|
36
|
+
# was edited mid-flight. bootout the label, then SIGTERM any survivors.
|
|
37
|
+
launchctl bootout "gui/$(id -u)/${LABEL}" 2>/dev/null || true
|
|
38
|
+
pkill -f "$ENTRY" 2>/dev/null || true
|
|
39
|
+
;;
|
|
40
|
+
Linux)
|
|
41
|
+
UNIT_PATH="$HOME_DIR/.config/systemd/user/$UNIT"
|
|
42
|
+
if [[ -f "$UNIT_PATH" ]]; then
|
|
43
|
+
systemctl --user disable --now "$UNIT" 2>/dev/null || true
|
|
44
|
+
rm -f "$UNIT_PATH"
|
|
45
|
+
systemctl --user daemon-reload
|
|
46
|
+
echo "[uninstall] removed $UNIT_PATH"
|
|
47
|
+
fi
|
|
48
|
+
pkill -f "$ENTRY" 2>/dev/null || true
|
|
49
|
+
;;
|
|
50
|
+
esac
|
|
51
|
+
done
|
|
44
52
|
echo "[uninstall] done."
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[Unit]
|
|
2
|
-
Description=
|
|
2
|
+
Description=wezard daemon (WeCom remote control for Claude Code)
|
|
3
3
|
After=network-online.target
|
|
4
4
|
Wants=network-online.target
|
|
5
5
|
|
|
@@ -9,8 +9,8 @@ WorkingDirectory=__REPO__
|
|
|
9
9
|
ExecStart=__NODE__ __REPO__/dist/daemon/index.js
|
|
10
10
|
Restart=always
|
|
11
11
|
RestartSec=5
|
|
12
|
-
StandardOutput=append:__HOME__/.
|
|
13
|
-
StandardError=append:__HOME__/.
|
|
12
|
+
StandardOutput=append:__HOME__/.wezard/daemon.stdout.log
|
|
13
|
+
StandardError=append:__HOME__/.wezard/daemon.stderr.log
|
|
14
14
|
Environment=NODE_ENV=production
|
|
15
15
|
|
|
16
16
|
[Install]
|
package/web/chat.css
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
由 /chat/app.css 拼在本文件之前 —— 这里只管三栏骨架、会话列表与页脚总账。 */
|
|
3
3
|
|
|
4
4
|
html, body { height: 100% }
|
|
5
|
-
|
|
5
|
+
/* overscroll-behavior:none 阻止整页橡皮筋回弹 —— webview 里它会和内层
|
|
6
|
+
.thread 抢滚动手势, 表现为"滚一下卡住/整页在弹"。 */
|
|
7
|
+
body { overflow: hidden; overscroll-behavior: none }
|
|
6
8
|
|
|
7
9
|
.app { display: flex; height: 100vh; height: 100dvh }
|
|
8
10
|
|
|
@@ -77,7 +79,10 @@ body { overflow: hidden }
|
|
|
77
79
|
.tags .empty-side { padding: 28px 12px; text-align: center; color: #8c959f; font-size: 12px }
|
|
78
80
|
|
|
79
81
|
/* ── 主区 ───────────────────────────────────────────────────────── */
|
|
80
|
-
|
|
82
|
+
/* min-height:0 给纵向 flex (mobile) 用: 缺了它 .main 的 min-height:auto 会被
|
|
83
|
+
内容撑破 100dvh, .thread 不产生内部滚动, 底部被 body overflow:hidden 裁掉。
|
|
84
|
+
横向 (桌面) 下无副作用 —— 高度本来就由 stretch 定死。 */
|
|
85
|
+
.main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column }
|
|
81
86
|
.topbar {
|
|
82
87
|
flex: none; display: flex; align-items: center; gap: 10px; padding: 11px 20px;
|
|
83
88
|
background: #fff; border-bottom: 1px solid #d0d7de;
|
|
@@ -93,6 +98,7 @@ body { overflow: hidden }
|
|
|
93
98
|
.thread {
|
|
94
99
|
flex: 1; min-height: 0; overflow-y: auto; overflow-anchor: none;
|
|
95
100
|
padding: 16px 20px 24px; -webkit-overflow-scrolling: touch;
|
|
101
|
+
overscroll-behavior: contain;
|
|
96
102
|
}
|
|
97
103
|
.thread-in { max-width: 920px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px }
|
|
98
104
|
.empty { color: #8c959f; text-align: center; padding: 60px 0; font-size: 13px }
|
|
@@ -124,11 +130,19 @@ body { overflow: hidden }
|
|
|
124
130
|
.tg-link { margin-left: auto; color: #8c959f; text-decoration: none; font-size: 13px }
|
|
125
131
|
.tg-link:hover { color: #0969da }
|
|
126
132
|
.turn-group .bubbles { margin-top: 0 }
|
|
133
|
+
/* 上下文断点 (/clear、/new、会话轮换): 断点条来自 TURN_CSS, 这里再给整张卡片
|
|
134
|
+
多留一口气 + 描边, 让"这一轮读不到上一轮"在滚动中一眼可辨。 */
|
|
135
|
+
.turn-group.cut { margin-top: 12px }
|
|
136
|
+
.turn-group.cut-clear, .turn-group.cut-new {
|
|
137
|
+
border-color: #d4a72c66; box-shadow: 0 1px 2px #1f23280a, 0 0 0 3px #d4a72c14;
|
|
138
|
+
}
|
|
127
139
|
|
|
128
140
|
/* ── 页脚总账 ───────────────────────────────────────────────────── */
|
|
129
141
|
.statusbar {
|
|
130
142
|
flex: none; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
|
|
131
|
-
|
|
143
|
+
/* viewport-fit=cover 已开, 底部给 home indicator 让位 (桌面 env=0, 无感)。 */
|
|
144
|
+
padding: 7px 20px calc(7px + env(safe-area-inset-bottom));
|
|
145
|
+
background: #fff; border-top: 1px solid #d0d7de;
|
|
132
146
|
font-size: 11.5px; color: #57606a; font-family: ui-monospace, Menlo, monospace;
|
|
133
147
|
}
|
|
134
148
|
.statusbar .st { display: flex; align-items: baseline; gap: 5px }
|
|
@@ -161,11 +175,11 @@ body { overflow: hidden }
|
|
|
161
175
|
|
|
162
176
|
@media (max-width: 760px) {
|
|
163
177
|
.app { flex-direction: column }
|
|
164
|
-
.side { width: auto; border-right: 0; border-bottom: 1px solid #d0d7de; max-height: 44vh }
|
|
178
|
+
.side { width: auto; border-right: 0; border-bottom: 1px solid #d0d7de; max-height: 44vh; max-height: 44dvh }
|
|
165
179
|
.app.reading .side { display: none }
|
|
166
180
|
.app.reading .topbar .back { display: block }
|
|
167
181
|
.thread { padding: 12px }
|
|
168
182
|
.turn-group { padding: 12px }
|
|
169
|
-
.statusbar { gap: 10px; padding: 7px 12px }
|
|
183
|
+
.statusbar { gap: 10px; padding: 7px 12px calc(7px + env(safe-area-inset-bottom)) }
|
|
170
184
|
.sb-io, .statusbar .model { display: none }
|
|
171
185
|
}
|