wezard 2.2.2 → 2.4.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 (112) hide show
  1. package/CLAUDE.md +9 -6
  2. package/README.md +5 -5
  3. package/config.example.jsonc +12 -0
  4. package/dist/cli/init.js +2 -1
  5. package/dist/cli/init.js.map +1 -1
  6. package/dist/daemon/approval.js +90 -6
  7. package/dist/daemon/approval.js.map +1 -1
  8. package/dist/daemon/chat-log.js +6 -1
  9. package/dist/daemon/chat-log.js.map +1 -1
  10. package/dist/daemon/chat-name.js +15 -0
  11. package/dist/daemon/chat-name.js.map +1 -1
  12. package/dist/daemon/config-api.js +265 -70
  13. package/dist/daemon/config-api.js.map +1 -1
  14. package/dist/daemon/danger.js +15 -0
  15. package/dist/daemon/danger.js.map +1 -1
  16. package/dist/daemon/detail.js +49 -0
  17. package/dist/daemon/detail.js.map +1 -1
  18. package/dist/daemon/handoff.js +12 -5
  19. package/dist/daemon/handoff.js.map +1 -1
  20. package/dist/daemon/idle-nudge.js +55 -0
  21. package/dist/daemon/idle-nudge.js.map +1 -0
  22. package/dist/daemon/inbound.js +19 -14
  23. package/dist/daemon/inbound.js.map +1 -1
  24. package/dist/daemon/index.js +1509 -259
  25. package/dist/daemon/index.js.map +1 -1
  26. package/dist/daemon/jobs.js +180 -32
  27. package/dist/daemon/jobs.js.map +1 -1
  28. package/dist/daemon/last-response.js +15 -0
  29. package/dist/daemon/last-response.js.map +1 -1
  30. package/dist/daemon/memory-steward.js +124 -68
  31. package/dist/daemon/memory-steward.js.map +1 -1
  32. package/dist/daemon/mirror-bridge.js +506 -124
  33. package/dist/daemon/mirror-bridge.js.map +1 -1
  34. package/dist/daemon/mirror-store.js.map +1 -1
  35. package/dist/daemon/model-select.js +102 -0
  36. package/dist/daemon/model-select.js.map +1 -1
  37. package/dist/daemon/notices.js +147 -33
  38. package/dist/daemon/notices.js.map +1 -1
  39. package/dist/daemon/peers.js +261 -124
  40. package/dist/daemon/peers.js.map +1 -1
  41. package/dist/daemon/pending-items.js +171 -0
  42. package/dist/daemon/pending-items.js.map +1 -0
  43. package/dist/daemon/receipts.js +428 -80
  44. package/dist/daemon/receipts.js.map +1 -1
  45. package/dist/daemon/route.js +133 -19
  46. package/dist/daemon/route.js.map +1 -1
  47. package/dist/daemon/spawn-tmux.js +24 -13
  48. package/dist/daemon/spawn-tmux.js.map +1 -1
  49. package/dist/daemon/steward-guard.js +32 -0
  50. package/dist/daemon/steward-guard.js.map +1 -0
  51. package/dist/daemon/task-registry.js +1 -1
  52. package/dist/daemon/task-registry.js.map +1 -1
  53. package/dist/daemon/tasks.js +12 -4
  54. package/dist/daemon/tasks.js.map +1 -1
  55. package/dist/daemon/usage.js +4 -11
  56. package/dist/daemon/usage.js.map +1 -1
  57. package/dist/daemon/wizard-memory.js +36 -4
  58. package/dist/daemon/wizard-memory.js.map +1 -1
  59. package/dist/daemon/wizard.js +174 -87
  60. package/dist/daemon/wizard.js.map +1 -1
  61. package/dist/mcp/server.js +209 -132
  62. package/dist/mcp/server.js.map +1 -1
  63. package/dist/shared/charter-view.js +35 -0
  64. package/dist/shared/charter-view.js.map +1 -0
  65. package/dist/shared/chat-http.js +134 -32
  66. package/dist/shared/chat-http.js.map +1 -1
  67. package/dist/shared/chat-render.js +6 -3
  68. package/dist/shared/chat-render.js.map +1 -1
  69. package/dist/shared/chat-view.js +17 -6
  70. package/dist/shared/chat-view.js.map +1 -1
  71. package/dist/shared/cli-backends.js +2 -0
  72. package/dist/shared/cli-backends.js.map +1 -1
  73. package/dist/shared/config-meta.js +91 -0
  74. package/dist/shared/config-meta.js.map +1 -0
  75. package/dist/shared/config-writer.js +5 -6
  76. package/dist/shared/config-writer.js.map +1 -1
  77. package/dist/shared/config.js +273 -294
  78. package/dist/shared/config.js.map +1 -1
  79. package/dist/shared/daemon-token.js +18 -0
  80. package/dist/shared/daemon-token.js.map +1 -0
  81. package/dist/shared/detail-render.js +233 -20
  82. package/dist/shared/detail-render.js.map +1 -1
  83. package/dist/shared/detail-store.js +33 -12
  84. package/dist/shared/detail-store.js.map +1 -1
  85. package/dist/shared/effort.js +11 -0
  86. package/dist/shared/effort.js.map +1 -0
  87. package/dist/shared/keepalive.js +5 -5
  88. package/dist/shared/keepalive.js.map +1 -1
  89. package/dist/shared/model-prices.js +258 -0
  90. package/dist/shared/model-prices.js.map +1 -0
  91. package/dist/shared/pricing.js +55 -0
  92. package/dist/shared/pricing.js.map +1 -0
  93. package/dist/shared/reminder.js +18 -4
  94. package/dist/shared/reminder.js.map +1 -1
  95. package/dist/shared/role-render.js +210 -8
  96. package/dist/shared/role-render.js.map +1 -1
  97. package/dist/shared/role-view.js +104 -26
  98. package/dist/shared/role-view.js.map +1 -1
  99. package/dist/shared/session-label.js +4 -0
  100. package/dist/shared/session-label.js.map +1 -1
  101. package/dist/shared/task-file.js +16 -1
  102. package/dist/shared/task-file.js.map +1 -1
  103. package/dist/shared/turn-state.js +24 -0
  104. package/dist/shared/turn-state.js.map +1 -0
  105. package/dist/shared/world.js +116 -13
  106. package/dist/shared/world.js.map +1 -1
  107. package/dist/svr/index.js +2 -1
  108. package/dist/svr/index.js.map +1 -1
  109. package/hooks/pre-tool-use.sh +15 -3
  110. package/package.json +1 -1
  111. package/web/chat.css +226 -74
  112. package/web/chat.js +1075 -370
@@ -5,10 +5,11 @@
5
5
  // 出 该 wizard 这一轮的回复: 复用 renderTurnGroup (文本 + 工具细节), 去掉问句 ——
6
6
  // 问句已经是上面那条入消息了; 本轮用量单独走 `meta`, 客户端写在名字那一行
7
7
  // 断点 视角 role 自己的 /clear /new
8
- import { renderCutMark, renderTurnGroup, splitReminders, escHtml, hashStr, tagSig } from "./detail-render.js";
8
+ import { renderCutMark, renderTurnGroup, splitReminders, escHtml, fmtTs, hashStr, tagSig, turnUsageChips } from "./detail-render.js";
9
9
  import { isTurn, staleAt, turnDone } from "./chat-view.js";
10
10
  import { isKeepaliveTurn } from "./keepalive.js";
11
- import { teammateOf, unwrapMates } from "./role-view.js";
11
+ import { jobProgress } from "./world.js";
12
+ import { channelOf, injectTurnsOf, teammateOf, unwrapMates } from "./role-view.js";
12
13
  // 入消息顶上的一行归因: 这句话不是人打的字时说清是谁派的。
13
14
  // 没有「公开」标记 —— 公开与否是**会话窗口**这一层的事, 不是消息这一层的:
14
15
  // send_peer 的 channel 就是 `isPublic ? channelOf(self) : ""` (daemon/index.ts),
@@ -17,35 +18,195 @@ import { teammateOf, unwrapMates } from "./role-view.js";
17
18
  // 时刻不在这里 —— 它写在气泡外的 .mwho 上 (每条消息只报一次时间), 所以
18
19
  // 没有归因要说时整行省掉, 免得留下一条空的内边距。
19
20
  const mateChip = (mate) => mate === undefined ? "" : `<span class="mchip sys">agent team${mate ? ` · ${escHtml(mate)}` : ""}</span>`;
21
+ /** 工单 badge: 只写工单号, 标题与进度由客户端按此刻的账填 (账会变, 片段的 sig 不该跟着变)。 */
22
+ const jobChip = (r) => r.from?.kind === "peer" && r.from.job ? `<button class="mchip job" data-job="${escHtml(r.from.job)}"></button>` : "";
20
23
  const inMeta = (r) => {
21
24
  const bits = [
22
25
  r.origin ? `<span class="mchip graph" title="graph ${escHtml(r.origin.runId)}">🕸 轮 ${r.origin.round}/${r.origin.rounds} · 步 ${r.origin.step}/${r.origin.steps}</span>` : "",
23
26
  r.from?.kind === "task" ? `<span class="mchip task">⏰ 定时 ${escHtml(r.from.taskId ?? "")}</span>` : "",
24
27
  mateChip(teammateOf(r.userQuery)),
25
- r.from?.job ? `<span class="mchip job">📋 ${escHtml(r.from.job)}</span>` : "",
28
+ jobChip(r),
26
29
  ].filter(Boolean);
27
30
  return bits.length ? `<div class="mmeta">${bits.join("")}</div>` : "";
28
31
  };
32
+ // 回执的定论 —— 标在交回结论的那一方 (答话方) 那一轮的出消息上: 那条消息才是回执;
33
+ // 收回执那一方的回执轮只是读到了它, 不再挂。
34
+ const RCPT = {
35
+ done: "已交", need: "反问", error: "报错", timeout: "超时", silent: "没答", dead: "失联", canceled: "撤回",
36
+ };
37
+ const turnsWhere = (records, pick) => records.filter(isTurn).filter(pick).sort((a, b) => a.createdAt - b.createdAt);
38
+ /** 派活的那些句: 开一轮的问话, 加上插进别人那一轮的插话 (各自一个轮次外形, 见 injectTurnsOf)。 */
39
+ const asksWhere = (records, pick) => records.filter(isTurn).flatMap((t) => [t, ...injectTurnsOf(t)]).filter(pick).sort((a, b) => a.createdAt - b.createdAt);
40
+ /** 一件活的派活那句 = 收信方接手的那一轮的入消息 (续问共用活号, 取最早那一轮)。 */
41
+ const dispatchOf = (records, turn) => indexOf(records).dispatch.get(turn);
42
+ const INDEX = new WeakMap();
43
+ const indexOf = (records) => {
44
+ const hit = INDEX.get(records);
45
+ if (hit)
46
+ return hit;
47
+ const asks = asksWhere(records, (t) => t.from?.kind === "peer" && !t.from.receipt && !!t.from.turn && !!t.userQuery?.trim());
48
+ const dispatch = asks.reduce((m, t) => (m.has(t.from.turn) ? m : m.set(t.from.turn, t)), new Map());
49
+ const byTarget = turnsWhere(records, (t) => !!t.target && !t.agent)
50
+ .reduce((m, t) => m.set(t.target, [...(m.get(t.target) ?? []), t]), new Map());
51
+ const ix = { dispatch, byTarget };
52
+ INDEX.set(records, ix);
53
+ return ix;
54
+ };
55
+ /** 跳到派活那句要的坐标。派活那句常常不在点击处这个会话窗口里 (私聊派的活, 回执落在群里),
56
+ * 所以带上它自己的消息 id / 时刻 / 频道 / 两端 —— 会话键随视角而变, 由客户端算 (片段与视角无关)。 */
57
+ const gotoAttrs = (turn, d) => ` data-goto="${escHtml(turn)}" data-gid="${escHtml(d.id)}:in" data-gts="${d.createdAt}" data-gch="${escHtml(channelOf(d))}"` +
58
+ ` data-gfrom="${escHtml(d.from?.from ?? "")}" data-gto="${escHtml(d.target ?? "")}"`;
59
+ const squash = (s) => s.replace(/\s+/g, " ").trim();
60
+ /** 一轮的终句 (说不清 final 的后端退回最后一段话)。 */
61
+ const finalOf = (t) => {
62
+ const texts = t.items.filter((it) => it.t === "text");
63
+ return (texts.filter((it) => it.final).at(-1) ?? texts.at(-1))?.body ?? "";
64
+ };
65
+ /** 终句压空白后的前 60 字 —— 回执按它认答话轮。按轮次对象记: store 里的对象跨请求不变, 轮次一写就换新对象。 */
66
+ const HEADS = new WeakMap();
67
+ const finalHead = (t) => HEADS.get(t) ?? ((h) => (HEADS.set(t, h), h))(squash(finalOf(t)).slice(0, 60));
68
+ /** 一份回执是答话方哪一轮交回来的。回执轮的那句话就是答话方那一轮的终句原样贴进来 ——
69
+ * 按正文认: 链式续回时终句在它后来的回执轮里, 活号对不上。认不出 (超时 / 失联这类合成的
70
+ * 定论没有正文) 就退回它接手这件活的最后一轮。 */
71
+ const answerOf = (rc, records) => {
72
+ const f = rc.from;
73
+ if (f?.kind !== "peer" || !f.receipt || !f.from)
74
+ return undefined;
75
+ const d = f.turn ? dispatchOf(records, f.turn) : undefined;
76
+ const mine = (indexOf(records).byTarget.get(f.from) ?? []).filter((t) => t.createdAt <= rc.createdAt && t.createdAt >= (d?.createdAt ?? 0));
77
+ const said = squash(rc.userQuery ?? "");
78
+ const byText = mine.filter((t) => ((p) => p.length >= 4 && said.includes(p))(finalHead(t))).at(-1);
79
+ return byText ?? mine.filter((t) => t.from?.kind === "peer" && !t.from.receipt && t.from.turn === f.turn).at(-1);
80
+ };
81
+ /** 答话方的轮次 id → 交回它的那份回执 (同一轮被认领多次取最新)。按 records 快照记一次: 每条出消息都要查。 */
82
+ const RECEIPTS = new WeakMap();
83
+ const receiptsByAnswer = (records) => {
84
+ const hit = RECEIPTS.get(records);
85
+ if (hit)
86
+ return hit;
87
+ const m = turnsWhere(records, (t) => t.from?.kind === "peer" && !!t.from.receipt)
88
+ .reduce((acc, rc) => ((a) => (a ? acc.set(a.id, rc) : acc))(answerOf(rc, records)), new Map());
89
+ RECEIPTS.set(records, m);
90
+ return m;
91
+ };
92
+ /** 回执 chip: 挂在答话方交回结论的那一轮上 —— 定论 + 工单里第几份; 找得到派活那句才可点,
93
+ * 点它跳过去 (跨会话也行)。 */
94
+ const receiptChip = (r, records, dir) => {
95
+ const rc = receiptsByAnswer(records).get(r.id), f = rc?.from;
96
+ if (!rc || f?.kind !== "peer")
97
+ return "";
98
+ const st = f.status ?? "done";
99
+ const seq = f.job && f.total ? ` · ${escHtml(f.job)} 第 ${f.done ?? 0}/${f.total} 份` : "";
100
+ const d = f.turn ? dispatchOf(records, f.turn) : undefined;
101
+ const what = `.${dir.nameOf(r.target ?? "")} 把 ${f.turn ? `${f.turn} ` : ""}的结论交回给 .${dir.nameOf(rc.target ?? "")}`;
102
+ const [tag, attrs] = f.turn && d
103
+ ? ["button", `${gotoAttrs(f.turn, d)} title="${escHtml(`${what} · 点击跳到派活那句`)}"`]
104
+ : ["span", ` title="${escHtml(`${what} · 派活那句已不在记录里`)}"`];
105
+ return `<${tag} class="mchip rcpt st-${escHtml(st)}"${attrs}>↩ 回执 · ${RCPT[st] ?? escHtml(st)}${seq}</${tag}>`;
106
+ };
107
+ /** 这一行移交落成的那句。同一个活号续问多次就有多句 (每次 tell_peer 一句): 按原文认 ——
108
+ * 落地的那句就是原文贴进去的 (外面裹着信封), 取首段比对; 认不出 (没原文) 退回最早那句。 */
109
+ const dispatchFor = (records, h) => {
110
+ const all = asksWhere(records, (t) => t.from?.kind === "peer" && !t.from.receipt && t.from.turn === h.turn && !!t.userQuery?.trim());
111
+ const head = squash(h.text).slice(0, 80);
112
+ return (head.length >= 4 ? all.find((t) => squash(t.userQuery ?? "").includes(head)) : undefined) ?? all[0];
113
+ };
114
+ /** 整行点了要开的那段往来: 移交双方 (发话方 = 这一轮的 role, 收信方) 在哪个频道 —— 派活那句在就以它为准
115
+ * 并带上落点; 还没接手就按这次调用公开与否推 (公开的落在发话方此刻的群)。会话键随视角, 由客户端算。 */
116
+ const pairAttrs = (r, to, h, d) => ` data-hfrom="${escHtml(r.target ?? "")}" data-hto="${escHtml(to)}" data-hch="${escHtml(d ? channelOf(d) : h.public ? channelOf(r) : "")}"` +
117
+ (d ? ` data-gid="${escHtml(d.id)}:in" data-gts="${d.createdAt}"` : "");
118
+ const FAIL = new Set(["timeout", "silent", "dead", "canceled"]);
119
+ /** 移交行的 rolepage 那一半: 对方是名录里的谁 (头像 + 名字), 整行点了开双方的那段往来并落到这一句,
120
+ * 这件活此刻到了哪一步 —— 这一句之后的第一份回执就是它的定论 (need 之后续问再交, 那是下一行的),
121
+ * 没落定就看它接手了没有。每次请求现算, 不进轮次缓存: 回执比派活那一轮晚到, 气泡的 sig 得跟着它变。 */
122
+ const handoffDeco = (r, records, dir, now) => {
123
+ // 老的 clone / spawn 回包不带活号: 分身的开场白就是这件活, 从它收到的第一句 (r 的主人私聊派来的) 读回来。
124
+ const turnOf = (h) => h.turn ?? ((id) => id && (h.via === "clone" || h.via === "spawn")
125
+ ? asksWhere(records, (t) => t.target === id && t.from?.kind === "peer" && !t.from.receipt && t.from.from === r.target && t.createdAt >= r.createdAt)[0]?.from?.turn
126
+ : undefined)(dir.resolve(h.name));
127
+ const landed = (h) => ((turn) => (turn ? dispatchFor(records, { ...h, turn }) : undefined))(turnOf(h));
128
+ return {
129
+ who: (name) => {
130
+ const id = dir.resolve(name);
131
+ return id
132
+ ? `<span class="ho-who"><span class="av">${escHtml(dir.labelOf(id))}</span><span class="nm wizard">${escHtml(dir.nameOf(id))}</span></span>`
133
+ : `<span class="ho-nm">.${escHtml(name)}</span>`;
134
+ },
135
+ role: (name) => ((id) => (id ? ` data-hrole="${escHtml(id)}" title="${escHtml(`以 .${dir.nameOf(id)} 为 viewpoint 看它的往来`)}"` : ""))(dir.resolve(name)),
136
+ plan: () => (r.target ? ` data-hplan="${escHtml(r.target)}"` : ""),
137
+ attrs: (h) => {
138
+ const id = dir.resolve(h.name);
139
+ return id ? `${pairAttrs(r, id, h, landed(h))} title="${escHtml(`打开 .${dir.nameOf(r.target ?? "")} 与 .${dir.nameOf(id)} 的往来, 定位到这一句`)}"` : "";
140
+ },
141
+ status: (h0) => {
142
+ const h = { ...h0, turn: turnOf(h0) };
143
+ if (!h.turn || !h.receipt)
144
+ return { key: "plain", tip: h.kind === "fyi" ? "只是知会, 不等回执" : "不等回执" };
145
+ const d = landed(h);
146
+ const rc = turnsWhere(records, (t) => t.from?.kind === "peer" && !!t.from.receipt && t.from.turn === h.turn && t.createdAt >= (d?.createdAt ?? 0))[0];
147
+ if (!rc)
148
+ return { key: "run", tip: d ? "在办 · 等回执" : "等它接手" };
149
+ const st = rc.from?.status ?? "done";
150
+ const key = st === "done" || st === "need" || st === "error" ? st : FAIL.has(st) ? "fail" : "run";
151
+ return { key, tip: `回执 · ${RCPT[st] ?? st}` };
152
+ },
153
+ acct: (h) => ((d) => (d ? turnUsageChips(d, now) : ""))(((d) => d && hostOf(d, records))(landed(h))),
154
+ };
155
+ };
156
+ /** 派活 / 续问那句带上它的活号, 回执凭它定位回来。 */
157
+ const pturnAttr = (r) => r.from?.kind === "peer" && r.from.turn && !r.from.receipt ? ` data-pturn="${escHtml(r.from.turn)}"` : "";
29
158
  const renderIn = (r) => {
30
159
  const q = splitReminders(unwrapMates(r.userQuery ?? ""));
31
- return tagSig(`<section class="bubble mq" data-key="${escHtml(r.id)}:in">${inMeta(r)}` +
160
+ return tagSig(`<section class="bubble mq" data-key="${escHtml(r.id)}:in"${pturnAttr(r)}>${inMeta(r)}` +
32
161
  `<div class="md-body"></div><script type="text/plain" class="md-src">${escHtml(q.body)}</script>${q.html}</section>`);
33
162
  };
34
163
  /** 子 agent 的轮次内联进父轮 —— 与旧线程视图同一规则 (见 chat-view.threadEntries)。 */
35
- const childrenOf = (records, turnId, now) => records.filter(isTurn)
164
+ const childrenOf = (records, turnId, now, deco) => records.filter(isTurn)
36
165
  .filter((r) => r.agent?.parentTurnId === turnId)
37
166
  .sort((a, b) => a.createdAt - b.createdAt)
38
- .map((c) => renderTurnGroup(c, now));
167
+ .map((c) => renderTurnGroup(c, now, [], true, deco));
39
168
  const base = (m, dir) => ({
40
169
  from: m.from, to: m.to, channel: m.channel,
41
170
  fromName: dir.nameOf(m.from), fromLabel: dir.labelOf(m.from),
42
171
  toName: dir.nameOf(m.to), toLabel: dir.labelOf(m.to),
43
172
  });
173
+ /** `who` 在 `ts` 这一刻正跑着的主会话轮次 —— 它这一刻说出去的话 (派活、插话、notify) 都记在这一轮的账上。 */
174
+ const turnAt = (records, who, ts) => records.filter(isTurn)
175
+ .filter((t) => t.target === who && !t.agent && t.createdAt <= ts)
176
+ .reduce((best, t) => (!best || t.createdAt > best.createdAt ? t : best), undefined);
177
+ /** 插话的轮次外形 (id `<轮>~<序号>`) 没有自己的账: 它落进的那一轮才是。 */
178
+ const hostOf = (t, records) => t.id.includes("~") ? records.filter(isTurn).find((x) => x.id === t.id.slice(0, t.id.indexOf("~"))) : t;
179
+ /** 同伴派来的那句是发话方某一轮里说出去的: 它的账 (模型 / ctx / 耗时) 就是这条入消息的描述 ——
180
+ * 与答话那一侧同一份 chips, 两方会话里同样只藏模型 / ctx。人说的、定时任务放的没有自己的账。 */
181
+ const senderTurn = (r, records) => r.from?.kind === "peer" && r.from.from ? turnAt(records, r.from.from, r.createdAt) : undefined;
182
+ /** notify 贴的那段话装在一个零时长的轮次外形里 (见 messageOfPost): 账记在发话 wizard 贴它时跑着的那一轮。 */
183
+ const POSTS = new WeakMap();
184
+ const isPostTurn = (r, records) => (POSTS.get(records) ?? ((s) => (POSTS.set(records, s), s))(new Set(records.filter((x) => x.kind === "post").map((x) => x.id)))).has(r.id);
185
+ /** 片段里读了 `r` 这一轮的账或结论的**别的**记录 —— `r` 变了它们得跟着重推:
186
+ * 记在 `r` 账上的入消息 / notify, `r` 接手 (或回执) 的那件活所在的移交行, 回执认领的答话轮。 */
187
+ export const dependentsOf = (r, records) => {
188
+ // 先按「r 之后、r 的主人说的」收窄, 再逐条认账 —— 每个脏轮都要算一遍, 不能对全表两两比。
189
+ const mine = (at) => at >= r.createdAt && turnAt(records, r.target ?? "", at)?.id === r.id;
190
+ const said = records.filter((x) => x.kind === "post" ? x.target === r.target && mine(x.createdAt)
191
+ : isTurn(x) && (x.from?.kind === "peer" && x.from.from === r.target && mine(x.createdAt) ||
192
+ // 插话那句的入消息渲染在它落进的那一轮里, 重推的是那一轮
193
+ (x.injects ?? []).some((i) => i.from?.kind === "peer" && i.from.from === r.target && mine(i.ts))));
194
+ const f = r.from?.kind === "peer" ? r.from : undefined;
195
+ const owner = f?.turn ? (f.receipt ? r.target : f.from) : undefined;
196
+ const handed = owner ? records.filter(isTurn).filter((t) => t.target === owner && t.items.some((it) => it.t === "tool_result" && it.body.includes(f.turn))) : [];
197
+ const answered = f?.receipt ? [answerOf(r, records)].filter((t) => !!t) : [];
198
+ return [...new Set([...said, ...handed, ...answered].map((x) => x.id))].filter((id) => id !== r.id);
199
+ };
44
200
  export const renderMsg = (m, records, dir, now) => {
45
201
  const r = m.turn;
202
+ const acct = (t) => (t ? turnUsageChips(t, now) : "");
203
+ const out = (g) => ({
204
+ html: g.html,
205
+ meta: receiptChip(r, records, dir) + jobChip(r) + (isPostTurn(r, records) ? acct(turnAt(records, r.target ?? "", r.createdAt)) : g.meta),
206
+ });
46
207
  const { html, meta } = m.dir === "in"
47
- ? { html: renderIn(r), meta: "" }
48
- : renderTurnGroup(r, now, childrenOf(records, r.id, now), false);
208
+ ? { html: renderIn(r), meta: acct(senderTurn(r, records)) }
209
+ : out(((deco) => renderTurnGroup(r, now, childrenOf(records, r.id, now, deco), false, deco))(handoffDeco(r, records, dir, now)));
49
210
  const live = m.dir === "out" && !turnDone(r, now);
50
211
  return {
51
212
  id: m.id, turnId: r.id, dir: m.dir, ...base(m, dir), ts: m.ts,
@@ -61,4 +222,45 @@ export const renderMark = (mk, role, dir) => {
61
222
  ts: mk.createdAt, ping: false, html: f.html, meta: "", sig: f.sig, staleAt: 0,
62
223
  };
63
224
  };
225
+ // 工单窗口的开工 / 收工两行: 不是哪一轮的消息, 是账本上的两个时刻。收工那行按成员列定论与交付物,
226
+ // 工单不再进群, 这两行就是收工结论唯一的落点; 还开着时开工那行列成员此刻的进度。
227
+ const OUTCOME = { ...RCPT, "": "在干" };
228
+ // 老 daemon 的快照不记成员定论: 收了工却没有定论的, 不说它「在干」。
229
+ /** 阶段的人话: deliver 在根单 = 等验收, 在子单 = 待收工。 */
230
+ export const STAGE_LABEL = (j) => j.status === "closed" || j.stage === "closed" ? (j.kind === "req" ? (j.end === "cancel" ? "取消" : "归档") : "收工")
231
+ : j.stage === "deliver" ? (j.kind === "req" ? "等验收" : "待收工")
232
+ : { plan: "规划", build: "实施", review: "评审", clarify: "澄清", stalled: "卡住", shelved: "搁置" }[j.stage ?? ""] ?? "";
233
+ const memberLine = (mm, dir, closed) => `<li><span class="jo st-${escHtml(mm.outcome ?? (closed ? "none" : "run"))}">${escHtml(mm.outcome ? OUTCOME[mm.outcome] ?? mm.outcome : closed ? "—" : OUTCOME[""])}</span>` +
234
+ (dir.isWizard(mm.target)
235
+ ? `<button class="go" data-r="${escHtml(mm.target)}">${escHtml(dir.labelOf(mm.target))} .${escHtml(dir.nameOf(mm.target))}</button>`
236
+ : `<span>${escHtml(dir.labelOf(mm.target))} ${escHtml(dir.nameOf(mm.target))}</span>`) +
237
+ (mm.role && ROLE_BADGE[mm.role] ? `<span class="jrole r-${mm.role}">${ROLE_BADGE[mm.role]}</span>` : "") +
238
+ (mm.forkOf && dir.isWizard(mm.forkOf) ? `<span class="jfork" title="clone 自它: 材料来自它">材料来自 .${escHtml(dir.nameOf(mm.forkOf))}</span>` : "") +
239
+ (mm.task ? `<em title="${escHtml(mm.task.trim())}">${escHtml(mm.task.trim())}</em>` : "") +
240
+ (mm.artifacts ?? []).map((a) => `<div class="ja">↳ ${escHtml(a.path)}${a.note ? ` — ${escHtml(a.note)}` : ""}</div>`).join("") + "</li>";
241
+ const ROLE_BADGE = { lead: "lead", reviewer: "评审", expert: "专家" };
242
+ /** 子单一行: 标题 + 阶段 + 进度, 点了进那张单 (data-job)。 */
243
+ const childLine = (c) => `<li><button class="go jc" data-job="${escHtml(c.id)}">📋 ${escHtml(c.title)}</button>` +
244
+ `<span class="jo st-run">${escHtml(STAGE_LABEL(c))}</span><span class="jn">${escHtml(c.id)} · ${c.status === "open" ? `${jobProgress(c).done}/${jobProgress(c).total}` : "收工"}</span></li>`;
245
+ export const renderJobMarks = (j, dir, all = []) => {
246
+ const kids = all.filter((x) => x.parent === j.id);
247
+ const kidsHtml = kids.length ? `<ul class="jmem jkids">${kids.map(childLine).join("")}</ul>` : "";
248
+ const owner = { from: j.owner, to: j.owner, channel: j.base };
249
+ const members = j.members.length ? `<ul class="jmem">${j.members.map((mm) => memberLine(mm, dir, j.status === "closed")).join("")}</ul>` : "";
250
+ const row = (phase, ts, body) => {
251
+ const html = tagSig(`<div class="tg-job ${phase}" data-key="j:${escHtml(j.id)}:${phase}">${body}</div>`);
252
+ return { id: `j:${j.id}:${phase}`, turnId: j.id, dir: "mark", ...base(owner, dir), ts, ping: false, html, meta: "", sig: hashStr(html), staleAt: 0 };
253
+ };
254
+ // 计划 / 结论是人写的 markdown, 换行要留着: 交给客户端同一个 markdown 渲染 (breaks:true)。
255
+ const md = (cls, text) => text?.trim() ? `<div class="md-body ${cls}"></div><script type="text/plain" class="md-src">${escHtml(text.trim())}</script>` : "";
256
+ const head = (verb) => `<div class="jh">📋 <b>${escHtml(j.id)}</b> ${verb} · <span class="jt">${escHtml(j.title)}</span><span class="s">${escHtml(fmtTs(verb === "开工" ? j.openedAt : j.closedAt ?? 0))}</span></div>`;
257
+ // 根单: 需求原话 + 验收标准 (人写的, 换行留着)。
258
+ const brief = (j.origin?.text?.trim() ? md("jorigin", `需求: ${j.origin.text.trim()}`) : "") + (j.criteria?.trim() ? md("jcrit", `验收标准: ${j.criteria.trim()}`) : "");
259
+ return [
260
+ row("open", j.openedAt, head("开工") + brief + md("jplan", j.plan) + (j.status === "open" ? members + kidsHtml : "")),
261
+ ...(j.status === "closed" && j.closedAt
262
+ ? [row("close", j.closedAt, head("收工") + members + kidsHtml + md("jsum", j.summary))]
263
+ : []),
264
+ ];
265
+ };
64
266
  //# sourceMappingURL=role-render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"role-render.js","sourceRoot":"","sources":["../../shared/role-render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"role-render.js","sourceRoot":"","sources":["../../shared/role-render.ts"],"names":[],"mappings":"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"}
@@ -7,8 +7,8 @@
7
7
  // 一轮 turn 在这里拆成两条消息:
8
8
  // 入 发话方 → 该 wizard userQuery
9
9
  // 出 该 wizard → 发话方 本轮的回复 (文本 + 工具细节)
10
- // 发话方: 同伴 (from.kind=peer) / 定时任务 (task) / 人 (speaker; 老记录没有就是
11
- // 「人」)。消息落在哪个会话由 channel 决定 —— 公开频道 (群 / 与人的单聊) 按 base
10
+ // 发话方: 同伴 (from.kind=peer) / 定时任务 (task) / 人 (speaker; 认不出就是
11
+ // 「未知」)。消息落在哪个会话由 channel 决定 —— 公开频道 (群 / 与人的单聊) 按 base
12
12
  // 归并, 私聊按对端 wizard 归并。
13
13
  //
14
14
  // role id: wizard 就是它的 target key; 人是 `human:<userid>` (`human:` = 不知道是谁);
@@ -19,6 +19,7 @@
19
19
  import { baseOfKey, labelFor, stripSigil, tagOfKey } from "./session-label.js";
20
20
  import { isGhostTurn, isMark, isPost, isTurn, staleAt, summarizeTag } from "./chat-view.js";
21
21
  import { isKeepaliveTurn } from "./keepalive.js";
22
+ import { jobProgress } from "./world.js";
22
23
  // ── 频道与发话方 ─────────────────────────────────────────────────────
23
24
  /** 见 TurnDetailRecord.channel: 老记录按 from 推 —— peer 私聊, 其余在 home。 */
24
25
  export const channelOf = (r) => r.channel !== undefined
@@ -60,9 +61,14 @@ export const senderOf = (r) => {
60
61
  * 视图把它折成一行 (见 isPing)。 */
61
62
  const convTurns = (records, now) => records.filter(isTurn).filter((r) => !!r.target && !r.agent && !isGhostTurn(r, now));
62
63
  /** 保温 ping 的那一条 —— 进时间轴, 但不进会话列表的条数/预览, 也不算一条关系。 */
63
- export const isPing = (m) => isKeepaliveTurn(m.turn);
64
- /** 一个公开频道里听话的那一方: 与人的单聊是那个人, 群里是「人」。 */
65
- const audienceOf = (channel) => (channel.startsWith("user:") ? humanOf(channel) : "human:");
64
+ export const isPing = (m) => PINGS.get(m.turn) ?? ((v) => (PINGS.set(m.turn, v), v))(isKeepaliveTurn(m.turn));
65
+ /** 按轮次对象记: 判定要对问话跑一串正则, 而 /api/glance 每张卡片都把全部消息筛一遍 ——
66
+ * 关系图几十张卡片就是几十万次。store 里的对象跨请求不变, 轮次一写就换新对象。 */
67
+ const PINGS = new WeakMap();
68
+ /** 一个公开频道里听话的那一方: 与人的单聊是那个人; 群里是这条链的链头 (守护进程写 turn /
69
+ * post 时顺着派活链记下的, 见 Asker) —— 只在他正是在这个群里开的口时才算; 认不出就是
70
+ * `human:` (未知), 不拿群里别的开口的人去猜: 一个 wizard 可能同时在答好几个人。 */
71
+ export const audienceOf = (channel, asker) => channel.startsWith("user:") ? humanOf(channel) : asker?.chat === channel ? humanOf(asker.who) : "human:";
66
72
  /** 回执轮: 守护进程把同伴那一轮的终句原样转进发话方的会话。 */
67
73
  const isReceipt = (r) => r.from?.kind === "peer" && r.from.receipt === true;
68
74
  /** 一轮 → 入/出两条消息。没问话的 (/clear 之后的续跑) 只有出; 还没产出也没在跑
@@ -70,12 +76,19 @@ const isReceipt = (r) => r.from?.kind === "peer" && r.from.receipt === true;
70
76
  * 回执轮例外: 入那一句就是同伴自己那一轮的出 (同一段话, 已在同伴的出消息里), 再画
71
77
  * 一遍就是重复, 所以没有入; 它的出是在频道里对那里的人说的 —— 公开频道答给人, 只有
72
78
  * 私聊回执 ("" 频道, 回复不进任何群) 才仍是对那个同伴。 */
79
+ /** 一轮里的插话 → 各自一个只有问话的轮次外形 (id `<轮>~<序号>`): 出处、频道、发话人都是它自己的,
80
+ * 不随被插的那一轮。它没有自己的回复 —— 回复在被插的那一轮的出消息里。 */
81
+ export const injectTurnsOf = (r) => (r.injects ?? []).map((x, i) => ({
82
+ kind: "turn", id: `${r.id}~${i}`, createdAt: x.ts, updatedAt: x.ts, closed: true, items: [],
83
+ target: r.target, sessionId: r.sessionId, userQuery: x.body, channel: x.channel,
84
+ ...(x.from ? { from: x.from } : {}), ...(x.speaker ? { speaker: x.speaker } : {}),
85
+ }));
73
86
  export const messagesOfTurn = (r) => {
74
87
  const w = r.target;
75
88
  const who = senderOf(r);
76
89
  const channel = channelOf(r);
77
90
  const receipt = isReceipt(r);
78
- const to = receipt && channel ? audienceOf(channel) : who;
91
+ const to = receipt && channel ? audienceOf(channel, r.from?.asker) : who;
79
92
  const firstOut = r.items.reduce((m, it) => Math.min(m, it.ts), Infinity);
80
93
  const inMsg = r.userQuery?.trim() && !receipt
81
94
  ? [{ id: `${r.id}:in`, turn: r, dir: "in", from: who, to: w, channel, ts: r.createdAt }]
@@ -83,7 +96,8 @@ export const messagesOfTurn = (r) => {
83
96
  const outMsg = r.items.length > 0 || !r.closed
84
97
  ? [{ id: `${r.id}:out`, turn: r, dir: "out", from: w, to, channel, ts: Math.max(r.createdAt + 1, Number.isFinite(firstOut) ? firstOut : r.createdAt + 1) }]
85
98
  : [];
86
- return [...inMsg, ...outMsg];
99
+ const injected = injectTurnsOf(r).map((t) => ({ id: `${t.id}:in`, turn: t, dir: "in", from: senderOf(t), to: w, channel: t.channel ?? "", ts: t.createdAt }));
100
+ return [...inMsg, ...outMsg, ...injected];
87
101
  };
88
102
  /** notify 贴进群的一段话 → 发话 wizard 在那个频道里的一条出消息, 对着那里的人说。
89
103
  * 装进一个已收口、只有一段终句的轮次外形, 渲染与未读水位都照出消息的老规矩走。 */
@@ -95,7 +109,7 @@ export const messageOfPost = (p) => ({
95
109
  },
96
110
  dir: "out",
97
111
  from: p.target,
98
- to: audienceOf(p.channel),
112
+ to: audienceOf(p.channel, p.asker),
99
113
  channel: p.channel,
100
114
  ts: p.createdAt,
101
115
  });
@@ -115,7 +129,7 @@ export const makeDirectory = (records, facts) => {
115
129
  if (wizards.has(id))
116
130
  return (facts_.get(id)?.name ?? "").trim() || tagOfKey(id) || chatName(baseOfKey(id)) || id;
117
131
  if (id === "human:")
118
- return "人";
132
+ return "未知";
119
133
  return id.startsWith("human:") ? id.slice(6) : id;
120
134
  };
121
135
  const labelOf = (id) => id.startsWith("task:") ? "⏰" : id === SYSTEM ? "🧙" : wizards.has(id) ? labelFor(nameOf(id)) : "👤";
@@ -141,7 +155,7 @@ export const makeDirectory = (records, facts) => {
141
155
  return undefined;
142
156
  const f = facts_.get(id);
143
157
  const t = untilOf(id);
144
- return { alive: f?.alive ?? false, busy: f?.busy ?? false, runningUntil: t > now ? t : 0 };
158
+ return { alive: f?.alive ?? false, busy: f?.busy ?? false, runningUntil: t > now ? t : 0, ...(f?.waiting?.length ? { waiting: f.waiting } : {}) };
145
159
  };
146
160
  return { nameOf, labelOf, resolve, fact: (id) => facts_.get(id), chatName, isWizard: (id) => wizards.has(id), status, wizards: () => [...wizards] };
147
161
  };
@@ -157,12 +171,13 @@ export const talkOf = (msgs, role, peers = [], chat) => {
157
171
  const withPeer = (m) => isPing(m) ? m.turn.target === role || pick.has(m.turn.target ?? "") : involves(m, role) && pick.has(other(m, role));
158
172
  return msgs.filter((m) => (chat === undefined || m.channel === chat) && (pick.size ? withPeer(m) : involves(m, role)));
159
173
  };
160
- /** `a:<x>` = x 参与的全部对话; `a:<x>|<p1>,<p2>` = x 与这几个对端之间的 —— 不分会话, 按时间排开。 */
174
+ /** `a:<x>` = x 参与的全部对话; `a:<x>|<p1>,<p2>` = x 与这几个对端之间的 —— 不分会话, 按时间排开。
175
+ * 再带一段 `|<base>` 就只在那个频道里 (`a:<x>||<base>` = x 在那个群里的全部记录, 对端不限)。 */
161
176
  export const parseTalkKey = (key) => {
162
177
  if (!key.startsWith("a:"))
163
178
  return undefined;
164
- const [who = "", rest] = key.slice(2).split("|");
165
- return { who, peers: rest ? rest.split(",").filter(Boolean) : [] };
179
+ const [who = "", rest, chat] = key.slice(2).split("|");
180
+ return { who, peers: rest ? rest.split(",").filter(Boolean) : [], ...(chat ? { chat } : {}) };
166
181
  };
167
182
  const stripMd = (s) => s.replace(/[`*_~|#>]/g, "").replace(/\s+/g, " ").trim();
168
183
  /** 一条消息里最后那句话与它说出的时刻: 入 = 问话 (轮次开始); 出 = 最后一段 text ——
@@ -205,17 +220,24 @@ const saidAt = (role) => (m) => {
205
220
  const t = [...m.turn.items].reverse().find((it) => it.t === "text" && (it.final === true || (it.final === undefined && !!m.turn.closed)));
206
221
  return t?.ts;
207
222
  };
223
+ const heardBy = (role) => (ms) => ms.flatMap((m) => {
224
+ const ts = saidAt(role)(m);
225
+ return ts === undefined ? [] : [[ts, m.from, m.to]];
226
+ }).sort((a, b) => a[0] - b[0]).slice(-HEARD_MAX);
227
+ /** 开口之后才进来的话才可能没读过: 回过话 = 读到了那里。回话要有正文 ——
228
+ * 只开了轮次、还在调工具没吐字的那条出消息不算开口 (saidOf 会退回轮次开始的时刻, 那会把
229
+ * 同时进来的问话误当成已读)。 */
230
+ const spokeBy = (role) => (ms) => ms.filter((m) => m.from === role).reduce((t, m) => {
231
+ const said = m.dir === "in" ? m.ts : m.turn.items.filter((it) => it.t === "text").reduce((a, it) => Math.max(a, it.ts ?? 0), 0);
232
+ return Math.max(t, said);
233
+ }, 0);
208
234
  /** 一个 role 参与的全部会话, 最近活动在前。群聊只列它**自己开过口**的 —— 住在里面
209
235
  * (home) 或只是被人叫过一声却没答话的, 都不算参与; 私聊则有往来就在列。 */
210
236
  export const convsOf = (all_, role, dir, now) => {
211
237
  // 会话列表讲的是"谁跟谁说过什么", ping 不是话: 条数与预览都不该被它顶掉。
212
238
  const msgs = all_.filter((m) => !isPing(m));
213
- const heard = (ms) => ms.flatMap((m) => {
214
- const ts = saidAt(role)(m);
215
- return ts === undefined ? [] : [[ts, involves(m, role) ? other(m, role) : ""]];
216
- }).sort((a, b) => a[0] - b[0]).slice(-HEARD_MAX);
217
- // 开口之后才进来的话才可能没读过: 回过话 = 读到了那里。
218
- const spoke = (ms) => ms.filter((m) => m.from === role).reduce((t, m) => Math.max(t, saidOf(m).ts), 0);
239
+ const heard = heardBy(role);
240
+ const spoke = spokeBy(role);
219
241
  const mine = talkOf(msgs, role);
220
242
  const keys = [...new Set(mine.filter((m) => !m.channel || m.from === role).map((m) => convKeyOf(m, role)))];
221
243
  return keys
@@ -226,40 +248,90 @@ export const convsOf = (all_, role, dir, now) => {
226
248
  return {
227
249
  key, kind: "wizard", name: dir.nameOf(peer), label: dir.labelOf(peer), base: "", peer,
228
250
  status: dir.status(peer, now),
229
- ...glanceOr(ms, speakerPrefix(dir, role, [peer])), count: ms.length, heard: heard(ms), mine: spoke(ms), subs: [],
251
+ ...glanceOr(ms, speakerPrefix(dir, role, [peer])), count: ms.length, heard: heard(ms), mine: spoke(ms), subs: [], ...withJobs(ms),
230
252
  };
231
253
  }
232
254
  const base = key.slice(2);
233
255
  const all = msgs.filter((m) => m.channel === base);
234
256
  const others = [...new Set(all.flatMap((m) => [m.from, m.to]))].filter((r) => r !== role && !r.startsWith("task:") && r !== SYSTEM);
257
+ // 子项成对: 群里与视角有往来的每个 role 一项, 内容是「我与它」在这个群里的对话 (与点进去的窗口同一份 talkOf)。
258
+ // 没往来的 count 为 0, 默认不列; 「chat 内全部」下用 whole (它在群里的全部记录) 列出来。
259
+ // 两份 glance 都走 glanceOfTalk —— 关系图卡片 (/api/glance) 的同一个实现。
235
260
  const subs = others
236
261
  .map((r) => {
237
262
  const pair = talkOf(all, role, [r]);
238
- const seen = talkOf(all, r);
239
263
  return {
240
264
  role: r, name: dir.nameOf(r), label: dir.labelOf(r), count: pair.length, mine: spoke(pair),
241
- ...(glance(pair, speakerPrefix(dir, role, [r])) ?? glanceOr(seen, speakerPrefix(dir, role, [r]))), status: dir.status(r, now),
265
+ ...glanceOfTalk(all, role, dir, role, [r], base), status: dir.status(r, now),
266
+ whole: { count: talkOf(all, r).length, ...glanceOfTalk(all, role, dir, r, [], base) }, ...withJobs(pair),
242
267
  };
243
268
  })
244
- // 与我有往来的排前, 再按最近。
245
- .sort((a, b) => Number(b.count > 0) - Number(a.count > 0) || b.lastTs - a.lastTs)
269
+ // 成对的排前 (默认只列它们), 其余按它们自己的记录排 —— 截断时先丢与我无往来的。
270
+ .sort((a, b) => Number(b.count > 0) - Number(a.count > 0) || (a.count ? b.lastTs - a.lastTs : b.whole.lastTs - a.whole.lastTs))
246
271
  .slice(0, SUB_MAX);
247
272
  return {
248
273
  key, kind: "group", base,
249
274
  name: dir.chatName(base) || (base.startsWith("user:") ? dir.nameOf(humanOf(base)) : base.replace(/^chat:/, "").slice(0, 10)),
250
275
  label: "💬",
251
- ...glanceOr(all, speakerPrefix(dir, role)), count: all.length, heard: heard(all), mine: spoke(all), subs,
276
+ ...glanceOr(all, speakerPrefix(dir, role)), count: all.length, heard: heard(all), mine: spoke(all), subs, ...withJobs(all),
252
277
  };
253
278
  })
254
279
  .sort((a, b) => b.lastTs - a.lastTs);
255
280
  };
281
+ // ── 工单 ─────────────────────────────────────────────────────────────
282
+ // `j:<id>` 是一张工单的全部往来: 归在它名下的派活、各成员的答话、送回开单者的回执 —— 不分
283
+ // 谁对谁, 也不按视角的 session 段裁 (成员各有各的 session)。开工 / 收工两行不是消息, 由
284
+ // chat-http 按 facts 现画。
285
+ export const jobOfKey = (key) => (key.startsWith("j:") ? key.slice(2) : undefined);
286
+ export const jobMessages = (msgs, id) => msgs.filter((m) => m.turn.from?.job === id);
287
+ /** 一组消息里出现过的工单号, 去重保序。 */
288
+ export const jobsIn = (msgs) => [...new Set(msgs.map((m) => m.turn.from?.job ?? "").filter(Boolean))];
289
+ const withJobs = (msgs) => ((js) => (js.length ? { jobs: js } : {}))(jobsIn(msgs));
290
+ /** 视角开的、或在里面的工单 —— 主区工单列表的一行, 数据与群 / 私聊同一套 (glance)。不进侧栏。 */
291
+ export const jobConvsOf = (all_, role, dir, jobs) => {
292
+ const msgs = all_.filter((m) => !isPing(m));
293
+ return jobs
294
+ .filter((j) => j.owner === role || j.members.some((mm) => mm.target === role))
295
+ .map((j) => {
296
+ const ms = jobMessages(msgs, j.id);
297
+ const g = glanceOr(ms, speakerPrefix(dir, role));
298
+ return {
299
+ key: `j:${j.id}`, kind: "job", name: j.title, label: "📋", base: j.base,
300
+ preview: g.preview, lastTs: Math.max(g.lastTs, j.closedAt ?? j.openedAt),
301
+ // 工单里的每句话同时也在某个群 / 私聊里, 未读只记在那一处 —— 两边各记一份, 读了一边另一边还亮着。
302
+ count: ms.length, heard: [], mine: 0, subs: [],
303
+ job: { id: j.id, owner: j.owner, status: j.status, ...(j.parent ? { parent: j.parent } : {}), ...(j.kind ? { kind: j.kind } : {}), ...(j.stage ? { stage: j.stage } : {}), ...jobProgress(j) },
304
+ };
305
+ });
306
+ };
307
+ /** 每个 role 对应的全部叶子项 —— 群里的成对子项 (它与某个 role 在那个群里有往来, 与 convsOf 的子项
308
+ * 同一口径) 与私聊项 (有往来就算)。侧栏名字旁的「+N」= 这份减去那一项自己。
309
+ * key 取绝对的 (`c:<base>|<a>|<b>` / `p:<a>|<b>`, 两端排序), 与视角无关。定时与系统不是聊天的一方。 */
310
+ export const chatKeysOf = (all_) => {
311
+ const party = (r) => !!r && !r.startsWith("task:") && r !== SYSTEM;
312
+ const index = all_.filter((m) => !isPing(m)).reduce((idx, m) => {
313
+ const add = (r, k) => idx.set(r, (idx.get(r) ?? new Set()).add(k));
314
+ if (party(m.from) && party(m.to)) {
315
+ const pair = [m.from, m.to].sort().join("|");
316
+ const k = m.channel ? `c:${m.channel}|${pair}` : `p:${pair}`;
317
+ add(m.from, k);
318
+ add(m.to, k);
319
+ }
320
+ return idx;
321
+ }, new Map());
322
+ return Object.fromEntries([...index].map(([r, ks]) => [r, [...ks]]));
323
+ };
256
324
  /** 一个会话窗口里的消息。`withRole` 只对公开频道有意义: 当前 role 与它在这个频道里的往来。
257
325
  * 整个公开频道 (不带 withRole) 是频道里所有人说的话, 不是某个 role 的往来 —— 唯一不走 talkOf 的。 */
258
326
  export const convMessages = (msgs, role, key, withRole) => {
327
+ const job = jobOfKey(key);
328
+ if (job)
329
+ return jobMessages(msgs, job);
259
330
  const t = talkArgs(role, key, withRole);
260
331
  return t ? talkOf(msgs, t.who, t.peers, t.chat) : msgs.filter((m) => m.channel === key.slice(2));
261
332
  };
262
- /** 一个窗口交给 talkOf 的入参; 整个公开频道不是谁的往来, 没有。 */
333
+ /** 一个窗口交给 talkOf 的入参; 整个公开频道不是谁的往来, 没有。群里选中一个子项 (withRole)
334
+ * 看的是视角与它在这个群里的往来。 */
263
335
  export const talkArgs = (role, key, withRole) => {
264
336
  const t = parseTalkKey(key);
265
337
  if (t)
@@ -268,6 +340,12 @@ export const talkArgs = (role, key, withRole) => {
268
340
  return { who: role, peers: [key.slice(2)], chat: "" };
269
341
  return withRole ? { who: role, peers: [withRole], chat: key.slice(2) } : undefined;
270
342
  };
343
+ /** 纯 wizard↔wizard 的私聊窗口 (两端都是 wizard、没限定到某个群): 里面不画断点 ——
344
+ * /new 的是 wizard 自己的上下文 (handoff 重开也记一条), 不是这场对话的边界, 署名还会落到人头上。 */
345
+ export const isWizardDm = (role, key, withRole, dir) => {
346
+ const t = talkArgs(role, key, withRole);
347
+ return !!t && !t.chat && t.peers.length > 0 && [t.who, ...t.peers].every(dir.isWizard);
348
+ };
271
349
  /** 窗口是视角与恰好另一个 role 之间的往来时, 那个 role; 否则 (群 / 多个对端 / 不含视角) 没有。 */
272
350
  export const counterpartOf = (viewer, t) => {
273
351
  if (t?.peers.length !== 1)