wezard 2.0.0 → 2.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.
Files changed (57) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CLAUDE.md +7 -8
  4. package/README.md +10 -11
  5. package/cli/wezard.sh +0 -62
  6. package/config.example.jsonc +3 -9
  7. package/dist/cli/init.js +12 -21
  8. package/dist/cli/init.js.map +1 -1
  9. package/dist/daemon/approval.js +2 -4
  10. package/dist/daemon/approval.js.map +1 -1
  11. package/dist/daemon/cc-session.js +136 -0
  12. package/dist/daemon/cc-session.js.map +1 -0
  13. package/dist/daemon/detail.js +1 -1
  14. package/dist/daemon/detail.js.map +1 -1
  15. package/dist/daemon/inbound.js +59 -102
  16. package/dist/daemon/inbound.js.map +1 -1
  17. package/dist/daemon/index.js +98 -86
  18. package/dist/daemon/index.js.map +1 -1
  19. package/dist/daemon/memory-steward.js +82 -0
  20. package/dist/daemon/memory-steward.js.map +1 -0
  21. package/dist/daemon/mirror-bridge.js +149 -36
  22. package/dist/daemon/mirror-bridge.js.map +1 -1
  23. package/dist/daemon/session-name.js +4 -27
  24. package/dist/daemon/session-name.js.map +1 -1
  25. package/dist/daemon/spawn-tmux.js +35 -13
  26. package/dist/daemon/spawn-tmux.js.map +1 -1
  27. package/dist/daemon/wizard-memory.js +21 -26
  28. package/dist/daemon/wizard-memory.js.map +1 -1
  29. package/dist/daemon/wizard.js +31 -11
  30. package/dist/daemon/wizard.js.map +1 -1
  31. package/dist/mcp/server.js +63 -153
  32. package/dist/mcp/server.js.map +1 -1
  33. package/dist/shared/chat-http.js +3 -1
  34. package/dist/shared/chat-http.js.map +1 -1
  35. package/dist/shared/chat-render.js +0 -1
  36. package/dist/shared/chat-render.js.map +1 -1
  37. package/dist/shared/cli-backends.js +2 -7
  38. package/dist/shared/cli-backends.js.map +1 -1
  39. package/dist/shared/config.js +4 -6
  40. package/dist/shared/config.js.map +1 -1
  41. package/dist/shared/detail-store.js +1 -1
  42. package/dist/shared/detail-store.js.map +1 -1
  43. package/dist/shared/role-render.js +4 -1
  44. package/dist/shared/role-render.js.map +1 -1
  45. package/dist/shared/role-view.js +23 -5
  46. package/dist/shared/role-view.js.map +1 -1
  47. package/dist/shared/world.js +11 -1
  48. package/dist/shared/world.js.map +1 -1
  49. package/hooks/pre-tool-use.sh +4 -4
  50. package/package.json +1 -2
  51. package/web/chat.css +45 -28
  52. package/web/chat.js +45 -26
  53. package/commands/wrc.md +0 -7
  54. package/dist/daemon/cc-bridge.js +0 -183
  55. package/dist/daemon/cc-bridge.js.map +0 -1
  56. package/dist/daemon/sessions.js +0 -4
  57. package/dist/daemon/sessions.js.map +0 -1
package/web/chat.css CHANGED
@@ -31,7 +31,7 @@ button { font: inherit; color: inherit }
31
31
  /* 名字 = 地址。点是地址的一部分, 也是这一页唯一的颜色记号。 */
32
32
  .nm { font-weight: 600 }
33
33
  .nm::before { content: "."; color: var(--accent); font-weight: 700 }
34
- .nm.human::before, .nm.task::before, .nm.chat::before { content: none }
34
+ .nm.human::before, .nm.task::before, .nm.system::before, .nm.chat::before { content: none }
35
35
 
36
36
  /* ── 侧栏: 我 + 会话 ─────────────────────────────────────────────── */
37
37
  .side {
@@ -44,8 +44,7 @@ button { font: inherit; color: inherit }
44
44
  position: relative; flex: none; padding: 16px 16px 14px; border-bottom: 1px solid var(--line);
45
45
  display: flex; flex-direction: column; gap: 8px; background: var(--card);
46
46
  }
47
- .rolebar .conn { position: absolute; top: 12px; right: 14px }
48
- .rolebar .id { display: flex; gap: 10px; align-items: center; min-width: 0; padding-right: 14px }
47
+ .rolebar .id { display: flex; gap: 10px; align-items: center; min-width: 0 }
49
48
  .rolebar .id .av { font-size: 26px; line-height: 1; flex: none }
50
49
  .rolebar .id .l { min-width: 0; display: flex; flex-direction: column; gap: 2px }
51
50
  .rolebar .id .nm { font-size: 18px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
@@ -53,10 +52,17 @@ button { font: inherit; color: inherit }
53
52
  .rolebar .job { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink); opacity: .8 }
54
53
  .rolebar .facts { display: flex; gap: 6px 12px; flex-wrap: wrap; font-size: 11.5px; color: var(--mute) }
55
54
  .rolebar .facts span { white-space: nowrap }
56
- .rolebar .facts .go { cursor: pointer; color: var(--accent) }
57
- .rolebar .facts .go:hover { text-decoration: underline }
55
+ .rolebar .go { cursor: pointer; color: var(--accent) }
56
+ .rolebar .go:hover { text-decoration: underline }
58
57
  .rolebar .acts { display: flex; gap: 6px; flex-wrap: wrap; align-items: center }
59
58
  .rolebar .acts:empty { display: none }
59
+ .bd {
60
+ font-size: 11px; line-height: 18px; padding: 0 8px; border: 0; border-radius: 9px; cursor: pointer;
61
+ background: #f1f3f6; color: var(--mute); white-space: nowrap;
62
+ }
63
+ .bd:hover { color: var(--accent) }
64
+ .bd.on { background: var(--mine-soft); color: var(--accent) }
65
+ .bd b { font-weight: 600; margin-left: 4px; font-variant-numeric: tabular-nums }
60
66
  /* session 切换: 按钮 + 浮层列表, 取代原生 <select>。 */
61
67
  .sp { position: relative; flex: 1 1 100%; min-width: 0 }
62
68
  .sp-btn {
@@ -123,9 +129,6 @@ button { font: inherit; color: inherit }
123
129
  .prof .lg { display: flex; align-items: center; gap: 4px; font-size: 10.5px; color: #8c959f }
124
130
  .prof .lg i { width: 8px; height: 8px; border-radius: 2px; flex: none }
125
131
  .prof .lg b { color: #1f2328; font-weight: 700; font-variant-numeric: tabular-nums }
126
- .conn { display: flex; align-items: center; gap: 5px }
127
- .conn .d { width: 7px; height: 7px; border-radius: 50%; background: #1a7f37 }
128
- .conn.off .d { background: #cf222e }
129
132
 
130
133
  /* 群聊头像 = 参与者头像拼图: 1 格居中, 2 格左右, 3/4 格田字。 */
131
134
  .mosaic {
@@ -164,23 +167,35 @@ button { font: inherit; color: inherit }
164
167
  .ci .pv { font-size: 12px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
165
168
  .ci .pv:empty { display: none }
166
169
  .ci .tag { font-size: 10.5px; border-radius: 4px; padding: 0 4px; flex: none }
170
+ /* 选中的 role 项上的换视角开关。 */
171
+ .sw {
172
+ flex: none; align-self: center; display: inline-grid; place-items: center;
173
+ width: 20px; height: 20px; border-radius: 5px; color: var(--accent); cursor: pointer;
174
+ }
175
+ .sw:hover { background: #2f55c91a }
167
176
  .ci .tag.priv { color: var(--priv); background: #9a5b1014 }
168
177
 
169
- /* 群里的其他 role —— 缩进挂在群下, 点开是「我与它在这个群里」的往来。 */
170
- .subs { margin: 0 0 6px 34px; border-left: 1px solid var(--line); padding-left: 6px }
178
+ /* 群里的其他 role —— 挂在群下, 与会话项同一种读法 (名字 · 时刻 / 最近一句), 只压一档。
179
+ 点开是「我与它在这个群里」的往来。 */
180
+ .subs { margin: 0 0 6px 16px; border-left: 1px solid var(--line); padding-left: 2px }
171
181
  .si {
172
- display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
173
- padding: 4px 8px; border: 0; border-radius: 7px; background: transparent; cursor: pointer;
174
- font-size: 12.5px; color: var(--ink);
182
+ display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; overflow: hidden;
183
+ padding: 5px 8px; border: 0; border-radius: 8px; background: transparent; cursor: pointer; color: var(--ink);
175
184
  }
176
185
  .si:hover { background: #f4f6f9 }
177
- .si.on { background: #eaf0fc; color: var(--accent) }
178
- .si .n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
179
- .si .c { margin-left: auto; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums }
180
- .si.quiet { color: var(--faint) }
186
+ .si.on { background: #eaf0fc }
187
+ .si > .av { font-size: 17px; line-height: 1; flex: none; width: 24px; text-align: center }
188
+ .si .b { min-width: 0; flex: 1; overflow: hidden }
189
+ .si .l1 { display: flex; align-items: baseline; gap: 6px }
190
+ .si .t { font-size: 12.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
191
+ .si.on .t { color: var(--accent) }
192
+ .si .ts { margin-left: auto; flex: none; font-size: 10.5px; color: var(--faint); font-variant-numeric: tabular-nums }
193
+ .si .pv { display: block; font-size: 11.5px; color: var(--mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
194
+ .si .pv:empty { display: none }
195
+ .si.quiet .t, .si.quiet > .av { opacity: .55 }
181
196
 
182
197
  /* ── 右栏头: 这个群聊 / 私聊是什么 ───────────────────────────────── */
183
- .main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--paper) }
198
+ .main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--card) }
184
199
  .chathead {
185
200
  flex: none; display: flex; align-items: center; gap: 12px; padding: 10px 20px; min-height: 58px;
186
201
  background: var(--card); border-bottom: 1px solid var(--line);
@@ -206,7 +221,7 @@ button { font: inherit; color: inherit }
206
221
  flex: 1; min-height: 0; overflow-y: auto; overflow-anchor: none;
207
222
  padding: 16px 20px 28px; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
208
223
  }
209
- .thread-in { max-width: 960px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px }
224
+ .thread-in { display: flex; flex-direction: column; gap: 14px }
210
225
  .empty { color: var(--faint); text-align: center; padding: 60px 0; font-size: 13px }
211
226
  .more-btn {
212
227
  align-self: center; background: var(--card); border: 1px solid var(--line); border-radius: 16px;
@@ -214,15 +229,16 @@ button { font: inherit; color: inherit }
214
229
  }
215
230
  .more-btn:hover { color: var(--accent); border-color: var(--accent) }
216
231
 
217
- .mrow { display: flex; align-items: flex-start; gap: 10px }
218
- .mrow .av {
219
- flex: none; width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--line);
220
- background: var(--card); font-size: 19px; line-height: 32px; text-align: center; cursor: default; padding: 0;
232
+ /* 头像已并进名字那一行, 不再占气泡旁的一列 —— 省下的那一格宽度 (--av) 还给气泡。 */
233
+ .mrow { --av: 24px; display: flex; align-items: flex-start; gap: 10px }
234
+ .mwho .av {
235
+ flex: none; align-self: center; width: var(--av); height: var(--av); border-radius: 50%; border: 1px solid var(--line);
236
+ background: var(--card); font-size: 14px; line-height: 22px; text-align: center; cursor: default; padding: 0;
221
237
  }
222
- .mcol { min-width: 0; max-width: min(78%, 760px); display: flex; flex-direction: column; gap: 4px }
238
+ .mcol { min-width: 0; max-width: min(78% + var(--av), 760px + var(--av)); display: flex; flex-direction: column; gap: 4px }
223
239
  .mrow.mine { flex-direction: row-reverse }
224
240
  .mrow.mine .mcol { align-items: flex-end }
225
- .mwho { font-size: 11.5px; color: var(--mute); display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap }
241
+ .mwho { font-size: 11.5px; color: var(--mute); display: flex; gap: 6px; align-items: center; flex-wrap: wrap }
226
242
  .mwho .to { color: var(--faint) }
227
243
  .mwho .ch { font-size: 10.5px; border-radius: 4px; padding: 0 4px }
228
244
  .mwho .ch.priv { color: var(--priv); background: #9a5b1014 }
@@ -241,6 +257,7 @@ button { font: inherit; color: inherit }
241
257
  .mchip.priv { color: var(--priv); background: #9a5b1014 }
242
258
  .mchip.pub { color: var(--pub); background: #237a5514 }
243
259
  .mchip.graph { color: #6639ba; background: #8250df12 }
260
+ .mchip.sys { color: #0a7d6b; background: #0a7d6b12 }
244
261
 
245
262
  /* 自己发出的那条: 整块就是视角色。TURN_CSS 里写死的白卡 / 灰底 (嵌套气泡、
246
263
  代码块、折叠头) 会在蓝底上显成一张张贴纸 —— 这里把它们收回到气泡自己的
@@ -275,8 +292,8 @@ button { font: inherit; color: inherit }
275
292
  .flip .fc { flex: none }
276
293
  .flip:hover, .flip:focus-visible { background: #2f55c90d; color: var(--accent) }
277
294
  .flip[disabled] { cursor: default; background: transparent !important; color: transparent !important }
278
- .mrow .av.go { cursor: pointer }
279
- .mrow .av.go:hover { border-color: var(--accent) }
295
+ .mwho .av.go { cursor: pointer }
296
+ .mwho .av.go:hover { border-color: var(--accent) }
280
297
 
281
298
  .mrow.mark { justify-content: center }
282
299
  .mrow.mark > * { flex: 1; max-width: 520px }
@@ -355,7 +372,7 @@ button { font: inherit; color: inherit }
355
372
  .chathead { padding: 8px 12px; gap: 8px }
356
373
  .chathead .back { display: block }
357
374
  .thread { padding: 12px }
358
- .mcol { max-width: 86% }
375
+ .mcol { max-width: calc(86% + var(--av)) }
359
376
  .flip { min-width: 16px; padding: 0 4px; font-size: 0 }
360
377
  .turn-group { padding: 12px }
361
378
  .thread { padding-bottom: calc(12px + env(safe-area-inset-bottom)) }
package/web/chat.js CHANGED
@@ -41,7 +41,6 @@
41
41
  var VIEW = 'msgs';
42
42
  var $ = function (s) { return document.querySelector(s); };
43
43
  var app = $('#app'), thread = $('#thread'), inner = $('#thread-in'), convsEl = $('#convs');
44
- var connEl = $('#conn');
45
44
  var wmapEl = $('#wmap'), wscrollEl = $('#wscroll'), wtoolsEl = $('#wtools'), planEl = $('#plan-in');
46
45
 
47
46
  var srvNow = function () { return R.at ? R.at + (Date.now() - R.recvAt) : Date.now(); };
@@ -115,7 +114,7 @@
115
114
  var names = {};
116
115
  var learn = function (id, name, label) { if (id && name) names[id] = { name: name, label: label || '' }; };
117
116
  var kindOf = function (id) {
118
- return /^task:/.test(id) ? 'task' : /^human:/.test(id) ? 'human' : 'wizard';
117
+ return /^task:/.test(id) ? 'task' : id === 'system:' ? 'system' : /^human:/.test(id) ? 'human' : 'wizard';
119
118
  };
120
119
  var nodeOf = function (target) {
121
120
  return W.nodes.filter(function (n) { return n.target === target; })[0];
@@ -126,14 +125,14 @@
126
125
  };
127
126
  var roleLabel = function (id) {
128
127
  var k = names[id] || {}, n = nodeOf(id);
129
- return k.label || (n && n.label) || (kindOf(id) === 'human' ? '👤' : kindOf(id) === 'task' ? '⏰' : '🧙');
128
+ return k.label || (n && n.label) || ({ human: '👤', task: '⏰', system: '🧙' })[kindOf(id)] || '🧙';
130
129
  };
131
130
  // `.name` 的点由 CSS 画 —— 人与定时任务没有地址, 不画点。
132
131
  var nm = function (id, name) {
133
132
  return '<span class="nm ' + kindOf(id) + '">' + esc(name || roleName(id)) + '</span>';
134
133
  };
135
134
  var nameOf = function (id) { return (kindOf(id) === 'wizard' ? '.' : '') + roleName(id); };
136
- var canSwitch = function (id) { return !!id && kindOf(id) !== 'task' && id !== 'human:'; };
135
+ var canSwitch = function (id) { return !!id && kindOf(id) !== 'task' && kindOf(id) !== 'system' && id !== 'human:'; };
137
136
 
138
137
  // ── markdown 渲染 (只对未渲染过的节点做, 复用节点不重绘) ──
139
138
  var md = null;
@@ -231,22 +230,35 @@
231
230
  ms.map(function (m) { return '<i>' + esc(m.label || roleLabel(m.role)) + '</i>'; }).join('') + '</span>';
232
231
  };
233
232
 
233
+ // 选中的那一项若是个 role (私聊对端 / 群里的某人), 行内给一个换视角的开关。
234
+ // 不能是 <button>: 它嵌在整行那颗按钮里。
235
+ var SWAP = '<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path d="M3 5.5h9M9.5 3l2.5 2.5L9.5 8M13 10.5H4M6.5 8 4 10.5 6.5 13" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>';
236
+ var swapOf = function (role) {
237
+ return canSwitch(role) && role !== ROLE
238
+ ? '<span class="sw" role="button" tabindex="0" data-sw="' + esc(role) + '" title="' + esc('切到 ' + nameOf(role) + ' 的视角') + '">' + SWAP + '</span>'
239
+ : '';
240
+ };
241
+ var line = function (title, sw, ts, pv) {
242
+ return '<span class="b"><span class="l1"><span class="t">' + title + '</span>' + sw +
243
+ '<span class="ts">' + esc(fmtAgo(ts)) + '</span></span>' +
244
+ '<span class="pv">' + esc(pv) + '</span></span>';
245
+ };
246
+
234
247
  var convItem = function (c) {
235
248
  var on = c.key === CONV;
236
249
  var title = c.kind === 'wizard' ? nm(c.peer, c.name) : '<span class="nm chat">' + esc(c.name) + '</span>';
237
250
  var subs = on && c.subs.length
238
251
  ? '<div class="subs">' + c.subs.map(function (s) {
239
- return '<button class="si' + (s.role === WITH ? ' on' : '') + (s.count ? '' : ' quiet') + '" data-conv="' + esc(c.key) + '" data-with="' + esc(s.role) + '" ' +
252
+ var sel = s.role === WITH;
253
+ return '<button class="si' + (sel ? ' on' : '') + (s.count ? '' : ' quiet') + '" data-conv="' + esc(c.key) + '" data-with="' + esc(s.role) + '" ' +
240
254
  'title="' + esc(s.count ? '我与 ' + nameOf(s.role) + ' 在这里的 ' + s.count + ' 条往来' : '在这里, 但还没和我说过话') + '">' +
241
- '<span>' + esc(s.label) + '</span><span class="n">' + nm(s.role, s.name) + '</span>' +
242
- (s.count ? '<span class="c">' + s.count + '</span>' : '') + '</button>';
255
+ '<span class="av">' + esc(s.label) + '</span>' +
256
+ line(nm(s.role, s.name), sel ? swapOf(s.role) : '', s.lastTs, s.preview) + '</button>';
243
257
  }).join('') + '</div>'
244
258
  : '';
245
- return '<button class="ci' + (on && !WITH ? ' on' : '') + '" data-conv="' + esc(c.key) + '">' +
246
- avatarOf(c) +
247
- '<span class="b"><span class="l1"><span class="t">' + title + '</span>' +
248
- '<span class="ts">' + esc(fmtAgo(c.lastTs)) + '</span></span>' +
249
- '<span class="pv">' + esc(c.preview) + '</span></span>' +
259
+ var sel = on && !WITH;
260
+ return '<button class="ci' + (sel ? ' on' : '') + '" data-conv="' + esc(c.key) + '">' +
261
+ avatarOf(c) + line(title, sel && c.kind === 'wizard' ? swapOf(c.peer) : '', c.lastTs, c.preview) +
250
262
  '</button>' + subs;
251
263
  };
252
264
 
@@ -263,6 +275,11 @@
263
275
  convsEl.querySelectorAll('[data-conv]').forEach(function (b) {
264
276
  b.onclick = function () { selectConv(b.getAttribute('data-conv'), b.getAttribute('data-with') || ''); };
265
277
  });
278
+ convsEl.querySelectorAll('[data-sw]').forEach(function (x) {
279
+ var go = function (e) { e.stopPropagation(); switchRole(x.getAttribute('data-sw')); };
280
+ x.onclick = go;
281
+ x.onkeydown = function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); go(e); } };
282
+ });
266
283
  };
267
284
 
268
285
  var shortCwd = function (p) {
@@ -321,16 +338,19 @@
321
338
  var renderRole = function () {
322
339
  var r = R.role;
323
340
  if (!r) return;
341
+ // 名字下面那一行就是出身 —— 有父亲的直接写成「谁的什么」(可点过去), 不再另起一条重复。
324
342
  // 分身 = 从父亲某个 session 节点 fork 出来的 (带着那一刻的上下文);
325
343
  // 子 wizard = 父亲 spawn 的白板, 只有出身、没有继承。
326
- var kind = r.kind === 'human' ? '人' : !r.parent ? 'wizard' : r.forkedFrom ? '分身' : '子 wizard';
327
- // 忙闲由右上角的状态点表达, 名片不再重复。
344
+ var kind = !r.parent
345
+ ? esc(r.kind === 'human' ? '人' : 'wizard')
346
+ : r.forkedFrom
347
+ ? '<span class="go" data-r="' + esc(r.parent.id) + '" title="从它的 session ' + esc(r.forkedFrom) + ' fork, 开局带着那一刻的上下文">⧉ .' + esc(r.parent.name) + ' 的分身 · @' + esc(r.forkedFrom.slice(0, 8)) + '</span>'
348
+ : '<span class="go" data-r="' + esc(r.parent.id) + '" title="它 spawn 的白板, 没有继承上下文">↳ .' + esc(r.parent.name) + ' 的子 wizard</span>';
328
349
  var facts = [];
329
350
  if (r.cwd) facts.push('<span title="' + esc(r.cwd) + '">📁 ' + esc(shortCwd(r.cwd)) + '</span>');
330
- if (r.bornAt) facts.push('<span title="创建时间">🐣 ' + esc(fmtDay(r.bornAt)) + '</span>');
331
- if (r.parent) facts.push(r.forkedFrom
332
- ? '<span class="go" data-r="' + esc(r.parent.id) + '" title="从它的 session ' + esc(r.forkedFrom) + ' fork, 开局带着那一刻的上下文">⧉ .' + esc(r.parent.name) + ' 的分身 · @' + esc(r.forkedFrom.slice(0, 8)) + '</span>'
333
- : '<span class="go" data-r="' + esc(r.parent.id) + '" title="它 spawn 的白板, 没有继承上下文">↳ .' + esc(r.parent.name) + ' 的子 wizard</span>');
351
+ // 生在哪个群、什么时候 —— 一件事, 一行。
352
+ var born = [r.chat, r.bornAt ? fmtAgo(r.bornAt) : ''].filter(Boolean);
353
+ if (born.length) facts.push('<span title="' + esc('创建于' + (r.chat ? ' ' + r.chat : '') + (r.bornAt ? ' · ' + fmtDay(r.bornAt) : '')) + '">🐣 ' + esc(born.join(' · ')) + '</span>');
334
354
  var kin = function (xs, what) {
335
355
  return xs.length ? '<span title="' + esc(xs.map(function (x) { return '.' + x.name; }).join(' ')) + '">' + xs.length + ' 个' + what + '</span>' : '';
336
356
  };
@@ -338,7 +358,7 @@
338
358
  $('#rb-who').innerHTML =
339
359
  '<div class="id"><span class="av">' + esc(r.label) + '</span>' +
340
360
  '<span class="l">' + nm(r.id, r.name) +
341
- '<span class="k">' + esc(kind + (r.chat ? ' · 住在 ' + r.chat : '')) + '</span></span></div>' +
361
+ '<span class="k">' + kind + '</span></span></div>' +
342
362
  (r.description ? '<p class="job">' + esc(r.description) + '</p>' : '') +
343
363
  '<div class="facts">' + facts.join('') + '</div>';
344
364
  $('#rb-who').querySelectorAll('.go').forEach(function (g) {
@@ -348,10 +368,11 @@
348
368
  bindSessPicker();
349
369
  syncFoot();
350
370
  var acts = [];
351
- if (R.relations) acts.push('<button class="vb' + (VIEW === 'world' ? ' on' : '') + '" data-view="world">关系图</button>');
352
- if (r.kind === 'wizard') acts.push('<button class="vb' + (VIEW === 'plan' ? ' on' : '') + '" data-view="plan">日程' + (R.schedules ? '<b>' + R.schedules + '</b>' : '') + '</button>');
371
+ // 入口只在有东西可看时出现, 且只是一枚徽标 —— 名片的主角是身份, 不是按钮。
372
+ if (R.relations) acts.push('<button class="bd' + (VIEW === 'world' ? ' on' : '') + '" data-view="world">关系图</button>');
373
+ if (R.schedules) acts.push('<button class="bd' + (VIEW === 'plan' ? ' on' : '') + '" data-view="plan">日程<b>' + R.schedules + '</b></button>');
353
374
  $('#rb-acts').innerHTML = acts.join('');
354
- $('#rb-acts').querySelectorAll('.vb').forEach(function (b) {
375
+ $('#rb-acts').querySelectorAll('.bd').forEach(function (b) {
355
376
  b.onclick = function () { setView(VIEW === b.getAttribute('data-view') ? 'msgs' : b.getAttribute('data-view')); };
356
377
  });
357
378
  // 标题就是这一页的主张: 你此刻站在谁的位置上。换视角 → 标题跟着换。
@@ -471,8 +492,7 @@
471
492
  var av = mine ? '' : '<button class="av' + (canSwitch(m.from) ? ' go' : '') + '" data-r="' + esc(m.from) + '" title="' + esc(nameOf(m.from)) + '"' + (canSwitch(m.from) ? '' : ' disabled') + '>' + esc(m.fromLabel || roleLabel(m.from)) + '</button>';
472
493
  return '<div class="mrow ' + (mine ? 'mine' : 'them') + '" data-id="' + esc(m.id) + '" data-turn="' + esc(m.turnId || m.id) + '" data-ts="' + m.ts + '"' +
473
494
  (m.ping ? ' data-ping="1"' : '') + ' data-sig="' + esc(m.sig) + '" data-stale-at="' + (m.staleAt || 0) + '">' +
474
- av +
475
- '<div class="mcol"><div class="mwho">' + who + '</div><div class="mb">' + m.html + '</div></div>' +
495
+ '<div class="mcol"><div class="mwho">' + av + who + '</div><div class="mb">' + m.html + '</div></div>' +
476
496
  flip +
477
497
  '</div>';
478
498
  };
@@ -625,9 +645,8 @@
625
645
  S.es = es;
626
646
  es.addEventListener('role', function (e) { try { applyRole(JSON.parse(e.data)); } catch (err) { } });
627
647
  es.addEventListener('msg', function (e) { try { upsertMsg(JSON.parse(e.data)); } catch (err) { } });
628
- es.onopen = function () { backoff = 1000; connEl.className = 'conn'; connEl.title = '实时连接'; };
648
+ es.onopen = function () { backoff = 1000; };
629
649
  es.onerror = function () {
630
- connEl.className = 'conn off'; connEl.title = '连接断开, 重连中';
631
650
  es.close(); if (S.es === es) S.es = null;
632
651
  setTimeout(function () { if (!S.es) connect(); }, backoff);
633
652
  backoff = Math.min(backoff * 2, 15000);
package/commands/wrc.md DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- description: WeCom remote control — mirror current agent session to WeCom
3
- allowed-tools: Bash(${CLAUDE_PLUGIN_ROOT}/cli/wezard.sh:*)
4
- argument-hint: [user:<userid>|chat:<chatid>]
5
- ---
6
-
7
- !`${CLAUDE_PLUGIN_ROOT}/cli/wezard.sh mirror $ARGUMENTS`
@@ -1,183 +0,0 @@
1
- // Headless Claude Code bridge. Spawns `claude -p` per WeCom message, streams
2
- // stdout (stream-json) back via WeCom replyStream. One in-flight subprocess
3
- // per principal; subsequent messages queue.
4
- import { spawn } from "node:child_process";
5
- import { createInterface } from "node:readline";
6
- import { expandHome } from "../shared/paths.js";
7
- import { augmentedPath } from "../shared/exec-path.js";
8
- import { resolveCliBackend } from "../shared/cli-backends.js";
9
- const FLUSH_INTERVAL_MS = 250;
10
- const deltaText = (line) => {
11
- if (line.type === "stream_event" &&
12
- line.event?.type === "content_block_delta" &&
13
- line.event.delta?.type === "text_delta") {
14
- return line.event.delta.text ?? "";
15
- }
16
- return undefined;
17
- };
18
- const assistantText = (line) => {
19
- if (line.type === "assistant" && line.message?.content) {
20
- return line.message.content
21
- .filter((b) => b.type === "text" && typeof b.text === "string")
22
- .map((b) => b.text)
23
- .join("");
24
- }
25
- return undefined;
26
- };
27
- const runOne = async (args) => {
28
- const { text, resumeSid, cfg, log, client, frame, streamId, principal, onSession } = args;
29
- const cliArgs = [
30
- "-p",
31
- text,
32
- "--output-format",
33
- "stream-json",
34
- ...resolveCliBackend(cfg.wrc).headlessStreamingArgs,
35
- ...cfg.wrc.extraArgs,
36
- ];
37
- if (resumeSid)
38
- cliArgs.push("--resume", resumeSid);
39
- log.info({ resumeSid, claudeBin: cfg.wrc.claudeBin }, "spawn claude");
40
- const proc = spawn(cfg.wrc.claudeBin, cliArgs, {
41
- cwd: expandHome(cfg.wrc.cwd),
42
- env: { ...process.env, PATH: augmentedPath(process.env.PATH) },
43
- stdio: ["ignore", "pipe", "pipe"],
44
- });
45
- let acc = "";
46
- let lastSent = "";
47
- let sawDelta = false; // gate assistant-event fallback (see deltaText/assistantText comment)
48
- let flushTimer;
49
- let stderrTail = "";
50
- const sendFlush = async (finish) => {
51
- if (acc === lastSent && !finish)
52
- return;
53
- lastSent = acc;
54
- try {
55
- await client.replyStream(frame, streamId, acc || " ", finish);
56
- }
57
- catch (e) {
58
- log.warn({ err: e.message, finish }, "replyStream failed");
59
- }
60
- };
61
- const scheduleFlush = () => {
62
- if (flushTimer)
63
- return;
64
- flushTimer = setTimeout(() => {
65
- flushTimer = undefined;
66
- void sendFlush(false);
67
- }, FLUSH_INTERVAL_MS);
68
- };
69
- const stdout = proc.stdout;
70
- const stderr = proc.stderr;
71
- if (!stdout || !stderr) {
72
- throw new Error("claude subprocess missing stdio pipes");
73
- }
74
- // ENOENT / EACCES 等 spawn 失败走 'error' 事件,不监听会 crash 整个 daemon。
75
- let spawnError;
76
- proc.on("error", (err) => {
77
- spawnError = err;
78
- log.error({ err: err.message, code: err.code }, "spawn error");
79
- });
80
- const rl = createInterface({ input: stdout });
81
- rl.on("line", (raw) => {
82
- if (!raw.trim())
83
- return;
84
- let line;
85
- try {
86
- line = JSON.parse(raw);
87
- }
88
- catch {
89
- log.debug({ raw: raw.slice(0, 200) }, "non-JSON stdout line");
90
- return;
91
- }
92
- if (line.type === "system" && line.subtype === "init" && line.session_id) {
93
- onSession(line.session_id);
94
- return;
95
- }
96
- const delta = deltaText(line);
97
- if (delta) {
98
- sawDelta = true;
99
- acc += delta;
100
- scheduleFlush();
101
- }
102
- else {
103
- const whole = assistantText(line);
104
- // Fallback only if we never saw any delta (e.g. cached / non-streaming response).
105
- if (whole && !sawDelta) {
106
- acc += whole;
107
- scheduleFlush();
108
- }
109
- }
110
- if (line.type === "result") {
111
- // result.result is the final assistant text in cases where no assistant event was emitted (e.g. no_response).
112
- if (!acc && typeof line.result === "string")
113
- acc = line.result;
114
- }
115
- });
116
- proc.stderr?.on("data", (chunk) => {
117
- const s = chunk.toString("utf8");
118
- stderrTail = (stderrTail + s).slice(-2000);
119
- });
120
- await new Promise((resolve) => {
121
- proc.on("close", async (code) => {
122
- if (flushTimer) {
123
- clearTimeout(flushTimer);
124
- flushTimer = undefined;
125
- }
126
- if (spawnError || code !== 0) {
127
- const reason = spawnError
128
- ? `spawn ${cfg.wrc.claudeBin}: ${spawnError.message}`
129
- : `claude exited ${code}`;
130
- log.error({ code, spawnErr: spawnError?.message, stderrTail: stderrTail.slice(-500) }, "claude failure");
131
- const fallback = acc
132
- ? `${acc}\n\n[${reason}]`
133
- : `[wezard] ${reason}\n${stderrTail.slice(-500)}`;
134
- acc = fallback;
135
- }
136
- await sendFlush(true);
137
- // WeCom 列表对 stream 消息硬编码 "…" 预览,唯一覆盖方式是在 stream 终止后补发一条普通消息。
138
- // 取 acc 按空行切分的最后一段——对应"最后一段话",多段冗长输出不会全压进列表。
139
- const tail = acc.split(/\n{2,}/).filter((s) => s.trim()).pop();
140
- if (tail) {
141
- const chatId = principal.includes(":") ? principal.slice(principal.indexOf(":") + 1) : principal;
142
- try {
143
- await client.sendMessage(chatId, { msgtype: "markdown", markdown: { content: tail } });
144
- }
145
- catch (e) {
146
- log.warn({ err: e.message }, "preview push failed");
147
- }
148
- }
149
- log.info({ code, chars: acc.length }, "claude done");
150
- resolve();
151
- });
152
- });
153
- };
154
- const queues = new Map();
155
- const enqueue = (key, job) => {
156
- const prev = queues.get(key) ?? Promise.resolve();
157
- const next = prev.then(job, job).catch(() => undefined);
158
- queues.set(key, next.finally(() => {
159
- if (queues.get(key) === next)
160
- queues.delete(key);
161
- }));
162
- return next;
163
- };
164
- export const makeBridge = (deps) => {
165
- return {
166
- dispatch: ({ principal, text, images, frame, streamId }) => enqueue(principal, () => {
167
- const refs = (images ?? []).map((p) => `@${p}`).join("\n");
168
- const finalText = refs ? (text ? `${refs}\n${text}` : refs) : text;
169
- return runOne({
170
- text: finalText,
171
- resumeSid: deps.sessions.get(principal),
172
- cfg: deps.cfg,
173
- log: deps.log.child({ principal }),
174
- client: deps.client,
175
- frame,
176
- streamId,
177
- principal,
178
- onSession: (sid) => deps.sessions.set(principal, sid),
179
- });
180
- }),
181
- };
182
- };
183
- //# sourceMappingURL=cc-bridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cc-bridge.js","sourceRoot":"","sources":["../../daemon/cc-bridge.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- // Persisted principal → claude session_id map. Single JSON file, write-through.
2
- import { loadJsonMap } from "../shared/json-map-store.js";
3
- export const loadSessionStore = (filePath) => loadJsonMap(filePath);
4
- //# sourceMappingURL=sessions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../daemon/sessions.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,OAAO,EAAE,WAAW,EAAgB,MAAM,6BAA6B,CAAC;AAIxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAgB,EAAE,CAAC,WAAW,CAAS,QAAQ,CAAC,CAAC"}