@aiti-ai/aiti-git-trace 0.0.0-stage → 0.2.12

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 (41) hide show
  1. package/AGENTS.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +38 -2
  4. package/api.ts +424 -0
  5. package/check-client.mjs +273 -0
  6. package/client/src/common.ts +179 -0
  7. package/client/src/entry.tsx +81 -0
  8. package/client/src/host-shim.ts +118 -0
  9. package/client/src/jsx-runtime.ts +2 -0
  10. package/client/src/panels.tsx +1377 -0
  11. package/client/src/trace-app.tsx +275 -0
  12. package/client/src/trace-files-row.pure.ts +88 -0
  13. package/client/src/trace-files-row.tsx +110 -0
  14. package/client/src/version-mention.ts +90 -0
  15. package/deploy-commit.mjs +52 -0
  16. package/dev-pack.mjs +246 -0
  17. package/dist/aiti-git-trace-client.mjs +4 -0
  18. package/dist/entry-C_le59dp.js +1594 -0
  19. package/dist/panels-BpC4XLni.js +1522 -0
  20. package/ext-icons-deploy.mjs +24 -0
  21. package/icon.svg +1 -0
  22. package/icons/git-branch.svg +1 -0
  23. package/icons/git-commit-horizontal.svg +1 -0
  24. package/index.ts +705 -0
  25. package/package.json +33 -4
  26. package/reconcile-deps.mjs +41 -0
  27. package/reload-instances.mjs +60 -0
  28. package/scripts/aiti-trace.mjs +117 -0
  29. package/skills/index.json +1 -0
  30. package/skills/rollback-session/SKILL.md +34 -0
  31. package/skills/trace-ops/SKILL.md +31 -0
  32. package/skills/watch-path/SKILL.md +34 -0
  33. package/test/fixtures/ops-sample.jsonl +3 -0
  34. package/tools/deploy.mjs +103 -0
  35. package/tools/trace-compact.mjs +58 -0
  36. package/trace-core.test.mjs +1120 -0
  37. package/trace-core.ts +1346 -0
  38. package/trace-files-row.test.mjs +66 -0
  39. package/tsconfig.check.json +21 -0
  40. package/version-mention.test.mjs +76 -0
  41. package/vite.config.ts +43 -0
@@ -0,0 +1,1522 @@
1
+ import { u as x, a as Ke, b as _, j as n, c as o, t as i, d as D, s as Ze, F as Q, e as qe, f as q, g as X, h as Tt, i as Dt, k as zt, l as ke, m as be, n as Ot, o as At, p as Bt, q as Oe, r as T, v as Fe, w as Ht, x as K, y as wt, T as J, z as Ye, A as ie, D as $e, B as Se, W as M, C as Ft, E as ge } from "./entry-C_le59dp.js";
2
+ const Kt = ["docs", "doc", "tmp", "temp", "design", "designs"];
3
+ function j(e) {
4
+ return String(e || "").replace(/\\/g, "/").replace(/\/+$/, "");
5
+ }
6
+ function Ge(e, l) {
7
+ if (!e || !l) return !1;
8
+ const r = j(e), s = j(l);
9
+ return !r || !s ? !1 : r === s || r.startsWith(s + "/") || s.startsWith(r + "/");
10
+ }
11
+ function qt(e, l) {
12
+ return !e || !l ? !1 : l === e || l.startsWith(e + "/");
13
+ }
14
+ function Gt(e, l) {
15
+ const r = new Set((l ?? Kt).map((h) => String(h).toLowerCase()));
16
+ let s = j(e);
17
+ for (; ; ) {
18
+ const h = s.split("/").pop() || "";
19
+ if (!h || !r.has(h.toLowerCase())) break;
20
+ const p = s.lastIndexOf("/");
21
+ if (p <= 0) break;
22
+ s = s.slice(0, p);
23
+ }
24
+ return s;
25
+ }
26
+ function we(e, l) {
27
+ let r = null;
28
+ for (const s of l) {
29
+ const h = j(String(s || ""));
30
+ h && qt(h, e) && (!r || h.length > r.length) && (r = h);
31
+ }
32
+ return r;
33
+ }
34
+ function Vt(e) {
35
+ const l = j(e.targetPath || e.targetDir || ""), r = j(e.targetDir || e.targetPath || ""), s = j(e.currentCwd || "");
36
+ if (!l && !r) return { cwd: s, switched: !1 };
37
+ if (s && (Ge(s, l) || r && r !== l && Ge(s, r)))
38
+ return { cwd: s, switched: !1 };
39
+ const h = [];
40
+ for (const k of Array.isArray(e.watchPaths) ? e.watchPaths : []) {
41
+ if (typeof k == "string") {
42
+ k && h.push(k);
43
+ continue;
44
+ }
45
+ const B = k ?? {};
46
+ h.push(j(B.repoRoot || B.path || ""));
47
+ }
48
+ const p = we(l, h) ?? (r && r !== l ? we(r, h) : null);
49
+ if (p) return { cwd: p, switched: !!s && p !== s };
50
+ const w = (Array.isArray(e.knownWorkspaces) ? e.knownWorkspaces : []).filter(Boolean), v = we(l, w) ?? (r && r !== l ? we(r, w) : null);
51
+ if (v) return { cwd: v, switched: !!s && v !== s };
52
+ const m = Gt(r || l, e.excludeNames), b = we(m, w) || m || r || l || "";
53
+ return { cwd: b, switched: !!s && b !== s };
54
+ }
55
+ function $t(e, l) {
56
+ const r = l ? e.replace(/\\/g, "/").replace(/\/+$/, "") + "/" : e;
57
+ return r.includes(" ") ? `@"${r}" ` : `@${r} `;
58
+ }
59
+ const Zt = 6e4, pe = { t: 0, list: [] };
60
+ async function Yt(e, l) {
61
+ const r = Date.now();
62
+ if (r - pe.t < Zt) return pe.list;
63
+ try {
64
+ const h = await (await l(e("/api/sessions"), { headers: { accept: "application/json" } })).json().catch(() => null), p = /* @__PURE__ */ new Set();
65
+ for (const w of h?.sessions ?? []) {
66
+ const v = j(w?.projectRoot ?? w?.cwd ?? "");
67
+ v && p.add(v);
68
+ }
69
+ pe.list = [...p];
70
+ } catch {
71
+ pe.list = [];
72
+ }
73
+ return pe.t = r, pe.list;
74
+ }
75
+ async function Jt(e) {
76
+ const l = j(e.targetPath || e.targetDir || ""), r = j(e.currentCwd || "");
77
+ if (r && l && Ge(r, l) || !e.targetDir && !e.targetPath) return r;
78
+ const s = e.fetchFn ?? ((...p) => fetch(...p)), h = await Yt(e.apiUrl, s);
79
+ try {
80
+ const w = await (await s(e.apiUrl("/api/extensions/aiti-git-trace/new-session-cwd"), {
81
+ method: "POST",
82
+ headers: { "content-type": "application/json" },
83
+ body: JSON.stringify({
84
+ targetDir: e.targetDir,
85
+ targetPath: e.targetPath || "",
86
+ cwd: e.currentCwd || "",
87
+ knownWorkspaces: h
88
+ })
89
+ })).json().catch(() => ({}));
90
+ if (w?.ok && typeof w.cwd == "string" && w.cwd) return w.cwd;
91
+ } catch {
92
+ }
93
+ return Vt({
94
+ targetDir: e.targetDir,
95
+ targetPath: e.targetPath,
96
+ currentCwd: e.currentCwd,
97
+ knownWorkspaces: h
98
+ }).cwd;
99
+ }
100
+ async function Xt(e) {
101
+ const l = e.windowRef !== void 0 ? e.windowRef : typeof window < "u" ? window : null;
102
+ l && (l.__piWebPendingComposer = { text: e.text, at: Date.now() });
103
+ const r = await Jt({
104
+ targetDir: e.targetDir,
105
+ targetPath: e.targetPath,
106
+ currentCwd: e.currentCwd,
107
+ apiUrl: e.apiUrl,
108
+ fetchFn: e.fetchFn
109
+ });
110
+ (e.dispatch ?? ((h) => (typeof window < "u" ? window : null)?.dispatchEvent?.(h)))(new CustomEvent("pi-web:new-session", { detail: { cwd: r } }));
111
+ }
112
+ async function Je(e) {
113
+ const l = e.extSvc?.("session-manager.mention");
114
+ if (l?.openNewSession) {
115
+ await l.openNewSession(e.text, { targetDir: e.targetDir, targetPath: e.targetPath, currentCwd: e.currentCwd });
116
+ return;
117
+ }
118
+ await Xt({
119
+ text: e.text,
120
+ targetDir: e.targetDir,
121
+ targetPath: e.targetPath,
122
+ currentCwd: e.currentCwd,
123
+ apiUrl: e.apiUrl,
124
+ fetchFn: e.fetchFn,
125
+ dispatch: e.dispatch,
126
+ windowRef: e.windowRef
127
+ });
128
+ }
129
+ const bt = (e) => e ? String(e).slice(0, 7) : "", Qt = (e) => String(e || "").replace(/\/+$/, "");
130
+ function Xe(e) {
131
+ const l = $t(e.path), r = Qt(e.root), s = `${r}/.aiti-trace`, h = e.target || null, p = e.base || null;
132
+ if (!h)
133
+ return l + "(⏱ 时间线工作区版本,无边路 commit;可能非当前文件)";
134
+ const w = [`after=${bt(h)}`];
135
+ if (p && p !== h && w.push(`base=${bt(p)}`), e.line != null) {
136
+ const c = e.lineKind === "old" ? "(旧文件)" : e.lineKind === "new" ? "(新文件)" : "";
137
+ w.push(`行${e.line}${c}`);
138
+ }
139
+ const v = `git --git-dir=${s} --work-tree=${r} show ${h}:${e.path}`, m = p && p !== h ? `
140
+ 或查看区间 diff:
141
+ git --git-dir=${s} --work-tree=${r} diff ${p}..${h} -- ${e.path}` : "";
142
+ return l + `
143
+ (⏱ 时间线历史版本 ${w.join(" ")};非当前文件,边路仓查看:
144
+ ${v}${m})`;
145
+ }
146
+ function en(e, l) {
147
+ let r = 0, s = 0, h = !1;
148
+ for (let p = 0; p <= l && p < e.length; p++) {
149
+ const w = e[p] || "", v = w.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
150
+ if (v) {
151
+ if (s = parseInt(v[1], 10), r = parseInt(v[3], 10), h = !0, p === l) return { line: null, lineKind: "hunk" };
152
+ continue;
153
+ }
154
+ if (h) {
155
+ if (p === l)
156
+ return w.startsWith("+") ? { line: r, lineKind: "new" } : w.startsWith("-") ? { line: s, lineKind: "old" } : { line: r, lineKind: "context" };
157
+ w.startsWith("+") ? r++ : (w.startsWith("-") || r++, s++);
158
+ }
159
+ }
160
+ return { line: null, lineKind: "other" };
161
+ }
162
+ function Et() {
163
+ return /* @__PURE__ */ o("svg", { width: 12, height: 12, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": !0, children: [
164
+ /* @__PURE__ */ n("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
165
+ /* @__PURE__ */ n("path", { d: "M3 3v5h5" })
166
+ ] });
167
+ }
168
+ function pn(e) {
169
+ return Qe(e, "float");
170
+ }
171
+ function hn(e) {
172
+ return Qe(e, "left");
173
+ }
174
+ function gn(e) {
175
+ return Qe(e, "right");
176
+ }
177
+ function Qe(e, l) {
178
+ Tt(e);
179
+ const [, r, s] = Dt("watch"), h = l === "float" ? s === "floating" : l === "right" ? s === "docked:right-panel" : zt(s), [p, w] = x(Se()), [v, m] = x(""), [c, b] = x(null), [k, B] = x(!1), [P, O] = x(null), [S, U] = x(""), [Ee, xe] = x(!0), [ee, N] = x(""), [Pe, G] = x(!1), [ue, Ne] = x(""), [re, oe] = x(null);
180
+ async function V(g) {
181
+ const R = (g ?? p).trim();
182
+ if (!R) {
183
+ N("cwd?");
184
+ return;
185
+ }
186
+ const W = await q("/workspace/resolve", { cwd: R, session: X() || void 0 });
187
+ if (!W.ok) {
188
+ N(W.error || "resolve failed");
189
+ return;
190
+ }
191
+ m(W.key), b(W.config), B(!!W.nogit), O(W.loose || null), Ne(W.repoRoot || R), oe(W.sessionStores || []), N("");
192
+ }
193
+ _(() => {
194
+ if (!h) return;
195
+ let g = p.trim();
196
+ if (!g) {
197
+ const R = SVC_SESSION?.cwd || CURRENT_SESSION?.cwd || "";
198
+ R && (w(R), g = R);
199
+ }
200
+ g ? V(g) : N(i("gt.watch.needCwd"));
201
+ }, [h, e?.currentSession?.id]);
202
+ async function H(g) {
203
+ if (!v) return;
204
+ const R = await q("/workspace", { key: v, ...g });
205
+ R.ok && (b(R.config), N(i("gt.watch.saved")), setTimeout(() => N(""), 1500));
206
+ }
207
+ async function Le() {
208
+ const g = S.trim();
209
+ if (!g || !c) return;
210
+ const R = await q("/watch/resolve", { path: g }), W = {
211
+ path: R.path || g,
212
+ origin: "user",
213
+ repoRoot: R.repoRoot || R.nested && R.nested[0] || null,
214
+ addedAt: Date.now()
215
+ }, Re = [...(c.paths || []).filter((fe) => fe.path !== W.path), W];
216
+ U(""), await H({ autoDiscover: c.autoDiscover, paths: Re });
217
+ }
218
+ async function le(g) {
219
+ c && await H({ autoDiscover: c.autoDiscover, paths: (c.paths || []).filter((R) => R.path !== g) });
220
+ }
221
+ async function ae() {
222
+ c && await H({ enabled: c.enabled !== !1, autoDiscover: !c.autoDiscover, paths: c.paths || [] });
223
+ }
224
+ async function se() {
225
+ c && await H({ enabled: c.enabled === !1, autoDiscover: c.autoDiscover, paths: c.paths || [] });
226
+ }
227
+ async function Ce() {
228
+ if (!ue) return;
229
+ const g = await q("/cleanup", { scope: "workspace", root: ue });
230
+ G(!1), N(g.ok ? i("gt.watch.cleanupDone") + ` (${i("gt.watch.cleanupSessions")}: ${g.sessions}${g.storeRemoved ? " · " + i("gt.watch.cleanupStore") : ""})` : g.error || "cleanup failed"), V();
231
+ }
232
+ const Z = l === "left" ? M : void 0;
233
+ if (Ot(M), At(Z, Z ? { refresh: () => {
234
+ V();
235
+ } } : null), Bt(Z, Z ? { cwd: p } : null), !h) return null;
236
+ const ye = s === "floating", ce = /* @__PURE__ */ o(Q, { children: [
237
+ /* @__PURE__ */ o("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }, children: [
238
+ ye && /* @__PURE__ */ o("b", { children: [
239
+ "⎇ ",
240
+ i("gt.watch.title")
241
+ ] }),
242
+ ye && /* @__PURE__ */ n("button", { title: i("gt.common.close"), onClick: () => r(!1), style: { background: "none", border: "none", color: "var(--text-muted)", cursor: "pointer", fontSize: 18, lineHeight: 1, padding: "0 4px" }, children: "×" })
243
+ ] }),
244
+ /* @__PURE__ */ o("div", { style: Ze, children: [
245
+ k && P?.allowed ? /* @__PURE__ */ o("div", { style: { border: "1px solid #2da44e", color: "#1a7f37", background: "var(--bg-subtle)", borderRadius: 6, padding: "6px 10px", marginBottom: 8 }, children: [
246
+ "⏣ ",
247
+ i("gt.watch.loose")
248
+ ] }) : k ? /* @__PURE__ */ o("div", { style: { border: "1px solid #d4a72c", color: "#9a6700", background: "var(--bg-subtle)", borderRadius: 6, padding: "6px 10px", marginBottom: 8 }, children: [
249
+ "⚠ ",
250
+ P?.reason === "no-git-oversize" ? i("gt.watch.oversize") : P?.reason === "no-git-denylist" ? i("gt.watch.denied") : i("gt.watch.nogit")
251
+ ] }) : null,
252
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, marginBottom: 8 }, children: [
253
+ /* @__PURE__ */ n("input", { style: Fe, value: p, onChange: (g) => w(g.target.value), placeholder: "cwd…" }),
254
+ /* @__PURE__ */ n("button", { style: D, onClick: V, children: "resolve" })
255
+ ] }),
256
+ c ? /* @__PURE__ */ o("div", { children: [
257
+ /* @__PURE__ */ o("label", { title: i("gt.watch.traceOffHint"), style: { display: "flex", gap: 6, alignItems: "center", marginBottom: 6, fontWeight: 600 }, children: [
258
+ /* @__PURE__ */ n("input", { type: "checkbox", checked: c.enabled !== !1, onChange: se }),
259
+ /* @__PURE__ */ n("span", { children: i("gt.watch.traceEnabled") })
260
+ ] }),
261
+ c.enabled === !1 && /* @__PURE__ */ o("div", { style: { border: "1px solid #d4a72c", color: "#9a6700", background: "var(--bg-subtle)", borderRadius: 6, padding: "6px 10px", marginBottom: 8 }, children: [
262
+ "⏸ ",
263
+ i("gt.watch.traceOff")
264
+ ] }),
265
+ /* @__PURE__ */ n("div", { style: { border: "1px dashed var(--border)", opacity: 0.75, borderRadius: 6, padding: "6px 10px", marginBottom: 8, fontSize: 12 }, children: i("gt.watch.experimental") }),
266
+ /* @__PURE__ */ o("label", { style: { display: "flex", gap: 6, alignItems: "center", marginBottom: 8 }, children: [
267
+ /* @__PURE__ */ n("input", { type: "checkbox", checked: !!c.autoDiscover, onChange: ae }),
268
+ /* @__PURE__ */ n("span", { children: i("gt.watch.auto") })
269
+ ] }),
270
+ (re || []).length > 0 && /* @__PURE__ */ o("div", { style: { marginBottom: 8 }, children: [
271
+ /* @__PURE__ */ n("div", { style: { fontSize: 10.5, opacity: 0.7, marginBottom: 4 }, children: i("gt.watch.sessionRepos") }),
272
+ /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: re.map((g) => {
273
+ const R = (c.paths || []).some((W) => W.repoRoot === g.root || W.path === g.root);
274
+ return /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: 11.5 }, children: [
275
+ /* @__PURE__ */ n("span", { style: { ...K("cross"), cursor: "default", marginLeft: 0 }, children: g.role === "primary" ? i("gt.watch.rolePrimary") : i("gt.watch.roleSecondary") }),
276
+ /* @__PURE__ */ n("span", { style: { fontFamily: "monospace", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1, minWidth: 0 }, title: g.root, children: String(g.root).split("/").pop() }),
277
+ R ? /* @__PURE__ */ n("span", { style: { fontSize: 10.5, opacity: 0.6 }, children: i("gt.watch.pinned") }) : /* @__PURE__ */ o("button", { style: { ...D, padding: "2px 8px", fontSize: 11 }, title: i("gt.watch.pinTip"), onClick: () => {
278
+ const W = { path: g.root, origin: "user", repoRoot: g.root, addedAt: Date.now() };
279
+ H({ enabled: c.enabled !== !1, autoDiscover: c.autoDiscover, paths: [...c.paths || [], W] });
280
+ }, children: [
281
+ "+ ",
282
+ i("gt.watch.pin")
283
+ ] })
284
+ ] }, g.root);
285
+ }) })
286
+ ] }),
287
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, marginBottom: 8 }, children: [
288
+ /* @__PURE__ */ n(
289
+ "input",
290
+ {
291
+ style: Fe,
292
+ value: S,
293
+ onChange: (g) => U(g.target.value),
294
+ placeholder: i("gt.watch.placeholder")
295
+ }
296
+ ),
297
+ /* @__PURE__ */ n("button", { style: D, onClick: Le, children: i("gt.watch.add") })
298
+ ] }),
299
+ (c.paths || []).length === 0 ? /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.watch.empty") }) : null,
300
+ /* @__PURE__ */ o("div", { style: { borderTop: "1px solid var(--border,#eee)", paddingTop: 8, marginTop: 4 }, children: [
301
+ Pe ? /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, alignItems: "center", flexWrap: "wrap" }, children: [
302
+ /* @__PURE__ */ n("span", { style: { fontSize: 11, color: "#c62828" }, children: i("gt.watch.cleanupConfirm") }),
303
+ /* @__PURE__ */ n("button", { style: { ...D, color: "#fff", background: "#c62828", borderColor: "#c62828" }, onClick: Ce, children: i("gt.common.confirm") }),
304
+ /* @__PURE__ */ n("button", { style: D, onClick: () => G(!1), children: i("gt.common.cancel") })
305
+ ] }) : /* @__PURE__ */ n("button", { style: { ...D, color: "#c62828", borderColor: "rgba(198,40,40,.5)" }, title: i("gt.watch.cleanupTip"), onClick: () => G(!0), children: i("gt.watch.cleanup") }),
306
+ /* @__PURE__ */ n("div", { style: { fontSize: 10.5, opacity: 0.7, marginTop: 4 }, children: i("gt.watch.cleanupTip") })
307
+ ] }),
308
+ (c.paths || []).length > 0 && /* @__PURE__ */ o("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
309
+ /* @__PURE__ */ n("thead", { children: /* @__PURE__ */ o("tr", { style: { opacity: 0.7, textAlign: "left" }, children: [
310
+ /* @__PURE__ */ n("th", { style: he, children: i("gt.watch.origin") }),
311
+ /* @__PURE__ */ n("th", { style: he, children: i("gt.watch.repo") }),
312
+ /* @__PURE__ */ n("th", { style: he })
313
+ ] }) }),
314
+ /* @__PURE__ */ n("tbody", { children: (c.paths || []).map((g) => /* @__PURE__ */ o("tr", { children: [
315
+ /* @__PURE__ */ o("td", { style: { ...he, wordBreak: "break-all" }, children: [
316
+ g.path,
317
+ " ",
318
+ /* @__PURE__ */ o("span", { style: { opacity: 0.6 }, children: [
319
+ "[",
320
+ g.origin,
321
+ "]"
322
+ ] }),
323
+ g.repoRoot ? null : /* @__PURE__ */ n("span", { style: K("nongit"), children: i("gt.watch.nongit") })
324
+ ] }),
325
+ /* @__PURE__ */ n("td", { style: { ...he, opacity: 0.75, whiteSpace: "nowrap" }, children: g.repoRoot ? "✓" : "—" }),
326
+ /* @__PURE__ */ n("td", { style: he, children: /* @__PURE__ */ n("button", { style: D, onClick: () => le(g.path), children: i("gt.watch.del") }) })
327
+ ] }, g.path)) })
328
+ ] }),
329
+ ee ? /* @__PURE__ */ n("div", { style: { marginTop: 6, color: "#1a7f37" }, children: ee }) : null,
330
+ /* @__PURE__ */ o("div", { style: { marginTop: 8, opacity: 0.65, fontSize: 11 }, children: [
331
+ "key = ",
332
+ v || "—"
333
+ ] })
334
+ ] }) : /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: "resolve cwd → …" })
335
+ ] })
336
+ ] });
337
+ if (ye)
338
+ return /* @__PURE__ */ n("div", { style: { ...Ye, zIndex: 10060 }, "data-ext-float": "1", "data-ext-float-full": "1", "data-ext-float-w": 460, "data-ext-float-h": 640, "data-ext-float-key": M, "data-ext-float-dock": `${ie(M)} right-panel`, "data-ext-float-dock-default": ie(M), children: ce });
339
+ const Ie = [ie(M), "right-panel"], de = /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", minHeight: 0, height: "100%", color: "var(--text)", fontSize: 12, padding: "8px 10px", boxSizing: "border-box" }, children: ce });
340
+ if (l === "right")
341
+ return /* @__PURE__ */ n(
342
+ $e,
343
+ {
344
+ itemKey: M,
345
+ zone: "right-panel",
346
+ title: "关注路径",
347
+ chrome: "tab",
348
+ zones: Ie,
349
+ defaultZone: ie(M),
350
+ children: de
351
+ }
352
+ );
353
+ const $ = [
354
+ { id: "refresh", title: i("gt.common.refresh") || "刷新", icon: /* @__PURE__ */ n(Et, {}), visibility: "always", onClick: () => {
355
+ Ft(M, "refresh");
356
+ } }
357
+ ];
358
+ return /* @__PURE__ */ n(
359
+ $e,
360
+ {
361
+ itemKey: M,
362
+ title: "关注路径",
363
+ chrome: "section",
364
+ kind: "dockable",
365
+ zones: Ie,
366
+ defaultZone: ie(M),
367
+ headerActions: $,
368
+ children: de
369
+ }
370
+ );
371
+ }
372
+ const he = { padding: "4px 6px", borderBottom: "1px solid var(--border)", textAlign: "left", verticalAlign: "top" };
373
+ function vt(e, l) {
374
+ const r = String(l || "");
375
+ return !r || e.root && e.root + "/" + e.path === r ? !0 : ("/" + e.path).endsWith("/" + r) || r.endsWith("/" + e.path);
376
+ }
377
+ const ne = {
378
+ display: "inline-flex",
379
+ alignItems: "center",
380
+ gap: 3,
381
+ padding: "2px 8px",
382
+ borderRadius: 6,
383
+ fontSize: 10.5,
384
+ cursor: "pointer",
385
+ border: "1px solid var(--border)",
386
+ background: "transparent",
387
+ color: "var(--text-muted)"
388
+ }, kt = { ...ne, background: "#0969da", color: "#fff", borderColor: "#0969da" };
389
+ function St(e, l) {
390
+ const r = String(l || ""), s = r.startsWith("/") || /^[A-Za-z]:[\\/]/.test(r) ? r : String(e || "").replace(/\/+$/, "") + "/" + r, h = String(Se() || ""), p = h && s.startsWith(h) ? s.slice(h.length).replace(/^[/\\]+/, "") : s;
391
+ return $t(p);
392
+ }
393
+ function xt(e, l) {
394
+ try {
395
+ navigator.clipboard.writeText(e);
396
+ } catch {
397
+ }
398
+ if (!l) return;
399
+ const r = l.textContent;
400
+ l.textContent = "✓ " + i("gt.timeline.copied"), l.style.color = "#1a7f37", setTimeout(() => {
401
+ try {
402
+ l.textContent = r, l.style.color = "";
403
+ } catch {
404
+ }
405
+ }, 1200);
406
+ }
407
+ async function tn(e, l) {
408
+ const r = Xe({
409
+ path: String(e.path || ""),
410
+ root: String(e.root || ""),
411
+ base: l?.base || null,
412
+ target: l?.target || null
413
+ }), s = String(e.root || "").replace(/\/+$/, "") + "/" + e.path;
414
+ try {
415
+ await Je({
416
+ text: r,
417
+ targetDir: String(e.root || ""),
418
+ targetPath: s,
419
+ currentCwd: Se(),
420
+ apiUrl: ke,
421
+ extSvc: ge
422
+ });
423
+ } catch {
424
+ }
425
+ }
426
+ async function nn(e) {
427
+ const l = Xe({ path: String(e.path || ""), root: "" }), r = String(e.path || "").replace(/[/\\][^/\\]+$/, "") || "/";
428
+ try {
429
+ await Je({
430
+ text: l,
431
+ targetDir: r,
432
+ targetPath: String(e.path || ""),
433
+ currentCwd: Se(),
434
+ apiUrl: ke,
435
+ extSvc: ge
436
+ });
437
+ } catch {
438
+ }
439
+ }
440
+ const ve = "aiti-git-trace.timeline.view2", rn = "aiti-git-trace.timeline.view";
441
+ function on() {
442
+ try {
443
+ const e = localStorage.getItem(ve);
444
+ if (e === "overview" || e === "msg" || e === "tree") return e;
445
+ const l = localStorage.getItem(rn);
446
+ if (l === "tree")
447
+ return localStorage.setItem(ve, "tree"), "tree";
448
+ if (l === "msg" || l === "file")
449
+ return localStorage.setItem(ve, "overview"), "overview";
450
+ } catch {
451
+ }
452
+ return "overview";
453
+ }
454
+ const He = (e) => {
455
+ const l = String(e || "").split("/").filter(Boolean);
456
+ return l.length ? l[l.length - 1] : String(e || "");
457
+ }, F = (e) => Number(e || 0).toLocaleString(), ln = (e) => e === "A" ? "#1a7f37" : e === "D" ? "#cf222e" : e === "R" || e === "C" ? "#0969da" : "#9a6700";
458
+ function an(e) {
459
+ const [l, r] = x(400), s = String(e.text || "").split(`
460
+ `), h = s.slice(0, l), p = (c) => c.startsWith("@@") ? { color: "var(--text-dim)", background: "var(--bg-subtle)" } : c.startsWith("+") ? { color: "#1a7f37", background: "rgba(46,160,67,.13)" } : c.startsWith("-") ? { color: "#cf222e", background: "rgba(207,34,46,.10)" } : { color: "var(--text-muted)" }, w = !!(e.root && e.path), v = (c) => {
461
+ if (!w) return;
462
+ const b = en(s, c), k = Xe({
463
+ path: e.path,
464
+ root: e.root,
465
+ base: e.base || null,
466
+ target: e.target || null,
467
+ line: b.line,
468
+ lineKind: b.lineKind
469
+ }), B = String(e.root || "").replace(/\/+$/, "") + "/" + e.path;
470
+ Je({
471
+ text: k,
472
+ targetDir: e.root,
473
+ targetPath: B,
474
+ currentCwd: Se(),
475
+ apiUrl: ke,
476
+ extSvc: ge
477
+ }).catch(() => {
478
+ });
479
+ }, m = { flexShrink: 0, marginLeft: 4, padding: "0 4px", fontSize: 10, cursor: "pointer", border: "1px solid var(--border)", background: "transparent", color: "var(--text-muted)", borderRadius: 4 };
480
+ return /* @__PURE__ */ o("div", { style: { border: "1px solid var(--border)", borderRadius: 6, marginBottom: 8, overflow: "hidden" }, children: [
481
+ /* @__PURE__ */ n("div", { style: { maxHeight: 320, overflowY: "auto", background: "var(--bg)", fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11.5, lineHeight: 1.45 }, children: h.map((c, b) => /* @__PURE__ */ o("div", { style: { ...p(c), padding: "0 8px", display: "flex", alignItems: "center" }, children: [
482
+ /* @__PURE__ */ n("span", { style: { flex: 1, whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: c === "" ? " " : c }),
483
+ w ? /* @__PURE__ */ n("button", { style: m, title: i("gt.tl.rowMention"), onClick: () => v(b), children: "@" }) : null
484
+ ] }, b)) }),
485
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 8, alignItems: "center", padding: "4px 8px", borderTop: "1px solid var(--border)", fontSize: 11, flexWrap: "wrap" }, children: [
486
+ s.length > l ? /* @__PURE__ */ n("button", { style: T, onClick: () => r((c) => c + 400), children: i("gt.ov.more") }) : null,
487
+ e.truncated ? /* @__PURE__ */ n("span", { style: { opacity: 0.7 }, children: i("gt.ov.diffTruncated", { n: String(e.total ?? s.length) }) }) : null,
488
+ e.onOpenReview ? /* @__PURE__ */ n("button", { style: T, onClick: e.onOpenReview, children: i("gt.ov.openReview") }) : null
489
+ ] })
490
+ ] });
491
+ }
492
+ function sn(e) {
493
+ const [l, r] = x({ loading: !0 });
494
+ return _(() => {
495
+ let s = !1;
496
+ r({ loading: !0 });
497
+ const h = "/file-diff?root=" + encodeURIComponent(e.root) + "&session=" + encodeURIComponent(e.sid || "") + "&base=" + encodeURIComponent(e.base) + "&target=" + encodeURIComponent(e.target) + "&path=" + encodeURIComponent(e.path);
498
+ return be(h).then((p) => {
499
+ s || (p && p.ok ? r({ loading: !1, text: p.text || "", truncated: !!p.truncated, total: p.total || 0 }) : r({ loading: !1, error: p && p.error || "diff failed" }));
500
+ }).catch(() => {
501
+ s || r({ loading: !1, error: "diff failed" });
502
+ }), () => {
503
+ s = !0;
504
+ };
505
+ }, [e.root, e.sid, e.base, e.target, e.path]), l.loading ? /* @__PURE__ */ n("div", { style: { opacity: 0.6, fontSize: 11, padding: "2px 0 6px" }, children: i("gt.ov.loading") }) : l.error ? /* @__PURE__ */ n("div", { style: { color: "#cf222e", fontSize: 11, padding: "2px 0 6px" }, children: l.error }) : String(l.text || "").trim() ? /* @__PURE__ */ n(an, { text: l.text, truncated: l.truncated, total: l.total, onOpenReview: e.onOpenReview, root: e.root, base: e.base, target: e.target, path: e.path }) : /* @__PURE__ */ n("div", { style: { opacity: 0.6, fontSize: 11, padding: "2px 0 6px" }, children: i("gt.ov.noFiles") });
506
+ }
507
+ function un(e) {
508
+ return et(e, "float");
509
+ }
510
+ function yn(e) {
511
+ return et(e, "right");
512
+ }
513
+ function mn(e) {
514
+ return et(e, "left");
515
+ }
516
+ function et(e, l) {
517
+ Tt(e);
518
+ const [r, s] = x(() => X()), h = e?.currentSession?.id || "";
519
+ _(() => {
520
+ !r && h && s(h);
521
+ }, [h, r]);
522
+ const [p, w] = x(null), [v, m] = x(() => {
523
+ try {
524
+ return localStorage.getItem("aiti-git-trace.timeline.showAll") === "1";
525
+ } catch {
526
+ return !1;
527
+ }
528
+ }), [c, b] = x(on), [k, B] = x(null), [P, O] = x([]), [S, U] = x(null), [Ee, xe] = x(!1), [ee, N] = x(""), [Pe, G] = x(0), [ue, Ne] = x(!1), re = Ke(null), [oe, V] = x([]), [H, Le] = x([]), [le, ae] = x(null), [se, Ce] = x(null), [Z, ye] = x(null), ce = Ke(!1), [, Ie, de] = Dt("timeline", (t) => {
529
+ if (t?.sessionId && (s(t.sessionId), ce.current = !0), t?.entryId && N(String(t.entryId)), t?.view === "file") {
530
+ b("overview");
531
+ try {
532
+ localStorage.setItem(ve, "overview");
533
+ } catch {
534
+ }
535
+ }
536
+ t?.file != null && (Ce(String(t.file)), re.current = String(t.file));
537
+ }), $ = l === "float" ? de === "floating" : l === "right" ? de === "docked:right-panel" : l === "left" ? zt(de) : !1;
538
+ async function g(t) {
539
+ const a = t ?? r ?? X();
540
+ if (!a) return;
541
+ s(a);
542
+ const d = await be("/ops?session=" + encodeURIComponent(a));
543
+ d.ok && (w(d.ops || []), V([]), ye(d.plan?.planRel ?? null));
544
+ }
545
+ _(() => {
546
+ if (!$) return;
547
+ let t = !1;
548
+ return fetch(ke("/api/sessions")).then((a) => a.json()).then((a) => {
549
+ if (t) return;
550
+ const d = a && a.sessions || [], u = SVC_SESSION?.id || CURRENT_SESSION?.id || r, I = d.find((z) => z.id === u), f = I?.projectKey, y = I?.cwd || SVC_SESSION?.cwd || CURRENT_SESSION?.cwd || "", C = d.filter((z) => f ? z.projectKey === f : y ? (z.cwd || "").startsWith(y) : !0).sort((z, te) => (te.modified || 0) - (z.modified || 0));
551
+ Le(C), !r && C.length && (s(C[0].id), g(C[0].id));
552
+ }).catch(() => {
553
+ }), () => {
554
+ t = !0;
555
+ };
556
+ }, [$, r]);
557
+ const R = (t) => t.name || t.firstMessage || t.id.slice(0, 8);
558
+ _(() => {
559
+ if (!$ || c !== "tree" || !r) return;
560
+ let t = !1;
561
+ return be("/lineage?session=" + encodeURIComponent(r)).then((a) => {
562
+ !t && a && a.ok && B(a);
563
+ }).catch(() => {
564
+ }), () => {
565
+ t = !0;
566
+ };
567
+ }, [$, c, r]), _(() => {
568
+ if (!$ || c !== "overview" || !r) return;
569
+ let t = !1;
570
+ xe(!0);
571
+ const a = "/files?session=" + encodeURIComponent(r) + (ee ? "&entryIds=" + encodeURIComponent(ee) : "");
572
+ return be(a).then((d) => {
573
+ if (t) return;
574
+ const u = d && d.ok ? d : null;
575
+ U(u), xe(!1);
576
+ const I = re.current;
577
+ if (I && u && Array.isArray(u.files)) {
578
+ const f = u.files.find((y) => vt(y, I));
579
+ if (f) {
580
+ const y = f.root + "\0" + f.path;
581
+ O((C) => C.includes(y) ? C : [...C, y]);
582
+ }
583
+ re.current = null;
584
+ }
585
+ }).catch(() => {
586
+ t || (U(null), xe(!1));
587
+ }), () => {
588
+ t = !0;
589
+ };
590
+ }, [$, c, r, ee, Pe]), _(() => {
591
+ if (!$ || !r) return;
592
+ let t = !1, a = null, d = null;
593
+ try {
594
+ d = new EventSource(ke(EXT_API + "/events")), d.addEventListener("op", (u) => {
595
+ try {
596
+ if (JSON.parse(String(u?.data || "{}"))?.sessionId !== r) return;
597
+ } catch {
598
+ return;
599
+ }
600
+ a && clearTimeout(a), a = setTimeout(() => {
601
+ t || (g(r), G((I) => I + 1));
602
+ }, 800);
603
+ });
604
+ } catch {
605
+ }
606
+ return () => {
607
+ t = !0, a && clearTimeout(a);
608
+ try {
609
+ d?.close();
610
+ } catch {
611
+ }
612
+ };
613
+ }, [$, r]), _(() => {
614
+ if (!$) return;
615
+ const t = X();
616
+ if (ce.current) {
617
+ ce.current = !1, g(r || t);
618
+ return;
619
+ }
620
+ t && t !== r && s(t), g(t || r);
621
+ }, [$, e?.currentSession?.id]);
622
+ async function W(t) {
623
+ const a = t.stores || [], d = (f) => f.files ? f.files.M + f.files.A + f.files.D : 0, u = a.find((f) => f.before && d(f) > 0) || a.find((f) => f.before && f.after && f.before !== f.after) || a[0];
624
+ if (!u) return;
625
+ if (!u.before) {
626
+ window.alert(i("gt.timeline.partialHint") || "该 op 为首触(无 before),最早可恢复点为其 after 提交");
627
+ return;
628
+ }
629
+ if (!window.confirm(i("gt.timeline.confirm"))) return;
630
+ const I = await q("/rollback-partial", {
631
+ storeRoot: u.root,
632
+ sessionId: r,
633
+ base: u.before,
634
+ target: u.after,
635
+ files: u.paths || [],
636
+ hunkIdx: []
637
+ });
638
+ I && I.ok ? g() : window.alert(I && I.error || "rollback failed");
639
+ }
640
+ async function Re(t) {
641
+ if (!t.before || !t.after) {
642
+ window.alert(i("gt.timeline.partialHint") || "无可逆基线");
643
+ return;
644
+ }
645
+ if (!window.confirm(i("gt.timeline.confirm"))) return;
646
+ const a = await q("/rollback-reversed", {
647
+ storeRoot: t.root,
648
+ sessionId: r,
649
+ refs: [{ op: -1, before: t.before, after: t.after }]
650
+ });
651
+ a && a.ok ? g() : window.alert(a && a.error || "撤销回撤失败");
652
+ }
653
+ function fe(t, a, d) {
654
+ const u = t.stores || [], I = (A) => A.files ? A.files.M + A.files.A + A.files.D : 0, f = a || u.find((A) => A.before && I(A) > 0) || u.find((A) => A.before && A.after && A.before !== A.after) || u[0];
655
+ if (!f || !f.after) {
656
+ window.alert(i("gt.timeline.empty"));
657
+ return;
658
+ }
659
+ if (!f.before) {
660
+ window.alert(i("gt.timeline.partialHint"));
661
+ return;
662
+ }
663
+ const y = t.sessionId || r || X(), C = { source: "trace", storeRoot: f.root, sessionId: y, base: f.before, target: f.after };
664
+ d && d.length && (C.files = d);
665
+ const z = ge("aiti-git-review.open") || window.__aitiGitReviewOpen;
666
+ if (typeof z == "function") {
667
+ z(C);
668
+ return;
669
+ }
670
+ const te = new URLSearchParams(location.search);
671
+ for (const [A, me] of Object.entries(C)) te.set(A, Array.isArray(me) ? JSON.stringify(me) : String(me));
672
+ location.href = location.pathname + "?" + te.toString();
673
+ }
674
+ function tt(t) {
675
+ const a = t.stores || [];
676
+ return a.find((d) => d.before && d.after && d.before !== d.after) || a[0] || null;
677
+ }
678
+ function nt(t, a) {
679
+ const d = t.map(Number).filter((E) => !isNaN(E)).sort((E, Ue) => E - Ue);
680
+ if (!d.length) return;
681
+ const u = String(d[0]), I = String(d[d.length - 1]), f = a[u] || [], y = a[I] || f, C = f.map(tt).find((E) => E && (E.before || E.after)), z = [...y].reverse().map(tt).find((E) => E && E.after);
682
+ if (!C || !z || !z.after) {
683
+ window.alert(i("gt.timeline.empty"));
684
+ return;
685
+ }
686
+ const te = C.before || C.after;
687
+ if (te === z.after) {
688
+ window.alert(i("gt.timeline.empty"));
689
+ return;
690
+ }
691
+ const A = f[0]?.sessionId || r || X(), me = d.length === 1 ? "prompt #" + u : "prompt #" + u + " - #" + I + "(含中间连续组)", ut = { source: "trace", storeRoot: C.root || z.root, sessionId: A, base: te, target: z.after, label: me }, yt = ge("aiti-git-review.open") || window.__aitiGitReviewOpen;
692
+ if (typeof yt == "function") {
693
+ yt(ut);
694
+ return;
695
+ }
696
+ const mt = new URLSearchParams(location.search);
697
+ for (const [E, Ue] of Object.entries(ut)) mt.set(E, String(Ue));
698
+ location.href = location.pathname + "?" + mt.toString();
699
+ }
700
+ function Pt(t) {
701
+ V((a) => a.includes(t) ? a.filter((d) => d !== t) : [...a, t]);
702
+ }
703
+ async function Nt(t) {
704
+ if (!r) return;
705
+ const a = await q("/cleanup", t ? { scope: "session", session: r, beforeOp: t } : { scope: "session", session: r });
706
+ ae(null), a.ok && (w(t ? (p || []).filter((d) => d.op >= t) : []), V([]), G((d) => d + 1));
707
+ }
708
+ function it(t) {
709
+ b(t);
710
+ try {
711
+ localStorage.setItem(ve, t);
712
+ } catch {
713
+ }
714
+ }
715
+ function Lt(t) {
716
+ O((a) => a.includes(t) ? a.filter((d) => d !== t) : [...a, t]);
717
+ }
718
+ function Mt(t, a) {
719
+ const d = (ot ? He(t.root) + "/" : "") + t.path, u = { source: "trace", storeRoot: t.root, sessionId: r || X(), base: a.base, target: a.target, label: d, files: [t.path] }, I = ge("aiti-git-review.open") || window.__aitiGitReviewOpen;
720
+ if (typeof I == "function") {
721
+ I(u);
722
+ return;
723
+ }
724
+ const f = new URLSearchParams(location.search);
725
+ for (const [y, C] of Object.entries(u)) f.set(y, Array.isArray(C) ? JSON.stringify(C) : String(C));
726
+ location.href = location.pathname + "?" + f.toString();
727
+ }
728
+ const We = l === "left" ? J : void 0, Me = Ot(J);
729
+ if (At(We, We ? { refresh: () => {
730
+ G((t) => t + 1), g();
731
+ } } : null), Bt(We, We ? { ops: (p || []).length } : null), !$) return null;
732
+ const rt = (t) => (t.stores || []).reduce((a, d) => a + (d.before && d.files ? (d.files.M || 0) + (d.files.A || 0) + (d.files.D || 0) : 0), 0), Te = (p || []).filter((t) => t?.kind === "rollback"), De = (p || []).filter((t) => t?.kind === "plan-accept" || t?.kind === "plan-discard"), _t = (p || []).filter((t) => t?.kind !== "rollback" && t?.kind !== "plan-accept" && t?.kind !== "plan-discard" && (v || rt(t) > 0 || (t.leaks || []).length > 0)), Y = {};
733
+ for (const t of _t) {
734
+ const a = String(t.msgSeq ?? "?");
735
+ (Y[a] = Y[a] || []).push(t);
736
+ }
737
+ const ze = Array.isArray(S?.files) ? S.files : [], L = S?.totals || null, _e = Array.isArray(S?.stores) ? S.stores : [], jt = new Map(_e.map((t) => [t.root, t])), ot = new Set(ze.map((t) => t.root)).size > 1, lt = se ? ze.filter((t) => vt(t, se)) : ze, Ut = _e.length > 0 && _e.every((t) => t.storeMissing), at = (() => {
738
+ const t = /* @__PURE__ */ new Map();
739
+ for (const a of ze) {
740
+ const d = t.get(a.root) || { root: a.root, adds: 0, dels: 0, files: 0 };
741
+ d.adds += a.adds || 0, d.dels += a.dels || 0, d.files += 1, t.set(a.root, d);
742
+ }
743
+ return [...t.values()];
744
+ })(), st = [];
745
+ {
746
+ const t = /* @__PURE__ */ new Set();
747
+ for (const a of p || []) {
748
+ const d = String(a?.userEntryId || a?.entryId || "");
749
+ !d || t.has(d) || (t.add(d), st.push({ id: d, label: "#" + String(a.msgSeq ?? "?") + " · " + String(a.prompt || i("gt.timeline.group")).slice(0, 40) }));
750
+ }
751
+ }
752
+ const ct = /* @__PURE__ */ o("div", { style: { border: "1px solid #f0c674", borderRadius: 6, overflow: "hidden" }, children: [
753
+ /* @__PURE__ */ o("div", { style: { padding: "6px 10px", background: "rgba(212,167,44,.12)", fontWeight: 600, fontSize: 12, color: "#9a6700" }, children: [
754
+ "↩ ",
755
+ Te.length,
756
+ " 次回撤记录"
757
+ ] }),
758
+ Te.map((t) => {
759
+ const a = t.rollback || {}, d = t.stores || [];
760
+ return /* @__PURE__ */ o("div", { style: { padding: "6px 10px", borderBottom: "1px solid var(--border)" }, children: [
761
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
762
+ /* @__PURE__ */ n("b", { style: { color: "#9a6700" }, children: "↩" }),
763
+ /* @__PURE__ */ n("span", { title: String(t.summary || ""), style: { opacity: 0.9, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", flex: 1, minWidth: 0 }, children: String(t.summary || "") }),
764
+ /* @__PURE__ */ n("span", { style: { opacity: 0.5, fontSize: 11, flexShrink: 0 }, children: Oe(t.t1) })
765
+ ] }),
766
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, marginTop: 4, alignItems: "center", flexWrap: "wrap" }, children: [
767
+ (a.targetOps || []).length ? /* @__PURE__ */ o("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
768
+ "撤销 op:",
769
+ a.targetOps.join(",")
770
+ ] }) : null,
771
+ d.slice(0, 2).map((u) => /* @__PURE__ */ o("span", { style: { fontSize: 11, fontFamily: "monospace", opacity: 0.7 }, children: [
772
+ String(u.root).split("/").pop(),
773
+ ": ",
774
+ u.before?.slice(0, 7),
775
+ "→",
776
+ u.after?.slice(0, 7)
777
+ ] }, u.root)),
778
+ /* @__PURE__ */ n("button", { style: T, title: i("gt.timeline.viewdiff"), onClick: () => fe({ stores: d }, d[0]), children: i("gt.timeline.viewdiff") }),
779
+ /* @__PURE__ */ n("button", { style: T, title: i("gt.timeline.rollback"), onClick: () => d[0] && Re(d[0]), children: i("gt.timeline.rollback") })
780
+ ] })
781
+ ] }, String(t.t1) + String(t.summary || ""));
782
+ })
783
+ ] }), dt = /* @__PURE__ */ o("div", { style: { border: "1px solid #b6a6e8", borderRadius: 6, overflow: "hidden" }, children: [
784
+ /* @__PURE__ */ o("div", { style: { padding: "6px 10px", background: "rgba(122,98,220,.10)", fontWeight: 600, fontSize: 12, color: "#5b45b8" }, children: [
785
+ De.length,
786
+ " 条方案采认记录"
787
+ ] }),
788
+ De.map((t, a) => /* @__PURE__ */ o("div", { style: { padding: "6px 10px", borderBottom: "1px solid var(--border)" }, children: [
789
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
790
+ /* @__PURE__ */ n("b", { style: { color: t.kind === "plan-accept" ? "#0a7d33" : "#9a6700", flexShrink: 0 }, children: t.kind === "plan-accept" ? "采认" : "丢弃" }),
791
+ /* @__PURE__ */ n("span", { title: String(t.summary || ""), style: { opacity: 0.9, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", flex: 1, minWidth: 0 }, children: String(t.summary || "") }),
792
+ /* @__PURE__ */ n("span", { style: { opacity: 0.5, fontSize: 11, flexShrink: 0 }, children: Oe(t.t) })
793
+ ] }),
794
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, marginTop: 4, alignItems: "center", flexWrap: "wrap" }, children: [
795
+ (t.files || []).length ? /* @__PURE__ */ o("span", { style: { fontSize: 11, opacity: 0.7 }, title: (t.files || []).join(`
796
+ `), children: [
797
+ t.files.length,
798
+ " 文件"
799
+ ] }) : null,
800
+ t.mission ? /* @__PURE__ */ o("span", { style: { fontSize: 11, fontFamily: "monospace", opacity: 0.6 }, children: [
801
+ "mission ",
802
+ String(t.mission).slice(0, 8)
803
+ ] }) : null,
804
+ t.sandbox ? /* @__PURE__ */ n("span", { style: { fontSize: 11, fontFamily: "monospace", opacity: 0.5 }, title: String(t.sandbox), children: "sandbox" }) : null
805
+ ] })
806
+ ] }, String(t.t) + String(a)))
807
+ ] }), ft = c === "overview" ? 640 : 560, je = l === "float", pt = /* @__PURE__ */ o(Q, { children: [
808
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 8 }, children: [
809
+ je && /* @__PURE__ */ o("b", { style: { flexShrink: 0 }, children: [
810
+ "⎇ ",
811
+ i("gt.timeline.title")
812
+ ] }),
813
+ /* @__PURE__ */ o(
814
+ "select",
815
+ {
816
+ value: r,
817
+ onChange: (t) => {
818
+ s(t.target.value), N(""), g(t.target.value);
819
+ },
820
+ title: r,
821
+ style: { ...Fe, flex: 1, minWidth: 0, cursor: "pointer" },
822
+ children: [
823
+ r && !H.some((t) => t.id === r) && /* @__PURE__ */ n("option", { value: r, children: r.slice(0, 8) + "…" }),
824
+ H.map((t) => /* @__PURE__ */ n("option", { value: t.id, children: R(t).slice(0, 40) + " · " + new Date(t.modified || 0).toLocaleString() }, t.id))
825
+ ]
826
+ }
827
+ ),
828
+ /* @__PURE__ */ n("button", { style: D, title: i("gt.timeline.load"), onClick: () => {
829
+ g(), c === "overview" && G((t) => t + 1);
830
+ }, children: "↻" }),
831
+ /* @__PURE__ */ n("button", { style: D, title: i("gt.tl.cleanAllTip"), onClick: () => ae({}), children: /* @__PURE__ */ o("svg", { width: 13, height: 13, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": !0, children: [
832
+ /* @__PURE__ */ n("path", { d: "m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21" }),
833
+ /* @__PURE__ */ n("path", { d: "M22 21H7" }),
834
+ /* @__PURE__ */ n("path", { d: "m5 11 9 9" })
835
+ ] }) }),
836
+ Z && /* @__PURE__ */ n("span", { title: "方案绑定:" + Z, style: { display: "inline-flex", alignItems: "center", gap: 4, fontSize: 11, padding: "2px 8px", borderRadius: 6, background: "color-mix(in srgb, var(--warn, #f59e0b) 12%, transparent)", color: "#f59e09", border: "1px solid color-mix(in srgb, var(--warn, #f59e0b) 35%, transparent)", whiteSpace: "nowrap", maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", flexShrink: 0 }, children: Z }),
837
+ /* @__PURE__ */ n("button", { title: i("gt.watch.title"), "aria-label": i("gt.watch.title"), onClick: () => Ht("watch"), style: { background: "none", border: "none", color: "var(--text-muted)", cursor: "pointer", padding: "0 4px", lineHeight: 1, display: "flex", alignItems: "center", flexShrink: 0 }, children: /* @__PURE__ */ o("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": !0, children: [
838
+ /* @__PURE__ */ n("line", { x1: "6", x2: "6", y1: "3", y2: "15" }),
839
+ /* @__PURE__ */ n("circle", { cx: "18", cy: "6", r: "3" }),
840
+ /* @__PURE__ */ n("circle", { cx: "6", cy: "18", r: "3" }),
841
+ /* @__PURE__ */ n("path", { d: "M18 9a9 9 0 0 1-9 9" })
842
+ ] }) }),
843
+ je && /* @__PURE__ */ n("button", { title: i("gt.common.close"), onClick: () => Ie(!1), style: { background: "none", border: "none", color: "var(--text-muted)", cursor: "pointer", fontSize: 18, lineHeight: 1, padding: "0 4px", flexShrink: 0 }, children: "×" })
844
+ ] }),
845
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 6, marginBottom: 10, alignItems: "center", flexWrap: "wrap" }, children: [
846
+ /* @__PURE__ */ n("div", { title: i("gt.timeline.viewTip2"), style: { display: "flex", border: "1px solid var(--border)", borderRadius: 6, overflow: "hidden", flexShrink: 0 }, children: ["overview", "msg", "tree"].map((t) => /* @__PURE__ */ n(
847
+ "button",
848
+ {
849
+ onClick: () => it(t),
850
+ style: {
851
+ ...T,
852
+ border: "none",
853
+ borderRadius: 0,
854
+ marginLeft: 0,
855
+ background: c === t ? "var(--bg-hover)" : "transparent",
856
+ fontWeight: c === t ? 600 : 400,
857
+ opacity: c === t ? 1 : 0.6
858
+ },
859
+ children: t === "overview" ? i("gt.timeline.viewOverview") : t === "msg" ? i("gt.timeline.viewMsg") : i("gt.timeline.viewTree")
860
+ },
861
+ t
862
+ )) }),
863
+ c === "overview" && /* @__PURE__ */ o(
864
+ "select",
865
+ {
866
+ value: ee,
867
+ onChange: (t) => N(t.target.value),
868
+ title: i("gt.timeline.turnFilter"),
869
+ style: { ...Fe, width: "auto", maxWidth: 280, minWidth: 120, cursor: "pointer", flexShrink: 1 },
870
+ children: [
871
+ /* @__PURE__ */ o("option", { value: "", children: [
872
+ "⏱ ",
873
+ i("gt.timeline.allTurns")
874
+ ] }),
875
+ st.map((t) => /* @__PURE__ */ n("option", { value: t.id, children: t.label }, t.id))
876
+ ]
877
+ }
878
+ ),
879
+ c === "msg" && /* @__PURE__ */ o("label", { title: i("gt.timeline.showAll"), style: { display: "flex", alignItems: "center", gap: 4, fontSize: 11, opacity: 0.8, cursor: "pointer", whiteSpace: "nowrap" }, children: [
880
+ /* @__PURE__ */ n("input", { type: "checkbox", checked: v, onChange: (t) => {
881
+ m(t.target.checked);
882
+ try {
883
+ localStorage.setItem("aiti-git-trace.timeline.showAll", t.target.checked ? "1" : "0");
884
+ } catch {
885
+ }
886
+ } }),
887
+ i("gt.timeline.showAll")
888
+ ] }),
889
+ c === "overview" && se && /* @__PURE__ */ o("span", { style: { display: "inline-flex", alignItems: "center", gap: 4, fontSize: 11, padding: "2px 8px", borderRadius: 6, background: "color-mix(in srgb, var(--warn, #f59e0b) 12%, transparent)", color: "#f59e09", border: "1px solid color-mix(in srgb, var(--warn, #f59e0b) 35%, transparent)", whiteSpace: "nowrap", maxWidth: 260, overflow: "hidden", textOverflow: "ellipsis" }, children: [
890
+ "📄 ",
891
+ se.split("/").pop(),
892
+ /* @__PURE__ */ n("button", { onClick: () => Ce(null), title: "清除单文件过滤", style: { background: "transparent", border: "none", color: "inherit", cursor: "pointer", padding: 0, fontWeight: 700 }, children: "×" })
893
+ ] }),
894
+ c === "msg" && oe.length > 0 && /* @__PURE__ */ o("button", { style: D, title: i("gt.timeline.reviewSelTip"), onClick: () => nt(oe, Y), children: [
895
+ "📋 ",
896
+ i("gt.timeline.reviewSel") + " (" + oe.length + ")"
897
+ ] })
898
+ ] }),
899
+ /* @__PURE__ */ o("div", { style: Ze, children: [
900
+ le && /* @__PURE__ */ o("div", { style: { border: "1px solid #c62828", color: "#c62828", borderRadius: 6, padding: "6px 10px", marginBottom: 8, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, children: [
901
+ /* @__PURE__ */ n("span", { style: { fontSize: 11.5, flex: 1, minWidth: 0 }, children: le.beforeOp ? i("gt.tl.cleanBefore", { n: le.beforeOp }) : i("gt.tl.cleanAll") }),
902
+ /* @__PURE__ */ n("button", { style: { ...D, color: "#fff", background: "#c62828", borderColor: "#c62828" }, onClick: () => Nt(le.beforeOp), children: i("gt.common.confirm") }),
903
+ /* @__PURE__ */ n("button", { style: D, onClick: () => ae(null), children: i("gt.common.cancel") })
904
+ ] }),
905
+ c === "tree" ? k && (k.ancestors.length + k.descendants.length > 0 || k.self.opCount > 0) ? /* @__PURE__ */ o("div", { children: [
906
+ /* @__PURE__ */ n("div", { style: { fontSize: 10.5, opacity: 0.7, marginBottom: 10 }, children: i("gt.timeline.treeSummary").replace("{n}", String(k.ancestors.length + 1 + k.descendants.length)) }),
907
+ [
908
+ ...k.ancestors.map((t, a) => ({ n: t, gen: a, kind: "ancestor" })),
909
+ { n: k.self, gen: k.ancestors.length, kind: "self" },
910
+ ...k.descendants.map((t, a) => ({ n: t, gen: t.gen, kind: "descendant" }))
911
+ ].map(({ n: t, gen: a, kind: d }) => {
912
+ const u = H.find((C) => C.id === t.id), I = u ? R(u) : t.id.slice(0, 8) + "…", f = d === "self", y = t.t1 ? new Date(t.t1).toLocaleString() : "";
913
+ return /* @__PURE__ */ o(
914
+ "div",
915
+ {
916
+ onClick: () => {
917
+ f || (s(t.id), g(t.id));
918
+ },
919
+ style: {
920
+ display: "flex",
921
+ alignItems: "center",
922
+ gap: 8,
923
+ padding: "6px 8px",
924
+ paddingLeft: 8 + a * 18,
925
+ marginBottom: 2,
926
+ borderRadius: 6,
927
+ cursor: f ? "default" : "pointer",
928
+ background: f ? "var(--bg-selected,rgba(25,118,210,.12))" : "transparent",
929
+ border: f ? "1px solid var(--border)" : "1px solid transparent"
930
+ },
931
+ title: t.id + (t.cwd ? " · " + t.cwd : ""),
932
+ children: [
933
+ /* @__PURE__ */ n("span", { style: { flexShrink: 0 }, children: d === "self" ? "⭐" : d === "ancestor" ? "📄" : "🌿" }),
934
+ /* @__PURE__ */ o("span", { style: { fontFamily: "ui-monospace, monospace", fontSize: 11.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0, flex: 1, fontWeight: f ? 700 : 500 }, children: [
935
+ I,
936
+ f ? `(${i("gt.timeline.treeCurrent")})` : ""
937
+ ] }),
938
+ t.planRel && /* @__PURE__ */ n("span", { title: "方案绑定:" + t.planRel, style: { fontSize: 10.5, flexShrink: 0, color: "#f59e09" }, children: "📋" }),
939
+ /* @__PURE__ */ o("span", { style: { fontSize: 10.5, opacity: 0.65, flexShrink: 0 }, children: [
940
+ t.opCount,
941
+ " ops",
942
+ y ? " · " + y : ""
943
+ ] }),
944
+ !f && /* @__PURE__ */ n(
945
+ "button",
946
+ {
947
+ style: { ...T, flexShrink: 0 },
948
+ title: i("gt.timeline.treeOpen"),
949
+ onClick: (C) => {
950
+ C.stopPropagation(), s(t.id), g(t.id);
951
+ },
952
+ children: i("gt.timeline.treeOpen")
953
+ }
954
+ ),
955
+ !f && /* @__PURE__ */ n(
956
+ "button",
957
+ {
958
+ style: { ...T, flexShrink: 0 },
959
+ title: "跳转到该会话的消息流",
960
+ onClick: (C) => {
961
+ C.stopPropagation();
962
+ try {
963
+ window.dispatchEvent(new CustomEvent("pi-web:open-session", { detail: { id: t.id } }));
964
+ } catch {
965
+ }
966
+ },
967
+ children: "💬"
968
+ }
969
+ )
970
+ ]
971
+ },
972
+ t.id
973
+ );
974
+ }),
975
+ /* @__PURE__ */ n("div", { style: { fontSize: 10.5, opacity: 0.6, marginTop: 8 }, children: i("gt.timeline.treeTip") })
976
+ ] }) : /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.timeline.treeEmpty") }) : c === "overview" ? /* @__PURE__ */ o(Q, { children: [
977
+ Ee && !S ? /* @__PURE__ */ n("div", { style: { opacity: 0.6 }, children: i("gt.ov.loading") }) : null,
978
+ L ? /* @__PURE__ */ o("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", border: "1px solid var(--border)", borderRadius: 6, padding: "6px 10px", marginBottom: 8, fontSize: 12 }, children: [
979
+ /* @__PURE__ */ o("span", { children: [
980
+ /* @__PURE__ */ n("b", { children: F(L.ops) }),
981
+ " ",
982
+ i("gt.ov.ops")
983
+ ] }),
984
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
985
+ /* @__PURE__ */ o("span", { children: [
986
+ /* @__PURE__ */ n("b", { children: F(L.files) }),
987
+ " ",
988
+ i("gt.ov.files")
989
+ ] }),
990
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
991
+ /* @__PURE__ */ o("span", { style: { color: "#1a7f37", fontWeight: 600 }, children: [
992
+ "+",
993
+ F(L.adds)
994
+ ] }),
995
+ /* @__PURE__ */ o("span", { style: { color: "#cf222e", fontWeight: 600 }, children: [
996
+ "−",
997
+ F(L.dels)
998
+ ] }),
999
+ L.rollbacks > 0 ? /* @__PURE__ */ o(Q, { children: [
1000
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
1001
+ /* @__PURE__ */ o("span", { style: { color: "#9a6700" }, children: [
1002
+ "↩ ",
1003
+ F(L.rollbacks),
1004
+ " ",
1005
+ i("gt.ov.rollbacks")
1006
+ ] })
1007
+ ] }) : null,
1008
+ L.binary > 0 ? /* @__PURE__ */ o(Q, { children: [
1009
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
1010
+ /* @__PURE__ */ o("span", { style: { opacity: 0.6, fontSize: 11 }, children: [
1011
+ i("gt.ov.binary"),
1012
+ " ",
1013
+ F(L.binary)
1014
+ ] })
1015
+ ] }) : null,
1016
+ L.leaks > 0 ? /* @__PURE__ */ o("span", { style: { ...K("leak"), marginLeft: 0, cursor: "pointer" }, title: i("gt.timeline.leak"), onClick: () => it("msg"), children: [
1017
+ i("gt.timeline.leak"),
1018
+ " ",
1019
+ F(L.leaks)
1020
+ ] }) : null,
1021
+ /* @__PURE__ */ n("span", { style: { flex: 1 } }),
1022
+ /* @__PURE__ */ n("span", { style: { opacity: 0.55, fontSize: 10.5 }, children: i("gt.ov.netNote") })
1023
+ ] }) : null,
1024
+ S?.filesTruncated ? /* @__PURE__ */ n("div", { style: { color: "#9a6700", fontSize: 11, marginBottom: 6 }, children: i("gt.ov.filesTruncated") }) : null,
1025
+ at.length > 1 ? /* @__PURE__ */ n("div", { style: { display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 8 }, children: at.map((t) => /* @__PURE__ */ o("span", { style: T, title: t.root, children: [
1026
+ He(t.root),
1027
+ ": ",
1028
+ /* @__PURE__ */ o("span", { style: { color: "#1a7f37" }, children: [
1029
+ "+",
1030
+ F(t.adds)
1031
+ ] }),
1032
+ " ",
1033
+ /* @__PURE__ */ o("span", { style: { color: "#cf222e" }, children: [
1034
+ "−",
1035
+ F(t.dels)
1036
+ ] }),
1037
+ " · ",
1038
+ t.files,
1039
+ " ",
1040
+ i("gt.ov.files")
1041
+ ] }, t.root)) }) : null,
1042
+ Ee || !S ? null : !p || p.length === 0 ? /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.timeline.empty") }) : Ut ? /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.ov.storeMissing") }) : lt.length === 0 ? /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.ov.noFiles") }) : lt.map((t) => {
1043
+ const a = t.root + "\0" + t.path, d = P.includes(a), u = jt.get(t.root), I = !!(u && u.base && u.target && u.base !== u.target && !u.storeMissing && !u.rejected);
1044
+ return /* @__PURE__ */ o("div", { style: { borderBottom: "1px solid var(--border)", padding: "6px 0" }, children: [
1045
+ /* @__PURE__ */ o(
1046
+ "div",
1047
+ {
1048
+ onClick: () => Lt(a),
1049
+ title: i("gt.timeline.fileExpand"),
1050
+ style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", cursor: "pointer" },
1051
+ children: [
1052
+ /* @__PURE__ */ n("span", { style: { ...T, flexShrink: 0, padding: "0 4px" }, children: d ? "▾" : "▸" }),
1053
+ /* @__PURE__ */ n("span", { title: t.status + (t.renamedFrom ? " ← " + t.renamedFrom : ""), style: { color: ln(t.status), fontWeight: 700, fontSize: 11.5, flexShrink: 0 }, children: t.status }),
1054
+ /* @__PURE__ */ o("span", { title: t.root + "/" + t.path, style: { fontFamily: "monospace", fontSize: 12, wordBreak: "break-all", flex: 1, minWidth: 0 }, children: [
1055
+ t.path,
1056
+ ot ? /* @__PURE__ */ o("span", { style: { opacity: 0.55 }, children: [
1057
+ " · ",
1058
+ He(t.root)
1059
+ ] }) : null
1060
+ ] }),
1061
+ /* @__PURE__ */ n("span", { style: { ...K("dim"), marginLeft: 0, flexShrink: 0 }, title: i("gt.timeline.fileTouch"), children: t.touches.length + " " + i("gt.timeline.fileTouch") }),
1062
+ /* @__PURE__ */ o("span", { style: { color: "#1a7f37", fontSize: 11, flexShrink: 0 }, children: [
1063
+ "+",
1064
+ F(t.adds)
1065
+ ] }),
1066
+ /* @__PURE__ */ o("span", { style: { color: "#cf222e", fontSize: 11, flexShrink: 0 }, children: [
1067
+ "−",
1068
+ F(t.dels)
1069
+ ] }),
1070
+ /* @__PURE__ */ n("span", { style: { opacity: 0.5, fontSize: 11, flexShrink: 0 }, children: Oe(t.lastT) }),
1071
+ /* @__PURE__ */ o("span", { style: { display: "inline-flex", gap: 3, flexShrink: 0, flexWrap: "wrap" }, onClick: (f) => f.stopPropagation(), children: [
1072
+ t.status !== "D" ? /* @__PURE__ */ n(
1073
+ "button",
1074
+ {
1075
+ style: kt,
1076
+ title: i("gt.timeline.openFileTip") + " · " + t.root + "/" + t.path,
1077
+ onClick: () => wt(t.root + "/" + t.path, String(t.path || "").split("/").pop() || t.path),
1078
+ children: i("gt.timeline.openFile")
1079
+ }
1080
+ ) : null,
1081
+ /* @__PURE__ */ o("button", { style: ne, title: i("gt.timeline.atRefTip"), onClick: () => qe(St(t.root, t.path)), children: [
1082
+ /* @__PURE__ */ n("b", { style: { fontWeight: 700 }, children: "@" }),
1083
+ i("gt.timeline.atRef")
1084
+ ] }),
1085
+ /* @__PURE__ */ o("button", { style: ne, title: i("gt.timeline.atNewTip"), onClick: () => tn(t, u), children: [
1086
+ /* @__PURE__ */ n("b", { style: { fontWeight: 700 }, children: "@" }),
1087
+ i("gt.timeline.atNew")
1088
+ ] }),
1089
+ /* @__PURE__ */ n("button", { style: ne, title: i("gt.timeline.copyPathTip"), onClick: (f) => xt(t.root + "/" + t.path, f.currentTarget), children: i("gt.timeline.copyPath") })
1090
+ ] })
1091
+ ]
1092
+ }
1093
+ ),
1094
+ d ? /* @__PURE__ */ o("div", { style: { margin: "4px 0 0 24px" }, children: [
1095
+ I ? /* @__PURE__ */ n(
1096
+ sn,
1097
+ {
1098
+ root: t.root,
1099
+ sid: r,
1100
+ base: u.base,
1101
+ target: u.target,
1102
+ path: t.path,
1103
+ onOpenReview: () => Mt(t, u)
1104
+ }
1105
+ ) : /* @__PURE__ */ n("div", { style: { opacity: 0.6, fontSize: 11, padding: "2px 0 6px" }, children: i("gt.timeline.partialHint") }),
1106
+ t.touches.map((f) => /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, padding: "2px 0", flexWrap: "wrap" }, children: [
1107
+ /* @__PURE__ */ o("span", { style: { opacity: 0.6, fontSize: 11, flexShrink: 0 }, children: [
1108
+ "#",
1109
+ f.msgSeq ?? "?",
1110
+ " · ",
1111
+ Oe(f.t1)
1112
+ ] }),
1113
+ f.kind === "rollback" ? /* @__PURE__ */ n("span", { title: i("gt.fork.title"), style: { color: "#9a6700", fontWeight: 600, flexShrink: 0 }, children: "↩" }) : null,
1114
+ /* @__PURE__ */ o("b", { children: [
1115
+ "#",
1116
+ f.op ?? "—"
1117
+ ] }),
1118
+ /* @__PURE__ */ o("span", { title: f.summary || "", style: { opacity: 0.85, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", flex: 1, minWidth: 0 }, children: [
1119
+ f.tool,
1120
+ ": ",
1121
+ String(f.summary || "").slice(0, 60)
1122
+ ] }),
1123
+ f.partial ? /* @__PURE__ */ n("span", { style: K("partial"), children: i("gt.timeline.partial") }) : null,
1124
+ f.truncated ? /* @__PURE__ */ n("span", { title: i("gt.timeline.truncTip"), style: { opacity: 0.6, fontSize: 11 }, children: "…" }) : null,
1125
+ /* @__PURE__ */ n("button", { style: T, title: i("gt.timeline.viewdiff"), onClick: () => fe({ stores: [{ root: t.root, before: f.before, after: f.after }] }, { root: t.root, before: f.before, after: f.after }, [t.path]), children: i("gt.timeline.viewdiff") }),
1126
+ f.kind === "rollback" ? /* @__PURE__ */ n("button", { style: T, title: i("gt.timeline.rollback"), onClick: () => Re({ root: t.root, before: f.before, after: f.after }), children: i("gt.timeline.rollback") }) : /* @__PURE__ */ n("button", { style: T, title: i("gt.timeline.rollback"), onClick: () => W({ stores: [{ root: t.root, before: f.before, after: f.after, paths: [t.path] }] }), children: i("gt.timeline.rollback") })
1127
+ ] }, String(f.op) + String(f.t1) + String(f.kind || "")))
1128
+ ] }) : null
1129
+ ] }, a);
1130
+ }),
1131
+ Te.length > 0 ? /* @__PURE__ */ o("div", { style: { marginTop: 10 }, children: [
1132
+ /* @__PURE__ */ o("div", { onClick: () => Ne((t) => !t), style: { padding: "6px 10px", background: "rgba(212,167,44,.12)", fontWeight: 600, fontSize: 12, color: "#9a6700", border: "1px solid #f0c674", borderRadius: 6, cursor: "pointer" }, children: [
1133
+ ue ? "▾" : "▸",
1134
+ " ↩ ",
1135
+ Te.length,
1136
+ " 次回撤记录"
1137
+ ] }),
1138
+ ue ? /* @__PURE__ */ n("div", { style: { marginTop: 8 }, children: ct }) : null
1139
+ ] }) : null,
1140
+ De.length > 0 ? /* @__PURE__ */ n("div", { style: { marginTop: 10 }, children: dt }) : null
1141
+ ] }) : !p || p.length === 0 ? /* @__PURE__ */ n("div", { style: { opacity: 0.7 }, children: i("gt.timeline.empty") }) : /* @__PURE__ */ o(Q, { children: [
1142
+ ct,
1143
+ De.length > 0 ? /* @__PURE__ */ n("div", { style: { marginTop: 8 }, children: dt }) : null,
1144
+ Object.keys(Y).map((t) => /* @__PURE__ */ o("div", { style: { marginBottom: 10 }, children: [
1145
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }, children: [
1146
+ /* @__PURE__ */ n("input", { type: "checkbox", checked: oe.includes(t), onChange: () => Pt(t), style: { margin: 0, flexShrink: 0 }, title: i("gt.timeline.selGroup") }),
1147
+ /* @__PURE__ */ o("div", { title: Y[t][0]?.prompt || "", style: { opacity: 0.85, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", fontWeight: 600, flex: 1, minWidth: 0 }, children: [
1148
+ "#",
1149
+ t,
1150
+ " · ",
1151
+ Y[t][0]?.prompt || i("gt.timeline.group")
1152
+ ] }),
1153
+ /* @__PURE__ */ n("button", { style: T, onClick: () => nt([t], Y), title: i("gt.timeline.reviewGroup"), children: i("gt.timeline.review") })
1154
+ ] }),
1155
+ Y[t].map((a) => {
1156
+ const d = rt(a), u = (a.stores || []).length > 1, I = (a.leaks || []).length > 0, f = (a.stores || []).some((y) => y.partial);
1157
+ return /* @__PURE__ */ o("div", { style: { borderBottom: "1px solid var(--border)", padding: "6px 0" }, children: [
1158
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1159
+ /* @__PURE__ */ o("b", { children: [
1160
+ "#",
1161
+ a.op
1162
+ ] }),
1163
+ /* @__PURE__ */ o("span", { style: { opacity: 0.85 }, children: [
1164
+ a.tool,
1165
+ ": ",
1166
+ String(a.summary || "").slice(0, 60)
1167
+ ] }),
1168
+ /* @__PURE__ */ o("span", { style: { opacity: 0.6 }, title: (a.stores || []).some((y) => y.before && y.pathsTruncated) ? i("gt.timeline.truncTip") : void 0, children: [
1169
+ "±",
1170
+ d
1171
+ ] }),
1172
+ u ? /* @__PURE__ */ n("span", { style: K("cross"), title: i("gt.timeline.cross"), children: i("gt.timeline.cross") }) : null,
1173
+ I ? /* @__PURE__ */ o("span", { style: K("leak"), title: i("gt.timeline.leak"), children: [
1174
+ i("gt.timeline.leak"),
1175
+ " ",
1176
+ a.leaks.length
1177
+ ] }) : null,
1178
+ f ? /* @__PURE__ */ n("span", { style: K("partial"), children: i("gt.timeline.partial") }) : null,
1179
+ a.suspect ? /* @__PURE__ */ n("span", { style: K("leak"), title: "疑似并行污染:非核心写工具的 op,变更可能是并行会话所为(已照记、回滚可用;绑定向导已忽略)", children: "👻" }) : null,
1180
+ /* @__PURE__ */ n("span", { style: { flex: 1 } }),
1181
+ (a.stores || []).filter((y) => y.before && (y.files ? y.files.M + y.files.A + y.files.D : 0) > 0).length > 1 ? (a.stores || []).filter((y) => y.before && (y.files ? y.files.M + y.files.A + y.files.D : 0) > 0).map((y) => /* @__PURE__ */ o("button", { style: { ...T, color: "#0a7d33", borderColor: "rgba(10,125,51,.5)" }, title: y.root, onClick: () => fe(a, y), children: [
1182
+ i("gt.timeline.viewdiff"),
1183
+ "·",
1184
+ String(y.root).split("/").pop()
1185
+ ] }, y.root)) : /* @__PURE__ */ n("button", { style: T, onClick: () => fe(a), children: i("gt.timeline.viewdiff") }),
1186
+ /* @__PURE__ */ n("button", { style: T, onClick: () => W(a), children: i("gt.timeline.rollback") }),
1187
+ a.entryId || a.userEntryId ? /* @__PURE__ */ n(
1188
+ "button",
1189
+ {
1190
+ style: T,
1191
+ title: "跳转到产生该操作的消息流(entry " + String(a.entryId || a.userEntryId) + ")",
1192
+ onClick: () => {
1193
+ try {
1194
+ window.dispatchEvent(new CustomEvent("pi-web:open-session", { detail: { id: r, entryId: a.entryId || a.userEntryId || void 0 } }));
1195
+ } catch {
1196
+ }
1197
+ },
1198
+ children: "💬"
1199
+ }
1200
+ ) : null,
1201
+ /* @__PURE__ */ n("button", { style: T, title: i("gt.tl.cleanBeforeTip"), onClick: () => ae({ beforeOp: a.op }), children: "⌫" })
1202
+ ] }),
1203
+ I ? /* @__PURE__ */ n("div", { style: { opacity: 0.85, fontSize: 11, marginTop: 2, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, children: a.leaks.map((y, C) => /* @__PURE__ */ o("span", { style: { display: "inline-flex", alignItems: "center", gap: 4, minWidth: 0 }, children: [
1204
+ /* @__PURE__ */ n("span", { title: y.path, style: { fontFamily: "monospace", wordBreak: "break-all" }, children: y.path }),
1205
+ /* @__PURE__ */ o("span", { style: { display: "inline-flex", gap: 3, flexShrink: 0, flexWrap: "wrap" }, children: [
1206
+ /* @__PURE__ */ n(
1207
+ "button",
1208
+ {
1209
+ style: kt,
1210
+ title: i("gt.timeline.openFile"),
1211
+ onClick: () => wt(y.path, String(y.path || "").split("/").pop() || y.path),
1212
+ children: i("gt.timeline.openFile")
1213
+ }
1214
+ ),
1215
+ /* @__PURE__ */ o("button", { style: ne, title: i("gt.timeline.atRefTip"), onClick: () => qe(St("", y.path)), children: [
1216
+ /* @__PURE__ */ n("b", { style: { fontWeight: 700 }, children: "@" }),
1217
+ i("gt.timeline.atRef")
1218
+ ] }),
1219
+ /* @__PURE__ */ o("button", { style: ne, title: i("gt.timeline.atNewTip"), onClick: () => nn(y), children: [
1220
+ /* @__PURE__ */ n("b", { style: { fontWeight: 700 }, children: "@" }),
1221
+ i("gt.timeline.atNew")
1222
+ ] }),
1223
+ /* @__PURE__ */ n("button", { style: ne, title: i("gt.timeline.copyPathTip"), onClick: (z) => xt(y.path, z.currentTarget), children: i("gt.timeline.copyPath") })
1224
+ ] })
1225
+ ] }, String(y.path) + C)) }) : null
1226
+ ] }, String(a.op) + String(a.t1));
1227
+ })
1228
+ ] }, t))
1229
+ ] })
1230
+ ] })
1231
+ ] });
1232
+ if (je)
1233
+ return /* @__PURE__ */ n("div", { style: { ...Ye, left: 18, right: "auto", top: 64, width: ft }, "data-ext-float": "1", "data-ext-float-full": "1", "data-ext-float-w": ft, "data-ext-float-h": 480, "data-ext-float-key": J, "data-ext-float-dock": `${ie(J)} right-panel`, "data-ext-float-dock-default": "right-panel", children: pt });
1234
+ const ht = [ie(J), "right-panel"], gt = /* @__PURE__ */ n("div", { style: { display: "flex", flexDirection: "column", minHeight: 0, height: "100%", color: "var(--text)", padding: "8px 10px", boxSizing: "border-box" }, children: pt });
1235
+ if (l === "left") {
1236
+ const t = [
1237
+ { id: "refresh", title: "刷新", icon: /* @__PURE__ */ n(Et, {}), visibility: "always", onClick: () => {
1238
+ Ft(J, "refresh");
1239
+ } }
1240
+ ];
1241
+ return /* @__PURE__ */ n(
1242
+ $e,
1243
+ {
1244
+ itemKey: J,
1245
+ title: "时间线",
1246
+ chrome: "section",
1247
+ kind: "dockable",
1248
+ count: typeof Me.ops == "number" && Me.ops > 0 ? Me.ops : void 0,
1249
+ zones: ht,
1250
+ defaultZone: "right-panel",
1251
+ headerActions: t,
1252
+ children: gt
1253
+ }
1254
+ );
1255
+ }
1256
+ return /* @__PURE__ */ n($e, { itemKey: J, zone: "right-panel", title: "时间线", chrome: "tab", zones: ht, defaultZone: "right-panel", children: gt });
1257
+ }
1258
+ let Ae = null, Be = null;
1259
+ const Ve = /* @__PURE__ */ new Set();
1260
+ function cn(e) {
1261
+ return new Promise((l) => {
1262
+ Be = {
1263
+ params: {
1264
+ sessionId: String(e?.sessionId || ""),
1265
+ entryId: String(e?.entryId || ""),
1266
+ cutUserEntryIds: Array.isArray(e?.cutUserEntryIds) ? e.cutUserEntryIds.map(String).filter(Boolean) : []
1267
+ },
1268
+ resolve: l
1269
+ };
1270
+ for (const r of [...Ve])
1271
+ try {
1272
+ r();
1273
+ } catch {
1274
+ }
1275
+ });
1276
+ }
1277
+ const Ct = (e) => (e.stores || []).reduce((l, r) => l + (r.before && r.files ? (r.files.M || 0) + (r.files.A || 0) + (r.files.D || 0) : 0), 0), It = (e) => (e.stores || []).some((l) => !l.before && l.files && (l.files.M || 0) + (l.files.A || 0) + (l.files.D || 0) > 0);
1278
+ function dn(e) {
1279
+ const l = /* @__PURE__ */ new Map();
1280
+ for (const s of e) {
1281
+ const h = String(s.userEntryId || s.msgSeq || "?");
1282
+ l.has(h) || l.set(h, { key: h, prompt: s.prompt || "", msgSeq: s.msgSeq, ops: [] }), l.get(h).ops.push(s);
1283
+ }
1284
+ const r = (s) => (s.ops || []).reduce((h, p) => Math.min(h, Number(p.op) || 0), 1 / 0);
1285
+ return [...l.values()].sort((s, h) => r(s) - r(h));
1286
+ }
1287
+ function Rt(e) {
1288
+ const l = /* @__PURE__ */ new Set();
1289
+ for (const r of e.ops || [])
1290
+ for (const s of r.stores || [])
1291
+ if (s.before)
1292
+ for (const h of s.paths || []) l.add(s.root + "\0" + h);
1293
+ return l.size;
1294
+ }
1295
+ function Wt(e) {
1296
+ const l = e.sessionId || "", r = String(l).replace(/[^A-Za-z0-9_-]/g, "-").slice(0, 16) || "s", h = (Array.isArray(e.roots) && e.roots.length ? e.roots : ["<repoRoot:未提供>"]).map((v) => `- ${v}/.aiti-trace`).join(`
1297
+ `), p = (e.refs || []).map((v) => `#${v.op} ${v.before ? v.before.slice(0, 8) : "(无基线)"} → ${v.after ? v.after.slice(0, 8) : ""}`).join(`
1298
+ `), w = e.failed ? `- 失败于 #${e.failed.op}:${e.failed.before?.slice(0, 8)} → ${e.failed.after?.slice(0, 8)}
1299
+ git apply 报错:${e.failed.stderr || "(无)"}` : "";
1300
+ return `【请处理一次未完成的「从这里编辑」回撤】
1301
+
1302
+ 上下文:会话 ${l || "?"} 里,用户「从这里编辑」;随后选择撤销被裁轮次的文件变更,但逐操作反向 patch 中途失败,剩余变更未能撤销。请你接手收尾。
1303
+
1304
+ 已成功撤销:${e.applied} 个操作;跳过(无基线 gap):${(e.skipped || []).join(",") || "无"}。
1305
+ ${w}
1306
+
1307
+ 涉及的 trace store(hermetic,别动用户 .git):
1308
+ - store 目录(每仓):
1309
+ ${h}
1310
+ - 会话分支:refs/heads/aiti/${r}
1311
+ - safety commit(回撤前完整现状,可整树还原):${e.safety || "?"}
1312
+ - 已生成的回撤记账 commit:${e.rollback || "?"}
1313
+ - 回撤目标 op:${e.targetOps ? e.targetOps.join(",") : "?"};每 op 快照对:
1314
+ ${p}
1315
+
1316
+ 细看要求:
1317
+ 1. 用 \`git --git-dir=<repoRoot>/.aiti-trace --work-tree=<repoRoot> diff <before> <after> | git apply -R --whitespace=nowarn\` 逆序逐 op 撤销(<repoRoot> 用上方真实路径,先 \`git status\` 确认位置);失败加 \`--3way\` 三方兜底。
1318
+ 2. 只移除这些被裁 op 引入的变更,保留用户手工改动与其他来源。
1319
+ 3. 完成后 \`git status\`(用户仓)核对:应只剩未被撤除的合法残留;如仍冲突,先说明冲突文件与原因再请示。
1320
+ 4. 红线:绝不动用户仓 .git,只用 <repoRoot>/.aiti-trace;任何一步先看 safety commit 上下文。`;
1321
+ }
1322
+ function wn() {
1323
+ const [e, l] = x({ visible: !1, ops: [], busy: "", fail: null, refs: [], sessionId: "", roots: [], totals: null }), r = Ke(null);
1324
+ _(() => {
1325
+ const m = r.current;
1326
+ if (!m) return;
1327
+ const c = window.setTimeout(() => {
1328
+ try {
1329
+ window.__piweFloat?.setMax?.(m, !0);
1330
+ } catch {
1331
+ }
1332
+ }, 100);
1333
+ return () => window.clearTimeout(c);
1334
+ }, [e.visible]), _(() => {
1335
+ const m = () => {
1336
+ if (!Be) return;
1337
+ const c = Be;
1338
+ Be = null, (async () => {
1339
+ let b = null;
1340
+ const { sessionId: k, entryId: B, cutUserEntryIds: P } = c.params, O = Array.isArray(P) ? P.map(String).filter(Boolean) : [];
1341
+ try {
1342
+ b = O.length ? await q("/fork-preview", { session: k || "", entryIds: O }) : await be("/fork-preview?session=" + encodeURIComponent(k || "") + "&entryId=" + encodeURIComponent(B || ""));
1343
+ } catch {
1344
+ b = null;
1345
+ }
1346
+ const S = (b && b.ops || []).filter((U) => Ct(U) > 0 || It(U));
1347
+ if (S.length === 0) {
1348
+ c.resolve({ action: "keep" });
1349
+ return;
1350
+ }
1351
+ Ae = c.resolve, l({ visible: !0, ops: S, busy: "", fail: null, refs: [], sessionId: k || "", roots: [], totals: b && b.totals || null });
1352
+ })();
1353
+ };
1354
+ return m(), Ve.add(m), () => {
1355
+ Ve.delete(m);
1356
+ };
1357
+ }, []), _(() => (window.__aitiGitTraceForkDialog = (m) => cn(m), () => {
1358
+ try {
1359
+ delete window.__aitiGitTraceForkDialog;
1360
+ } catch {
1361
+ }
1362
+ }), []);
1363
+ function s() {
1364
+ const m = /* @__PURE__ */ new Map();
1365
+ for (const c of e.ops) for (const b of c.stores || [])
1366
+ m.has(b.root) || m.set(b.root, []), m.get(b.root).push({ op: c.op, before: b.before || null, after: b.after || null });
1367
+ return [...m.entries()].map(([c, b]) => ({ storeRoot: c, refs: b.sort((k, B) => k.op - B.op) }));
1368
+ }
1369
+ async function h() {
1370
+ const m = s();
1371
+ if (m.length === 0) {
1372
+ window.alert("no restorable baseline");
1373
+ return;
1374
+ }
1375
+ l({ ...e, busy: "rollback", fail: null });
1376
+ let c = 0, b = null;
1377
+ const k = [];
1378
+ let B = "", P = "";
1379
+ for (const O of m) {
1380
+ const S = await q("/rollback-reversed", { storeRoot: O.storeRoot, sessionId: X(), refs: O.refs });
1381
+ if (S && S.failed && (b = S.failed), S && S.safety && (B = S.safety), S && S.rollback && (P = S.rollback), c += S && S.applied || 0, Array.isArray(S && S.skipped)) for (const U of S.skipped) k.push(U);
1382
+ if (S && S.failed) break;
1383
+ }
1384
+ if (b) {
1385
+ l({ ...e, busy: "", fail: { failed: b, applied: c, skipped: k, safety: B, rollback: P, refs: m.flatMap((O) => O.refs) }, refs: m.flatMap((O) => O.refs), roots: m.map((O) => O.storeRoot), sessionId: e.sessionId });
1386
+ return;
1387
+ }
1388
+ k.length && window.alert(i("gt.fork.skippedHint", { n: String(k.length) })), p({ action: "rollback", done: i("gt.fork.done") });
1389
+ }
1390
+ function p(m) {
1391
+ l({ visible: !1, ops: [], busy: "", fail: null, refs: [], sessionId: "", roots: [], totals: null });
1392
+ try {
1393
+ Ae && Ae(m);
1394
+ } catch {
1395
+ }
1396
+ Ae = null;
1397
+ }
1398
+ function w(m) {
1399
+ if (m.action === "ai") {
1400
+ const c = Wt({ sessionId: e.sessionId, roots: e.roots, refs: e.refs, applied: e.fail?.applied, skipped: e.fail?.skipped, failed: e.fail?.failed, safety: e.fail?.safety, rollback: e.fail?.rollback, targetOps: e.fail?.refs ? e.fail.refs.map((b) => b.op) : [] });
1401
+ qe(c);
1402
+ }
1403
+ p({ action: "keep" });
1404
+ }
1405
+ const v = dn(e.ops);
1406
+ return e.visible ? /* @__PURE__ */ n("div", { style: { position: "fixed", inset: 0, zIndex: 10060, background: "rgba(0,0,0,.5)", display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ o(
1407
+ "div",
1408
+ {
1409
+ ref: r,
1410
+ style: { ...Ye, position: "static", width: 720, maxWidth: "94vw", maxHeight: "86vh", padding: 0, display: "flex", flexDirection: "column", overflow: "hidden" },
1411
+ "data-ext-float": "1",
1412
+ "data-ext-float-full": "1",
1413
+ "data-ext-float-w": 720,
1414
+ "data-ext-float-h": 560,
1415
+ children: [
1416
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px 14px", borderBottom: "1px solid var(--border)", flexShrink: 0, cursor: "move" }, children: [
1417
+ /* @__PURE__ */ n("b", { style: { fontSize: 13 }, children: i("gt.fork.title") }),
1418
+ /* @__PURE__ */ n(
1419
+ "button",
1420
+ {
1421
+ type: "button",
1422
+ title: i("gt.fork.cancel"),
1423
+ "aria-label": i("gt.fork.cancel"),
1424
+ onClick: () => p({ action: "cancel" }),
1425
+ style: { ...D, border: "none", background: "transparent", padding: "2px 8px", fontSize: 14, lineHeight: 1 },
1426
+ children: "✕"
1427
+ }
1428
+ )
1429
+ ] }),
1430
+ /* @__PURE__ */ o("div", { style: Ze, children: [
1431
+ e.fail ? /* @__PURE__ */ o("div", { style: { padding: "12px 14px 0" }, children: [
1432
+ /* @__PURE__ */ n("div", { style: { color: "#cf222e", fontWeight: 600, marginBottom: 8 }, children: i("gt.fork.failTitle") }),
1433
+ /* @__PURE__ */ n("div", { style: { fontSize: 12, opacity: 0.85, marginBottom: 6 }, children: i("gt.fork.failDetail", { applied: String(e.fail.applied), skipped: (e.fail.skipped || []).map((m) => "#" + m.op).join(",") || "—", op: String(e.fail.failed.op), err: String(e.fail.failed.stderr || "").slice(0, 120) }) }),
1434
+ /* @__PURE__ */ n("div", { style: { border: "1px solid var(--border)", borderRadius: 6, marginBottom: 10, padding: "6px 10px", fontSize: 12, fontFamily: "monospace", whiteSpace: "pre-wrap", wordBreak: "break-all", maxHeight: 140, overflow: "auto", opacity: 0.9 }, children: Wt({ sessionId: e.sessionId, roots: e.roots, refs: e.refs, applied: e.fail.applied, skipped: e.fail.skipped, failed: e.fail.failed, safety: e.fail.safety, rollback: e.fail.rollback, targetOps: e.refs.map((m) => m.op) }) }),
1435
+ /* @__PURE__ */ n("div", { style: { fontSize: 12, opacity: 0.7 }, children: i("gt.fork.failHint") })
1436
+ ] }) : /* @__PURE__ */ o("div", { style: { padding: "12px 14px 0" }, children: [
1437
+ /* @__PURE__ */ n("div", { style: { opacity: 0.8, marginBottom: 10 }, children: i("gt.fork.desc") }),
1438
+ e.totals ? /* @__PURE__ */ o("div", { style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", border: "1px solid var(--border)", borderRadius: 6, padding: "6px 10px", marginBottom: 10, fontSize: 12 }, children: [
1439
+ /* @__PURE__ */ o("span", { children: [
1440
+ /* @__PURE__ */ n("b", { children: F(e.totals.ops) }),
1441
+ " ",
1442
+ i("gt.ov.ops")
1443
+ ] }),
1444
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
1445
+ /* @__PURE__ */ o("span", { children: [
1446
+ /* @__PURE__ */ n("b", { children: F(e.totals.files) }),
1447
+ " ",
1448
+ i("gt.ov.files")
1449
+ ] }),
1450
+ /* @__PURE__ */ n("span", { style: { opacity: 0.4 }, children: "·" }),
1451
+ /* @__PURE__ */ o("span", { style: { color: "#1a7f37", fontWeight: 600 }, children: [
1452
+ "+",
1453
+ F(e.totals.adds)
1454
+ ] }),
1455
+ /* @__PURE__ */ o("span", { style: { color: "#cf222e", fontWeight: 600 }, children: [
1456
+ "−",
1457
+ F(e.totals.dels)
1458
+ ] })
1459
+ ] }) : null,
1460
+ v.map((m) => /* @__PURE__ */ o("div", { style: { border: "1px solid var(--border)", borderRadius: 6, marginBottom: 10 }, children: [
1461
+ /* @__PURE__ */ o("div", { style: { display: "flex", alignItems: "center", gap: 6, padding: "6px 10px", borderBottom: "1px solid var(--border)", fontSize: 12, fontWeight: 600 }, children: [
1462
+ /* @__PURE__ */ o("span", { title: m.prompt || "", style: { opacity: 0.9, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", flex: 1, minWidth: 0 }, children: [
1463
+ "🗣 ",
1464
+ String(m.prompt || "").slice(0, 60) || "(无 prompt)"
1465
+ ] }),
1466
+ Rt(m) > 0 ? /* @__PURE__ */ n("span", { style: { fontSize: 11, opacity: 0.65, flexShrink: 0, whiteSpace: "nowrap" }, children: i("gt.fork.turnFiles", { n: String(Rt(m)) }) }) : null
1467
+ ] }),
1468
+ m.ops.map((c) => /* @__PURE__ */ o("div", { style: { padding: "6px 10px", borderBottom: "1px solid var(--border)" }, children: [
1469
+ /* @__PURE__ */ o("b", { children: [
1470
+ "#",
1471
+ c.op
1472
+ ] }),
1473
+ " ",
1474
+ /* @__PURE__ */ o("span", { children: [
1475
+ c.tool,
1476
+ ": ",
1477
+ String(c.summary || "").slice(0, 70)
1478
+ ] }),
1479
+ /* @__PURE__ */ o("span", { style: { opacity: 0.6 }, children: [
1480
+ " · ±",
1481
+ Ct(c)
1482
+ ] }),
1483
+ It(c) ? /* @__PURE__ */ o("span", { title: i("gt.fork.gapTip"), style: { color: "#9a6700", border: "1px solid #f0c674", borderRadius: 4, padding: "0 5px", fontSize: 11, marginLeft: 4 }, children: [
1484
+ "⏭ ",
1485
+ i("gt.fork.gap")
1486
+ ] }) : null
1487
+ ] }, String(c.op) + String(c.t1)))
1488
+ ] }, m.key))
1489
+ ] }),
1490
+ e.busy ? /* @__PURE__ */ o("div", { style: { padding: "0 14px 4px", opacity: 0.7 }, children: [
1491
+ e.busy,
1492
+ "…"
1493
+ ] }) : null
1494
+ ] }),
1495
+ /* @__PURE__ */ n("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end", padding: "10px 14px", borderTop: "1px solid var(--border)", flexShrink: 0 }, children: e.fail ? /* @__PURE__ */ o(Q, { children: [
1496
+ /* @__PURE__ */ o("button", { style: D, disabled: !!e.busy, onClick: () => w({ action: "ai" }), children: [
1497
+ "🤖 ",
1498
+ i("gt.fork.aiTakeover")
1499
+ ] }),
1500
+ /* @__PURE__ */ n("button", { style: D, disabled: !!e.busy, onClick: () => w({ action: "ignore" }), children: i("gt.fork.ignore") })
1501
+ ] }) : /* @__PURE__ */ o(Q, { children: [
1502
+ /* @__PURE__ */ o("button", { style: D, disabled: !!e.busy, onClick: () => h(), children: [
1503
+ "↩ ",
1504
+ i("gt.fork.rollback")
1505
+ ] }),
1506
+ /* @__PURE__ */ n("button", { style: D, disabled: !!e.busy, onClick: () => p({ action: "keep" }), children: i("gt.fork.keep") }),
1507
+ /* @__PURE__ */ n("button", { style: D, disabled: !!e.busy, onClick: () => p({ action: "cancel" }), children: i("gt.fork.cancel") })
1508
+ ] }) })
1509
+ ]
1510
+ }
1511
+ ) }) : null;
1512
+ }
1513
+ export {
1514
+ wn as ForkDialogSlot,
1515
+ mn as TimelineDockLeft,
1516
+ yn as TimelineDockRight,
1517
+ un as TimelineSlot,
1518
+ hn as WatchDockLeft,
1519
+ gn as WatchDockRight,
1520
+ pn as WatchPanelSlot,
1521
+ cn as requestForkDialog
1522
+ };