@c0sc0s/codex-tags 0.5.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 (48) hide show
  1. package/.codex-plugin/plugin.json +24 -0
  2. package/AGENTS.md +44 -0
  3. package/CHANGELOG.md +75 -0
  4. package/README.md +87 -0
  5. package/README.zh-CN.md +87 -0
  6. package/assets/README.md +19 -0
  7. package/assets/banner.png +0 -0
  8. package/assets/icon.icns +0 -0
  9. package/assets/logo.png +0 -0
  10. package/bin/codex-tags.mjs +89 -0
  11. package/docs/architecture.md +56 -0
  12. package/docs/compatibility.md +47 -0
  13. package/docs/development.md +84 -0
  14. package/docs/distribution.md +65 -0
  15. package/docs/protocol.md +89 -0
  16. package/docs/roadmap.md +40 -0
  17. package/hooks/hooks.json +40 -0
  18. package/hooks/session-naming.mjs +107 -0
  19. package/package.json +65 -0
  20. package/runtime/dist/injected.js +3161 -0
  21. package/runtime/src/cdp-client.mjs +100 -0
  22. package/runtime/src/codex-process.mjs +115 -0
  23. package/runtime/src/content-index.mjs +138 -0
  24. package/runtime/src/controller-router.mjs +84 -0
  25. package/runtime/src/controller-state.mjs +17 -0
  26. package/runtime/src/controller.mjs +290 -0
  27. package/runtime/src/inject-expression.mjs +49 -0
  28. package/runtime/src/protocol.d.mts +31 -0
  29. package/runtime/src/protocol.mjs +43 -0
  30. package/runtime/src/runtime-target-registry.mjs +92 -0
  31. package/runtime/src/search-index.mjs +191 -0
  32. package/runtime/src/session-catalog.mjs +52 -0
  33. package/runtime/src/settings-repository.mjs +58 -0
  34. package/runtime/src/tag-settings.d.mts +18 -0
  35. package/runtime/src/tag-settings.mjs +65 -0
  36. package/runtime/src/title-format.d.mts +11 -0
  37. package/runtime/src/title-format.mjs +33 -0
  38. package/scripts/cli-options.mjs +17 -0
  39. package/scripts/health.mjs +20 -0
  40. package/scripts/lifecycle-lock.mjs +21 -0
  41. package/scripts/manage.mjs +19 -0
  42. package/scripts/manager-core.mjs +463 -0
  43. package/skills/doctor/SKILL.md +18 -0
  44. package/skills/doctor/agents/openai.yaml +4 -0
  45. package/skills/initial/SKILL.md +22 -0
  46. package/skills/initial/agents/openai.yaml +4 -0
  47. package/skills/rename/SKILL.md +20 -0
  48. package/skills/rename/agents/openai.yaml +4 -0
@@ -0,0 +1,3161 @@
1
+ "use strict";
2
+ var CodexTagsInjected = (() => {
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // runtime/src/injected/entry.ts
22
+ var entry_exports = {};
23
+ __export(entry_exports, {
24
+ installRuntime: () => installRuntime
25
+ });
26
+
27
+ // runtime/src/tag-settings.mjs
28
+ var TAG_COLOR_PRESETS = Object.freeze([
29
+ { name: "\u6D77\u84DD", color: "#4f8fd7" },
30
+ { name: "\u9E22\u7D2B", color: "#956ad1" },
31
+ { name: "\u73CA\u745A", color: "#d95c5c" },
32
+ { name: "\u7425\u73C0", color: "#c98b28" },
33
+ { name: "\u677E\u7EFF", color: "#3f9a6b" },
34
+ { name: "\u96FE\u7070", color: "#7c8798" }
35
+ ]);
36
+ var PRESET_COLORS = Object.fromEntries(TAG_COLOR_PRESETS.map(({ name, color }) => [name, color]));
37
+ var LEGACY_TONE_COLORS = Object.freeze({
38
+ amber: PRESET_COLORS["\u7425\u73C0"],
39
+ blue: PRESET_COLORS["\u6D77\u84DD"],
40
+ red: PRESET_COLORS["\u73CA\u745A"],
41
+ purple: PRESET_COLORS["\u9E22\u7D2B"],
42
+ green: PRESET_COLORS["\u677E\u7EFF"],
43
+ neutral: PRESET_COLORS["\u96FE\u7070"]
44
+ });
45
+ var DEFAULT_TAG_DEFINITIONS = Object.freeze([
46
+ { name: "Feature", color: PRESET_COLORS["\u6D77\u84DD"], description: "Build or extend functionality. Use when the main goal is to implement a new capability or improve existing behavior, rather than fix a defect." },
47
+ { name: "Bug", color: PRESET_COLORS["\u73CA\u745A"], description: "Diagnose and fix incorrect behavior, errors, or regressions. Use when the goal is to restore expected behavior, including investigation needed for the fix." },
48
+ { name: "Design", color: PRESET_COLORS["\u9E22\u7D2B"], description: "Define how a solution should look or work: UI, interactions, architecture, or technical plans. Use when the main deliverable is a design or specification." },
49
+ { name: "Research", color: PRESET_COLORS["\u677E\u7EFF"], description: "Explore a topic, understand existing code, compare options, or assess feasibility. Use when the main deliverable is findings or an explanation, rather than a design or implementation." }
50
+ ]);
51
+ function normalizeColor(value, legacyTone, fallbackColor) {
52
+ if (typeof value === "string" && /^#[0-9a-f]{6}$/iu.test(value.trim())) return value.trim().toLocaleLowerCase();
53
+ return LEGACY_TONE_COLORS[legacyTone] ?? fallbackColor ?? LEGACY_TONE_COLORS.neutral;
54
+ }
55
+ function normalizeDescription(value, fallbackDescription = "") {
56
+ if (typeof value !== "string") return fallbackDescription;
57
+ return value.replace(/\s+/gu, " ").trim().slice(0, 240);
58
+ }
59
+ function normalizeTagDefinitions(value, fallback = DEFAULT_TAG_DEFINITIONS) {
60
+ if (!Array.isArray(value)) return fallback.map((item) => ({ ...item }));
61
+ const defaultsByName = new Map(fallback.map((item) => [item.name.toLocaleLowerCase(), item]));
62
+ const seen = /* @__PURE__ */ new Set();
63
+ const definitions = [];
64
+ for (const item of value) {
65
+ const name = typeof item?.name === "string" ? item.name.trim() : "";
66
+ const key = name.toLocaleLowerCase();
67
+ if (!name || name.length > 32 || /[\[\]【】\r\n]/u.test(name) || seen.has(key)) continue;
68
+ const defaultDefinition = defaultsByName.get(key);
69
+ seen.add(key);
70
+ definitions.push({
71
+ name,
72
+ color: normalizeColor(item?.color, item?.tone, defaultDefinition?.color),
73
+ description: normalizeDescription(item?.description, defaultDefinition?.description)
74
+ });
75
+ if (definitions.length >= 32) break;
76
+ }
77
+ return definitions;
78
+ }
79
+
80
+ // runtime/src/title-format.mjs
81
+ var MAX_TAG_LENGTH = 32;
82
+ var MAX_TIME_LENGTH = 32;
83
+ var BRACKETED_TITLE = /^(?:\[([^\]\r\n]{1,32})\]|【([^】\r\n]{1,32})】)(?:(?:\[([^\]\r\n]{1,32})\]|【([^】\r\n]{1,32})】))?\s*(.+)$/u;
84
+ var TAG_COLORS = new Map(DEFAULT_TAG_DEFINITIONS.map(({ name, color }) => [name.toLocaleLowerCase(), color]));
85
+ function parseTitleMetadata(value) {
86
+ if (typeof value !== "string") return null;
87
+ const raw = value.trim();
88
+ const match = BRACKETED_TITLE.exec(raw);
89
+ if (!match) return null;
90
+ const tag = (match[1] ?? match[2] ?? "").trim();
91
+ const time = (match[3] ?? match[4] ?? "").trim();
92
+ const title = match[5].trim();
93
+ if (!tag || !title || tag.length > MAX_TAG_LENGTH || time.length > MAX_TIME_LENGTH) return null;
94
+ return { raw, tag, time, title };
95
+ }
96
+ var titlePatternSource = BRACKETED_TITLE.source;
97
+
98
+ // runtime/src/protocol.mjs
99
+ var RUNTIME_PROTOCOL_VERSION = 1;
100
+ var RuntimeMessageType = Object.freeze({
101
+ hello: "hello",
102
+ searchRequest: "search.request",
103
+ searchResult: "search.result",
104
+ settingsGet: "settings.get",
105
+ settingsSnapshot: "settings.snapshot",
106
+ settingsUpdate: "settings.update",
107
+ settingsError: "settings.error",
108
+ runtimeStatus: "runtime.status",
109
+ catalogSnapshot: "catalog.snapshot",
110
+ navigationOpen: "navigation.open"
111
+ });
112
+ function createRuntimeMessage(type, payload = {}, requestId) {
113
+ if (typeof type !== "string" || !type) throw new TypeError("Runtime message type must be a non-empty string");
114
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) throw new TypeError("Runtime message payload must be an object");
115
+ if (requestId !== void 0 && !Number.isSafeInteger(requestId)) throw new TypeError("Runtime message requestId must be a safe integer");
116
+ return {
117
+ protocolVersion: RUNTIME_PROTOCOL_VERSION,
118
+ type,
119
+ ...requestId === void 0 ? {} : { requestId },
120
+ payload
121
+ };
122
+ }
123
+ function parseRuntimeMessage(value) {
124
+ let candidate = value;
125
+ if (typeof candidate === "string") {
126
+ try {
127
+ candidate = JSON.parse(candidate);
128
+ } catch {
129
+ return { ok: false, reason: "invalid-json" };
130
+ }
131
+ }
132
+ if (candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) return { ok: false, reason: "invalid-envelope" };
133
+ if (candidate.protocolVersion !== RUNTIME_PROTOCOL_VERSION) return { ok: false, reason: "unsupported-version" };
134
+ if (typeof candidate.type !== "string" || !candidate.type) return { ok: false, reason: "invalid-type" };
135
+ if (candidate.payload === null || typeof candidate.payload !== "object" || Array.isArray(candidate.payload)) return { ok: false, reason: "invalid-payload" };
136
+ if (candidate.requestId !== void 0 && !Number.isSafeInteger(candidate.requestId)) return { ok: false, reason: "invalid-request-id" };
137
+ return { ok: true, message: candidate };
138
+ }
139
+
140
+ // runtime/src/injected/codex-dom-adapter.ts
141
+ var codexSelectors = {
142
+ projectRow: "[data-app-action-sidebar-project-row]",
143
+ projectsHeader: "[data-projects-header]",
144
+ sectionToggle: "[data-app-action-sidebar-section-toggle]",
145
+ threadRow: "[data-app-action-sidebar-thread-row]",
146
+ threadTitle: "[data-thread-title]"
147
+ };
148
+ var codexLabels = {
149
+ pinned: ["Pinned", "\u7F6E\u9876", "\u5DF2\u7F6E\u9876"],
150
+ plugins: ["Plugins", "\u63D2\u4EF6"]
151
+ };
152
+ function detectCodexCapabilities() {
153
+ return {
154
+ adapter: "codex-private-dom-v1",
155
+ threadTitles: Boolean(document.querySelector(codexSelectors.threadTitle)),
156
+ navigationAnchor: Boolean(findNavigationButton(codexLabels.plugins)),
157
+ pinnedSection: Boolean(findSectionToggle(codexLabels.pinned)),
158
+ projects: Boolean(document.querySelector(codexSelectors.projectRow))
159
+ };
160
+ }
161
+ function queryThreadTitles(toolbarId) {
162
+ return Array.from(document.querySelectorAll(codexSelectors.threadTitle)).filter(
163
+ (node) => !node.closest(`#${toolbarId}`)
164
+ );
165
+ }
166
+ function findNavigationButton(labels) {
167
+ const candidates = typeof labels === "string" ? [labels] : labels;
168
+ return Array.from(document.querySelectorAll("button")).find(
169
+ (button) => candidates.includes(button.textContent?.trim() ?? "")
170
+ );
171
+ }
172
+ function findSectionToggle(labels) {
173
+ const candidates = typeof labels === "string" ? [labels] : labels;
174
+ return Array.from(document.querySelectorAll(codexSelectors.sectionToggle)).find(
175
+ (toggle) => candidates.includes(toggle.textContent?.trim() ?? "")
176
+ );
177
+ }
178
+ function findVisibleThreadRow(threadId) {
179
+ if (!threadId) return null;
180
+ return Array.from(document.querySelectorAll(codexSelectors.threadRow)).find(
181
+ (row) => row.getAttribute("data-app-action-sidebar-thread-id") === threadId && row.getClientRects().length > 0
182
+ ) ?? null;
183
+ }
184
+ function findThreadRow(titleNode) {
185
+ return titleNode.closest(codexSelectors.threadRow);
186
+ }
187
+ function threadIdForRow(row) {
188
+ return row?.getAttribute("data-app-action-sidebar-thread-id") ?? void 0;
189
+ }
190
+ function isPinnedThreadRow(row) {
191
+ return row?.getAttribute("data-app-action-sidebar-thread-pinned") === "true";
192
+ }
193
+ function findFirstProjectRow() {
194
+ return document.querySelector(codexSelectors.projectRow);
195
+ }
196
+ function findProjectsHeader() {
197
+ return document.querySelector(codexSelectors.projectsHeader);
198
+ }
199
+ function findAnySectionToggle() {
200
+ return document.querySelector(codexSelectors.sectionToggle);
201
+ }
202
+ function hasVisiblePinnedThread() {
203
+ return Boolean(document.querySelector("[data-app-action-sidebar-thread-pinned='true']"));
204
+ }
205
+ function projectIdForThreadRow(row) {
206
+ for (let parent = row?.parentElement; parent; parent = parent.parentElement) {
207
+ const projectRows = parent.querySelectorAll(codexSelectors.projectRow);
208
+ if (projectRows.length === 1) return projectRows[0].getAttribute("data-app-action-sidebar-project-id");
209
+ }
210
+ return null;
211
+ }
212
+ function sectionToggleForThreadRow(row) {
213
+ for (let parent = row?.parentElement; parent; parent = parent.parentElement) {
214
+ const toggles = parent.querySelectorAll(codexSelectors.sectionToggle);
215
+ if (toggles.length === 1) return toggles[0];
216
+ }
217
+ return null;
218
+ }
219
+ function isThreadTitleElement(element) {
220
+ return Boolean(element.closest(codexSelectors.threadTitle));
221
+ }
222
+ function findProjectRow(projectId) {
223
+ return Array.from(document.querySelectorAll(codexSelectors.projectRow)).find(
224
+ (row) => row.getAttribute("data-app-action-sidebar-project-id") === projectId
225
+ );
226
+ }
227
+ function isProjectCollapsed(projectRow) {
228
+ return projectRow?.getAttribute("data-app-action-sidebar-project-collapsed") === "true";
229
+ }
230
+ function mutationContainsSidebarNode(node) {
231
+ if (!(node instanceof Element)) return false;
232
+ const selector = Object.values(codexSelectors).join(",");
233
+ return node.matches(selector) || Boolean(node.querySelector(selector));
234
+ }
235
+
236
+ // node_modules/preact/dist/preact.module.js
237
+ var n;
238
+ var l;
239
+ var u;
240
+ var t;
241
+ var i;
242
+ var r;
243
+ var o;
244
+ var e;
245
+ var f;
246
+ var c;
247
+ var a;
248
+ var s;
249
+ var h;
250
+ var p;
251
+ var v;
252
+ var y;
253
+ var d = {};
254
+ var w = [];
255
+ var _ = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
256
+ var g = Array.isArray;
257
+ function m(n2, l2) {
258
+ for (var u3 in l2) n2[u3] = l2[u3];
259
+ return n2;
260
+ }
261
+ function b(n2) {
262
+ n2 && n2.parentNode && n2.parentNode.removeChild(n2);
263
+ }
264
+ function k(l2, u3, t2) {
265
+ var i2, r2, o2, e2 = {};
266
+ for (o2 in u3) "key" == o2 ? i2 = u3[o2] : "ref" == o2 ? r2 = u3[o2] : e2[o2] = u3[o2];
267
+ if (arguments.length > 2 && (e2.children = arguments.length > 3 ? n.call(arguments, 2) : t2), "function" == typeof l2 && null != l2.defaultProps) for (o2 in l2.defaultProps) void 0 === e2[o2] && (e2[o2] = l2.defaultProps[o2]);
268
+ return x(l2, e2, i2, r2, null);
269
+ }
270
+ function x(n2, t2, i2, r2, o2) {
271
+ var e2 = { type: n2, props: t2, key: i2, ref: r2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: null == o2 ? ++u : o2, __i: -1, __u: 0 };
272
+ return null == o2 && null != l.vnode && l.vnode(e2), e2;
273
+ }
274
+ function S(n2) {
275
+ return n2.children;
276
+ }
277
+ function C(n2, l2) {
278
+ this.props = n2, this.context = l2;
279
+ }
280
+ function $(n2, l2) {
281
+ if (null == l2) return n2.__ ? $(n2.__, n2.__i + 1) : null;
282
+ for (var u3; l2 < n2.__k.length; l2++) if (null != (u3 = n2.__k[l2]) && null != u3.__e) return u3.__e;
283
+ return "function" == typeof n2.type ? $(n2) : null;
284
+ }
285
+ function I(n2) {
286
+ if (n2.__P && n2.__d) {
287
+ var u3 = n2.__v, t2 = u3.__e, i2 = [], r2 = [], o2 = m({}, u3);
288
+ o2.__v = u3.__v + 1, l.vnode && l.vnode(o2), q(n2.__P, o2, u3, n2.__n, n2.__P.namespaceURI, 32 & u3.__u ? [t2] : null, i2, null == t2 ? $(u3) : t2, !!(32 & u3.__u), r2), o2.__v = u3.__v, o2.__.__k[o2.__i] = o2, D(i2, o2, r2), u3.__e = u3.__ = null, o2.__e != t2 && P(o2);
289
+ }
290
+ }
291
+ function P(n2) {
292
+ if (null != (n2 = n2.__) && null != n2.__c) return n2.__e = n2.__c.base = null, n2.__k.some(function(l2) {
293
+ if (null != l2 && null != l2.__e) return n2.__e = n2.__c.base = l2.__e;
294
+ }), P(n2);
295
+ }
296
+ function A(n2) {
297
+ (!n2.__d && (n2.__d = true) && i.push(n2) && !H.__r++ || r != l.debounceRendering) && ((r = l.debounceRendering) || o)(H);
298
+ }
299
+ function H() {
300
+ try {
301
+ for (var n2, l2 = 1; i.length; ) i.length > l2 && i.sort(e), n2 = i.shift(), l2 = i.length, I(n2);
302
+ } finally {
303
+ i.length = H.__r = 0;
304
+ }
305
+ }
306
+ function L(n2, l2, u3, t2, i2, r2, o2, e2, f3, c2, a2) {
307
+ var s2, h2, p2, v2, y2, _2, g2 = t2 && t2.__k || w, m2 = l2.length;
308
+ for (f3 = T(u3, l2, g2, f3, m2), s2 = 0; s2 < m2; s2++) null != (p2 = u3.__k[s2]) && (h2 = -1 != p2.__i && g2[p2.__i] || d, p2.__i = s2, _2 = q(n2, p2, h2, i2, r2, o2, e2, f3, c2, a2), v2 = p2.__e, p2.ref && h2.ref != p2.ref && (h2.ref && J(h2.ref, null, p2), a2.push(p2.ref, p2.__c || v2, p2)), null == y2 && null != v2 && (y2 = v2), 4 & p2.__u ? (f3 = j(p2, f3, n2), h2.__e && (h2.__e = null)) : "function" == typeof p2.type && void 0 !== _2 ? f3 = _2 : v2 && (f3 = v2.nextSibling), p2.__u &= -7);
309
+ return u3.__e = y2, f3;
310
+ }
311
+ function T(n2, l2, u3, t2, i2) {
312
+ var r2, o2, e2, f3, c2, a2 = u3.length, s2 = a2, h2 = 0;
313
+ for (n2.__k = new Array(i2), r2 = 0; r2 < i2; r2++) null != (o2 = l2[r2]) && "boolean" != typeof o2 && "function" != typeof o2 ? ("string" == typeof o2 || "number" == typeof o2 || "bigint" == typeof o2 || o2.constructor == String ? o2 = n2.__k[r2] = x(null, o2, null, null, null) : g(o2) ? o2 = n2.__k[r2] = x(S, { children: o2 }, null, null, null) : void 0 === o2.constructor && o2.__b > 0 ? o2 = n2.__k[r2] = x(o2.type, o2.props, o2.key, o2.ref ? o2.ref : null, o2.__v) : n2.__k[r2] = o2, f3 = r2 + h2, o2.__ = n2, o2.__b = n2.__b + 1, e2 = null, -1 != (c2 = o2.__i = O(o2, u3, f3, s2)) && (s2--, (e2 = u3[c2]) && (e2.__u |= 2)), null == e2 || null == e2.__v ? (-1 == c2 && (i2 > a2 ? h2-- : i2 < a2 && h2++), "function" != typeof o2.type && (o2.__u |= 4)) : c2 != f3 && (c2 == f3 - 1 ? h2-- : c2 == f3 + 1 ? h2++ : (c2 > f3 ? h2-- : h2++, o2.__u |= 4))) : n2.__k[r2] = null;
314
+ if (s2) for (r2 = 0; r2 < a2; r2++) null != (e2 = u3[r2]) && 0 == (2 & e2.__u) && (e2.__e == t2 && (t2 = $(e2)), K(e2, e2));
315
+ return t2;
316
+ }
317
+ function j(n2, l2, u3) {
318
+ var t2, i2;
319
+ if ("function" == typeof n2.type) {
320
+ for (t2 = n2.__k, i2 = 0; t2 && i2 < t2.length; i2++) t2[i2] && (t2[i2].__ = n2, l2 = j(t2[i2], l2, u3));
321
+ return l2;
322
+ }
323
+ n2.__e != l2 && (l2 && n2.type && !l2.parentNode && (l2 = $(n2)), l2 = u3.insertBefore(n2.__e, l2 || null));
324
+ do {
325
+ l2 = l2 && l2.nextSibling;
326
+ } while (null != l2 && 8 == l2.nodeType);
327
+ return l2;
328
+ }
329
+ function O(n2, l2, u3, t2) {
330
+ var i2, r2, o2, e2 = n2.key, f3 = n2.type, c2 = l2[u3], a2 = null != c2 && 0 == (2 & c2.__u);
331
+ if (null === c2 && null == e2 || a2 && e2 == c2.key && f3 == c2.type) return u3;
332
+ if (t2 > (a2 ? 1 : 0)) {
333
+ for (i2 = u3 - 1, r2 = u3 + 1; i2 >= 0 || r2 < l2.length; ) if (null != (c2 = l2[o2 = i2 >= 0 ? i2-- : r2++]) && 0 == (2 & c2.__u) && e2 == c2.key && f3 == c2.type) return o2;
334
+ }
335
+ return -1;
336
+ }
337
+ function z(n2, l2, u3) {
338
+ "-" == l2[0] ? n2.setProperty(l2, null == u3 ? "" : u3) : n2[l2] = null == u3 ? "" : "number" != typeof u3 || _.test(l2) ? u3 : u3 + "px";
339
+ }
340
+ function N(n2, l2, u3, t2, i2) {
341
+ var r2, o2;
342
+ n: if ("style" == l2) if ("string" == typeof u3) n2.style.cssText = u3;
343
+ else {
344
+ if ("string" == typeof t2 && (n2.style.cssText = t2 = ""), t2) for (l2 in t2) u3 && l2 in u3 || z(n2.style, l2, "");
345
+ if (u3) for (l2 in u3) t2 && u3[l2] == t2[l2] || z(n2.style, l2, u3[l2]);
346
+ }
347
+ else if ("o" == l2[0] && "n" == l2[1]) r2 = l2 != (l2 = l2.replace(s, "$1")), o2 = l2.toLowerCase(), l2 = o2 in n2 || "onFocusOut" == l2 || "onFocusIn" == l2 ? o2.slice(2) : l2.slice(2), n2.l || (n2.l = {}), n2.l[l2 + r2] = u3, u3 ? t2 ? u3[a] = t2[a] : (u3[a] = h, n2.addEventListener(l2, r2 ? v : p, r2)) : n2.removeEventListener(l2, r2 ? v : p, r2);
348
+ else {
349
+ if ("http://www.w3.org/2000/svg" == i2) l2 = l2.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
350
+ else if ("width" != l2 && "height" != l2 && "href" != l2 && "list" != l2 && "form" != l2 && "tabIndex" != l2 && "download" != l2 && "rowSpan" != l2 && "colSpan" != l2 && "role" != l2 && "popover" != l2 && l2 in n2) try {
351
+ n2[l2] = null == u3 ? "" : u3;
352
+ break n;
353
+ } catch (n3) {
354
+ }
355
+ "function" == typeof u3 || (null == u3 || false === u3 && "-" != l2[4] ? n2.removeAttribute(l2) : n2.setAttribute(l2, "popover" == l2 && 1 == u3 ? "" : u3));
356
+ }
357
+ }
358
+ function V(n2) {
359
+ return function(u3) {
360
+ if (this.l) {
361
+ var t2 = this.l[u3.type + n2];
362
+ if (null == u3[c]) u3[c] = h++;
363
+ else if (u3[c] < t2[a]) return;
364
+ return t2(l.event ? l.event(u3) : u3);
365
+ }
366
+ };
367
+ }
368
+ function q(n2, u3, t2, i2, r2, o2, e2, f3, c2, a2) {
369
+ var s2, h2, p2, v2, y2, d2, _2, k2, x2, M, I2, P2, A2, H2, T2, j2, F = u3.type;
370
+ if (void 0 !== u3.constructor) return null;
371
+ 128 & t2.__u && (c2 = !!(32 & t2.__u), o2 = [f3 = u3.__e = t2.__e]), (s2 = l.__b) && s2(u3);
372
+ n: if ("function" == typeof F) {
373
+ h2 = e2.length;
374
+ try {
375
+ if (x2 = u3.props, M = F.prototype && F.prototype.render, I2 = (s2 = F.contextType) && i2[s2.__c], P2 = s2 ? I2 ? I2.props.value : s2.__ : i2, t2.__c ? k2 = (p2 = u3.__c = t2.__c).__ = p2.__E : (M ? u3.__c = p2 = new F(x2, P2) : (u3.__c = p2 = new C(x2, P2), p2.constructor = F, p2.render = Q), I2 && I2.sub(p2), p2.state || (p2.state = {}), p2.__n = i2, v2 = p2.__d = true, p2.__h = [], p2._sb = []), M && null == p2.__s && (p2.__s = p2.state), M && null != F.getDerivedStateFromProps && (p2.__s == p2.state && (p2.__s = m({}, p2.__s)), m(p2.__s, F.getDerivedStateFromProps(x2, p2.__s))), y2 = p2.props, d2 = p2.state, p2.__v = u3, v2) M && null == F.getDerivedStateFromProps && null != p2.componentWillMount && p2.componentWillMount(), M && null != p2.componentDidMount && p2.__h.push(p2.componentDidMount);
376
+ else {
377
+ if (M && null == F.getDerivedStateFromProps && x2 !== y2 && null != p2.componentWillReceiveProps && p2.componentWillReceiveProps(x2, P2), u3.__v == t2.__v || !p2.__e && null != p2.shouldComponentUpdate && false === p2.shouldComponentUpdate(x2, p2.__s, P2)) {
378
+ u3.__v != t2.__v && (p2.props = x2, p2.state = p2.__s, p2.__d = false), u3.__e = t2.__e, u3.__k = t2.__k, u3.__k.some(function(n3) {
379
+ n3 && (n3.__ = u3);
380
+ }), w.push.apply(p2.__h, p2._sb), p2._sb = [], p2.__h.length && e2.push(p2), f3 = $(t2);
381
+ break n;
382
+ }
383
+ null != p2.componentWillUpdate && p2.componentWillUpdate(x2, p2.__s, P2), M && null != p2.componentDidUpdate && p2.__h.push(function() {
384
+ p2.componentDidUpdate(y2, d2, _2);
385
+ });
386
+ }
387
+ if (p2.context = P2, p2.props = x2, p2.__P = n2, p2.__e = false, A2 = l.__r, H2 = 0, M) p2.state = p2.__s, p2.__d = false, A2 && A2(u3), s2 = p2.render(p2.props, p2.state, p2.context), w.push.apply(p2.__h, p2._sb), p2._sb = [];
388
+ else do {
389
+ p2.__d = false, A2 && A2(u3), s2 = p2.render(p2.props, p2.state, p2.context), p2.state = p2.__s;
390
+ } while (p2.__d && ++H2 < 25);
391
+ p2.state = p2.__s, null != p2.getChildContext && (i2 = m(m({}, i2), p2.getChildContext())), M && !v2 && null != p2.getSnapshotBeforeUpdate && (_2 = p2.getSnapshotBeforeUpdate(y2, d2)), T2 = null != s2 && s2.type === S && null == s2.key ? E(s2.props.children) : s2, f3 = L(n2, g(T2) ? T2 : [T2], u3, t2, i2, r2, o2, e2, f3, c2, a2), p2.base = u3.__e, u3.__u &= -161, p2.__h.length && e2.push(p2), k2 && (p2.__E = p2.__ = null);
392
+ } catch (n3) {
393
+ if (e2.length = h2, u3.__v = null, c2 || null != o2) {
394
+ if (n3.then) {
395
+ for (u3.__u |= c2 ? 160 : 128; f3 && 8 == f3.nodeType && f3.nextSibling; ) f3 = f3.nextSibling;
396
+ null != o2 && (o2[o2.indexOf(f3)] = null), u3.__e = f3;
397
+ } else if (null != o2) for (j2 = o2.length; j2--; ) b(o2[j2]);
398
+ } else u3.__e = t2.__e;
399
+ null == u3.__k && (u3.__k = t2.__k || []), n3.then || B(u3), l.__e(n3, u3, t2);
400
+ }
401
+ } else null == o2 && u3.__v == t2.__v ? (u3.__k = t2.__k, u3.__e = t2.__e) : f3 = u3.__e = G(t2.__e, u3, t2, i2, r2, o2, e2, c2, a2);
402
+ return (s2 = l.diffed) && s2(u3), 128 & u3.__u ? void 0 : f3;
403
+ }
404
+ function B(n2) {
405
+ n2 && (n2.__c && (n2.__c.__e = true), n2.__k && n2.__k.some(B));
406
+ }
407
+ function D(n2, u3, t2) {
408
+ for (var i2 = 0; i2 < t2.length; i2++) J(t2[i2], t2[++i2], t2[++i2]);
409
+ l.__c && l.__c(u3, n2), n2.some(function(u4) {
410
+ try {
411
+ n2 = u4.__h, u4.__h = [], n2.some(function(n3) {
412
+ n3.call(u4);
413
+ });
414
+ } catch (n3) {
415
+ l.__e(n3, u4.__v);
416
+ }
417
+ });
418
+ }
419
+ function E(n2) {
420
+ return "object" != typeof n2 || null == n2 || n2.__b > 0 ? n2 : g(n2) ? n2.map(E) : void 0 !== n2.constructor ? null : m({}, n2);
421
+ }
422
+ function G(u3, t2, i2, r2, o2, e2, f3, c2, a2) {
423
+ var s2, h2, p2, v2, y2, w2, _2, m2 = i2.props || d, k2 = t2.props, x2 = t2.type;
424
+ if ("svg" == x2 ? o2 = "http://www.w3.org/2000/svg" : "math" == x2 ? o2 = "http://www.w3.org/1998/Math/MathML" : o2 || (o2 = "http://www.w3.org/1999/xhtml"), null != e2) {
425
+ for (s2 = 0; s2 < e2.length; s2++) if ((y2 = e2[s2]) && "setAttribute" in y2 == !!x2 && (x2 ? y2.localName == x2 : 3 == y2.nodeType)) {
426
+ u3 = y2, e2[s2] = null;
427
+ break;
428
+ }
429
+ }
430
+ if (null == u3) {
431
+ if (null == x2) return document.createTextNode(k2);
432
+ u3 = document.createElementNS(o2, x2, k2.is && k2), c2 && (l.__m && l.__m(t2, e2), c2 = false), e2 = null;
433
+ }
434
+ if (null == x2) m2 === k2 || c2 && u3.data == k2 || (u3.data = k2);
435
+ else {
436
+ if (e2 = "textarea" == x2 && null != k2.defaultValue ? null : e2 && n.call(u3.childNodes), !c2 && null != e2) for (m2 = {}, s2 = 0; s2 < u3.attributes.length; s2++) m2[(y2 = u3.attributes[s2]).name] = y2.value;
437
+ for (s2 in m2) y2 = m2[s2], "dangerouslySetInnerHTML" == s2 ? p2 = y2 : "children" == s2 || s2 in k2 || "value" == s2 && "defaultValue" in k2 || "checked" == s2 && "defaultChecked" in k2 || N(u3, s2, null, y2, o2);
438
+ for (s2 in k2) y2 = k2[s2], "children" == s2 ? v2 = y2 : "dangerouslySetInnerHTML" == s2 ? h2 = y2 : "value" == s2 ? w2 = y2 : "checked" == s2 ? _2 = y2 : c2 && "function" != typeof y2 || m2[s2] === y2 || N(u3, s2, y2, m2[s2], o2);
439
+ if (h2) c2 || p2 && (h2.__html == p2.__html || h2.__html == u3.innerHTML) || (u3.innerHTML = h2.__html), t2.__k = [];
440
+ else if (p2 && (u3.innerHTML = ""), L("template" == t2.type ? u3.content : u3, g(v2) ? v2 : [v2], t2, i2, r2, "foreignObject" == x2 ? "http://www.w3.org/1999/xhtml" : o2, e2, f3, e2 ? e2[0] : i2.__k && $(i2, 0), c2, a2), null != e2) for (s2 = e2.length; s2--; ) b(e2[s2]);
441
+ c2 && "textarea" != x2 || (s2 = "value", "progress" == x2 && null == w2 ? u3.removeAttribute("value") : null != w2 && (w2 !== u3[s2] || "progress" == x2 && !w2 || "option" == x2 && w2 != m2[s2]) && N(u3, s2, w2, m2[s2], o2), s2 = "checked", null != _2 && _2 != u3[s2] && N(u3, s2, _2, m2[s2], o2));
442
+ }
443
+ return u3;
444
+ }
445
+ function J(n2, u3, t2) {
446
+ try {
447
+ if ("function" == typeof n2) {
448
+ var i2 = "function" == typeof n2.__u;
449
+ i2 && n2.__u(), i2 && null == u3 || (n2.__u = n2(u3));
450
+ } else n2.current = u3;
451
+ } catch (n3) {
452
+ l.__e(n3, t2);
453
+ }
454
+ }
455
+ function K(n2, u3, t2) {
456
+ var i2, r2;
457
+ if (l.unmount && l.unmount(n2), (i2 = n2.ref) && (i2.current && i2.current != n2.__e || J(i2, null, u3)), null != (i2 = n2.__c)) {
458
+ if (i2.componentWillUnmount) try {
459
+ i2.componentWillUnmount();
460
+ } catch (n3) {
461
+ l.__e(n3, u3);
462
+ }
463
+ i2.base = i2.__P = i2.__n = null;
464
+ }
465
+ if (i2 = n2.__k) for (r2 = 0; r2 < i2.length; r2++) i2[r2] && K(i2[r2], u3, t2 || "function" != typeof n2.type);
466
+ t2 || b(n2.__e), n2.__c = n2.__ = n2.__e = void 0;
467
+ }
468
+ function Q(n2, l2, u3) {
469
+ return this.constructor(n2, u3);
470
+ }
471
+ function R(u3, t2, i2) {
472
+ var r2, o2, e2, f3;
473
+ t2 == document && (t2 = document.documentElement), l.__ && l.__(u3, t2), o2 = (r2 = "function" == typeof i2) ? null : i2 && i2.__k || t2.__k, e2 = [], f3 = [], q(t2, u3 = (!r2 && i2 || t2).__k = k(S, null, [u3]), o2 || d, d, t2.namespaceURI, !r2 && i2 ? [i2] : o2 ? null : t2.firstChild ? n.call(t2.childNodes) : null, e2, !r2 && i2 ? i2 : o2 ? o2.__e : t2.firstChild, r2, f3), D(e2, u3, f3), u3.props.children = null;
474
+ }
475
+ n = w.slice, l = { __e: function(n2, l2, u3, t2) {
476
+ for (var i2, r2, o2; l2 = l2.__; ) if ((i2 = l2.__c) && !i2.__) try {
477
+ if ((r2 = i2.constructor) && null != r2.getDerivedStateFromError && (i2.setState(r2.getDerivedStateFromError(n2)), o2 = i2.__d), null != i2.componentDidCatch && (i2.componentDidCatch(n2, t2 || {}), o2 = i2.__d), o2) return i2.__E = i2;
478
+ } catch (l3) {
479
+ n2 = l3;
480
+ }
481
+ throw n2;
482
+ } }, u = 0, t = function(n2) {
483
+ return null != n2 && void 0 === n2.constructor;
484
+ }, C.prototype.setState = function(n2, l2) {
485
+ var u3;
486
+ u3 = null != this.__s && this.__s != this.state ? this.__s : this.__s = m({}, this.state), "function" == typeof n2 && (n2 = n2(m({}, u3), this.props)), n2 && m(u3, n2), null != n2 && this.__v && (l2 && this._sb.push(l2), A(this));
487
+ }, C.prototype.forceUpdate = function(n2) {
488
+ this.__v && (this.__e = true, n2 && this.__h.push(n2), A(this));
489
+ }, C.prototype.render = S, i = [], o = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, e = function(n2, l2) {
490
+ return n2.__v.__b - l2.__v.__b;
491
+ }, H.__r = 0, f = Math.random().toString(8), c = "__d" + f, a = "__a" + f, s = /(PointerCapture)$|Capture$/i, h = 0, p = V(false), v = V(true), y = 0;
492
+
493
+ // node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js
494
+ var f2 = 0;
495
+ function u2(e2, t2, n2, o2, i2, u3) {
496
+ t2 || (t2 = {});
497
+ var a2, c2, p2 = t2;
498
+ if ("ref" in p2) for (c2 in p2 = {}, t2) "ref" == c2 ? a2 = t2[c2] : p2[c2] = t2[c2];
499
+ var l2 = { type: e2, props: p2, key: n2, ref: a2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: --f2, __i: -1, __u: 0, __source: i2, __self: u3 };
500
+ if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 === p2[c2] && (p2[c2] = a2[c2]);
501
+ return l.vnode && l.vnode(l2), l2;
502
+ }
503
+
504
+ // runtime/src/injected/components/results-list.tsx
505
+ function HighlightedText({ text, query }) {
506
+ const needle = query.trim();
507
+ if (!needle) return /* @__PURE__ */ u2(S, { children: text });
508
+ const matcher = new RegExp(needle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "giu");
509
+ const parts = [];
510
+ let cursor = 0;
511
+ for (const match of text.matchAll(matcher)) {
512
+ const index = match.index ?? 0;
513
+ if (index > cursor) parts.push(text.slice(cursor, index));
514
+ parts.push(/* @__PURE__ */ u2("mark", { class: "codex-sidebar-search-mark", children: match[0] }, `match-${index}`));
515
+ cursor = index + match[0].length;
516
+ }
517
+ if (cursor === 0) return /* @__PURE__ */ u2(S, { children: text });
518
+ if (cursor < text.length) parts.push(text.slice(cursor));
519
+ return /* @__PURE__ */ u2(S, { children: parts });
520
+ }
521
+ function ResultsList({ entries, query, sort, emptyMessage, onOpen }) {
522
+ let lastGroup = null;
523
+ if (entries.length === 0) return /* @__PURE__ */ u2("div", { class: "codex-sidebar-results-empty", children: emptyMessage });
524
+ return /* @__PURE__ */ u2(S, { children: entries.flatMap((entry) => {
525
+ const nodes = [];
526
+ if (sort === "tag" && entry.tag !== lastGroup) {
527
+ lastGroup = entry.tag;
528
+ nodes.push(/* @__PURE__ */ u2("div", { class: "codex-sidebar-result-group", children: entry.tag }, `group-${entry.tag}`));
529
+ }
530
+ nodes.push(
531
+ /* @__PURE__ */ u2("button", { type: "button", class: "codex-sidebar-result", role: "listitem", title: entry.raw, onClick: () => onOpen(entry), children: [
532
+ /* @__PURE__ */ u2("span", { class: "codex-sidebar-result-tag", style: { "--codex-sidebar-tag-color": entry.color }, children: entry.tag }),
533
+ /* @__PURE__ */ u2("span", { class: "codex-sidebar-result-content", children: [
534
+ /* @__PURE__ */ u2("span", { class: "codex-sidebar-result-title", children: /* @__PURE__ */ u2(HighlightedText, { text: entry.title, query }) }),
535
+ entry.snippet ? /* @__PURE__ */ u2("span", { class: "codex-sidebar-result-snippet", children: /* @__PURE__ */ u2(HighlightedText, { text: entry.snippet, query }) }) : null
536
+ ] })
537
+ ] }, entry.key)
538
+ );
539
+ return nodes;
540
+ }) });
541
+ }
542
+ function renderResultsList(host, props) {
543
+ R(/* @__PURE__ */ u2(ResultsList, { ...props }), host);
544
+ }
545
+
546
+ // node_modules/motion-utils/dist/es/format-error-message.mjs
547
+ function formatErrorMessage(message, errorCode) {
548
+ return errorCode ? `${message}. For more information and steps for solving, visit https://motion.dev/troubleshooting/${errorCode}` : message;
549
+ }
550
+
551
+ // node_modules/motion-utils/dist/es/errors.mjs
552
+ var warning = () => {
553
+ };
554
+ var invariant = () => {
555
+ };
556
+ if (typeof process !== "undefined" && true) {
557
+ warning = (check, message, errorCode) => {
558
+ if (!check && typeof console !== "undefined") {
559
+ console.warn(formatErrorMessage(message, errorCode));
560
+ }
561
+ };
562
+ invariant = (check, message, errorCode) => {
563
+ if (!check) {
564
+ throw new Error(formatErrorMessage(message, errorCode));
565
+ }
566
+ };
567
+ }
568
+
569
+ // node_modules/motion-utils/dist/es/memo.mjs
570
+ // @__NO_SIDE_EFFECTS__
571
+ function memo(callback) {
572
+ let result;
573
+ return () => {
574
+ if (result === void 0)
575
+ result = callback();
576
+ return result;
577
+ };
578
+ }
579
+
580
+ // node_modules/motion-utils/dist/es/noop.mjs
581
+ var noop = /* @__NO_SIDE_EFFECTS__ */ (any) => any;
582
+
583
+ // node_modules/motion-utils/dist/es/time-conversion.mjs
584
+ var secondsToMilliseconds = /* @__NO_SIDE_EFFECTS__ */ (seconds) => seconds * 1e3;
585
+ var millisecondsToSeconds = /* @__NO_SIDE_EFFECTS__ */ (milliseconds) => milliseconds / 1e3;
586
+
587
+ // node_modules/motion-utils/dist/es/easing/utils/is-bezier-definition.mjs
588
+ var isBezierDefinition = /* @__NO_SIDE_EFFECTS__ */ (easing) => Array.isArray(easing) && typeof easing[0] === "number";
589
+
590
+ // node_modules/motion-dom/dist/es/animation/waapi/utils/linear.mjs
591
+ var generateLinearEasing = (easing, duration, resolution = 10) => {
592
+ let points = "";
593
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
594
+ for (let i2 = 0; i2 < numPoints; i2++) {
595
+ points += Math.round(easing(i2 / (numPoints - 1)) * 1e4) / 1e4 + ", ";
596
+ }
597
+ return `linear(${points.substring(0, points.length - 2)})`;
598
+ };
599
+
600
+ // node_modules/motion-dom/dist/es/animation/keyframes/get-final.mjs
601
+ var isNotNull = (value) => value !== null;
602
+ function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe, speed = 1) {
603
+ const resolvedKeyframes = keyframes.filter(isNotNull);
604
+ const useFirstKeyframe = speed < 0 || repeat && repeatType !== "loop" && repeat % 2 === 1;
605
+ const index = useFirstKeyframe ? 0 : resolvedKeyframes.length - 1;
606
+ return !index || finalKeyframe === void 0 ? resolvedKeyframes[index] : finalKeyframe;
607
+ }
608
+
609
+ // node_modules/motion-dom/dist/es/animation/utils/WithPromise.mjs
610
+ var WithPromise = class {
611
+ constructor() {
612
+ this.updateFinished();
613
+ }
614
+ get finished() {
615
+ return this._finished;
616
+ }
617
+ updateFinished() {
618
+ this._finished = new Promise((resolve) => {
619
+ this.resolve = resolve;
620
+ });
621
+ }
622
+ notifyFinished() {
623
+ this.resolve();
624
+ }
625
+ /**
626
+ * Allows the animation to be awaited.
627
+ *
628
+ * @deprecated Use `finished` instead.
629
+ */
630
+ then(onResolve, onReject) {
631
+ return this.finished.then(onResolve, onReject);
632
+ }
633
+ };
634
+
635
+ // node_modules/motion-dom/dist/es/animation/keyframes/utils/fill-wildcards.mjs
636
+ function fillWildcards(keyframes) {
637
+ for (let i2 = 1; i2 < keyframes.length; i2++) {
638
+ keyframes[i2] ?? (keyframes[i2] = keyframes[i2 - 1]);
639
+ }
640
+ }
641
+
642
+ // node_modules/motion-dom/dist/es/render/dom/is-css-var.mjs
643
+ var isCSSVar = (name) => name.startsWith("--");
644
+
645
+ // node_modules/motion-dom/dist/es/render/dom/style-set.mjs
646
+ function setStyle(element, name, value) {
647
+ isCSSVar(name) ? element.style.setProperty(name, value) : element.style[name] = value;
648
+ }
649
+
650
+ // node_modules/motion-dom/dist/es/utils/supports/flags.mjs
651
+ var supportsFlags = {};
652
+
653
+ // node_modules/motion-dom/dist/es/utils/supports/memo.mjs
654
+ function memoSupports(callback, supportsFlag) {
655
+ const memoized = memo(callback);
656
+ return () => supportsFlags[supportsFlag] ?? memoized();
657
+ }
658
+
659
+ // node_modules/motion-dom/dist/es/utils/supports/scroll-timeline.mjs
660
+ var supportsScrollTimeline = /* @__PURE__ */ memoSupports(() => window.ScrollTimeline !== void 0, "scrollTimeline");
661
+
662
+ // node_modules/motion-dom/dist/es/utils/supports/linear-easing.mjs
663
+ var supportsLinearEasing = /* @__PURE__ */ memoSupports(() => {
664
+ try {
665
+ document.createElement("div").animate({ opacity: 0 }, { easing: "linear(0, 1)" });
666
+ } catch (e2) {
667
+ return false;
668
+ }
669
+ return true;
670
+ }, "linearEasing");
671
+
672
+ // node_modules/motion-dom/dist/es/animation/waapi/easing/cubic-bezier.mjs
673
+ var cubicBezierAsString = ([a2, b2, c2, d2]) => `cubic-bezier(${a2}, ${b2}, ${c2}, ${d2})`;
674
+
675
+ // node_modules/motion-dom/dist/es/animation/waapi/easing/supported.mjs
676
+ var supportedWaapiEasing = {
677
+ linear: "linear",
678
+ ease: "ease",
679
+ easeIn: "ease-in",
680
+ easeOut: "ease-out",
681
+ easeInOut: "ease-in-out",
682
+ circIn: /* @__PURE__ */ cubicBezierAsString([0, 0.65, 0.55, 1]),
683
+ circOut: /* @__PURE__ */ cubicBezierAsString([0.55, 0, 1, 0.45]),
684
+ backIn: /* @__PURE__ */ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
685
+ backOut: /* @__PURE__ */ cubicBezierAsString([0.33, 1.53, 0.69, 0.99])
686
+ };
687
+
688
+ // node_modules/motion-dom/dist/es/animation/waapi/easing/map-easing.mjs
689
+ function mapEasingToNativeEasing(easing, duration) {
690
+ if (!easing) {
691
+ return void 0;
692
+ } else if (typeof easing === "function") {
693
+ return supportsLinearEasing() ? generateLinearEasing(easing, duration) : "ease-out";
694
+ } else if (isBezierDefinition(easing)) {
695
+ return cubicBezierAsString(easing);
696
+ } else if (Array.isArray(easing)) {
697
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) || supportedWaapiEasing.easeOut);
698
+ } else {
699
+ return supportedWaapiEasing[easing];
700
+ }
701
+ }
702
+
703
+ // node_modules/motion-dom/dist/es/animation/waapi/start-waapi-animation.mjs
704
+ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "easeOut", times } = {}, pseudoElement = void 0) {
705
+ const keyframeOptions = {
706
+ [valueName]: keyframes
707
+ };
708
+ if (times)
709
+ keyframeOptions.offset = times;
710
+ const easing = mapEasingToNativeEasing(ease, duration);
711
+ if (Array.isArray(easing))
712
+ keyframeOptions.easing = easing;
713
+ const options = {
714
+ delay,
715
+ duration,
716
+ easing: !Array.isArray(easing) ? easing : "linear",
717
+ fill: "both",
718
+ iterations: repeat + 1,
719
+ direction: repeatType === "reverse" ? "alternate" : "normal"
720
+ };
721
+ if (pseudoElement)
722
+ options.pseudoElement = pseudoElement;
723
+ return element.animate(keyframeOptions, options);
724
+ }
725
+
726
+ // node_modules/motion-dom/dist/es/animation/generators/utils/is-generator.mjs
727
+ function isGenerator(type) {
728
+ return typeof type === "function" && "applyToOptions" in type;
729
+ }
730
+
731
+ // node_modules/motion-dom/dist/es/animation/waapi/utils/apply-generator.mjs
732
+ function applyGeneratorOptions({ type, ...options }) {
733
+ if (isGenerator(type) && supportsLinearEasing()) {
734
+ return type.applyToOptions(options);
735
+ } else {
736
+ options.duration ?? (options.duration = 300);
737
+ options.ease ?? (options.ease = "easeOut");
738
+ }
739
+ return options;
740
+ }
741
+
742
+ // node_modules/motion-dom/dist/es/animation/NativeAnimation.mjs
743
+ var NativeAnimation = class extends WithPromise {
744
+ constructor(options) {
745
+ super();
746
+ this.finishedTime = null;
747
+ this.isStopped = false;
748
+ this.manualStartTime = null;
749
+ if (!options)
750
+ return;
751
+ const { element, name, keyframes, pseudoElement, allowFlatten = false, finalKeyframe, onComplete } = options;
752
+ this.isPseudoElement = Boolean(pseudoElement);
753
+ this.allowFlatten = allowFlatten;
754
+ this.options = options;
755
+ invariant(typeof options.type !== "string", `Mini animate() doesn't support "type" as a string.`, "mini-spring");
756
+ const transition = applyGeneratorOptions(options);
757
+ this.animation = startWaapiAnimation(element, name, keyframes, transition, pseudoElement);
758
+ if (transition.autoplay === false) {
759
+ this.animation.pause();
760
+ }
761
+ this.animation.onfinish = () => {
762
+ this.finishedTime = this.time;
763
+ if (!pseudoElement) {
764
+ const keyframe = getFinalKeyframe(keyframes, this.options, finalKeyframe, this.speed);
765
+ if (this.updateMotionValue) {
766
+ this.updateMotionValue(keyframe);
767
+ }
768
+ setStyle(element, name, keyframe);
769
+ this.animation.cancel();
770
+ }
771
+ onComplete?.();
772
+ this.notifyFinished();
773
+ };
774
+ }
775
+ play() {
776
+ if (this.isStopped)
777
+ return;
778
+ this.manualStartTime = null;
779
+ this.animation.play();
780
+ if (this.state === "finished") {
781
+ this.updateFinished();
782
+ }
783
+ }
784
+ pause() {
785
+ this.animation.pause();
786
+ }
787
+ complete() {
788
+ this.animation.finish?.();
789
+ }
790
+ cancel() {
791
+ try {
792
+ this.animation.cancel();
793
+ } catch (e2) {
794
+ }
795
+ }
796
+ stop() {
797
+ if (this.isStopped)
798
+ return;
799
+ this.isStopped = true;
800
+ const { state } = this;
801
+ if (state === "idle" || state === "finished") {
802
+ return;
803
+ }
804
+ if (this.updateMotionValue) {
805
+ this.updateMotionValue();
806
+ } else {
807
+ this.commitStyles();
808
+ }
809
+ if (!this.isPseudoElement)
810
+ this.cancel();
811
+ }
812
+ /**
813
+ * WAAPI doesn't natively have any interruption capabilities.
814
+ *
815
+ * In this method, we commit styles back to the DOM before cancelling
816
+ * the animation.
817
+ *
818
+ * This is designed to be overridden by NativeAnimationExtended, which
819
+ * will create a renderless JS animation and sample it twice to calculate
820
+ * its current value, "previous" value, and therefore allow
821
+ * Motion to also correctly calculate velocity for any subsequent animation
822
+ * while deferring the commit until the next animation frame.
823
+ */
824
+ commitStyles() {
825
+ const element = this.options?.element;
826
+ if (!this.isPseudoElement && element?.isConnected) {
827
+ this.animation.commitStyles?.();
828
+ }
829
+ }
830
+ get duration() {
831
+ const duration = this.animation.effect?.getComputedTiming?.().duration || 0;
832
+ return millisecondsToSeconds(Number(duration));
833
+ }
834
+ get iterationDuration() {
835
+ const { delay = 0 } = this.options || {};
836
+ return this.duration + millisecondsToSeconds(delay);
837
+ }
838
+ get time() {
839
+ return millisecondsToSeconds(Number(this.animation.currentTime) || 0);
840
+ }
841
+ set time(newTime) {
842
+ const wasFinished = this.finishedTime !== null;
843
+ this.manualStartTime = null;
844
+ this.finishedTime = null;
845
+ this.animation.currentTime = secondsToMilliseconds(newTime);
846
+ if (wasFinished) {
847
+ this.animation.pause();
848
+ }
849
+ }
850
+ /**
851
+ * The playback speed of the animation.
852
+ * 1 = normal speed, 2 = double speed, 0.5 = half speed.
853
+ */
854
+ get speed() {
855
+ return this.animation.playbackRate;
856
+ }
857
+ set speed(newSpeed) {
858
+ if (newSpeed < 0)
859
+ this.finishedTime = null;
860
+ this.animation.playbackRate = newSpeed;
861
+ }
862
+ get state() {
863
+ return this.finishedTime !== null ? "finished" : this.animation.playState;
864
+ }
865
+ get startTime() {
866
+ return this.manualStartTime ?? Number(this.animation.startTime);
867
+ }
868
+ set startTime(newStartTime) {
869
+ this.manualStartTime = this.animation.startTime = newStartTime;
870
+ }
871
+ /**
872
+ * Attaches a timeline to the animation, for instance the `ScrollTimeline`.
873
+ */
874
+ attachTimeline({ timeline, rangeStart, rangeEnd, observe }) {
875
+ if (this.allowFlatten) {
876
+ this.animation.effect?.updateTiming({ easing: "linear" });
877
+ }
878
+ this.animation.onfinish = null;
879
+ if (timeline && supportsScrollTimeline()) {
880
+ this.animation.timeline = timeline;
881
+ if (rangeStart)
882
+ this.animation.rangeStart = rangeStart;
883
+ if (rangeEnd)
884
+ this.animation.rangeEnd = rangeEnd;
885
+ return noop;
886
+ } else {
887
+ return observe(this);
888
+ }
889
+ }
890
+ };
891
+
892
+ // node_modules/motion-dom/dist/es/animation/GroupAnimation.mjs
893
+ var GroupAnimation = class {
894
+ constructor(animations) {
895
+ this.stop = () => this.runAll("stop");
896
+ this.animations = animations.filter(Boolean);
897
+ }
898
+ get finished() {
899
+ return Promise.all(this.animations.map((animation) => animation.finished));
900
+ }
901
+ /**
902
+ * TODO: Filter out cancelled or stopped animations before returning
903
+ */
904
+ getAll(propName) {
905
+ return this.animations[0][propName];
906
+ }
907
+ setAll(propName, newValue) {
908
+ for (let i2 = 0; i2 < this.animations.length; i2++) {
909
+ this.animations[i2][propName] = newValue;
910
+ }
911
+ }
912
+ attachTimeline(timeline) {
913
+ const subscriptions = this.animations.map((animation) => animation.attachTimeline(timeline));
914
+ return () => {
915
+ subscriptions.forEach((cancel, i2) => {
916
+ cancel && cancel();
917
+ this.animations[i2].stop();
918
+ });
919
+ };
920
+ }
921
+ get time() {
922
+ return this.getAll("time");
923
+ }
924
+ set time(time) {
925
+ this.setAll("time", time);
926
+ }
927
+ get speed() {
928
+ return this.getAll("speed");
929
+ }
930
+ set speed(speed) {
931
+ this.setAll("speed", speed);
932
+ }
933
+ get state() {
934
+ return this.getAll("state");
935
+ }
936
+ get startTime() {
937
+ return this.getAll("startTime");
938
+ }
939
+ get duration() {
940
+ return getMax(this.animations, "duration");
941
+ }
942
+ get iterationDuration() {
943
+ return getMax(this.animations, "iterationDuration");
944
+ }
945
+ runAll(methodName) {
946
+ this.animations.forEach((controls) => controls[methodName]());
947
+ }
948
+ play() {
949
+ this.runAll("play");
950
+ }
951
+ pause() {
952
+ this.runAll("pause");
953
+ }
954
+ cancel() {
955
+ this.runAll("cancel");
956
+ }
957
+ complete() {
958
+ this.runAll("complete");
959
+ }
960
+ };
961
+ function getMax(animations, propName) {
962
+ let max = 0;
963
+ for (let i2 = 0; i2 < animations.length; i2++) {
964
+ const value = animations[i2][propName];
965
+ if (value !== null && value > max) {
966
+ max = value;
967
+ }
968
+ }
969
+ return max;
970
+ }
971
+
972
+ // node_modules/motion-dom/dist/es/animation/GroupAnimationWithThen.mjs
973
+ var GroupAnimationWithThen = class extends GroupAnimation {
974
+ then(onResolve, _onReject) {
975
+ return this.finished.finally(onResolve).then(() => {
976
+ });
977
+ }
978
+ };
979
+
980
+ // node_modules/motion-dom/dist/es/animation/utils/active-animations.mjs
981
+ var animationMaps = /* @__PURE__ */ new WeakMap();
982
+ var animationMapKey = (name, pseudoElement = "") => `${name}:${pseudoElement}`;
983
+ function getAnimationMap(element) {
984
+ let map = animationMaps.get(element);
985
+ if (!map) {
986
+ map = /* @__PURE__ */ new Map();
987
+ animationMaps.set(element, map);
988
+ }
989
+ return map;
990
+ }
991
+
992
+ // node_modules/motion-dom/dist/es/animation/utils/resolve-transition.mjs
993
+ function resolveTransition(transition, parentTransition) {
994
+ if (transition?.inherit && parentTransition) {
995
+ const { inherit: _2, ...rest } = transition;
996
+ return { ...parentTransition, ...rest };
997
+ }
998
+ return transition;
999
+ }
1000
+
1001
+ // node_modules/motion-dom/dist/es/animation/utils/get-value-transition.mjs
1002
+ function getValueTransition(transition, key) {
1003
+ const valueTransition = transition?.[key] ?? transition?.["default"] ?? transition;
1004
+ if (valueTransition !== transition) {
1005
+ return resolveTransition(valueTransition, transition);
1006
+ }
1007
+ return valueTransition;
1008
+ }
1009
+
1010
+ // node_modules/motion-dom/dist/es/utils/border-radius.mjs
1011
+ var cornerRadiusProps = [
1012
+ "borderTopLeftRadius",
1013
+ "borderTopRightRadius",
1014
+ "borderBottomRightRadius",
1015
+ "borderBottomLeftRadius"
1016
+ ];
1017
+
1018
+ // node_modules/motion-dom/dist/es/animation/waapi/utils/px-values.mjs
1019
+ var pxValues = /* @__PURE__ */ new Set([
1020
+ // Border props
1021
+ "borderWidth",
1022
+ "borderTopWidth",
1023
+ "borderRightWidth",
1024
+ "borderBottomWidth",
1025
+ "borderLeftWidth",
1026
+ "borderRadius",
1027
+ ...cornerRadiusProps,
1028
+ // Positioning props
1029
+ "width",
1030
+ "maxWidth",
1031
+ "height",
1032
+ "maxHeight",
1033
+ "top",
1034
+ "right",
1035
+ "bottom",
1036
+ "left",
1037
+ "inset",
1038
+ "insetBlock",
1039
+ "insetBlockStart",
1040
+ "insetBlockEnd",
1041
+ "insetInline",
1042
+ "insetInlineStart",
1043
+ "insetInlineEnd",
1044
+ // Spacing props
1045
+ "padding",
1046
+ "paddingTop",
1047
+ "paddingRight",
1048
+ "paddingBottom",
1049
+ "paddingLeft",
1050
+ "paddingBlock",
1051
+ "paddingBlockStart",
1052
+ "paddingBlockEnd",
1053
+ "paddingInline",
1054
+ "paddingInlineStart",
1055
+ "paddingInlineEnd",
1056
+ "margin",
1057
+ "marginTop",
1058
+ "marginRight",
1059
+ "marginBottom",
1060
+ "marginLeft",
1061
+ "marginBlock",
1062
+ "marginBlockStart",
1063
+ "marginBlockEnd",
1064
+ "marginInline",
1065
+ "marginInlineStart",
1066
+ "marginInlineEnd",
1067
+ // Typography
1068
+ "fontSize",
1069
+ // Misc
1070
+ "backgroundPositionX",
1071
+ "backgroundPositionY"
1072
+ ]);
1073
+
1074
+ // node_modules/motion-dom/dist/es/animation/keyframes/utils/apply-px-defaults.mjs
1075
+ function applyPxDefaults(keyframes, name) {
1076
+ for (let i2 = 0; i2 < keyframes.length; i2++) {
1077
+ if (typeof keyframes[i2] === "number" && pxValues.has(name)) {
1078
+ keyframes[i2] = keyframes[i2] + "px";
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ // node_modules/motion-dom/dist/es/utils/resolve-elements.mjs
1084
+ function resolveElements(elementOrSelector, scope, selectorCache) {
1085
+ if (elementOrSelector == null) {
1086
+ return [];
1087
+ }
1088
+ if (elementOrSelector instanceof EventTarget) {
1089
+ return [elementOrSelector];
1090
+ } else if (typeof elementOrSelector === "string") {
1091
+ let root = document;
1092
+ if (scope) {
1093
+ root = scope.current;
1094
+ }
1095
+ const elements = selectorCache?.[elementOrSelector] ?? root.querySelectorAll(elementOrSelector);
1096
+ return elements ? Array.from(elements) : [];
1097
+ }
1098
+ return Array.from(elementOrSelector).filter((element) => element != null);
1099
+ }
1100
+
1101
+ // node_modules/motion-dom/dist/es/render/dom/style-computed.mjs
1102
+ function getComputedStyle2(element, name) {
1103
+ const computedStyle = window.getComputedStyle(element);
1104
+ return isCSSVar(name) ? computedStyle.getPropertyValue(name) : computedStyle[name];
1105
+ }
1106
+
1107
+ // node_modules/framer-motion/dist/es/animation/animators/waapi/animate-elements.mjs
1108
+ function animateElements(elementOrSelector, keyframes, options, scope) {
1109
+ if (elementOrSelector == null) {
1110
+ return [];
1111
+ }
1112
+ const elements = resolveElements(elementOrSelector, scope);
1113
+ const numElements = elements.length;
1114
+ invariant(Boolean(numElements), "No valid elements provided.", "no-valid-elements");
1115
+ const animationDefinitions = [];
1116
+ for (let i2 = 0; i2 < numElements; i2++) {
1117
+ const element = elements[i2];
1118
+ const elementTransition = { ...options };
1119
+ if (typeof elementTransition.delay === "function") {
1120
+ elementTransition.delay = elementTransition.delay(i2, numElements);
1121
+ }
1122
+ for (const valueName in keyframes) {
1123
+ let valueKeyframes = keyframes[valueName];
1124
+ if (!Array.isArray(valueKeyframes)) {
1125
+ valueKeyframes = [valueKeyframes];
1126
+ }
1127
+ const valueOptions = {
1128
+ ...getValueTransition(elementTransition, valueName)
1129
+ };
1130
+ valueOptions.duration && (valueOptions.duration = secondsToMilliseconds(valueOptions.duration));
1131
+ valueOptions.delay && (valueOptions.delay = secondsToMilliseconds(valueOptions.delay));
1132
+ const map = getAnimationMap(element);
1133
+ const key = animationMapKey(valueName, valueOptions.pseudoElement || "");
1134
+ const currentAnimation = map.get(key);
1135
+ currentAnimation && currentAnimation.stop();
1136
+ animationDefinitions.push({
1137
+ map,
1138
+ key,
1139
+ unresolvedKeyframes: valueKeyframes,
1140
+ options: {
1141
+ ...valueOptions,
1142
+ element,
1143
+ name: valueName,
1144
+ allowFlatten: !elementTransition.type && !elementTransition.ease
1145
+ }
1146
+ });
1147
+ }
1148
+ }
1149
+ for (let i2 = 0; i2 < animationDefinitions.length; i2++) {
1150
+ const { unresolvedKeyframes, options: animationOptions } = animationDefinitions[i2];
1151
+ const { element, name, pseudoElement } = animationOptions;
1152
+ if (!pseudoElement && unresolvedKeyframes[0] === null) {
1153
+ unresolvedKeyframes[0] = getComputedStyle2(element, name);
1154
+ }
1155
+ fillWildcards(unresolvedKeyframes);
1156
+ applyPxDefaults(unresolvedKeyframes, name);
1157
+ if (!pseudoElement && unresolvedKeyframes.length < 2) {
1158
+ unresolvedKeyframes.unshift(getComputedStyle2(element, name));
1159
+ }
1160
+ animationOptions.keyframes = unresolvedKeyframes;
1161
+ }
1162
+ const animations = [];
1163
+ for (let i2 = 0; i2 < animationDefinitions.length; i2++) {
1164
+ const { map, key, options: animationOptions } = animationDefinitions[i2];
1165
+ const animation = new NativeAnimation(animationOptions);
1166
+ map.set(key, animation);
1167
+ animation.finished.finally(() => map.delete(key));
1168
+ animations.push(animation);
1169
+ }
1170
+ return animations;
1171
+ }
1172
+
1173
+ // node_modules/framer-motion/dist/es/animation/animators/waapi/animate-style.mjs
1174
+ var createScopedWaapiAnimate = (scope) => {
1175
+ function scopedAnimate(elementOrSelector, keyframes, options) {
1176
+ return new GroupAnimationWithThen(animateElements(elementOrSelector, keyframes, options, scope));
1177
+ }
1178
+ return scopedAnimate;
1179
+ };
1180
+ var animateMini = /* @__PURE__ */ createScopedWaapiAnimate();
1181
+
1182
+ // runtime/src/injected/motion.ts
1183
+ var reducedMotionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
1184
+ var easeOut = [0.2, 0.8, 0.2, 1];
1185
+ var EXIT_SETTLE_TIMEOUT_MS = 240;
1186
+ function enterDashboard(overlay, dialog) {
1187
+ animateMini(overlay, { opacity: [0, 1] }, { duration: reducedMotionQuery.matches ? 0.1 : 0.14, ease: "easeOut" });
1188
+ if (reducedMotionQuery.matches) return;
1189
+ animateMini(
1190
+ dialog,
1191
+ {
1192
+ opacity: [0, 1],
1193
+ transform: ["translateY(6px) scale(.985)", "translateY(0) scale(1)"]
1194
+ },
1195
+ { duration: 0.18, ease: easeOut }
1196
+ );
1197
+ }
1198
+ async function exitDashboard(overlay, dialog) {
1199
+ const animations = [animateMini(overlay, { opacity: 0 }, { duration: reducedMotionQuery.matches ? 0.08 : 0.12, ease: "easeIn" })];
1200
+ if (!reducedMotionQuery.matches) {
1201
+ animations.push(animateMini(
1202
+ dialog,
1203
+ { opacity: 0, transform: "translateY(4px) scale(.99)" },
1204
+ { duration: 0.12, ease: "easeIn" }
1205
+ ));
1206
+ }
1207
+ await Promise.race([
1208
+ Promise.all(animations),
1209
+ new Promise((resolve) => setTimeout(resolve, EXIT_SETTLE_TIMEOUT_MS))
1210
+ ]);
1211
+ }
1212
+ function enterSortMenu(menu) {
1213
+ if (reducedMotionQuery.matches) return;
1214
+ animateMini(
1215
+ menu,
1216
+ { opacity: [0, 1], transform: ["translateY(-4px) scale(.98)", "translateY(0) scale(1)"] },
1217
+ { duration: 0.12, ease: easeOut }
1218
+ );
1219
+ }
1220
+ function enterDashboardContent(content) {
1221
+ animateMini(
1222
+ content,
1223
+ reducedMotionQuery.matches ? { opacity: [0, 1] } : { opacity: [0, 1], transform: ["translateY(2px)", "translateY(0)"] },
1224
+ { duration: reducedMotionQuery.matches ? 0.08 : 0.12, ease: "easeOut" }
1225
+ );
1226
+ }
1227
+ function refreshResults(results) {
1228
+ animateMini(
1229
+ results,
1230
+ reducedMotionQuery.matches ? { opacity: [0.72, 1] } : { opacity: [0.72, 1], transform: ["translateY(2px)", "translateY(0)"] },
1231
+ { duration: reducedMotionQuery.matches ? 0.08 : 0.12, ease: "easeOut" }
1232
+ );
1233
+ }
1234
+
1235
+ // runtime/src/injected/search.ts
1236
+ function selectVisibleEntries(entries, state, contentMatches) {
1237
+ const query = state.query.trim().toLocaleLowerCase();
1238
+ const filtered = entries.flatMap((entry) => {
1239
+ if (state.tag !== "all" && entry.tag !== state.tag) return [];
1240
+ if (!query) return [{ ...entry, matchType: "none", snippet: "" }];
1241
+ if (`${entry.tag} ${entry.time} ${entry.title}`.toLocaleLowerCase().includes(query)) {
1242
+ return [{ ...entry, matchType: "title", snippet: "" }];
1243
+ }
1244
+ const contentMatch = contentMatches.get(entry.threadId ?? "");
1245
+ if (!contentMatch) return [];
1246
+ return [{ ...entry, matchType: "content", snippet: `${contentMatch.role}\uFF1A${contentMatch.snippet}` }];
1247
+ });
1248
+ if (state.sort === "time") return filtered.sort((left, right) => (right.updatedAt ?? 0) - (left.updatedAt ?? 0) || left.index - right.index);
1249
+ if (state.sort === "tag") return filtered.sort((left, right) => left.tag.localeCompare(right.tag, "zh-CN") || left.title.localeCompare(right.title, "zh-CN"));
1250
+ if (state.sort === "title") return filtered.sort((left, right) => left.title.localeCompare(right.title, "zh-CN", { numeric: true }));
1251
+ return filtered.sort((left, right) => left.index - right.index);
1252
+ }
1253
+
1254
+ // runtime/src/injected/dashboard-view.ts
1255
+ var DashboardView = class {
1256
+ constructor(options) {
1257
+ this.options = options;
1258
+ document.querySelectorAll(".codex-sidebar-dashboard-overlay").forEach((overlay) => overlay.remove());
1259
+ }
1260
+ options;
1261
+ modal = null;
1262
+ closing = false;
1263
+ deletedDefinition = null;
1264
+ composing = false;
1265
+ get isClosing() {
1266
+ return this.closing;
1267
+ }
1268
+ get visibleResultCount() {
1269
+ return this.modal?.querySelectorAll(".codex-sidebar-result").length ?? 0;
1270
+ }
1271
+ hasFocus() {
1272
+ return Boolean(this.modal?.matches(":focus-within"));
1273
+ }
1274
+ contains(target) {
1275
+ return Boolean(this.modal?.contains(target));
1276
+ }
1277
+ async close(reason) {
1278
+ const { state, store, trace, requestRender } = this.options;
1279
+ if (!state.open || this.closing) return;
1280
+ this.closing = true;
1281
+ trace("dashboard-close-start", { reason });
1282
+ store.dispatch({ type: "sort-menu.set", value: false });
1283
+ const closingModal = this.modal;
1284
+ const dialog = closingModal?.querySelector(".codex-sidebar-dashboard-dialog");
1285
+ try {
1286
+ if (closingModal && dialog) await exitDashboard(closingModal, dialog);
1287
+ } finally {
1288
+ if (this.modal === closingModal) {
1289
+ store.dispatch({ type: "dashboard.close" });
1290
+ requestRender(reason);
1291
+ }
1292
+ this.closing = false;
1293
+ trace("dashboard-close-end", { reason });
1294
+ }
1295
+ }
1296
+ render(entries, reason = "state") {
1297
+ const {
1298
+ state,
1299
+ store,
1300
+ ensureToolbar,
1301
+ getNavigationTemplate,
1302
+ getTagDefinitions,
1303
+ getSearchState,
1304
+ i18n,
1305
+ requestRender
1306
+ } = this.options;
1307
+ if (this.closing && state.open) return;
1308
+ const backgroundUpdate = ["catalog-snapshot", "settings-snapshot", "search-result"].includes(reason);
1309
+ if (backgroundUpdate && this.modal && (state.view === "settings" || state.sortOpen || this.composing)) return;
1310
+ const previousScroll = this.modal?.querySelector(".codex-sidebar-results-list")?.scrollTop ?? 0;
1311
+ const toolbar = ensureToolbar(entries.map((entry2) => entry2.node).filter((node) => Boolean(node)));
1312
+ if (!toolbar) return;
1313
+ const activeInput = document.activeElement instanceof HTMLInputElement && document.activeElement.matches(".codex-sidebar-search-input, .codex-sidebar-tag-input, .codex-sidebar-tag-description") ? document.activeElement : null;
1314
+ const activeInputClass = activeInput?.className ?? null;
1315
+ const selectionStart = activeInput?.selectionStart ?? null;
1316
+ this.modal?.remove();
1317
+ this.modal = null;
1318
+ toolbar.replaceChildren();
1319
+ const entry = document.createElement("div");
1320
+ entry.className = "codex-sidebar-dashboard-entry";
1321
+ const navigationTemplate = getNavigationTemplate();
1322
+ const launcher = navigationTemplate?.cloneNode(true) ?? this.button("", "Tags");
1323
+ launcher.classList.add("codex-sidebar-dashboard-launcher");
1324
+ if (!navigationTemplate) launcher.dataset.dashboardFallback = "true";
1325
+ launcher.querySelector(".text-fade-truncate")?.replaceChildren(document.createTextNode("Tags"));
1326
+ const icon = launcher.querySelector("svg");
1327
+ if (icon) this.renderTagsIcon(icon);
1328
+ launcher.title = i18n.t("launcherLabel");
1329
+ launcher.setAttribute("aria-label", i18n.t("launcherLabel"));
1330
+ launcher.setAttribute("aria-haspopup", "dialog");
1331
+ launcher.setAttribute("aria-expanded", String(state.open));
1332
+ launcher.addEventListener("click", () => {
1333
+ this.closing = false;
1334
+ store.dispatch({ type: "dashboard.open" });
1335
+ requestRender("open-dashboard");
1336
+ });
1337
+ entry.appendChild(launcher);
1338
+ toolbar.appendChild(entry);
1339
+ if (!state.open) return;
1340
+ const overlay = document.createElement("div");
1341
+ overlay.className = "codex-sidebar-dashboard-overlay";
1342
+ const dialog = document.createElement("section");
1343
+ dialog.className = "codex-sidebar-dashboard-dialog";
1344
+ dialog.setAttribute("role", "dialog");
1345
+ dialog.setAttribute("aria-modal", "true");
1346
+ dialog.setAttribute("aria-label", i18n.t("sessionsDashboard"));
1347
+ const header = document.createElement("header");
1348
+ header.className = "codex-sidebar-dashboard-header";
1349
+ const headingGroup = document.createElement("div");
1350
+ const heading = document.createElement("h2");
1351
+ heading.className = "codex-sidebar-dashboard-heading";
1352
+ heading.textContent = i18n.t(state.view === "sessions" ? "sessionsDashboard" : "tagSettings");
1353
+ const subtitle = document.createElement("div");
1354
+ subtitle.className = "codex-sidebar-dashboard-subtitle";
1355
+ const searchState = getSearchState();
1356
+ subtitle.textContent = state.view === "sessions" ? i18n.t(searchState.indexStatus.phase === "ready" ? "indexReady" : "indexOnDemand", { count: entries.length }) : i18n.t("configuredTags", { count: getTagDefinitions().length });
1357
+ headingGroup.append(heading, subtitle);
1358
+ const tabs = document.createElement("div");
1359
+ tabs.className = "codex-sidebar-dashboard-tabs";
1360
+ tabs.setAttribute("role", "tablist");
1361
+ const dashboardTabs = [["sessions", i18n.t("sessions")], ["settings", i18n.t("tagSettings")]];
1362
+ dashboardTabs.forEach(([value, label]) => {
1363
+ const tab = this.button("codex-sidebar-dashboard-tab", label);
1364
+ tab.setAttribute("role", "tab");
1365
+ tab.setAttribute("aria-selected", String(state.view === value));
1366
+ tab.addEventListener("click", () => {
1367
+ store.dispatch({ type: "view.set", value });
1368
+ requestRender("dashboard-tab");
1369
+ });
1370
+ tabs.appendChild(tab);
1371
+ });
1372
+ const close = this.button("codex-sidebar-dashboard-close", "\xD7");
1373
+ close.title = i18n.t("close");
1374
+ close.setAttribute("aria-label", i18n.t("closeDashboard"));
1375
+ close.addEventListener("click", () => {
1376
+ void this.close("close-dashboard");
1377
+ });
1378
+ header.append(headingGroup, tabs, close);
1379
+ const body = document.createElement("div");
1380
+ body.className = "codex-sidebar-dashboard-body";
1381
+ if (state.view === "sessions") {
1382
+ this.renderSessions(body, entries, searchState);
1383
+ } else {
1384
+ this.renderSettings(body, entries);
1385
+ }
1386
+ dialog.append(header, body);
1387
+ overlay.appendChild(dialog);
1388
+ overlay.addEventListener("pointerdown", (event) => {
1389
+ if (event.target === overlay) void this.close("backdrop");
1390
+ });
1391
+ dialog.addEventListener("pointerdown", (event) => {
1392
+ if (!state.sortOpen || event.target instanceof Element && event.target.closest(".codex-sidebar-sort-control")) return;
1393
+ store.dispatch({ type: "sort-menu.set", value: false });
1394
+ dialog.querySelector(".codex-sidebar-sort-menu")?.remove();
1395
+ dialog.querySelector(".codex-sidebar-sort-trigger")?.setAttribute("aria-expanded", "false");
1396
+ }, true);
1397
+ dialog.addEventListener("keydown", (event) => {
1398
+ if (event.key === "Escape") {
1399
+ event.preventDefault();
1400
+ void this.close("escape");
1401
+ return;
1402
+ }
1403
+ if (event.key !== "Tab") return;
1404
+ const focusable = [...dialog.querySelectorAll("button, input, select")].filter((item) => !item.disabled);
1405
+ if (focusable.length === 0) return;
1406
+ const first = focusable[0];
1407
+ const last = focusable[focusable.length - 1];
1408
+ if (event.shiftKey && document.activeElement === first) {
1409
+ event.preventDefault();
1410
+ last.focus();
1411
+ } else if (!event.shiftKey && document.activeElement === last) {
1412
+ event.preventDefault();
1413
+ first.focus();
1414
+ }
1415
+ });
1416
+ this.modal = overlay;
1417
+ document.body.appendChild(overlay);
1418
+ if (backgroundUpdate) {
1419
+ const list = overlay.querySelector(".codex-sidebar-results-list");
1420
+ if (list) list.scrollTop = previousScroll;
1421
+ }
1422
+ if (reason === "open-dashboard") enterDashboard(overlay, dialog);
1423
+ if (reason === "dashboard-tab") enterDashboardContent(body);
1424
+ const sortMenuElement = dialog.querySelector(".codex-sidebar-sort-menu");
1425
+ if (reason === "sort-toggle" && state.sortOpen && sortMenuElement) enterSortMenu(sortMenuElement);
1426
+ const resultsElement = dialog.querySelector(".codex-sidebar-results");
1427
+ if (["tag", "sort", "search-result"].includes(reason) && resultsElement) refreshResults(resultsElement);
1428
+ const restoredInput = activeInputClass ? dialog.querySelector(`.${activeInputClass}`) : null;
1429
+ if (restoredInput) {
1430
+ restoredInput.focus({ preventScroll: true });
1431
+ if (selectionStart !== null) restoredInput.setSelectionRange(selectionStart, selectionStart);
1432
+ } else {
1433
+ requestAnimationFrame(() => dialog.querySelector(state.view === "sessions" ? ".codex-sidebar-search-input" : ".codex-sidebar-tag-input")?.focus({ preventScroll: true }));
1434
+ }
1435
+ }
1436
+ dispose() {
1437
+ this.modal?.remove();
1438
+ this.modal = null;
1439
+ this.closing = false;
1440
+ this.composing = false;
1441
+ }
1442
+ renderSessions(body, entries, searchState) {
1443
+ const { state, store, i18n, getEntries, scheduleContentSearch, requestRender, trace, onOpenEntry } = this.options;
1444
+ const controls = document.createElement("div");
1445
+ controls.className = "codex-sidebar-dashboard-controls";
1446
+ const search = document.createElement("label");
1447
+ search.className = "codex-sidebar-search";
1448
+ search.dataset.loading = String(searchState.loading);
1449
+ const searchIcon = document.createElement("span");
1450
+ searchIcon.className = "codex-sidebar-search-icon";
1451
+ searchIcon.textContent = "\u2315";
1452
+ const input = document.createElement("input");
1453
+ input.className = "codex-sidebar-search-input";
1454
+ input.type = "search";
1455
+ input.placeholder = i18n.t("searchPlaceholder");
1456
+ input.value = state.query;
1457
+ input.setAttribute("aria-label", i18n.t("searchLabel"));
1458
+ let composing = false;
1459
+ input.addEventListener("compositionstart", () => {
1460
+ composing = true;
1461
+ this.composing = true;
1462
+ });
1463
+ input.addEventListener("compositionend", (event) => {
1464
+ composing = false;
1465
+ this.composing = false;
1466
+ store.dispatch({ type: "query.set", value: event.currentTarget.value });
1467
+ const currentEntries = getEntries();
1468
+ scheduleContentSearch(currentEntries);
1469
+ requestRender("compositionend");
1470
+ });
1471
+ input.addEventListener("input", (event) => {
1472
+ store.dispatch({ type: "query.set", value: event.currentTarget.value });
1473
+ if (!composing && !event.isComposing) {
1474
+ const currentEntries = getEntries();
1475
+ scheduleContentSearch(currentEntries);
1476
+ requestRender("query");
1477
+ }
1478
+ });
1479
+ search.append(searchIcon, input);
1480
+ const sortOptions = [
1481
+ ["sidebar", i18n.t("sortDefault")],
1482
+ ["time", i18n.t("sortDateDescending")],
1483
+ ["tag", i18n.t("sortTag")],
1484
+ ["title", i18n.t("sortTitle")]
1485
+ ];
1486
+ const sortControl = document.createElement("div");
1487
+ sortControl.className = "codex-sidebar-sort-control";
1488
+ const sortTrigger = this.button("codex-sidebar-sort-trigger", "");
1489
+ sortTrigger.setAttribute("aria-label", i18n.t("sortAria"));
1490
+ sortTrigger.setAttribute("aria-haspopup", "listbox");
1491
+ sortTrigger.setAttribute("aria-expanded", String(state.sortOpen));
1492
+ sortTrigger.setAttribute("aria-controls", "codex-sidebar-sort-menu");
1493
+ const sortLabel = document.createElement("span");
1494
+ sortLabel.className = "codex-sidebar-sort-label";
1495
+ sortLabel.textContent = i18n.t("sort");
1496
+ const sortValue = document.createElement("span");
1497
+ sortValue.className = "codex-sidebar-sort-value";
1498
+ sortValue.textContent = sortOptions.find(([value]) => value === state.sort)?.[1] ?? i18n.t("sortDefault");
1499
+ const sortChevron = document.createElement("span");
1500
+ sortChevron.className = "codex-sidebar-sort-chevron";
1501
+ sortTrigger.append(sortLabel, sortValue, sortChevron);
1502
+ const focusSort = (selector = ".codex-sidebar-sort-trigger") => requestAnimationFrame(() => document.querySelector(selector)?.focus({ preventScroll: true }));
1503
+ sortTrigger.addEventListener("click", () => {
1504
+ store.dispatch({ type: "sort-menu.set", value: !state.sortOpen });
1505
+ requestRender("sort-toggle");
1506
+ focusSort(state.sortOpen ? ".codex-sidebar-sort-option[aria-selected='true']" : void 0);
1507
+ });
1508
+ sortTrigger.addEventListener("keydown", (event) => {
1509
+ if (!["ArrowDown", "ArrowUp", "Escape"].includes(event.key)) return;
1510
+ event.preventDefault();
1511
+ event.stopPropagation();
1512
+ store.dispatch({ type: "sort-menu.set", value: event.key !== "Escape" });
1513
+ requestRender("sort-keyboard");
1514
+ focusSort(event.key === "Escape" ? void 0 : event.key === "ArrowUp" ? ".codex-sidebar-sort-option:last-child" : ".codex-sidebar-sort-option[aria-selected='true']");
1515
+ });
1516
+ sortControl.appendChild(sortTrigger);
1517
+ if (state.sortOpen) {
1518
+ const sortMenu = document.createElement("div");
1519
+ sortMenu.id = "codex-sidebar-sort-menu";
1520
+ sortMenu.className = "codex-sidebar-sort-menu";
1521
+ sortMenu.setAttribute("role", "listbox");
1522
+ sortOptions.forEach(([value, label], index) => {
1523
+ const option = this.button("codex-sidebar-sort-option", "");
1524
+ option.dataset.value = value;
1525
+ option.setAttribute("role", "option");
1526
+ option.setAttribute("aria-selected", String(state.sort === value));
1527
+ const optionLabel = document.createElement("span");
1528
+ optionLabel.textContent = label;
1529
+ const check = document.createElement("span");
1530
+ check.className = "codex-sidebar-sort-check";
1531
+ check.textContent = state.sort === value ? "\u2713" : "";
1532
+ option.append(optionLabel, check);
1533
+ option.addEventListener("click", () => {
1534
+ store.dispatch({ type: "sort.set", value });
1535
+ trace("sort-change", { value: state.sort });
1536
+ requestRender("sort");
1537
+ focusSort();
1538
+ });
1539
+ option.addEventListener("keydown", (event) => {
1540
+ const options = [...sortMenu.querySelectorAll(".codex-sidebar-sort-option")];
1541
+ if (event.key === "Escape") {
1542
+ event.preventDefault();
1543
+ event.stopPropagation();
1544
+ store.dispatch({ type: "sort-menu.set", value: false });
1545
+ requestRender("sort-escape");
1546
+ focusSort();
1547
+ } else if (["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
1548
+ event.preventDefault();
1549
+ const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : (index + (event.key === "ArrowDown" ? 1 : -1) + options.length) % options.length;
1550
+ options[nextIndex]?.focus({ preventScroll: true });
1551
+ }
1552
+ });
1553
+ sortMenu.appendChild(option);
1554
+ });
1555
+ sortControl.appendChild(sortMenu);
1556
+ }
1557
+ controls.append(search, sortControl);
1558
+ const counts = /* @__PURE__ */ new Map();
1559
+ entries.forEach((item) => counts.set(item.tag, (counts.get(item.tag) ?? 0) + 1));
1560
+ const rail = document.createElement("div");
1561
+ rail.className = "codex-sidebar-filter-rail";
1562
+ rail.setAttribute("role", "group");
1563
+ rail.setAttribute("aria-label", i18n.t("filterByTag"));
1564
+ const dashboardFilters = [["all", i18n.t("all"), entries.length], ...Array.from(counts, ([tag, count]) => [tag, tag, count])];
1565
+ dashboardFilters.sort((left, right) => left[0] === "all" ? -1 : right[0] === "all" ? 1 : i18n.compare(left[1], right[1])).forEach(([value, label, count]) => {
1566
+ const chip = this.button("codex-sidebar-filter-chip", label);
1567
+ chip.dataset.value = value;
1568
+ chip.setAttribute("aria-pressed", String(state.tag === value));
1569
+ chip.title = `${label} \xB7 ${i18n.t("sessionCount", { count })}`;
1570
+ const badge = document.createElement("span");
1571
+ badge.className = "codex-sidebar-filter-count";
1572
+ badge.textContent = String(count);
1573
+ chip.appendChild(badge);
1574
+ chip.addEventListener("click", () => {
1575
+ store.dispatch({ type: "tag.set", value: state.tag === value && value !== "all" ? "all" : value });
1576
+ trace("tag-click", { value, selected: state.tag });
1577
+ requestRender("tag");
1578
+ });
1579
+ rail.appendChild(chip);
1580
+ });
1581
+ const results = selectVisibleEntries(entries, state, searchState.contentMatches);
1582
+ const panel = document.createElement("div");
1583
+ panel.className = "codex-sidebar-results";
1584
+ panel.dataset.loading = String(searchState.loading);
1585
+ const panelHead = document.createElement("div");
1586
+ panelHead.className = "codex-sidebar-results-head";
1587
+ const summary = document.createElement("span");
1588
+ summary.setAttribute("aria-live", "polite");
1589
+ const resultCount = i18n.t("resultCount", { visible: results.length, total: entries.length });
1590
+ summary.textContent = searchState.loading ? `${resultCount} \xB7 ${i18n.t("searchingContent")}` : searchState.error ? `${resultCount} \xB7 ${searchState.error}` : `${resultCount}${state.query ? ` \xB7 ${i18n.t("nameAndContent")}` : ""}`;
1591
+ panelHead.appendChild(summary);
1592
+ const list = document.createElement("div");
1593
+ list.className = "codex-sidebar-results-list";
1594
+ list.setAttribute("role", "list");
1595
+ renderResultsList(list, { entries: results, query: state.query, sort: state.sort, emptyMessage: i18n.t("noMatches"), onOpen: onOpenEntry });
1596
+ panel.append(panelHead, list);
1597
+ body.append(controls, rail, panel);
1598
+ }
1599
+ renderSettings(body, entries) {
1600
+ const { state, store, i18n, getTagDefinitions, onTagDefinitionsChanged, colorPresets, fallbackBlue, requestRender } = this.options;
1601
+ const tagDefinitions = getTagDefinitions();
1602
+ const configured = new Set(tagDefinitions.map(({ name }) => name.toLocaleLowerCase()));
1603
+ const detected = [...new Set(entries.filter((item) => item.tagged && !configured.has(item.tag.toLocaleLowerCase())).map((item) => item.tag))];
1604
+ const note = document.createElement("p");
1605
+ note.className = "codex-sidebar-tag-settings-note";
1606
+ note.appendChild(document.createTextNode(i18n.t("settingsNote")));
1607
+ const settingsError = this.options.getSearchState().error;
1608
+ if (settingsError) {
1609
+ const alert = document.createElement("p");
1610
+ alert.setAttribute("role", "alert");
1611
+ alert.textContent = settingsError;
1612
+ note.append(alert);
1613
+ }
1614
+ if (this.deletedDefinition) {
1615
+ const deleted = this.deletedDefinition;
1616
+ const undo = this.button("codex-sidebar-tag-add", i18n.t("undoDelete", { name: deleted.name }));
1617
+ undo.addEventListener("click", () => {
1618
+ const current = getTagDefinitions();
1619
+ if (current.length >= 32) {
1620
+ undo.textContent = i18n.t("tagLimit");
1621
+ return;
1622
+ }
1623
+ if (!current.some((item) => item.name.toLowerCase() === deleted.name.toLowerCase())) onTagDefinitionsChanged([...current, deleted]);
1624
+ this.deletedDefinition = null;
1625
+ requestRender("tag-config-undo");
1626
+ });
1627
+ note.append(undo);
1628
+ }
1629
+ if (detected.length) {
1630
+ const unconfigured = document.createElement("span");
1631
+ unconfigured.className = "codex-sidebar-tag-settings-unconfigured";
1632
+ unconfigured.textContent = i18n.t("unconfigured", { names: detected.join(i18n.locale === "zh-CN" ? "\u3001" : ", ") });
1633
+ note.appendChild(unconfigured);
1634
+ }
1635
+ const form = document.createElement("form");
1636
+ form.className = "codex-sidebar-tag-form";
1637
+ const formRow = document.createElement("div");
1638
+ formRow.className = "codex-sidebar-tag-form-row";
1639
+ const nameField = document.createElement("label");
1640
+ nameField.className = "codex-sidebar-tag-field";
1641
+ const nameLabel = document.createElement("span");
1642
+ nameLabel.className = "codex-sidebar-tag-field-label";
1643
+ nameLabel.textContent = i18n.t("tagName");
1644
+ const tagInput = document.createElement("input");
1645
+ tagInput.className = "codex-sidebar-tag-input";
1646
+ tagInput.placeholder = i18n.t("tagNamePlaceholder");
1647
+ tagInput.maxLength = 32;
1648
+ tagInput.setAttribute("aria-label", i18n.t("newTagName"));
1649
+ nameField.append(nameLabel, tagInput);
1650
+ const descriptionField = document.createElement("label");
1651
+ descriptionField.className = "codex-sidebar-tag-field";
1652
+ const descriptionLabel = document.createElement("span");
1653
+ descriptionLabel.className = "codex-sidebar-tag-field-label";
1654
+ descriptionLabel.textContent = i18n.t("classificationDescriptionOptional");
1655
+ const descriptionInput = document.createElement("input");
1656
+ descriptionInput.className = "codex-sidebar-tag-description";
1657
+ descriptionInput.placeholder = i18n.t("descriptionPlaceholder");
1658
+ descriptionInput.maxLength = 240;
1659
+ descriptionInput.setAttribute("aria-label", i18n.t("tagDescription"));
1660
+ descriptionField.append(descriptionLabel, descriptionInput);
1661
+ const colorField = document.createElement("div");
1662
+ colorField.className = "codex-sidebar-tag-color-field";
1663
+ const colorLabel = document.createElement("span");
1664
+ colorLabel.className = "codex-sidebar-tag-field-label";
1665
+ colorLabel.textContent = i18n.t("tagColor");
1666
+ const colorRow = document.createElement("div");
1667
+ colorRow.className = "codex-sidebar-tag-color-row";
1668
+ const presetGroup = document.createElement("div");
1669
+ presetGroup.className = "codex-sidebar-tag-color-presets";
1670
+ presetGroup.setAttribute("role", "group");
1671
+ presetGroup.setAttribute("aria-label", i18n.t("presetColors"));
1672
+ let selectedColor = colorPresets[0]?.color ?? fallbackBlue;
1673
+ const colorInput = document.createElement("input");
1674
+ colorInput.className = "codex-sidebar-tag-color-custom";
1675
+ colorInput.type = "color";
1676
+ colorInput.value = selectedColor;
1677
+ colorInput.title = i18n.t("customColor");
1678
+ colorInput.setAttribute("aria-label", i18n.t("customTagColor"));
1679
+ const customColorControl = document.createElement("label");
1680
+ customColorControl.className = "codex-sidebar-tag-color-custom-control";
1681
+ customColorControl.title = i18n.t("selectCustomColor");
1682
+ const customColorPreview = document.createElement("span");
1683
+ customColorPreview.className = "codex-sidebar-tag-color-custom-preview";
1684
+ customColorPreview.style.setProperty("--custom-color", selectedColor);
1685
+ const customColorLabel = document.createElement("span");
1686
+ customColorLabel.textContent = i18n.t("custom");
1687
+ customColorControl.append(colorInput, customColorPreview, customColorLabel);
1688
+ const updateColor = (color) => {
1689
+ selectedColor = color.toLocaleLowerCase();
1690
+ colorInput.value = selectedColor;
1691
+ customColorPreview.style.setProperty("--custom-color", selectedColor);
1692
+ presetGroup.querySelectorAll(".codex-sidebar-tag-color-preset").forEach((preset) => {
1693
+ preset.setAttribute("aria-pressed", String(preset.dataset.color === selectedColor));
1694
+ });
1695
+ };
1696
+ colorPresets.forEach(({ name: presetName, color }) => {
1697
+ const preset = this.button("codex-sidebar-tag-color-preset", "");
1698
+ preset.dataset.color = color;
1699
+ preset.style.setProperty("--preset-color", color);
1700
+ const localizedName = i18n.colorName(presetName);
1701
+ preset.title = `${localizedName} ${color}`;
1702
+ preset.setAttribute("aria-label", `${localizedName} ${color}`);
1703
+ preset.setAttribute("aria-pressed", String(color === selectedColor));
1704
+ preset.addEventListener("click", () => updateColor(color));
1705
+ presetGroup.appendChild(preset);
1706
+ });
1707
+ colorInput.addEventListener("input", () => updateColor(colorInput.value));
1708
+ colorRow.append(presetGroup, customColorControl);
1709
+ colorField.append(colorLabel, colorRow);
1710
+ const error = document.createElement("div");
1711
+ error.className = "codex-sidebar-tag-error";
1712
+ error.textContent = state.tagError === "invalid-name" ? i18n.t("invalidTagName") : state.tagError === "duplicate" ? i18n.t("duplicateTag") : "";
1713
+ const add = this.button("codex-sidebar-tag-add", i18n.t("add"));
1714
+ let editingName = null;
1715
+ const cancel = this.button("codex-sidebar-tag-delete", i18n.t("cancel"));
1716
+ cancel.hidden = true;
1717
+ cancel.addEventListener("click", () => requestRender("tag-edit-cancel"));
1718
+ add.type = "submit";
1719
+ formRow.append(nameField, descriptionField, add, cancel);
1720
+ form.append(formRow, colorField, error);
1721
+ form.addEventListener("submit", (event) => {
1722
+ event.preventDefault();
1723
+ const name = tagInput.value.trim();
1724
+ const description = descriptionInput.value.replace(/\s+/gu, " ").trim();
1725
+ const current = getTagDefinitions();
1726
+ if (!name || name.length > 32 || /[\[\]【】\r\n]/u.test(name) || name.toLowerCase() === "uncategorized") {
1727
+ error.textContent = i18n.t("invalidTagName");
1728
+ return;
1729
+ } else if (!editingName && current.some((item) => item.name.toLocaleLowerCase() === name.toLocaleLowerCase())) {
1730
+ error.textContent = i18n.t("duplicateTag");
1731
+ return;
1732
+ } else if (!editingName && current.length >= 32) {
1733
+ error.textContent = i18n.t("tagLimit");
1734
+ return;
1735
+ } else {
1736
+ const updated = { name, color: selectedColor, description };
1737
+ onTagDefinitionsChanged(editingName ? current.map((item) => item.name === editingName ? updated : item) : [...current, updated]);
1738
+ store.dispatch({ type: "tag-error.set", value: "" });
1739
+ }
1740
+ requestRender("tag-config-add");
1741
+ });
1742
+ const configList = document.createElement("div");
1743
+ configList.className = "codex-sidebar-tag-config-list";
1744
+ const configHeader = document.createElement("div");
1745
+ configHeader.className = "codex-sidebar-tag-config-header";
1746
+ const headerSpacer = document.createElement("span");
1747
+ const nameHeader = document.createElement("span");
1748
+ nameHeader.textContent = i18n.t("tagHeader", { count: tagDefinitions.length });
1749
+ const descriptionHeader = document.createElement("span");
1750
+ descriptionHeader.textContent = i18n.t("classificationDescription");
1751
+ const actionSpacer = document.createElement("span");
1752
+ configHeader.append(headerSpacer, nameHeader, descriptionHeader, actionSpacer);
1753
+ configList.appendChild(configHeader);
1754
+ tagDefinitions.slice().sort((left, right) => i18n.compare(left.name, right.name)).forEach((definition) => {
1755
+ const row = document.createElement("div");
1756
+ row.className = "codex-sidebar-tag-config-row";
1757
+ const swatch = document.createElement("span");
1758
+ swatch.className = "codex-sidebar-tag-config-swatch";
1759
+ swatch.style.setProperty("--codex-sidebar-tag-color", definition.color);
1760
+ const name = this.button("codex-sidebar-tag-config-name", definition.name);
1761
+ name.className = "codex-sidebar-tag-config-name";
1762
+ name.style.setProperty("--codex-sidebar-tag-color", definition.color);
1763
+ name.textContent = definition.name;
1764
+ name.title = i18n.t("editTag", { name: definition.name });
1765
+ name.setAttribute("aria-label", name.title);
1766
+ name.addEventListener("click", () => {
1767
+ editingName = definition.name;
1768
+ tagInput.value = definition.name;
1769
+ tagInput.readOnly = true;
1770
+ descriptionInput.value = definition.description;
1771
+ updateColor(definition.color);
1772
+ add.textContent = i18n.t("save");
1773
+ cancel.hidden = false;
1774
+ descriptionInput.focus();
1775
+ });
1776
+ const description = document.createElement("span");
1777
+ description.className = "codex-sidebar-tag-config-description";
1778
+ description.dataset.empty = String(!definition.description);
1779
+ description.textContent = definition.description || i18n.t("noClassificationDescription");
1780
+ description.title = definition.description || i18n.t("noClassificationDescription");
1781
+ const remove = this.button("codex-sidebar-tag-delete", "\xD7");
1782
+ remove.title = i18n.t("deleteTag", { name: definition.name });
1783
+ remove.setAttribute("aria-label", i18n.t("deleteTag", { name: definition.name }));
1784
+ remove.addEventListener("click", () => {
1785
+ if (remove.dataset.confirm !== "true") {
1786
+ remove.dataset.confirm = "true";
1787
+ remove.textContent = i18n.t("confirmDelete");
1788
+ remove.title = i18n.t("deleteImpact", { count: entries.filter((entry) => entry.tag.toLowerCase() === definition.name.toLowerCase()).length });
1789
+ remove.setAttribute("aria-label", remove.title);
1790
+ return;
1791
+ }
1792
+ onTagDefinitionsChanged(getTagDefinitions().filter((item) => item.name !== definition.name));
1793
+ this.deletedDefinition = definition;
1794
+ requestRender("tag-config-delete");
1795
+ });
1796
+ row.append(swatch, name, description, remove);
1797
+ configList.appendChild(row);
1798
+ });
1799
+ body.append(note, form, configList);
1800
+ }
1801
+ button(className, text) {
1802
+ const element = document.createElement("button");
1803
+ element.type = "button";
1804
+ element.className = className;
1805
+ element.textContent = text;
1806
+ return element;
1807
+ }
1808
+ renderTagsIcon(icon) {
1809
+ const namespace = "http://www.w3.org/2000/svg";
1810
+ const outline = document.createElementNS(namespace, "path");
1811
+ outline.setAttribute("d", "M2.25 2.25h4.32c.43 0 .84.17 1.14.47l5.61 5.61a1.6 1.6 0 0 1 0 2.27l-2.72 2.72a1.6 1.6 0 0 1-2.27 0L2.72 7.71a1.61 1.61 0 0 1-.47-1.14V2.25Z");
1812
+ outline.setAttribute("fill", "none");
1813
+ outline.setAttribute("stroke", "currentColor");
1814
+ outline.setAttribute("stroke-width", "1.15");
1815
+ outline.setAttribute("stroke-linejoin", "round");
1816
+ const aperture = document.createElementNS(namespace, "circle");
1817
+ aperture.setAttribute("cx", "5.15");
1818
+ aperture.setAttribute("cy", "5.15");
1819
+ aperture.setAttribute("r", ".82");
1820
+ aperture.setAttribute("fill", "currentColor");
1821
+ icon.replaceChildren(outline, aperture);
1822
+ }
1823
+ };
1824
+
1825
+ // runtime/src/injected/host-lifecycle.ts
1826
+ var HostLifecycle = class {
1827
+ constructor(options) {
1828
+ this.options = options;
1829
+ }
1830
+ options;
1831
+ observer = null;
1832
+ queued = false;
1833
+ queuedFrame = null;
1834
+ queuedTimer = null;
1835
+ pointerActive = false;
1836
+ pendingRefresh = false;
1837
+ refreshCount = 0;
1838
+ get observerRefreshCount() {
1839
+ return this.refreshCount;
1840
+ }
1841
+ mount(root) {
1842
+ if (this.observer) return;
1843
+ document.addEventListener("pointerdown", this.trackPointerDown, true);
1844
+ document.addEventListener("pointerup", this.trackPointerEnd, true);
1845
+ document.addEventListener("pointercancel", this.trackPointerEnd, true);
1846
+ document.addEventListener("focusout", this.trackFocusOut, true);
1847
+ this.observer = new MutationObserver((mutations) => {
1848
+ if (!mutations.some(this.options.isRelevantMutation) || this.queued) return;
1849
+ this.refreshCount += 1;
1850
+ this.scheduleObserverRefresh();
1851
+ });
1852
+ this.observer.observe(root, { childList: true, subtree: true, characterData: true });
1853
+ }
1854
+ deferIfInteracting(reason) {
1855
+ const focusWithin = this.options.hasInteractionFocus();
1856
+ if (!this.pointerActive && !focusWithin) return false;
1857
+ this.pendingRefresh = true;
1858
+ this.options.trace("render-deferred", { reason, pointerActive: this.pointerActive, focusWithin });
1859
+ return true;
1860
+ }
1861
+ didRender() {
1862
+ this.pendingRefresh = false;
1863
+ }
1864
+ dispose() {
1865
+ this.observer?.disconnect();
1866
+ this.observer = null;
1867
+ if (this.queuedFrame !== null) cancelAnimationFrame(this.queuedFrame);
1868
+ if (this.queuedTimer !== null) clearTimeout(this.queuedTimer);
1869
+ this.queued = false;
1870
+ this.queuedFrame = null;
1871
+ this.queuedTimer = null;
1872
+ this.pointerActive = false;
1873
+ this.pendingRefresh = false;
1874
+ document.removeEventListener("pointerdown", this.trackPointerDown, true);
1875
+ document.removeEventListener("pointerup", this.trackPointerEnd, true);
1876
+ document.removeEventListener("pointercancel", this.trackPointerEnd, true);
1877
+ document.removeEventListener("focusout", this.trackFocusOut, true);
1878
+ }
1879
+ scheduleObserverRefresh() {
1880
+ this.queued = true;
1881
+ const flush = () => {
1882
+ if (!this.queued) return;
1883
+ this.queued = false;
1884
+ if (this.queuedFrame !== null) cancelAnimationFrame(this.queuedFrame);
1885
+ if (this.queuedTimer !== null) clearTimeout(this.queuedTimer);
1886
+ this.queuedFrame = null;
1887
+ this.queuedTimer = null;
1888
+ this.options.onRefresh("observer");
1889
+ };
1890
+ this.queuedFrame = requestAnimationFrame(flush);
1891
+ this.queuedTimer = setTimeout(flush, 32);
1892
+ }
1893
+ trackPointerDown = (event) => {
1894
+ if (!(event.target instanceof Node) || !this.options.isInsideOwnedSurface(event.target)) return;
1895
+ this.pointerActive = true;
1896
+ const control = event.target instanceof Element ? event.target.closest("button,select,input")?.className : null;
1897
+ this.options.trace("pointerdown", { control: control ?? "toolbar" });
1898
+ };
1899
+ trackPointerEnd = () => {
1900
+ if (!this.pointerActive) return;
1901
+ setTimeout(() => {
1902
+ this.pointerActive = false;
1903
+ this.options.trace("pointerend");
1904
+ this.flushDeferredRefresh();
1905
+ }, 0);
1906
+ };
1907
+ trackFocusOut = (event) => {
1908
+ if (!(event.target instanceof Node) || !this.options.isInsideOwnedSurface(event.target)) return;
1909
+ setTimeout(() => this.flushDeferredRefresh(), 0);
1910
+ };
1911
+ flushDeferredRefresh() {
1912
+ if (!this.pendingRefresh || this.pointerActive || this.options.hasInteractionFocus()) return;
1913
+ this.options.onRefresh("interaction-end");
1914
+ }
1915
+ };
1916
+
1917
+ // runtime/src/injected/i18n.ts
1918
+ var zhCN = {
1919
+ add: () => "\u6DFB\u52A0",
1920
+ cancel: () => "\u53D6\u6D88",
1921
+ save: () => "\u4FDD\u5B58",
1922
+ editTag: ({ name }) => `\u7F16\u8F91 ${name} \u7684\u989C\u8272\u548C\u63CF\u8FF0`,
1923
+ confirmDelete: () => "\u786E\u8BA4\u5220\u9664",
1924
+ deleteImpact: ({ count }) => `\u5DF2\u53D1\u73B0 ${count} \u4E2A\u4F1A\u8BDD\u4F7F\u7528\u6B64\u6807\u7B7E\uFF1B\u53EA\u5220\u9664\u914D\u7F6E\uFF0C\u4E0D\u4FEE\u6539\u4F1A\u8BDD\u6807\u9898\u3002\u518D\u6B21\u70B9\u51FB\u786E\u8BA4\u3002`,
1925
+ undoDelete: ({ name }) => `\u64A4\u9500\u5220\u9664 ${name}`,
1926
+ tagLimit: () => "\u6700\u591A\u652F\u6301 32 \u4E2A\u6807\u7B7E",
1927
+ settingsSaveFailed: () => "\u6807\u7B7E\u4FDD\u5B58\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u5DF2\u4FDD\u5B58\u7684\u914D\u7F6E\u3002\u8BF7\u8FD0\u884C CLI doctor \u68C0\u67E5\u3002",
1928
+ catalogUnavailable: () => "\u672C\u5730\u4F1A\u8BDD\u76EE\u5F55\u6682\u4E0D\u53EF\u7528\uFF0C\u5F53\u524D\u4EC5\u5C55\u793A\u4FA7\u8FB9\u680F\u5DF2\u53D1\u73B0\u7684\u4F1A\u8BDD\u3002",
1929
+ all: () => "\u5168\u90E8",
1930
+ classificationDescription: () => "\u5206\u7C7B\u63CF\u8FF0",
1931
+ classificationDescriptionOptional: () => "\u5206\u7C7B\u63CF\u8FF0\uFF08\u53EF\u9009\uFF09",
1932
+ close: () => "\u5173\u95ED",
1933
+ closeDashboard: () => "\u5173\u95ED\u4F1A\u8BDD\u770B\u677F",
1934
+ configuredTags: ({ count }) => `${count} \u4E2A\u5DF2\u914D\u7F6E\u6807\u7B7E`,
1935
+ custom: () => "\u81EA\u5B9A\u4E49",
1936
+ customColor: () => "\u81EA\u5B9A\u4E49\u989C\u8272",
1937
+ customTagColor: () => "\u81EA\u5B9A\u4E49\u6807\u7B7E\u989C\u8272",
1938
+ deleteTag: ({ name }) => `\u5220\u9664 ${name} \u6807\u7B7E\u914D\u7F6E`,
1939
+ descriptionPlaceholder: () => "\u4F8B\u5982\uFF1A\u9700\u8981\u5B9A\u4F4D\u539F\u56E0\u6216\u8BC4\u4F30\u53EF\u884C\u6027\u7684\u4EFB\u52A1",
1940
+ duplicateTag: () => "\u8FD9\u4E2A\u6807\u7B7E\u5DF2\u7ECF\u5B58\u5728",
1941
+ filterByTag: () => "\u6309\u6807\u7B7E\u7B5B\u9009",
1942
+ filterSidebarByTag: () => "\u6309\u6807\u7B7E\u7B5B\u9009\u4FA7\u8FB9\u680F\u4F1A\u8BDD",
1943
+ indexOnDemand: ({ count }) => `${count} \u4E2A\u4F1A\u8BDD \xB7 \u672C\u5730\u7D22\u5F15\u6309\u9700\u52A0\u8F7D`,
1944
+ indexReady: ({ count }) => `${count} \u4E2A\u4F1A\u8BDD \xB7 \u672C\u5730\u7D22\u5F15\u5DF2\u5C31\u7EEA`,
1945
+ invalidTagName: () => "\u8BF7\u8F93\u5165 1\u201332 \u4E2A\u5B57\u7B26\uFF0C\u4E0D\u542B\u62EC\u53F7\uFF1BUncategorized \u4E3A\u4FDD\u7559\u540D\u79F0",
1946
+ launcherLabel: () => "\u6253\u5F00 Tags",
1947
+ nameAndContent: () => "\u540D\u79F0\u4E0E\u6B63\u6587",
1948
+ newTagName: () => "\u65B0\u6807\u7B7E\u540D\u79F0",
1949
+ noClassificationDescription: () => "\u672A\u8BBE\u7F6E\u5206\u7C7B\u63CF\u8FF0",
1950
+ noMatches: () => "\u6CA1\u6709\u5339\u914D\u7684\u4F1A\u8BDD",
1951
+ presetColors: () => "\u9884\u8BBE\u989C\u8272",
1952
+ resultCount: ({ visible, total }) => `${visible} / ${total} \u4E2A\u4F1A\u8BDD`,
1953
+ searchLabel: () => "\u641C\u7D22\u4F1A\u8BDD",
1954
+ searchPlaceholder: () => "\u641C\u7D22\u4F1A\u8BDD\u540D\u79F0\u6216\u5185\u5BB9\u2026",
1955
+ searchUnavailable: () => "\u672C\u5730\u641C\u7D22\u670D\u52A1\u5C1A\u672A\u8FDE\u63A5",
1956
+ searchingContent: () => "\u6B63\u5728\u641C\u7D22\u6B63\u6587\u2026",
1957
+ selectCustomColor: () => "\u9009\u62E9\u81EA\u5B9A\u4E49\u989C\u8272",
1958
+ sessionCount: ({ count }) => `${count} \u4E2A\u4F1A\u8BDD`,
1959
+ sessions: () => "\u4F1A\u8BDD",
1960
+ sessionsDashboard: () => "\u4F1A\u8BDD\u770B\u677F",
1961
+ settingsNote: () => "\u63CF\u8FF0\u5E2E\u52A9 AI \u5728\u9996\u6B21\u547D\u540D\u65F6\u9009\u62E9\u6807\u7B7E\uFF1B\u989C\u8272\u4EC5\u7528\u4E8E\u663E\u793A\u3002",
1962
+ sort: () => "\u6392\u5E8F",
1963
+ sortAria: () => "\u4F1A\u8BDD\u6392\u5E8F",
1964
+ sortDateDescending: () => "\u6700\u8FD1\u66F4\u65B0",
1965
+ sortDefault: () => "\u9ED8\u8BA4",
1966
+ sortTag: () => "\u6807\u7B7E",
1967
+ sortTitle: () => "\u6807\u9898",
1968
+ tagColor: () => "\u6807\u7B7E\u989C\u8272",
1969
+ tagDescription: () => "\u6807\u7B7E\u5206\u7C7B\u63CF\u8FF0",
1970
+ tagHeader: ({ count }) => `\u6807\u7B7E \xB7 ${count}`,
1971
+ tagName: () => "\u6807\u7B7E\u540D\u79F0",
1972
+ tagNamePlaceholder: () => "\u4F8B\u5982 Review",
1973
+ tagSettings: () => "\u6807\u7B7E\u8BBE\u7F6E",
1974
+ tags: () => "\u6807\u7B7E",
1975
+ unconfigured: ({ names }) => `\u672A\u914D\u7F6E\uFF1A${names}`,
1976
+ uncategorized: () => "\u672A\u5206\u7C7B"
1977
+ };
1978
+ var enUS = {
1979
+ add: () => "Add tag",
1980
+ cancel: () => "Cancel",
1981
+ save: () => "Save",
1982
+ editTag: ({ name }) => `Edit color and description for ${name}`,
1983
+ confirmDelete: () => "Confirm",
1984
+ deleteImpact: ({ count }) => `${count} known sessions use this tag. Only the configuration is removed; titles are unchanged. Click again to confirm.`,
1985
+ undoDelete: ({ name }) => `Undo deletion of ${name}`,
1986
+ tagLimit: () => "Up to 32 tags are supported",
1987
+ settingsSaveFailed: () => "Tags could not be saved. Saved settings were restored. Run CLI doctor to investigate.",
1988
+ catalogUnavailable: () => "Local catalog unavailable. Results currently include only sessions discovered in the sidebar.",
1989
+ all: () => "All",
1990
+ classificationDescription: () => "Classification description",
1991
+ classificationDescriptionOptional: () => "Classification description (optional)",
1992
+ close: () => "Close",
1993
+ closeDashboard: () => "Close session dashboard",
1994
+ configuredTags: ({ count }) => `${count} configured ${Number(count) === 1 ? "tag" : "tags"}`,
1995
+ custom: () => "Custom",
1996
+ customColor: () => "Custom color",
1997
+ customTagColor: () => "Custom tag color",
1998
+ deleteTag: ({ name }) => `Delete ${name} tag configuration`,
1999
+ descriptionPlaceholder: () => "For example: tasks that require investigation or feasibility analysis",
2000
+ duplicateTag: () => "This tag already exists",
2001
+ filterByTag: () => "Filter by tag",
2002
+ filterSidebarByTag: () => "Filter sidebar sessions by tag",
2003
+ indexOnDemand: ({ count }) => `${count} ${Number(count) === 1 ? "session" : "sessions"} \xB7 Index loads on demand`,
2004
+ indexReady: ({ count }) => `${count} ${Number(count) === 1 ? "session" : "sessions"} \xB7 Local index ready`,
2005
+ invalidTagName: () => "Enter 1\u201332 characters without brackets; Uncategorized is reserved",
2006
+ launcherLabel: () => "Open Tags",
2007
+ nameAndContent: () => "Title and content",
2008
+ newTagName: () => "New tag name",
2009
+ noClassificationDescription: () => "No classification description",
2010
+ noMatches: () => "No matching sessions",
2011
+ presetColors: () => "Preset colors",
2012
+ resultCount: ({ visible, total }) => `${visible} / ${total} ${Number(total) === 1 ? "session" : "sessions"}`,
2013
+ searchLabel: () => "Search sessions",
2014
+ searchPlaceholder: () => "Search session titles or content\u2026",
2015
+ searchUnavailable: () => "Local search service is not connected",
2016
+ searchingContent: () => "Searching content\u2026",
2017
+ selectCustomColor: () => "Choose a custom color",
2018
+ sessionCount: ({ count }) => `${count} ${Number(count) === 1 ? "session" : "sessions"}`,
2019
+ sessions: () => "Sessions",
2020
+ sessionsDashboard: () => "Sessions",
2021
+ settingsNote: () => "Descriptions help AI choose a tag when first naming a session; colors only affect display.",
2022
+ sort: () => "Sort",
2023
+ sortAria: () => "Sort sessions",
2024
+ sortDateDescending: () => "Recently updated",
2025
+ sortDefault: () => "Default",
2026
+ sortTag: () => "Tag",
2027
+ sortTitle: () => "Title",
2028
+ tagColor: () => "Tag color",
2029
+ tagDescription: () => "Tag classification description",
2030
+ tagHeader: ({ count }) => `Tags \xB7 ${count}`,
2031
+ tagName: () => "Tag name",
2032
+ tagNamePlaceholder: () => "For example: Review",
2033
+ tagSettings: () => "Tag settings",
2034
+ tags: () => "Tags",
2035
+ unconfigured: ({ names }) => `Not configured: ${names}`,
2036
+ uncategorized: () => "Uncategorized"
2037
+ };
2038
+ var messages = {
2039
+ "en-US": enUS,
2040
+ "zh-CN": zhCN
2041
+ };
2042
+ var colorNames = {
2043
+ "en-US": {
2044
+ "\u6D77\u84DD": "Ocean blue",
2045
+ "\u9E22\u7D2B": "Violet",
2046
+ "\u73CA\u745A": "Coral",
2047
+ "\u7425\u73C0": "Amber",
2048
+ "\u677E\u7EFF": "Pine green",
2049
+ "\u96FE\u7070": "Mist gray"
2050
+ },
2051
+ "zh-CN": {
2052
+ "\u6D77\u84DD": "\u6D77\u84DD",
2053
+ "\u9E22\u7D2B": "\u9E22\u7D2B",
2054
+ "\u73CA\u745A": "\u73CA\u745A",
2055
+ "\u7425\u73C0": "\u7425\u73C0",
2056
+ "\u677E\u7EFF": "\u677E\u7EFF",
2057
+ "\u96FE\u7070": "\u96FE\u7070"
2058
+ }
2059
+ };
2060
+ function resolveUiLocale(language) {
2061
+ return language?.trim().toLocaleLowerCase().startsWith("zh") ? "zh-CN" : "en-US";
2062
+ }
2063
+ function readCodexLocale() {
2064
+ return resolveUiLocale(document.documentElement.lang || navigator.language);
2065
+ }
2066
+ var RuntimeI18n = class {
2067
+ currentLocale;
2068
+ constructor(language) {
2069
+ this.currentLocale = language === void 0 ? readCodexLocale() : resolveUiLocale(language);
2070
+ }
2071
+ get locale() {
2072
+ return this.currentLocale;
2073
+ }
2074
+ setLocale(locale) {
2075
+ if (locale === this.currentLocale) return false;
2076
+ this.currentLocale = locale;
2077
+ return true;
2078
+ }
2079
+ t(key, params = {}) {
2080
+ return messages[this.currentLocale][key](params);
2081
+ }
2082
+ compare(left, right) {
2083
+ return left.localeCompare(right, this.currentLocale);
2084
+ }
2085
+ colorName(name) {
2086
+ return colorNames[this.currentLocale][name] ?? name;
2087
+ }
2088
+ };
2089
+ function observeCodexLocale(onChange) {
2090
+ const observer = new MutationObserver(() => onChange(readCodexLocale()));
2091
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["lang"] });
2092
+ return () => observer.disconnect();
2093
+ }
2094
+
2095
+ // runtime/src/injected/runtime-client.ts
2096
+ var RuntimeClient = class {
2097
+ constructor(bindingName, onMessage, onRejectedMessage, resolveBinding = (name) => window[name]) {
2098
+ this.bindingName = bindingName;
2099
+ this.onMessage = onMessage;
2100
+ this.onRejectedMessage = onRejectedMessage;
2101
+ this.resolveBinding = resolveBinding;
2102
+ }
2103
+ bindingName;
2104
+ onMessage;
2105
+ onRejectedMessage;
2106
+ resolveBinding;
2107
+ protocolVersion = RUNTIME_PROTOCOL_VERSION;
2108
+ get connected() {
2109
+ return typeof this.resolveBinding(this.bindingName) === "function";
2110
+ }
2111
+ send(type, payload, requestId) {
2112
+ const binding = this.resolveBinding(this.bindingName);
2113
+ if (typeof binding !== "function") return false;
2114
+ binding(JSON.stringify(createRuntimeMessage(type, payload, requestId)));
2115
+ return true;
2116
+ }
2117
+ handle(value) {
2118
+ const parsed = parseRuntimeMessage(value);
2119
+ if (!parsed.ok) {
2120
+ this.onRejectedMessage(parsed.reason);
2121
+ return false;
2122
+ }
2123
+ return this.onMessage(parsed.message);
2124
+ }
2125
+ };
2126
+
2127
+ // runtime/src/injected/runtime-config.ts
2128
+ var HEX_COLOR = /^#[0-9a-f]{6}$/iu;
2129
+ function isRecord(value) {
2130
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2131
+ }
2132
+ function parseRuntimeConfig(value) {
2133
+ if (!isRecord(value)) throw new Error("Invalid Codex Tags runtime config");
2134
+ if (typeof value.version !== "string" || !value.version.trim()) throw new Error("Invalid Codex Tags runtime version");
2135
+ if (value.protocolVersion !== RUNTIME_PROTOCOL_VERSION) throw new Error(`Unsupported Codex Tags protocol ${String(value.protocolVersion)}`);
2136
+ if (value.settingsSource !== "repository" && value.settingsSource !== "defaults") throw new Error("Invalid Codex Tags settings source");
2137
+ if (typeof value.requestBinding !== "string" || !/^__[A-Za-z0-9]+$/u.test(value.requestBinding)) throw new Error("Invalid Codex Tags runtime binding");
2138
+ if (!Array.isArray(value.tagDefinitions)) throw new Error("Invalid Codex Tags tag definitions");
2139
+ const colorPresets = Array.isArray(value.colorPresets) ? value.colorPresets.flatMap((item) => {
2140
+ if (!isRecord(item) || typeof item.name !== "string" || typeof item.color !== "string" || !HEX_COLOR.test(item.color)) return [];
2141
+ return [{ name: item.name.trim(), color: item.color.toLocaleLowerCase() }];
2142
+ }) : [];
2143
+ if (colorPresets.length === 0) throw new Error("Invalid Codex Tags color presets");
2144
+ if (!isRecord(value.legacyToneColors)) throw new Error("Invalid Codex Tags legacy colors");
2145
+ const legacyToneColors = Object.fromEntries(
2146
+ Object.entries(value.legacyToneColors).filter((entry) => typeof entry[1] === "string" && HEX_COLOR.test(entry[1]))
2147
+ );
2148
+ if (!legacyToneColors.neutral || !legacyToneColors.blue) throw new Error("Codex Tags neutral and blue colors are required");
2149
+ return {
2150
+ version: value.version,
2151
+ protocolVersion: value.protocolVersion,
2152
+ tagDefinitions: normalizeTagDefinitions(value.tagDefinitions, []),
2153
+ settingsSource: value.settingsSource,
2154
+ colorPresets,
2155
+ legacyToneColors,
2156
+ requestBinding: value.requestBinding
2157
+ };
2158
+ }
2159
+
2160
+ // runtime/src/injected/session-registry.ts
2161
+ var SessionRegistry = class {
2162
+ constructor(storage, cacheKey, parseTitle, colorForTag) {
2163
+ this.storage = storage;
2164
+ this.cacheKey = cacheKey;
2165
+ this.parseTitle = parseTitle;
2166
+ this.colorForTag = colorForTag;
2167
+ this.restore();
2168
+ }
2169
+ storage;
2170
+ cacheKey;
2171
+ parseTitle;
2172
+ colorForTag;
2173
+ catalogIds = null;
2174
+ entriesByKey = /* @__PURE__ */ new Map();
2175
+ persistedCacheJson = null;
2176
+ ingest(nodes, bindings) {
2177
+ nodes.forEach((node, index) => {
2178
+ const raw = node.getAttribute(bindings.rawTitleAttribute) ?? node.textContent?.trim() ?? "";
2179
+ const parsed = this.parseTitle(raw);
2180
+ if (!parsed) return;
2181
+ const row = bindings.rowForTitle(node);
2182
+ row?.setAttribute(bindings.rowAttribute, "true");
2183
+ const threadId = bindings.threadIdForRow(row);
2184
+ const localId = threadId?.replace(/^local:/u, "");
2185
+ const key = localId ?? `title:${raw}`;
2186
+ if (this.catalogIds && localId && !localId.includes(":") && !this.catalogIds.has(localId)) return;
2187
+ const pinned = bindings.isPinnedRow(row);
2188
+ if (pinned) {
2189
+ const toggle = bindings.sectionToggleForRow(row);
2190
+ if (toggle) bindings.onPinnedToggle(toggle);
2191
+ }
2192
+ this.entriesByKey.set(key, {
2193
+ ...this.entriesByKey.get(key),
2194
+ ...parsed,
2195
+ key,
2196
+ threadId,
2197
+ node,
2198
+ row,
2199
+ index: this.entriesByKey.get(key)?.index ?? index,
2200
+ pinned,
2201
+ projectId: bindings.projectIdForRow(row)
2202
+ });
2203
+ });
2204
+ this.persist();
2205
+ return this.values();
2206
+ }
2207
+ values() {
2208
+ return Array.from(this.entriesByKey.values(), (entry) => ({
2209
+ ...entry,
2210
+ node: entry.node?.isConnected ? entry.node : null,
2211
+ row: entry.row?.isConnected ? entry.row : null
2212
+ }));
2213
+ }
2214
+ applyCatalog(items) {
2215
+ const ids = /* @__PURE__ */ new Set();
2216
+ for (const item of items) {
2217
+ if (!item || typeof item !== "object") continue;
2218
+ const candidate = item;
2219
+ if (typeof candidate.threadId !== "string" || typeof candidate.raw !== "string") continue;
2220
+ const parsed = this.parseTitle(candidate.raw);
2221
+ if (!parsed) continue;
2222
+ const key = candidate.threadId;
2223
+ ids.add(key);
2224
+ this.entriesByKey.set(key, {
2225
+ ...this.entriesByKey.get(key),
2226
+ ...parsed,
2227
+ key,
2228
+ threadId: this.entriesByKey.get(key)?.threadId ?? key,
2229
+ updatedAt: typeof candidate.updatedAt === "number" && Number.isFinite(candidate.updatedAt) ? candidate.updatedAt : 0,
2230
+ index: this.entriesByKey.get(key)?.index ?? ids.size,
2231
+ pinned: typeof candidate.pinned === "boolean" ? candidate.pinned : this.entriesByKey.get(key)?.pinned ?? false,
2232
+ projectId: typeof candidate.projectId === "string" ? candidate.projectId : this.entriesByKey.get(key)?.projectId ?? null
2233
+ });
2234
+ }
2235
+ this.catalogIds = ids;
2236
+ for (const [key, entry] of this.entriesByKey) {
2237
+ const localId = entry.threadId?.replace(/^local:/u, "");
2238
+ if (localId && !localId.includes(":") && !ids.has(localId)) this.entriesByKey.delete(key);
2239
+ }
2240
+ this.persist();
2241
+ }
2242
+ updateColors() {
2243
+ this.entriesByKey.forEach((entry) => {
2244
+ entry.color = this.colorForTag(entry.tag);
2245
+ });
2246
+ this.persist();
2247
+ }
2248
+ reparse() {
2249
+ this.entriesByKey.forEach((entry) => {
2250
+ const parsed = this.parseTitle(entry.raw);
2251
+ if (parsed) Object.assign(entry, parsed);
2252
+ });
2253
+ this.persist();
2254
+ }
2255
+ delete(key) {
2256
+ this.entriesByKey.delete(key);
2257
+ this.persist();
2258
+ }
2259
+ threadIds() {
2260
+ return Array.from(this.entriesByKey.values(), ({ threadId }) => threadId).filter((threadId) => Boolean(threadId));
2261
+ }
2262
+ debugIndex() {
2263
+ return Array.from(this.entriesByKey.values(), ({ key, threadId, title, projectId, pinned }) => ({ key, threadId, title, projectId, pinned }));
2264
+ }
2265
+ get size() {
2266
+ return this.entriesByKey.size;
2267
+ }
2268
+ clearPersistentCache() {
2269
+ try {
2270
+ this.storage.removeItem(this.cacheKey);
2271
+ } catch {
2272
+ }
2273
+ }
2274
+ restore() {
2275
+ try {
2276
+ const savedEntries = JSON.parse(this.storage.getItem(this.cacheKey) ?? "[]");
2277
+ if (!Array.isArray(savedEntries)) return;
2278
+ savedEntries.forEach((candidate) => {
2279
+ if (!candidate || typeof candidate !== "object") return;
2280
+ const entry = candidate;
2281
+ if (typeof entry.key !== "string" || typeof entry.raw !== "string" || typeof entry.tag !== "string") return;
2282
+ const key = entry.threadId?.replace(/^local:/u, "") ?? entry.key;
2283
+ this.entriesByKey.set(key, {
2284
+ ...entry,
2285
+ key,
2286
+ color: this.colorForTag(entry.tag),
2287
+ node: null,
2288
+ row: null
2289
+ });
2290
+ });
2291
+ this.persistedCacheJson = JSON.stringify(savedEntries);
2292
+ } catch {
2293
+ }
2294
+ }
2295
+ persist() {
2296
+ try {
2297
+ const savedEntries = Array.from(this.entriesByKey.values(), ({ node: _node, row: _row, ...entry }) => entry);
2298
+ const nextCacheJson = JSON.stringify(savedEntries);
2299
+ if (nextCacheJson === this.persistedCacheJson) return;
2300
+ this.storage.setItem(this.cacheKey, nextCacheJson);
2301
+ this.persistedCacheJson = nextCacheJson;
2302
+ } catch {
2303
+ }
2304
+ }
2305
+ };
2306
+
2307
+ // runtime/src/injected/sidebar-tag-filter.ts
2308
+ var SidebarTagFilter = class {
2309
+ constructor(options) {
2310
+ this.options = options;
2311
+ }
2312
+ options;
2313
+ apply(entries) {
2314
+ const selectedTag = this.options.getSelectedTag();
2315
+ const selected = selectedTag.toLocaleLowerCase();
2316
+ if (selectedTag === "all") document.documentElement.removeAttribute(this.options.activeAttribute);
2317
+ else document.documentElement.setAttribute(this.options.activeAttribute, "true");
2318
+ entries.forEach((entry) => {
2319
+ if (!entry.row?.isConnected) return;
2320
+ const matches = selectedTag === "all" || entry.tag.toLocaleLowerCase() === selected;
2321
+ if (matches) entry.row.removeAttribute(this.options.filteredAttribute);
2322
+ else entry.row.setAttribute(this.options.filteredAttribute, "true");
2323
+ });
2324
+ }
2325
+ render(entries) {
2326
+ const mounted = this.options.ensureHost();
2327
+ if (!mounted) return;
2328
+ const { filterHost, pinnedToggle } = mounted;
2329
+ const previousRail = filterHost.querySelector(".codex-sidebar-quick-filter-rail");
2330
+ const previousScrollLeft = previousRail?.scrollLeft ?? 0;
2331
+ const focusedValue = filterHost.contains(document.activeElement) ? document.activeElement?.closest(".codex-sidebar-quick-filter")?.dataset.value : null;
2332
+ filterHost.replaceChildren();
2333
+ const heading = document.createElement("div");
2334
+ heading.className = "codex-sidebar-tags-section-heading";
2335
+ heading.textContent = "Tags";
2336
+ const pinnedStyle = getComputedStyle(pinnedToggle);
2337
+ ["color", "font-family", "font-size", "font-style", "font-weight", "letter-spacing", "line-height", "padding-left", "padding-right"].forEach((property) => heading.style.setProperty(property, pinnedStyle.getPropertyValue(property)));
2338
+ const counts = /* @__PURE__ */ new Map();
2339
+ entries.forEach((entry) => counts.set(entry.tag, (counts.get(entry.tag) ?? 0) + 1));
2340
+ const configuredOrder = new Map(this.options.getDefinitions().map(({ name }, index) => [name.toLocaleLowerCase(), index]));
2341
+ const filters = [{ value: "all", label: this.options.i18n.t("all"), count: entries.length, color: null }];
2342
+ Array.from(counts, ([tag, count]) => ({
2343
+ value: tag,
2344
+ label: tag,
2345
+ count,
2346
+ color: this.options.colorForTag(tag) ?? this.options.neutralColor
2347
+ })).sort((left, right) => {
2348
+ const leftOrder = configuredOrder.get(left.value.toLocaleLowerCase()) ?? Number.MAX_SAFE_INTEGER;
2349
+ const rightOrder = configuredOrder.get(right.value.toLocaleLowerCase()) ?? Number.MAX_SAFE_INTEGER;
2350
+ return leftOrder - rightOrder || this.options.i18n.compare(left.label, right.label);
2351
+ }).forEach((item) => filters.push(item));
2352
+ const rail = document.createElement("div");
2353
+ rail.className = "codex-sidebar-quick-filter-rail";
2354
+ rail.setAttribute("role", "group");
2355
+ rail.setAttribute("aria-label", this.options.i18n.t("tags"));
2356
+ rail.style.paddingLeft = pinnedStyle.paddingLeft;
2357
+ rail.style.paddingRight = pinnedStyle.paddingRight;
2358
+ filters.forEach(({ value, label, count, color }) => {
2359
+ const filter = document.createElement("button");
2360
+ filter.type = "button";
2361
+ filter.className = "codex-sidebar-quick-filter";
2362
+ filter.textContent = label;
2363
+ filter.dataset.value = value;
2364
+ if (color) filter.style.setProperty("--codex-sidebar-tag-color", color);
2365
+ filter.setAttribute("aria-pressed", String(this.options.getSelectedTag() === value));
2366
+ filter.title = `${label} \xB7 ${this.options.i18n.t("sessionCount", { count })}`;
2367
+ const badge = document.createElement("span");
2368
+ badge.className = "codex-sidebar-quick-filter-count";
2369
+ badge.textContent = String(count);
2370
+ filter.appendChild(badge);
2371
+ filter.addEventListener("click", () => {
2372
+ const next = this.options.getSelectedTag() === value && value !== "all" ? "all" : value;
2373
+ this.options.setSelectedTag(next);
2374
+ this.options.trace("sidebar-tag-click", { value, selected: next });
2375
+ this.render(this.options.getEntries());
2376
+ });
2377
+ rail.appendChild(filter);
2378
+ });
2379
+ filterHost.append(heading, rail);
2380
+ rail.scrollLeft = previousScrollLeft;
2381
+ this.apply(entries);
2382
+ if (focusedValue) {
2383
+ const filterButtons = [...rail.querySelectorAll(".codex-sidebar-quick-filter")];
2384
+ const nextFocus = filterButtons.find((item) => item.dataset.value === focusedValue) ?? filterButtons.find((item) => item.dataset.value === this.options.getSelectedTag());
2385
+ nextFocus?.focus({ preventScroll: true });
2386
+ rail.scrollLeft = previousScrollLeft;
2387
+ }
2388
+ }
2389
+ dispose(filteredRows) {
2390
+ for (const row of filteredRows) row.removeAttribute(this.options.filteredAttribute);
2391
+ document.documentElement.removeAttribute(this.options.activeAttribute);
2392
+ document.getElementById(this.options.hostId)?.remove();
2393
+ }
2394
+ };
2395
+
2396
+ // runtime/src/injected/store.ts
2397
+ function createInitialState() {
2398
+ return {
2399
+ query: "",
2400
+ tag: "all",
2401
+ sort: "sidebar",
2402
+ sortOpen: false,
2403
+ open: false,
2404
+ view: "sessions",
2405
+ tagError: ""
2406
+ };
2407
+ }
2408
+ function reduceRuntimeState(state, action) {
2409
+ if (action.type === "query.set") return { ...state, query: action.value };
2410
+ if (action.type === "tag.set") return { ...state, tag: action.value };
2411
+ if (action.type === "sort.set") return { ...state, sort: action.value, sortOpen: false };
2412
+ if (action.type === "sort-menu.set") return { ...state, sortOpen: action.value };
2413
+ if (action.type === "view.set") return { ...state, view: action.value, sortOpen: false, tagError: "" };
2414
+ if (action.type === "tag-error.set") return { ...state, tagError: action.value };
2415
+ if (action.type === "dashboard.open") return { ...state, open: true, view: "sessions", sortOpen: false };
2416
+ if (action.type === "dashboard.close") return { ...state, open: false, sortOpen: false };
2417
+ return { ...state, query: "", tag: "all", sortOpen: false };
2418
+ }
2419
+ var RuntimeStore = class {
2420
+ state;
2421
+ constructor(initialState = createInitialState()) {
2422
+ this.state = initialState;
2423
+ }
2424
+ dispatch(action) {
2425
+ Object.assign(this.state, reduceRuntimeState(this.state, action));
2426
+ }
2427
+ };
2428
+
2429
+ // runtime/src/injected/styles.ts
2430
+ function buildRuntimeStyles({
2431
+ enhancedAttribute,
2432
+ toolbarId,
2433
+ filterBarId,
2434
+ filteredAttribute,
2435
+ rowAttribute
2436
+ }) {
2437
+ const ENHANCED = enhancedAttribute;
2438
+ const TOOLBAR_ID = toolbarId;
2439
+ const FILTER_BAR_ID = filterBarId;
2440
+ const FILTERED = filteredAttribute;
2441
+ const ROW = rowAttribute;
2442
+ return `
2443
+
2444
+ [${ENHANCED}] { min-width: 0; }
2445
+ .codex-sidebar-tag-layout { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 6px; min-width: 0; max-width: 100%; vertical-align: middle; }
2446
+ .codex-sidebar-filter-chip {
2447
+ display: inline-flex; flex: 0 0 auto; align-items: center; border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
2448
+ border-radius: 999px; font-weight: 650; letter-spacing: .01em;
2449
+ }
2450
+ .codex-sidebar-tag-chip, .codex-sidebar-result-tag {
2451
+ display: inline-flex; align-items: center; min-width: 0; height: 18px; padding: 0;
2452
+ border: 0; color: color-mix(in srgb, var(--codex-sidebar-tag-color, var(--color-text-tertiary, #777)) 44%, var(--color-text-tertiary, var(--color-token-text-tertiary, #777)));
2453
+ background: transparent; font-size: 10px; font-weight: 600; line-height: 18px; white-space: nowrap; transition: color 120ms ease;
2454
+ }
2455
+ [${ROW}="true"]:hover .codex-sidebar-tag-chip { color: color-mix(in srgb, var(--codex-sidebar-tag-color, var(--color-text-secondary, #999)) 68%, var(--color-text-secondary, var(--color-token-text-secondary, #999))); }
2456
+ [data-codex-sidebar-tags-filter-active="true"] .codex-sidebar-tag-layout { grid-template-columns: minmax(0, 1fr); gap: 0; }
2457
+ [data-codex-sidebar-tags-filter-active="true"] .codex-sidebar-tag-chip { display: none; }
2458
+ .codex-sidebar-tag-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2459
+
2460
+ #${FILTER_BAR_ID} { min-width: 0; margin: 0 0 6px; color: var(--color-text-foreground, var(--color-token-text-primary, inherit)); }
2461
+ .codex-sidebar-tags-section-heading { min-height: 28px; margin: 0; pointer-events: none; }
2462
+ .codex-sidebar-quick-filter-rail {
2463
+ display: flex; min-width: 0; gap: 3px; padding: 1px 4px 5px; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
2464
+ }
2465
+ .codex-sidebar-quick-filter-rail::-webkit-scrollbar { display: none; }
2466
+ .codex-sidebar-quick-filter {
2467
+ display: inline-flex; flex: 0 0 auto; align-items: center; min-height: 26px; gap: 4px; padding: 0 7px; border: 0; border-radius: 6px;
2468
+ color: var(--color-text-secondary, var(--color-token-text-secondary, inherit)); background: transparent; font: inherit; font-size: 12px; cursor: pointer;
2469
+ transition: color 100ms ease, background 100ms ease, transform 100ms ease;
2470
+ }
2471
+ .codex-sidebar-quick-filter:hover { background: var(--color-token-list-hover-background, #8882); }
2472
+ .codex-sidebar-quick-filter:active { transform: scale(.97); }
2473
+ .codex-sidebar-quick-filter:focus-visible { outline: 2px solid var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); outline-offset: -2px; }
2474
+ .codex-sidebar-quick-filter:not([data-value="all"]) { color: color-mix(in srgb, var(--codex-sidebar-tag-color, var(--color-text-secondary, inherit)) 36%, var(--color-text-secondary, var(--color-token-text-secondary, inherit))); }
2475
+ .codex-sidebar-quick-filter[aria-pressed="true"] {
2476
+ color: color-mix(in srgb, var(--codex-sidebar-tag-color, var(--color-text-foreground, inherit)) 86%, var(--color-text-foreground, var(--color-token-list-active-selection-foreground, inherit)));
2477
+ background: color-mix(in srgb, var(--codex-sidebar-tag-color, #888) 9%, var(--color-token-list-active-selection-background, #8883));
2478
+ }
2479
+ .codex-sidebar-quick-filter-count { color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 11px; font-variant-numeric: tabular-nums; }
2480
+ [${ROW}="true"][${FILTERED}="true"] { display: none !important; }
2481
+
2482
+ #${TOOLBAR_ID} {
2483
+ display: contents; color: var(--color-text-foreground, var(--color-token-text-primary, inherit));
2484
+ }
2485
+ .codex-sidebar-dashboard-entry { display: contents; }
2486
+ .codex-sidebar-dashboard-launcher { width: 100%; color: inherit; font: inherit; }
2487
+ .codex-sidebar-dashboard-launcher[data-dashboard-fallback="true"] {
2488
+ display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 12px; border: 0; border-radius: 6px;
2489
+ background: transparent; text-align: left; cursor: pointer; transition: background 100ms ease, transform 100ms ease;
2490
+ }
2491
+ .codex-sidebar-dashboard-launcher[data-dashboard-fallback="true"]:hover { background: var(--color-token-list-hover-background, #8882); }
2492
+ .codex-sidebar-dashboard-launcher:active { transform: scale(.985); }
2493
+ .codex-sidebar-dashboard-launcher:focus-visible { outline: 2px solid var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); outline-offset: -2px; }
2494
+
2495
+ .codex-sidebar-dashboard-overlay {
2496
+ position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; padding: 24px;
2497
+ background: #0006; backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
2498
+ }
2499
+ .codex-sidebar-dashboard-dialog {
2500
+ display: flex; width: min(680px, calc(100vw - 40px)); max-height: min(720px, calc(100vh - 48px)); flex-direction: column;
2501
+ border: 1px solid var(--color-border-light, var(--color-token-menu-border, #8884)); border-radius: 16px;
2502
+ color: var(--color-text-foreground, var(--color-token-text-primary, inherit)); background: var(--color-background-elevated-base, var(--color-token-menu-background, #181818));
2503
+ box-shadow: 0 24px 70px #0007, 0 4px 18px #0003; overflow: hidden; transform-origin: 50% 45%;
2504
+ }
2505
+ .codex-sidebar-dashboard-header { display: flex; align-items: center; gap: 12px; padding: 15px 16px 12px; border-bottom: 1px solid var(--color-border-light, var(--color-token-border-light, #8883)); }
2506
+ .codex-sidebar-dashboard-heading { margin: 0; font-size: 17px; font-weight: 650; }
2507
+ .codex-sidebar-dashboard-subtitle { color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 12px; }
2508
+ .codex-sidebar-dashboard-tabs { display: flex; gap: 3px; margin-left: auto; padding: 3px; border-radius: 8px; background: var(--color-background-control, var(--color-token-input-background, #8881)); }
2509
+ .codex-sidebar-dashboard-tab { height: 29px; padding: 0 11px; border: 0; border-radius: 6px; color: var(--color-text-secondary, inherit); background: transparent; font: inherit; font-size: 12px; cursor: pointer; transition: color 120ms ease, background 120ms ease, box-shadow 120ms ease, transform 100ms ease; }
2510
+ .codex-sidebar-dashboard-tab[aria-selected="true"] { color: var(--color-text-foreground, inherit); background: var(--color-background-elevated-high, var(--color-token-list-active-selection-background, #8883)); box-shadow: 0 1px 2px #0002; }
2511
+ .codex-sidebar-dashboard-tab:active, .codex-sidebar-dashboard-close:active, .codex-sidebar-sort-trigger:active, .codex-sidebar-tag-add:active, .codex-sidebar-tag-delete:active { transform: scale(.97); }
2512
+ .codex-sidebar-dashboard-close { display: grid; width: 28px; height: 28px; place-items: center; padding: 0; border: 0; border-radius: 7px; color: var(--color-text-tertiary, inherit); background: transparent; font: inherit; font-size: 17px; cursor: pointer; transition: color 100ms ease, background 100ms ease, transform 100ms ease; }
2513
+ .codex-sidebar-dashboard-close:hover { color: var(--color-text-foreground, inherit); background: var(--color-token-toolbar-hover-background, #8882); }
2514
+ .codex-sidebar-dashboard-body { min-height: 0; padding: 14px 16px 16px; overflow-y: auto; }
2515
+ .codex-sidebar-dashboard-controls { display: flex; align-items: center; gap: 8px; }
2516
+ .codex-sidebar-search {
2517
+ display: flex; flex: 1 1 auto; align-items: center; min-width: 0; height: 36px; border: 1px solid var(--color-border-light, var(--color-token-input-border, #8883)); border-radius: 8px;
2518
+ background: var(--color-background-control, var(--color-token-input-background, #8881)); transition: border-color 120ms ease, background 120ms ease, box-shadow 120ms ease;
2519
+ }
2520
+ .codex-sidebar-search:focus-within {
2521
+ border-color: var(--color-border-focus, var(--color-token-focus-border, #4b8cff));
2522
+ background: var(--color-background-control-opaque, var(--color-token-input-background, #8882));
2523
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-border-focus, #4b8cff) 18%, transparent);
2524
+ }
2525
+ .codex-sidebar-search-icon { width: 29px; flex: 0 0 29px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 15px; text-align: center; pointer-events: none; }
2526
+ .codex-sidebar-search[data-loading="true"] .codex-sidebar-search-icon { font-size: 0; }
2527
+ .codex-sidebar-search[data-loading="true"] .codex-sidebar-search-icon::after {
2528
+ display: inline-block; width: 11px; height: 11px; border: 1.5px solid color-mix(in srgb, currentColor 30%, transparent); border-top-color: currentColor; border-radius: 50%; content: ""; animation: codex-sidebar-search-spin 700ms linear infinite;
2529
+ }
2530
+ @keyframes codex-sidebar-search-spin { to { transform: rotate(360deg); } }
2531
+ .codex-sidebar-search-input {
2532
+ width: 100%; min-width: 0; border: 0; outline: 0; padding: 0 7px 0 0; color: var(--color-text-foreground, var(--color-token-input-foreground, inherit));
2533
+ background: transparent; font: inherit; font-size: 14px;
2534
+ }
2535
+ .codex-sidebar-search-input::placeholder { color: var(--color-text-tertiary, var(--color-token-input-placeholder-foreground, #888)); }
2536
+ .codex-sidebar-sort-control {
2537
+ position: relative; display: flex; flex: 0 0 144px; align-items: center; height: 36px;
2538
+ }
2539
+ .codex-sidebar-sort-trigger {
2540
+ display: flex; width: 100%; height: 36px; align-items: center; gap: 7px; padding: 0 10px; border: 1px solid var(--color-border-light, var(--color-token-input-border, #8883)); border-radius: 8px;
2541
+ color: var(--color-text-foreground, var(--color-token-input-foreground, inherit)); background: var(--color-background-control, var(--color-token-input-background, #8881)); font: inherit; font-size: 13px; cursor: pointer; transition: border-color 120ms ease, background 100ms ease, box-shadow 120ms ease, transform 100ms ease;
2542
+ }
2543
+ .codex-sidebar-sort-trigger:hover { background: var(--color-background-control-opaque, var(--color-token-list-hover-background, #8882)); }
2544
+ .codex-sidebar-sort-trigger:focus-visible, .codex-sidebar-sort-trigger[aria-expanded="true"] { outline: 0; border-color: var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-border-focus, #4b8cff) 18%, transparent); }
2545
+ .codex-sidebar-sort-label { color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); pointer-events: none; }
2546
+ .codex-sidebar-sort-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2547
+ .codex-sidebar-sort-chevron { width: 7px; height: 7px; margin: -3px 2px 0 auto; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; opacity: .7; transform: rotate(45deg); transition: transform 120ms ease; }
2548
+ .codex-sidebar-sort-trigger[aria-expanded="true"] .codex-sidebar-sort-chevron { margin-top: 3px; transform: rotate(225deg); }
2549
+ .codex-sidebar-sort-menu {
2550
+ position: absolute; top: calc(100% + 5px); right: 0; z-index: 8; width: 144px; padding: 4px;
2551
+ border: 1px solid var(--color-border-light, var(--color-token-menu-border, #8884)); border-radius: 9px;
2552
+ color: var(--color-text-foreground, var(--color-token-dropdown-foreground, inherit)); background: var(--color-background-elevated-high, var(--color-token-menu-background, #202020));
2553
+ box-shadow: 0 12px 32px #0006, 0 2px 8px #0003; transform-origin: top right;
2554
+ }
2555
+ .codex-sidebar-sort-option { display: flex; width: 100%; height: 32px; align-items: center; padding: 0 9px; border: 0; border-radius: 6px; color: inherit; background: transparent; font: inherit; font-size: 13px; text-align: left; cursor: pointer; transition: background 100ms ease; }
2556
+ .codex-sidebar-sort-option:hover, .codex-sidebar-sort-option:focus-visible { outline: 0; background: var(--color-token-list-hover-background, #8882); }
2557
+ .codex-sidebar-sort-option[aria-selected="true"] { background: var(--color-token-list-active-selection-background, #8883); }
2558
+ .codex-sidebar-sort-check { width: 14px; margin-left: auto; color: var(--color-text-secondary, inherit); text-align: center; }
2559
+ .codex-sidebar-filter-rail { display: flex; gap: 5px; margin-top: 10px; padding: 0 1px 2px; overflow-x: auto; scrollbar-width: none; }
2560
+ .codex-sidebar-filter-rail::-webkit-scrollbar { display: none; }
2561
+ .codex-sidebar-filter-chip {
2562
+ height: 27px; padding: 0 7px; border-color: transparent; color: var(--color-text-secondary, var(--color-token-text-secondary, inherit));
2563
+ background: var(--color-background-control, var(--color-token-input-background, #8881)); font: inherit; font-size: 12px; cursor: pointer; transition: transform 100ms ease, color 100ms ease, background 100ms ease;
2564
+ }
2565
+ .codex-sidebar-filter-chip:hover { background: var(--color-background-control, var(--color-token-list-hover-background, #8882)); }
2566
+ .codex-sidebar-filter-chip:active { transform: scale(.97); }
2567
+ .codex-sidebar-filter-chip[aria-pressed="true"] {
2568
+ color: var(--color-text-foreground, var(--color-token-list-active-selection-foreground, inherit));
2569
+ border-color: var(--color-border-light, var(--color-token-border-light, #8884));
2570
+ background: var(--color-background-elevated-base, var(--color-token-list-active-selection-background, #8883)); box-shadow: 0 1px 2px #0001;
2571
+ }
2572
+ .codex-sidebar-filter-count { margin-left: 4px; opacity: .62; font-variant-numeric: tabular-nums; }
2573
+ .codex-sidebar-results {
2574
+ margin-top: 12px; padding: 6px; border: 1px solid var(--color-border-light, var(--color-token-border-light, #8883)); border-radius: 11px;
2575
+ background: var(--color-background-surface, var(--color-token-bg-secondary, #8881)); overflow-anchor: none; transition: opacity 120ms ease;
2576
+ }
2577
+ .codex-sidebar-results[data-loading="true"] { opacity: .78; }
2578
+ .codex-sidebar-results-head { display: flex; align-items: center; justify-content: space-between; min-height: 26px; padding: 0 5px 5px 7px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 12px; }
2579
+ .codex-sidebar-results-list { max-height: min(430px, calc(100vh - 250px)); overflow-y: auto; overscroll-behavior: contain; }
2580
+ .codex-sidebar-result-group {
2581
+ position: sticky; top: 0; z-index: 1; padding: 5px 7px 3px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888));
2582
+ background: var(--color-background-elevated-base, var(--color-token-menu-background, #181818)); font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
2583
+ }
2584
+ .codex-sidebar-result {
2585
+ display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 8px; width: 100%; min-height: 40px; padding: 8px;
2586
+ border: 0; border-radius: 8px; color: var(--color-text-foreground, var(--color-token-text-primary, inherit)); background: transparent; text-align: left; font: inherit; cursor: pointer; transition: background 100ms ease, transform 100ms ease;
2587
+ }
2588
+ .codex-sidebar-result:hover, .codex-sidebar-result:focus-visible { outline: 0; background: var(--color-token-list-hover-background, #8882); }
2589
+ .codex-sidebar-result:active { transform: scale(.995); }
2590
+ .codex-sidebar-result-tag { font-size: 11px; }
2591
+ .codex-sidebar-result-content { min-width: 0; }
2592
+ .codex-sidebar-result-title { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; line-height: 1.4; }
2593
+ .codex-sidebar-result-snippet { display: -webkit-box; margin-top: 4px; overflow: hidden; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 11px; line-height: 1.5; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
2594
+ .codex-sidebar-search-mark {
2595
+ padding: 0 1px; border-radius: 3px; color: var(--color-text-foreground, var(--color-token-text-primary, inherit));
2596
+ background: color-mix(in srgb, var(--color-border-focus, var(--color-token-focus-border, #4b8cff)) 32%, transparent);
2597
+ font-weight: 650; box-decoration-break: clone; -webkit-box-decoration-break: clone; animation: codex-sidebar-search-mark-in 180ms ease-out;
2598
+ }
2599
+ @keyframes codex-sidebar-search-mark-in { from { background-color: transparent; } }
2600
+ .codex-sidebar-results-empty { padding: 17px 8px 19px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 13px; text-align: center; }
2601
+ .codex-sidebar-tag-settings-note { margin: 0 0 14px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 12px; line-height: 1.45; }
2602
+ .codex-sidebar-tag-settings-unconfigured { display: inline-flex; margin-left: 7px; padding: 1px 6px; border-radius: 5px; color: var(--color-text-secondary, inherit); background: var(--color-token-list-hover-background, #8882); }
2603
+ .codex-sidebar-tag-form { display: grid; gap: 9px; margin-bottom: 14px; padding: 0 0 14px; border-bottom: 1px solid var(--color-border-light, var(--color-token-border-light, #8883)); }
2604
+ .codex-sidebar-tag-form-row { display: grid; grid-template-columns: minmax(130px, .7fr) minmax(220px, 1.5fr) auto; align-items: end; gap: 8px; }
2605
+ .codex-sidebar-tag-field { display: grid; min-width: 0; gap: 5px; }
2606
+ .codex-sidebar-tag-field-label { color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 11px; font-weight: 600; }
2607
+ .codex-sidebar-tag-input, .codex-sidebar-tag-description {
2608
+ min-width: 0; border: 1px solid var(--color-border-light, var(--color-token-input-border, #8883)); border-radius: 8px; outline: 0;
2609
+ color: var(--color-text-foreground, inherit); background: var(--color-background-control, var(--color-token-input-background, #8881)); font: inherit; font-size: 13px;
2610
+ }
2611
+ .codex-sidebar-tag-input { height: 34px; padding: 0 9px; }
2612
+ .codex-sidebar-tag-description { height: 34px; padding: 0 9px; }
2613
+ .codex-sidebar-tag-input:focus, .codex-sidebar-tag-description:focus, .codex-sidebar-tag-color-custom:focus-visible { border-color: var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-border-focus, #4b8cff) 18%, transparent); }
2614
+ .codex-sidebar-tag-color-field { display: flex; min-width: 0; align-items: center; gap: 10px; }
2615
+ .codex-sidebar-tag-color-field > .codex-sidebar-tag-field-label { flex: 0 0 auto; }
2616
+ .codex-sidebar-tag-color-row { display: flex; min-width: 0; align-items: center; gap: 5px; }
2617
+ .codex-sidebar-tag-color-presets { display: flex; align-items: center; gap: 3px; }
2618
+ .codex-sidebar-tag-color-preset { display: grid; width: 27px; height: 27px; place-items: center; padding: 0; border: 1px solid transparent; border-radius: 7px; background: transparent; cursor: pointer; }
2619
+ .codex-sidebar-tag-color-preset::after { display: block; width: 14px; height: 14px; border-radius: 999px; background: var(--preset-color); box-shadow: inset 0 0 0 1px #fff4; content: ""; }
2620
+ .codex-sidebar-tag-color-preset:hover { background: var(--color-token-list-hover-background, #8882); }
2621
+ .codex-sidebar-tag-color-preset[aria-pressed="true"] { border-color: var(--color-border-light, #8884); background: var(--color-token-list-active-selection-background, #8883); }
2622
+ .codex-sidebar-tag-color-preset:focus-visible { outline: 2px solid var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); outline-offset: 1px; }
2623
+ .codex-sidebar-tag-color-custom-control { position: relative; display: inline-flex; height: 27px; align-items: center; gap: 6px; margin-left: 3px; padding: 0 8px 0 6px; border: 1px solid var(--color-border-light, var(--color-token-input-border, #8883)); border-radius: 7px; color: var(--color-text-secondary, inherit); background: transparent; font-size: 11px; cursor: pointer; }
2624
+ .codex-sidebar-tag-color-custom-control:hover { background: var(--color-token-list-hover-background, #8882); }
2625
+ .codex-sidebar-tag-color-custom-preview { width: 12px; height: 12px; border-radius: 3px; background: var(--custom-color); box-shadow: inset 0 0 0 1px #fff4; }
2626
+ .codex-sidebar-tag-color-custom { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
2627
+ .codex-sidebar-tag-color-custom:focus-visible { outline: 2px solid var(--color-border-focus, var(--color-token-focus-border, #4b8cff)); outline-offset: 1px; }
2628
+ .codex-sidebar-tag-add { height: 34px; padding: 0 13px; border: 1px solid var(--color-border-light, #8884); border-radius: 8px; color: var(--color-token-button-foreground, inherit); background: var(--color-token-button-background, #8882); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; transition: background 100ms ease, transform 100ms ease; }
2629
+ .codex-sidebar-tag-add:hover { background: var(--color-token-list-hover-background, #8883); }
2630
+ .codex-sidebar-tag-error { color: #c53b3b; font-size: 12px; }
2631
+ .codex-sidebar-tag-error:empty { display: none; }
2632
+ .codex-sidebar-tag-config-list { overflow: hidden; border: 1px solid var(--color-border-light, var(--color-token-border-light, #8883)); border-radius: 10px; }
2633
+ .codex-sidebar-tag-config-header, .codex-sidebar-tag-config-row { display: grid; grid-template-columns: 12px minmax(92px, .55fr) minmax(0, 1.8fr) 28px; align-items: center; gap: 9px; padding: 0 7px 0 11px; }
2634
+ .codex-sidebar-tag-config-header { min-height: 30px; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); background: var(--color-background-surface, var(--color-token-bg-secondary, #8881)); font-size: 10px; font-weight: 600; }
2635
+ .codex-sidebar-tag-config-row { min-height: 40px; border-top: 1px solid var(--color-border-light, var(--color-token-border-light, #8882)); background: transparent; transition: background 100ms ease; }
2636
+ .codex-sidebar-tag-config-row:hover { background: var(--color-token-list-hover-background, #8881); }
2637
+ .codex-sidebar-tag-config-swatch { width: 9px; height: 9px; border-radius: 3px; background: var(--codex-sidebar-tag-color); box-shadow: inset 0 0 0 1px #fff3; }
2638
+ .codex-sidebar-tag-config-name { min-width: 0; color: var(--color-text-foreground, inherit); font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border: 0; background: transparent; padding: 0; text-align: left; cursor: pointer; }
2639
+ .codex-sidebar-tag-config-name:hover { text-decoration: underline; }
2640
+ .codex-sidebar-tag-delete[data-confirm="true"] { width: auto; font-size: 10px; }
2641
+ .codex-sidebar-tag-config-description { min-width: 0; color: var(--color-text-tertiary, var(--color-token-text-tertiary, #888)); font-size: 12px; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2642
+ .codex-sidebar-tag-config-description[data-empty="true"] { opacity: .6; font-style: italic; }
2643
+ .codex-sidebar-tag-delete { display: grid; width: 26px; height: 26px; place-items: center; padding: 0; border: 0; border-radius: 6px; color: var(--color-text-tertiary, inherit); background: transparent; font: inherit; cursor: pointer; transition: color 100ms ease, background 100ms ease, transform 100ms ease; }
2644
+ .codex-sidebar-tag-delete:hover { color: #c53b3b; background: #ef444418; }
2645
+ @media (max-width: 760px) {
2646
+ .codex-sidebar-dashboard-overlay { padding: 10px; }
2647
+ .codex-sidebar-dashboard-dialog { width: calc(100vw - 20px); max-height: calc(100vh - 20px); }
2648
+ .codex-sidebar-dashboard-header { flex-wrap: wrap; }
2649
+ .codex-sidebar-dashboard-tabs { order: 3; width: 100%; margin-left: 0; }
2650
+ .codex-sidebar-dashboard-tab { flex: 1; }
2651
+ .codex-sidebar-tag-form-row { grid-template-columns: minmax(0, 1fr) auto; }
2652
+ .codex-sidebar-tag-form-row .codex-sidebar-tag-field:nth-child(2) { grid-column: 1 / -1; grid-row: 2; }
2653
+ .codex-sidebar-tag-add { grid-column: 2; grid-row: 1; }
2654
+ .codex-sidebar-tag-color-field { align-items: flex-start; flex-direction: column; gap: 5px; }
2655
+ .codex-sidebar-tag-config-header, .codex-sidebar-tag-config-row { grid-template-columns: 12px minmax(64px, .6fr) minmax(0, 1.4fr) 28px; }
2656
+ .codex-sidebar-results-list { max-height: calc(100vh - 300px); }
2657
+ }
2658
+ @media (prefers-reduced-motion: reduce) {
2659
+ .codex-sidebar-dashboard-launcher, .codex-sidebar-dashboard-tab, .codex-sidebar-dashboard-close, .codex-sidebar-search, .codex-sidebar-sort-trigger, .codex-sidebar-sort-chevron, .codex-sidebar-sort-option, .codex-sidebar-filter-chip, .codex-sidebar-quick-filter, .codex-sidebar-results, .codex-sidebar-result, .codex-sidebar-search-mark, .codex-sidebar-tag-add, .codex-sidebar-tag-delete { animation: none; transition: none; }
2660
+ .codex-sidebar-search[data-loading="true"] .codex-sidebar-search-icon::after { animation: none; border-color: currentColor; opacity: .65; }
2661
+ }
2662
+ `;
2663
+ }
2664
+
2665
+ // runtime/src/injected/title-decorator.ts
2666
+ var TitleDecorator = class {
2667
+ constructor(options) {
2668
+ this.options = options;
2669
+ }
2670
+ options;
2671
+ originalNodeState = /* @__PURE__ */ new WeakMap();
2672
+ enhance(node) {
2673
+ const { version, toolbarId, enhancedAttribute, rawTitleAttribute } = this.options;
2674
+ if (node.closest(`#${toolbarId}`)) return;
2675
+ const generated = node.querySelector(":scope > .codex-sidebar-tag-layout");
2676
+ if (node.getAttribute(enhancedAttribute) === version && generated) return;
2677
+ const existingRaw = node.getAttribute(rawTitleAttribute);
2678
+ const raw = existingRaw !== null && generated ? existingRaw : node.textContent?.trim() ?? "";
2679
+ const parsed = this.options.parseTitle(raw);
2680
+ if (!parsed?.tagged) {
2681
+ if (existingRaw !== null) this.restore(node);
2682
+ return;
2683
+ }
2684
+ if (!this.originalNodeState.has(node)) {
2685
+ this.originalNodeState.set(node, {
2686
+ children: [...node.childNodes].map((child) => child.cloneNode(true)),
2687
+ ariaLabel: node.getAttribute("aria-label"),
2688
+ title: node.getAttribute("title")
2689
+ });
2690
+ }
2691
+ const layout = document.createElement("span");
2692
+ layout.className = "codex-sidebar-tag-layout";
2693
+ const tag = document.createElement("span");
2694
+ tag.className = "codex-sidebar-tag-chip";
2695
+ tag.style.setProperty("--codex-sidebar-tag-color", parsed.color);
2696
+ tag.textContent = parsed.tag;
2697
+ const title = document.createElement("span");
2698
+ title.className = "codex-sidebar-tag-title";
2699
+ title.textContent = parsed.title;
2700
+ layout.append(tag, title);
2701
+ node.setAttribute(rawTitleAttribute, parsed.raw);
2702
+ node.setAttribute(enhancedAttribute, version);
2703
+ node.setAttribute("aria-label", parsed.raw);
2704
+ node.setAttribute("title", parsed.raw);
2705
+ node.replaceChildren(layout);
2706
+ }
2707
+ refreshColors(nodes) {
2708
+ for (const node of nodes) {
2709
+ const parsed = this.options.parseTitle(node.getAttribute(this.options.rawTitleAttribute));
2710
+ const chip = node.querySelector(":scope > .codex-sidebar-tag-layout > .codex-sidebar-tag-chip");
2711
+ if (parsed && chip) chip.style.setProperty("--codex-sidebar-tag-color", parsed.color);
2712
+ }
2713
+ }
2714
+ restore(node) {
2715
+ const { enhancedAttribute, rawTitleAttribute } = this.options;
2716
+ const raw = node.getAttribute(rawTitleAttribute);
2717
+ if (raw === null) return;
2718
+ const original = this.originalNodeState.get(node);
2719
+ if (original) node.replaceChildren(...original.children.map((child) => child.cloneNode(true)));
2720
+ else node.replaceChildren(document.createTextNode(raw));
2721
+ node.removeAttribute(enhancedAttribute);
2722
+ node.removeAttribute(rawTitleAttribute);
2723
+ this.restoreAttribute(node, "aria-label", original?.ariaLabel);
2724
+ this.restoreAttribute(node, "title", original?.title);
2725
+ this.originalNodeState.delete(node);
2726
+ }
2727
+ dispose(nodes) {
2728
+ for (const node of nodes) this.restore(node);
2729
+ }
2730
+ restoreAttribute(node, name, value) {
2731
+ if (value == null) node.removeAttribute(name);
2732
+ else node.setAttribute(name, value);
2733
+ }
2734
+ };
2735
+
2736
+ // runtime/src/injected/runtime.ts
2737
+ function installRuntime(input) {
2738
+ const config = parseRuntimeConfig(input);
2739
+ const { version, colorPresets, legacyToneColors, requestBinding } = config;
2740
+ const STYLE_ID = "codex-sidebar-tags-style";
2741
+ const TOOLBAR_ID = "codex-sidebar-tags-toolbar";
2742
+ const FILTER_BAR_ID = "codex-sidebar-tags-filter-bar";
2743
+ const CACHE_KEY = "codex-sidebar-tags-index-v1";
2744
+ const TAG_CONFIG_KEY = "codex-sidebar-tags-config-v1";
2745
+ const ENHANCED = "data-codex-sidebar-tags-enhanced";
2746
+ const RAW = "data-codex-sidebar-tags-raw";
2747
+ const FILTERED = "data-codex-sidebar-tags-filtered";
2748
+ const ROW = "data-codex-sidebar-tags-row";
2749
+ const previous = window.__codexSidebarTags;
2750
+ if (previous?.version === version) return previous.status();
2751
+ try {
2752
+ previous?.dispose?.();
2753
+ } catch {
2754
+ }
2755
+ const defaultDefinitions = config.tagDefinitions.map((item) => ({ ...item }));
2756
+ let tagDefinitions = normalizeTagDefinitions(config.tagDefinitions, defaultDefinitions);
2757
+ try {
2758
+ const savedDefinitions = JSON.parse(localStorage.getItem(TAG_CONFIG_KEY) ?? "null");
2759
+ if (config.settingsSource !== "repository" && Array.isArray(savedDefinitions)) tagDefinitions = normalizeTagDefinitions(savedDefinitions, defaultDefinitions);
2760
+ } catch {
2761
+ }
2762
+ let tagColors = new Map(tagDefinitions.map(({ name, color }) => [name.toLocaleLowerCase(), color]));
2763
+ const contentMatches = /* @__PURE__ */ new Map();
2764
+ let searchRequestTimer = null;
2765
+ let activeSearchRequestId = 0;
2766
+ let searchLoading = false;
2767
+ let searchError = "";
2768
+ let catalogError = "";
2769
+ let searchIndexStatus = { phase: "idle", completed: 0, total: 0 };
2770
+ const runtimeStore = new RuntimeStore();
2771
+ const state = runtimeStore.state;
2772
+ let host = null;
2773
+ let filterHost = null;
2774
+ let navTemplate = null;
2775
+ let renderedIndexSignature = null;
2776
+ let renderCount = 0;
2777
+ let pinnedToggleRef = null;
2778
+ const debugEvents = [];
2779
+ const i18n = new RuntimeI18n();
2780
+ let stopLocaleObserver = () => {
2781
+ };
2782
+ const clearPendingSearch = () => {
2783
+ if (searchRequestTimer !== null) clearTimeout(searchRequestTimer);
2784
+ searchRequestTimer = null;
2785
+ };
2786
+ const trace = (event, details = {}) => {
2787
+ debugEvents.push({ at: (/* @__PURE__ */ new Date()).toISOString(), event, ...details });
2788
+ if (debugEvents.length > 80) debugEvents.shift();
2789
+ };
2790
+ let receiveRuntimeMessage = () => false;
2791
+ const runtimeClient = new RuntimeClient(
2792
+ requestBinding,
2793
+ (message) => receiveRuntimeMessage(message),
2794
+ (reason) => trace("protocol-rejected", { reason })
2795
+ );
2796
+ const parse = (value) => {
2797
+ const raw = typeof value === "string" ? value.trim() : "";
2798
+ const parsed = parseTitleMetadata(raw);
2799
+ if (!parsed) return raw ? { raw, tag: i18n.t("uncategorized"), time: "", title: raw, color: legacyToneColors.neutral, tagged: false } : null;
2800
+ if (parsed.tag.toLowerCase() === "uncategorized") return { ...parsed, tag: i18n.t("uncategorized"), color: legacyToneColors.neutral, tagged: false };
2801
+ return { ...parsed, color: tagColors.get(parsed.tag.toLocaleLowerCase()) ?? legacyToneColors.neutral, tagged: true };
2802
+ };
2803
+ const titleDecorator = new TitleDecorator({
2804
+ version,
2805
+ toolbarId: TOOLBAR_ID,
2806
+ enhancedAttribute: ENHANCED,
2807
+ rawTitleAttribute: RAW,
2808
+ parseTitle: parse
2809
+ });
2810
+ const sessionRegistry = new SessionRegistry(
2811
+ localStorage,
2812
+ CACHE_KEY,
2813
+ parse,
2814
+ (tag) => tagColors.get(tag.toLocaleLowerCase()) ?? legacyToneColors.neutral
2815
+ );
2816
+ const persistTagDefinitions = () => {
2817
+ try {
2818
+ localStorage.setItem(TAG_CONFIG_KEY, JSON.stringify(tagDefinitions));
2819
+ } catch {
2820
+ }
2821
+ };
2822
+ const syncTagDefinitions = (notifyController = true) => {
2823
+ tagColors = new Map(tagDefinitions.map(({ name, color }) => [name.toLocaleLowerCase(), color]));
2824
+ sessionRegistry.updateColors();
2825
+ titleDecorator.refreshColors(document.querySelectorAll(`[${ENHANCED}]`));
2826
+ persistTagDefinitions();
2827
+ if (notifyController) {
2828
+ runtimeClient.send(RuntimeMessageType.settingsUpdate, {
2829
+ tags: tagDefinitions.map(({ name, color, description }) => ({ name, color, description }))
2830
+ });
2831
+ }
2832
+ };
2833
+ let style = document.getElementById(STYLE_ID);
2834
+ if (!style) {
2835
+ style = document.createElement("style");
2836
+ style.id = STYLE_ID;
2837
+ (document.head ?? document.documentElement).appendChild(style);
2838
+ }
2839
+ style.textContent = buildRuntimeStyles({
2840
+ enhancedAttribute: ENHANCED,
2841
+ toolbarId: TOOLBAR_ID,
2842
+ filterBarId: FILTER_BAR_ID,
2843
+ filteredAttribute: FILTERED,
2844
+ rowAttribute: ROW
2845
+ });
2846
+ const titleNodes = () => queryThreadTitles(TOOLBAR_ID);
2847
+ const commonAncestor = (left, right) => {
2848
+ if (!left || !right) return left?.parentElement ?? null;
2849
+ const parents = /* @__PURE__ */ new Set();
2850
+ for (let node = left; node; node = node.parentElement) parents.add(node);
2851
+ for (let node = right; node; node = node.parentElement) if (parents.has(node)) return node;
2852
+ return null;
2853
+ };
2854
+ const ensureToolbar = (nodes) => {
2855
+ if (host?.isConnected) {
2856
+ host.setAttribute("aria-label", i18n.t("sessionsDashboard"));
2857
+ return host;
2858
+ }
2859
+ host = document.getElementById(TOOLBAR_ID);
2860
+ if (host) return host;
2861
+ const pluginsButton = findNavigationButton(codexLabels.plugins);
2862
+ if (pluginsButton) {
2863
+ navTemplate = pluginsButton;
2864
+ const anchor2 = pluginsButton.parentElement?.classList.contains("contents") ? pluginsButton.parentElement : pluginsButton;
2865
+ host = document.createElement("div");
2866
+ host.id = TOOLBAR_ID;
2867
+ host.setAttribute("aria-label", i18n.t("sessionsDashboard"));
2868
+ anchor2.insertAdjacentElement("afterend", host);
2869
+ return host;
2870
+ }
2871
+ const pinnedToggle = pinnedToggleRef?.isConnected ? pinnedToggleRef : findAnySectionToggle();
2872
+ const projectRow = findFirstProjectRow();
2873
+ const first = nodes[0] ?? pinnedToggle ?? projectRow;
2874
+ if (!first) return null;
2875
+ const projectsHeader = findProjectsHeader();
2876
+ const boundary = commonAncestor(first, projectsHeader ?? projectRow ?? nodes[nodes.length - 1] ?? first);
2877
+ if (!(boundary instanceof HTMLElement)) return null;
2878
+ let anchor = first;
2879
+ while (anchor.parentElement && anchor.parentElement !== boundary) anchor = anchor.parentElement;
2880
+ host = document.createElement("div");
2881
+ host.id = TOOLBAR_ID;
2882
+ host.setAttribute("aria-label", i18n.t("sessionsDashboard"));
2883
+ boundary.insertBefore(host, anchor);
2884
+ return host;
2885
+ };
2886
+ const ensureFilterHost = () => {
2887
+ const pinnedToggle = findSectionToggle(codexLabels.pinned) ?? (pinnedToggleRef?.isConnected ? pinnedToggleRef : null);
2888
+ if (!pinnedToggle) return null;
2889
+ const pinnedHeadingRow = pinnedToggle.parentElement ?? pinnedToggle;
2890
+ filterHost = document.getElementById(FILTER_BAR_ID);
2891
+ if (!filterHost) {
2892
+ filterHost = document.createElement("section");
2893
+ filterHost.id = FILTER_BAR_ID;
2894
+ }
2895
+ filterHost.setAttribute("aria-label", i18n.t("filterSidebarByTag"));
2896
+ if (filterHost.nextElementSibling !== pinnedHeadingRow) pinnedHeadingRow.insertAdjacentElement("beforebegin", filterHost);
2897
+ return { filterHost, pinnedToggle };
2898
+ };
2899
+ const entriesFrom = (nodes) => {
2900
+ return sessionRegistry.ingest(nodes, {
2901
+ rawTitleAttribute: RAW,
2902
+ rowAttribute: ROW,
2903
+ rowForTitle: findThreadRow,
2904
+ threadIdForRow,
2905
+ isPinnedRow: isPinnedThreadRow,
2906
+ projectIdForRow: projectIdForThreadRow,
2907
+ sectionToggleForRow: sectionToggleForThreadRow,
2908
+ onPinnedToggle: (toggle) => {
2909
+ pinnedToggleRef = toggle;
2910
+ }
2911
+ });
2912
+ };
2913
+ const sidebarTagFilter = new SidebarTagFilter({
2914
+ hostId: FILTER_BAR_ID,
2915
+ filteredAttribute: FILTERED,
2916
+ activeAttribute: "data-codex-sidebar-tags-filter-active",
2917
+ i18n,
2918
+ neutralColor: legacyToneColors.neutral,
2919
+ ensureHost: ensureFilterHost,
2920
+ getEntries: () => entriesFrom(titleNodes()),
2921
+ getDefinitions: () => tagDefinitions,
2922
+ getSelectedTag: () => state.tag,
2923
+ setSelectedTag: (value) => {
2924
+ runtimeStore.dispatch({ type: "tag.set", value });
2925
+ },
2926
+ colorForTag: (tag) => tagColors.get(tag.toLocaleLowerCase()) ?? legacyToneColors.neutral,
2927
+ trace
2928
+ });
2929
+ let dashboardView;
2930
+ let hostLifecycle;
2931
+ const openEntry = async (entry) => {
2932
+ const owningProject = entry.projectId ? findProjectRow(entry.projectId) : null;
2933
+ const projectCollapsed = isProjectCollapsed(owningProject);
2934
+ let row = projectCollapsed ? null : entry.row?.isConnected && entry.row.getClientRects().length > 0 ? entry.row : findVisibleThreadRow(entry.threadId);
2935
+ trace("open-entry", { threadId: entry.threadId, projectId: entry.projectId, pinned: entry.pinned, visibleRow: Boolean(row) });
2936
+ runtimeStore.dispatch({ type: "entry.open" });
2937
+ clearPendingSearch();
2938
+ contentMatches.clear();
2939
+ searchLoading = false;
2940
+ searchError = "";
2941
+ await dashboardView.close("open-entry");
2942
+ if (!row && entry.pinned) {
2943
+ const pinnedToggle = pinnedToggleRef?.isConnected ? pinnedToggleRef : findAnySectionToggle();
2944
+ if (pinnedToggle && !hasVisiblePinnedThread()) pinnedToggle.click();
2945
+ }
2946
+ if (!row && entry.projectId) {
2947
+ const projectRow = owningProject ?? findProjectRow(entry.projectId);
2948
+ if (projectRow && isProjectCollapsed(projectRow)) {
2949
+ trace("expand-project", { projectId: entry.projectId });
2950
+ projectRow.click();
2951
+ }
2952
+ }
2953
+ for (let attempt = 0; !row && attempt < 80; attempt += 1) {
2954
+ await new Promise((resolve) => setTimeout(resolve, 25));
2955
+ row = findVisibleThreadRow(entry.threadId);
2956
+ }
2957
+ if (row) {
2958
+ row.scrollIntoView({ block: "nearest" });
2959
+ row.click();
2960
+ } else {
2961
+ if (entry.threadId) runtimeClient.send(RuntimeMessageType.navigationOpen, { threadId: entry.threadId });
2962
+ }
2963
+ };
2964
+ const indexSignature = (entries) => entries.map((entry) => [entry.key, entry.raw, entry.pinned, entry.projectId].join("")).join("");
2965
+ const scheduleContentSearch = (entries) => {
2966
+ clearPendingSearch();
2967
+ contentMatches.clear();
2968
+ searchError = "";
2969
+ const query = state.query.trim();
2970
+ if (!query) {
2971
+ searchLoading = false;
2972
+ return;
2973
+ }
2974
+ searchLoading = true;
2975
+ activeSearchRequestId += 1;
2976
+ const requestId = activeSearchRequestId;
2977
+ searchRequestTimer = setTimeout(() => {
2978
+ searchRequestTimer = null;
2979
+ if (!runtimeClient.connected) {
2980
+ searchLoading = false;
2981
+ searchError = i18n.t("searchUnavailable");
2982
+ renderToolbar(entriesFrom(titleNodes()), "search-unavailable");
2983
+ return;
2984
+ }
2985
+ runtimeClient.send(RuntimeMessageType.searchRequest, {
2986
+ query,
2987
+ threadIds: entries.map(({ threadId }) => threadId).filter((threadId) => Boolean(threadId)),
2988
+ limit: 100
2989
+ }, requestId);
2990
+ trace("search-request", { requestId, queryLength: query.length, threads: entries.length });
2991
+ }, 200);
2992
+ };
2993
+ dashboardView = new DashboardView({
2994
+ state,
2995
+ store: runtimeStore,
2996
+ i18n,
2997
+ colorPresets,
2998
+ fallbackBlue: legacyToneColors.blue,
2999
+ ensureToolbar,
3000
+ getNavigationTemplate: () => navTemplate,
3001
+ getEntries: () => entriesFrom(titleNodes()),
3002
+ getTagDefinitions: () => tagDefinitions,
3003
+ getSearchState: () => ({
3004
+ loading: searchLoading,
3005
+ error: searchError || catalogError,
3006
+ indexStatus: searchIndexStatus,
3007
+ contentMatches
3008
+ }),
3009
+ scheduleContentSearch,
3010
+ onTagDefinitionsChanged: (definitions) => {
3011
+ tagDefinitions = definitions;
3012
+ syncTagDefinitions();
3013
+ },
3014
+ onOpenEntry: (entry) => {
3015
+ void openEntry(entry);
3016
+ },
3017
+ requestRender: (reason) => renderToolbar(entriesFrom(titleNodes()), reason),
3018
+ trace
3019
+ });
3020
+ const renderToolbar = (entries, reason = "state") => {
3021
+ if (dashboardView.isClosing && state.open) return;
3022
+ hostLifecycle.didRender();
3023
+ renderedIndexSignature = indexSignature(entries);
3024
+ renderCount += 1;
3025
+ trace("render", { reason, count: entries.length, open: state.open });
3026
+ sidebarTagFilter.render(entries);
3027
+ dashboardView.render(entries, reason);
3028
+ };
3029
+ const refresh = (reason = "observer") => {
3030
+ const nodes = titleNodes();
3031
+ nodes.forEach((node) => titleDecorator.enhance(node));
3032
+ const entries = entriesFrom(nodes);
3033
+ sidebarTagFilter.apply(entries);
3034
+ if (host?.isConnected && renderedIndexSignature === indexSignature(entries)) return;
3035
+ if (hostLifecycle.deferIfInteracting(reason)) return;
3036
+ renderToolbar(entries, reason);
3037
+ };
3038
+ hostLifecycle = new HostLifecycle({
3039
+ isInsideOwnedSurface: (target) => Boolean(host?.contains(target) || filterHost?.contains(target) || dashboardView.contains(target)),
3040
+ hasInteractionFocus: () => Boolean(host?.matches(":focus-within") || filterHost?.matches(":focus-within") || dashboardView.hasFocus()),
3041
+ isRelevantMutation: (mutation) => {
3042
+ const target = mutation.target instanceof Element ? mutation.target : mutation.target.parentElement;
3043
+ if (!target || host?.contains(target) || filterHost?.contains(target) || dashboardView.contains(target)) return false;
3044
+ if (isThreadTitleElement(target)) return true;
3045
+ return [...mutation.addedNodes, ...mutation.removedNodes].some(mutationContainsSidebarNode);
3046
+ },
3047
+ onRefresh: refresh,
3048
+ trace
3049
+ });
3050
+ hostLifecycle.mount(document.body ?? document.documentElement);
3051
+ refresh("install");
3052
+ stopLocaleObserver = observeCodexLocale((locale) => {
3053
+ const previousUncategorized = i18n.t("uncategorized");
3054
+ const previousSearchUnavailable = i18n.t("searchUnavailable");
3055
+ if (!i18n.setLocale(locale)) return;
3056
+ if (state.tag === previousUncategorized) runtimeStore.dispatch({ type: "tag.set", value: i18n.t("uncategorized") });
3057
+ if (searchError === previousSearchUnavailable) searchError = i18n.t("searchUnavailable");
3058
+ sessionRegistry.reparse();
3059
+ trace("locale-change", { locale });
3060
+ renderToolbar(entriesFrom(titleNodes()), "locale");
3061
+ });
3062
+ const isRecord2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
3063
+ const applySearchResult = (value) => {
3064
+ if (!isRecord2(value) || value.type !== "searchResult" || value.requestId !== activeSearchRequestId || value.query !== state.query.trim()) return false;
3065
+ contentMatches.clear();
3066
+ if (Array.isArray(value.items)) {
3067
+ value.items.forEach((item) => {
3068
+ if (!isRecord2(item) || typeof item.threadId !== "string" || typeof item.snippet !== "string") return;
3069
+ contentMatches.set(item.threadId, {
3070
+ role: typeof item.role === "string" ? item.role : "Codex",
3071
+ snippet: item.snippet,
3072
+ score: typeof item.score === "number" ? item.score : 0
3073
+ });
3074
+ });
3075
+ }
3076
+ searchLoading = false;
3077
+ searchError = typeof value.error === "string" ? value.error : "";
3078
+ if (isRecord2(value.indexStatus) && typeof value.indexStatus.phase === "string") searchIndexStatus = { ...value.indexStatus, phase: value.indexStatus.phase };
3079
+ trace("search-result", { requestId: value.requestId, results: contentMatches.size, error: searchError || null });
3080
+ if (state.open) renderToolbar(entriesFrom(titleNodes()), "search-result");
3081
+ return true;
3082
+ };
3083
+ const handleRuntimeMessage = (message) => {
3084
+ if (message.type === RuntimeMessageType.settingsError) {
3085
+ searchError = i18n.t("settingsSaveFailed");
3086
+ renderToolbar(entriesFrom(titleNodes()), "settings-error");
3087
+ return true;
3088
+ }
3089
+ if (message.type === RuntimeMessageType.catalogSnapshot) {
3090
+ catalogError = message.payload.complete === true ? "" : i18n.t("catalogUnavailable");
3091
+ if (message.payload.complete === true && Array.isArray(message.payload.items)) {
3092
+ sessionRegistry.applyCatalog(message.payload.items);
3093
+ const entries = entriesFrom(titleNodes());
3094
+ if (state.query.trim()) scheduleContentSearch(entries);
3095
+ renderToolbar(entries, "catalog-snapshot");
3096
+ }
3097
+ if (catalogError && state.open) renderToolbar(entriesFrom(titleNodes()), "catalog-snapshot");
3098
+ return true;
3099
+ }
3100
+ if (message.type === RuntimeMessageType.searchResult) {
3101
+ return applySearchResult({ type: "searchResult", requestId: message.requestId, ...message.payload });
3102
+ }
3103
+ if (message.type === RuntimeMessageType.settingsSnapshot) {
3104
+ if (searchError === i18n.t("settingsSaveFailed")) searchError = "";
3105
+ const settings = isRecord2(message.payload.settings) ? message.payload.settings : null;
3106
+ const nextDefinitions = normalizeTagDefinitions(settings?.tags, defaultDefinitions);
3107
+ tagDefinitions = nextDefinitions;
3108
+ syncTagDefinitions(false);
3109
+ if (state.open) renderToolbar(entriesFrom(titleNodes()), "settings-snapshot");
3110
+ return true;
3111
+ }
3112
+ return false;
3113
+ };
3114
+ receiveRuntimeMessage = handleRuntimeMessage;
3115
+ const runtime = {
3116
+ version,
3117
+ protocolVersion: RUNTIME_PROTOCOL_VERSION,
3118
+ tagDefinitions: () => tagDefinitions.map(({ name, color, description }) => ({ name, color, description })),
3119
+ contentThreadIds: () => sessionRegistry.threadIds(),
3120
+ debugIndex: () => sessionRegistry.debugIndex(),
3121
+ handleMessage: (value) => runtimeClient.handle(value),
3122
+ setSearchResult: applySearchResult,
3123
+ status: () => ({
3124
+ version,
3125
+ locale: i18n.locale,
3126
+ protocolVersion: RUNTIME_PROTOCOL_VERSION,
3127
+ enhanced: document.querySelectorAll(`[${ENHANCED}]`).length,
3128
+ indexed: sessionRegistry.size,
3129
+ searchLoading,
3130
+ searchResults: contentMatches.size,
3131
+ searchIndexStatus,
3132
+ capabilities: detectCodexCapabilities(),
3133
+ lastError: searchError || catalogError || null,
3134
+ toolbar: Boolean(document.getElementById(TOOLBAR_ID)),
3135
+ sidebarFilter: Boolean(document.getElementById(FILTER_BAR_ID)),
3136
+ activeTag: state.tag,
3137
+ visibleResults: dashboardView.visibleResultCount,
3138
+ renderCount,
3139
+ observerRefreshCount: hostLifecycle.observerRefreshCount
3140
+ }),
3141
+ debug: () => debugEvents.slice(),
3142
+ dispose: () => {
3143
+ clearPendingSearch();
3144
+ stopLocaleObserver();
3145
+ hostLifecycle.dispose();
3146
+ titleDecorator.dispose(document.querySelectorAll(`[${ENHANCED}]`));
3147
+ sidebarTagFilter.dispose(document.querySelectorAll(`[${FILTERED}]`));
3148
+ document.querySelectorAll(`[${ROW}]`).forEach((row) => row.removeAttribute(ROW));
3149
+ dashboardView.dispose();
3150
+ document.getElementById(TOOLBAR_ID)?.remove();
3151
+ document.getElementById(STYLE_ID)?.remove();
3152
+ sessionRegistry.clearPersistentCache();
3153
+ if (window.__codexSidebarTags === runtime) delete window.__codexSidebarTags;
3154
+ return true;
3155
+ }
3156
+ };
3157
+ window.__codexSidebarTags = runtime;
3158
+ return runtime.status();
3159
+ }
3160
+ return __toCommonJS(entry_exports);
3161
+ })();