wezard 0.3.3 → 1.0.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.
Files changed (65) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +3 -3
  3. package/CLAUDE.md +14 -14
  4. package/LICENSE +1 -1
  5. package/README.md +38 -38
  6. package/cli/{weclaude.sh → wezard.sh} +40 -35
  7. package/commands/audit.md +2 -2
  8. package/commands/wrc.md +2 -2
  9. package/config.example.jsonc +24 -11
  10. package/dist/cli/audit.js +2 -2
  11. package/dist/cli/audit.js.map +1 -1
  12. package/dist/cli/init.js +97 -24
  13. package/dist/cli/init.js.map +1 -1
  14. package/dist/cli/migrate.js +213 -0
  15. package/dist/cli/migrate.js.map +1 -0
  16. package/dist/cli/sync.js +34 -26
  17. package/dist/cli/sync.js.map +1 -1
  18. package/dist/daemon/approval.js +45 -21
  19. package/dist/daemon/approval.js.map +1 -1
  20. package/dist/daemon/audit.js +1 -1
  21. package/dist/daemon/audit.js.map +1 -1
  22. package/dist/daemon/cc-bridge.js +1 -1
  23. package/dist/daemon/cc-bridge.js.map +1 -1
  24. package/dist/daemon/cfg-sync.js +4 -4
  25. package/dist/daemon/cfg-sync.js.map +1 -1
  26. package/dist/daemon/claim.js +2 -2
  27. package/dist/daemon/claim.js.map +1 -1
  28. package/dist/daemon/danger.js +102 -0
  29. package/dist/daemon/danger.js.map +1 -0
  30. package/dist/daemon/inbound.js +42 -40
  31. package/dist/daemon/inbound.js.map +1 -1
  32. package/dist/daemon/index.js +7 -7
  33. package/dist/daemon/index.js.map +1 -1
  34. package/dist/daemon/mirror-bridge.js +18 -12
  35. package/dist/daemon/mirror-bridge.js.map +1 -1
  36. package/dist/daemon/pending.js +4 -0
  37. package/dist/daemon/pending.js.map +1 -1
  38. package/dist/daemon/quota.js +1 -1
  39. package/dist/daemon/quota.js.map +1 -1
  40. package/dist/daemon/session-scan.js +88 -26
  41. package/dist/daemon/session-scan.js.map +1 -1
  42. package/dist/daemon/spawn-tmux.js +5 -5
  43. package/dist/daemon/spawn-tmux.js.map +1 -1
  44. package/dist/daemon/usage.js +1 -1
  45. package/dist/daemon/usage.js.map +1 -1
  46. package/dist/daemon/wedoc.js +2 -2
  47. package/dist/daemon/wedoc.js.map +1 -1
  48. package/dist/mcp/server.js +4 -4
  49. package/dist/mcp/server.js.map +1 -1
  50. package/dist/shared/config-writer.js +1 -1
  51. package/dist/shared/config-writer.js.map +1 -1
  52. package/dist/shared/config.js +32 -19
  53. package/dist/shared/config.js.map +1 -1
  54. package/dist/shared/svr-token.js +22 -0
  55. package/dist/shared/svr-token.js.map +1 -0
  56. package/dist/svr/index.js +16 -31
  57. package/dist/svr/index.js.map +1 -1
  58. package/hooks/pre-tool-use.sh +24 -24
  59. package/launchd/{com.weclaude.daemon.plist.template → com.wezard.daemon.plist.template} +3 -3
  60. package/package.json +17 -14
  61. package/scripts/install.sh +15 -8
  62. package/scripts/postinstall.sh +2 -2
  63. package/scripts/uninstall.sh +35 -27
  64. package/systemd/{weclaude.service.template → wezard.service.template} +3 -3
  65. package/web/chat.css +13 -5
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "wezard",
3
- "version": "0.3.3",
3
+ "version": "1.0.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/weclaude.git"
9
+ "url": "git+https://github.com/guxi11/wezard.git"
10
10
  },
11
- "homepage": "https://github.com/guxi11/weclaude#readme",
11
+ "homepage": "https://github.com/guxi11/wezard#readme",
12
12
  "bugs": {
13
- "url": "https://github.com/guxi11/weclaude/issues"
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
- "weclaude": "./cli/weclaude.sh",
26
- "weclaude-daemon": "./dist/daemon/index.js",
27
- "weclaude-mcp": "./dist/mcp/server.js",
28
- "weclaude-init": "./dist/cli/init.js",
29
- "weclaude-svr": "./dist/svr/index.js"
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/weclaude.sh",
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.weclaude.daemon.plist.template",
57
- "systemd/weclaude.service.template",
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/weclaude.ts",
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",
@@ -1,21 +1,28 @@
1
1
  #!/usr/bin/env bash
2
- # Install resident daemon. Auto-detects macOS (launchd) vs Linux (systemd --user).
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
- LABEL="com.weclaude.daemon"
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/dist/daemon/index.js" ]]; then
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/.weclaude"
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/weclaude.service"
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/weclaude.service.template" > "$UNIT_DST"
71
+ "$REPO/systemd/${UNIT}.template" > "$UNIT_DST"
65
72
  systemctl --user daemon-reload
66
- systemctl --user enable --now weclaude.service
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/.weclaude/daemon.{stdout,stderr,log}"
80
+ echo "[install] $COMPONENT done. Logs at $HOME_DIR/.wezard/"
@@ -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/weclaude-local/ stays
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 weclaude-local >/dev/null 2>&1 || true
11
+ claude plugin marketplace update wezard-local >/dev/null 2>&1 || true
12
12
  exit 0
@@ -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 `weclaude init`. Tries both `claude` and `claude-internal` since either
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 weclaude@weclaude-local 2>/dev/null && \
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
- case "$OS" in
21
- Darwin)
22
- PLIST="$HOME_DIR/Library/LaunchAgents/${LABEL}.plist"
23
- if [[ -f "$PLIST" ]]; then
24
- launchctl unload "$PLIST" 2>/dev/null || true
25
- rm -f "$PLIST"
26
- echo "[uninstall] removed $PLIST"
27
- fi
28
- # Belt-and-braces: launchctl unload can leave a stray process if the plist
29
- # was edited mid-flight. bootout the label, then SIGTERM any survivors.
30
- launchctl bootout "gui/$(id -u)/${LABEL}" 2>/dev/null || true
31
- pkill -f "dist/daemon/index.js" 2>/dev/null || true
32
- ;;
33
- Linux)
34
- UNIT="$HOME_DIR/.config/systemd/user/weclaude.service"
35
- if [[ -f "$UNIT" ]]; then
36
- systemctl --user disable --now weclaude.service 2>/dev/null || true
37
- rm -f "$UNIT"
38
- systemctl --user daemon-reload
39
- echo "[uninstall] removed $UNIT"
40
- fi
41
- pkill -f "dist/daemon/index.js" 2>/dev/null || true
42
- ;;
43
- esac
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=weclaude daemon (WeCom remote control for Claude Code)
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__/.weclaude/daemon.stdout.log
13
- StandardError=append:__HOME__/.weclaude/daemon.stderr.log
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
- body { overflow: hidden }
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
- .main { flex: 1; min-width: 0; display: flex; flex-direction: column }
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 }
@@ -128,7 +134,9 @@ body { overflow: hidden }
128
134
  /* ── 页脚总账 ───────────────────────────────────────────────────── */
129
135
  .statusbar {
130
136
  flex: none; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
131
- padding: 7px 20px; background: #fff; border-top: 1px solid #d0d7de;
137
+ /* viewport-fit=cover 已开, 底部给 home indicator 让位 (桌面 env=0, 无感)。 */
138
+ padding: 7px 20px calc(7px + env(safe-area-inset-bottom));
139
+ background: #fff; border-top: 1px solid #d0d7de;
132
140
  font-size: 11.5px; color: #57606a; font-family: ui-monospace, Menlo, monospace;
133
141
  }
134
142
  .statusbar .st { display: flex; align-items: baseline; gap: 5px }
@@ -161,11 +169,11 @@ body { overflow: hidden }
161
169
 
162
170
  @media (max-width: 760px) {
163
171
  .app { flex-direction: column }
164
- .side { width: auto; border-right: 0; border-bottom: 1px solid #d0d7de; max-height: 44vh }
172
+ .side { width: auto; border-right: 0; border-bottom: 1px solid #d0d7de; max-height: 44vh; max-height: 44dvh }
165
173
  .app.reading .side { display: none }
166
174
  .app.reading .topbar .back { display: block }
167
175
  .thread { padding: 12px }
168
176
  .turn-group { padding: 12px }
169
- .statusbar { gap: 10px; padding: 7px 12px }
177
+ .statusbar { gap: 10px; padding: 7px 12px calc(7px + env(safe-area-inset-bottom)) }
170
178
  .sb-io, .statusbar .model { display: none }
171
179
  }