dsh-context 0.55.0 → 0.56.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.
- package/README.md +10 -1
- package/lib/client.js +435 -353
- package/lib/index.d.ts +43 -56
- package/lib/index.js +54 -124
- package/package.json +27 -13
package/lib/client.js
CHANGED
|
@@ -91,7 +91,7 @@ window.__ModuleLoader__.load({
|
|
|
91
91
|
"plugin.name": "插件",
|
|
92
92
|
"plugin.github": "GitHub",
|
|
93
93
|
"plugin.settings": "设置",
|
|
94
|
-
"plugin.settingsOpen": "
|
|
94
|
+
"plugin.settingsOpen": "打开插件设置",
|
|
95
95
|
"trend.title": "上下文趋势",
|
|
96
96
|
"gran.step": "步骤",
|
|
97
97
|
"gran.turn": "轮次",
|
|
@@ -363,9 +363,15 @@ window.__ModuleLoader__.load({
|
|
|
363
363
|
"ov.heat.sub": "按日期筛选",
|
|
364
364
|
"ov.heat.empty": "暂无活跃数据 — 会话产生模型请求后,这里会显示每日用量",
|
|
365
365
|
"ov.heat.sessions": "{n} 个活跃会话",
|
|
366
|
-
"ov.heat.
|
|
367
|
-
"ov.heat.
|
|
368
|
-
"ov.heat.
|
|
366
|
+
"ov.heat.less": "少",
|
|
367
|
+
"ov.heat.more": "多",
|
|
368
|
+
"ov.heat.metric": "指标",
|
|
369
|
+
"ov.heat.metric.sessions": "会话",
|
|
370
|
+
"ov.heat.metric.steps": "步数",
|
|
371
|
+
"ov.heat.steps": "{n} 步",
|
|
372
|
+
"ov.heat.wd.1": "星期一",
|
|
373
|
+
"ov.heat.wd.3": "星期三",
|
|
374
|
+
"ov.heat.wd.5": "星期五",
|
|
369
375
|
"ov.heat.mon.01": "1月",
|
|
370
376
|
"ov.heat.mon.02": "2月",
|
|
371
377
|
"ov.heat.mon.03": "3月",
|
|
@@ -379,7 +385,7 @@ window.__ModuleLoader__.load({
|
|
|
379
385
|
"ov.heat.mon.11": "11月",
|
|
380
386
|
"ov.heat.mon.12": "12月",
|
|
381
387
|
"ov.list.title": "会话",
|
|
382
|
-
"ov.list.search": "
|
|
388
|
+
"ov.list.search": "搜索标题 / 目录 / 最后消息…",
|
|
383
389
|
"ov.list.sortLabel": "排序",
|
|
384
390
|
"ov.list.sort.recent": "最近更新",
|
|
385
391
|
"ov.list.sort.tokens": "Token 总用量",
|
|
@@ -464,7 +470,7 @@ window.__ModuleLoader__.load({
|
|
|
464
470
|
"plugin.name": "Plugin",
|
|
465
471
|
"plugin.github": "GitHub",
|
|
466
472
|
"plugin.settings": "Settings",
|
|
467
|
-
"plugin.settingsOpen": "Open
|
|
473
|
+
"plugin.settingsOpen": "Open plugin settings",
|
|
468
474
|
"trend.title": "Context Trend",
|
|
469
475
|
"gran.step": "Step",
|
|
470
476
|
"gran.turn": "Turn",
|
|
@@ -736,9 +742,15 @@ window.__ModuleLoader__.load({
|
|
|
736
742
|
"ov.heat.sub": "Filter by date",
|
|
737
743
|
"ov.heat.empty": "No activity yet — daily usage appears once sessions make model requests",
|
|
738
744
|
"ov.heat.sessions": "{n} active sessions",
|
|
739
|
-
"ov.heat.
|
|
740
|
-
"ov.heat.
|
|
741
|
-
"ov.heat.
|
|
745
|
+
"ov.heat.less": "Less",
|
|
746
|
+
"ov.heat.more": "More",
|
|
747
|
+
"ov.heat.metric": "Metric",
|
|
748
|
+
"ov.heat.metric.sessions": "Sessions",
|
|
749
|
+
"ov.heat.metric.steps": "Steps",
|
|
750
|
+
"ov.heat.steps": "{n} steps",
|
|
751
|
+
"ov.heat.wd.1": "Mon",
|
|
752
|
+
"ov.heat.wd.3": "Wed",
|
|
753
|
+
"ov.heat.wd.5": "Fri",
|
|
742
754
|
"ov.heat.mon.01": "Jan",
|
|
743
755
|
"ov.heat.mon.02": "Feb",
|
|
744
756
|
"ov.heat.mon.03": "Mar",
|
|
@@ -752,7 +764,7 @@ window.__ModuleLoader__.load({
|
|
|
752
764
|
"ov.heat.mon.11": "Nov",
|
|
753
765
|
"ov.heat.mon.12": "Dec",
|
|
754
766
|
"ov.list.title": "Sessions",
|
|
755
|
-
"ov.list.search": "Search title
|
|
767
|
+
"ov.list.search": "Search title / path / last message…",
|
|
756
768
|
"ov.list.sortLabel": "Sort",
|
|
757
769
|
"ov.list.sort.recent": "Last updated",
|
|
758
770
|
"ov.list.sort.tokens": "Total Tokens",
|
|
@@ -2033,12 +2045,11 @@ window.__ModuleLoader__.load({
|
|
|
2033
2045
|
}
|
|
2034
2046
|
/**
|
|
2035
2047
|
* Map one raw durable event into the epoch content the browser renders. A
|
|
2036
|
-
* `request/header` yields
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
2039
|
-
*
|
|
2040
|
-
*
|
|
2041
|
-
* envelope carries neither.
|
|
2048
|
+
* `request/header` yields each tool's producer description and raw schema; a
|
|
2049
|
+
* `system/message` yields the prompt text alone (its tools live in the
|
|
2050
|
+
* request header). Both mirror the host fold's per-entry guards — a null or
|
|
2051
|
+
* primitive tool entry degrades to an unnamed row instead of throwing the
|
|
2052
|
+
* read. Null when the event carries neither.
|
|
2042
2053
|
*/
|
|
2043
2054
|
function headerContentOf(event) {
|
|
2044
2055
|
const { type, data } = event;
|
|
@@ -2061,18 +2072,15 @@ window.__ModuleLoader__.load({
|
|
|
2061
2072
|
schema: t
|
|
2062
2073
|
});
|
|
2063
2074
|
}
|
|
2064
|
-
return {
|
|
2065
|
-
...typeof rawHeader.system === "string" && rawHeader.system !== "" ? { system: rawHeader.system } : {},
|
|
2066
|
-
tools
|
|
2067
|
-
};
|
|
2075
|
+
return { tools };
|
|
2068
2076
|
}
|
|
2069
2077
|
/**
|
|
2070
2078
|
* The on-demand CONTENT fetch for the browser's System and Tools sections —
|
|
2071
2079
|
* the lazy counterpart of the node fetcher above. One seq-anchored history
|
|
2072
2080
|
* read off the requested seq returns the page holding that event (non-message
|
|
2073
2081
|
* events ride the page verbatim); a `request/header` maps to the epoch's
|
|
2074
|
-
* tools
|
|
2075
|
-
*
|
|
2082
|
+
* tools, a `system/message` to the prompt's text. Landed content caches per
|
|
2083
|
+
* seq (history is immutable), and OLDER
|
|
2076
2084
|
* epochs sharing the page cache for free — stepping back through epochs walks
|
|
2077
2085
|
* the same pages. Undefined when no history face exists — the browser keeps a
|
|
2078
2086
|
* metadata-only degradation instead.
|
|
@@ -2374,8 +2382,9 @@ window.__ModuleLoader__.load({
|
|
|
2374
2382
|
* node at or before it carrying tokens, which is exactly the host fold's
|
|
2375
2383
|
* "last nonempty surviving system" rule and therefore agrees with the
|
|
2376
2384
|
* per-step `system` figure the fold recorded. Rows folded before `systems`
|
|
2377
|
-
* existed carry none; the header epoch's
|
|
2378
|
-
*
|
|
2385
|
+
* existed carry none; the header epoch's own figure stands in for them (the
|
|
2386
|
+
* legacy wire shape older plugin builds served — current epochs fold
|
|
2387
|
+
* metadata-only, so the fallback only ever fires on those cached rows).
|
|
2379
2388
|
*/
|
|
2380
2389
|
function systemAt(data, header, seq) {
|
|
2381
2390
|
const systems = data.systems;
|
|
@@ -6094,8 +6103,8 @@ window.__ModuleLoader__.load({
|
|
|
6094
6103
|
/**
|
|
6095
6104
|
* The panel's row pipeline: range (by last-activity), then the heatmap's
|
|
6096
6105
|
* picked day (sessions contributing to that day's merged ledger), then the
|
|
6097
|
-
* search box (title or
|
|
6098
|
-
* cannot prove out of the result — never an exception.
|
|
6106
|
+
* search box (title, directory, or last-message substring). Each stage keeps
|
|
6107
|
+
* the rows it cannot prove out of the result — never an exception.
|
|
6099
6108
|
*/
|
|
6100
6109
|
function filterRows(rows, opts, now) {
|
|
6101
6110
|
const start = rangeStartOf(opts.range, now);
|
|
@@ -6109,7 +6118,9 @@ window.__ModuleLoader__.load({
|
|
|
6109
6118
|
if (query !== "") {
|
|
6110
6119
|
const inTitle = row.title.toLowerCase().includes(query);
|
|
6111
6120
|
const inCwd = row.cwd !== void 0 && row.cwd.toLowerCase().includes(query);
|
|
6112
|
-
|
|
6121
|
+
const lastUser = row.timeline?.lastUser;
|
|
6122
|
+
const inLastUser = typeof lastUser === "string" && lastUser.toLowerCase().includes(query);
|
|
6123
|
+
if (!inTitle && !inCwd && !inLastUser) return false;
|
|
6113
6124
|
}
|
|
6114
6125
|
return true;
|
|
6115
6126
|
});
|
|
@@ -6290,6 +6301,114 @@ window.__ModuleLoader__.load({
|
|
|
6290
6301
|
return t("ov.time.d", { n: Math.floor(hours / 24) });
|
|
6291
6302
|
}
|
|
6292
6303
|
//#endregion
|
|
6304
|
+
//#region src/client/settingsJump.ts
|
|
6305
|
+
/**
|
|
6306
|
+
* Best-effort jump to this plugin's preferences. Two generations of chrome:
|
|
6307
|
+
* - dsh 0.1.7+ (Config-form generation): the preferences live on the
|
|
6308
|
+
* bundle's page of the Plugins main panel — the jump clicks the panel's
|
|
6309
|
+
* sidebar entry (its shipped aria-label), then follows the page with a
|
|
6310
|
+
* bounded poll for the bundle card's open control, found by the shipped,
|
|
6311
|
+
* locale-independent `data-plugin-package` list identity: the card lists
|
|
6312
|
+
* once the page's package load settles, and inside it the one button
|
|
6313
|
+
* that is not the enable switch is the title that opens the page. A
|
|
6314
|
+
* poll that never finds the card (still loading, plugin absent, or the
|
|
6315
|
+
* page already open on the detail view — the list unmounts there)
|
|
6316
|
+
* degrades to the card list, and every step stays silent.
|
|
6317
|
+
* - older lines: Settings → Plugins → Plugin configuration — the settings
|
|
6318
|
+
* panel keeps its open state inside the shell component (no plugin-facing
|
|
6319
|
+
* open face exists), so the jump drives the real chrome: click the
|
|
6320
|
+
* sidebar's settings trigger, then the Plugins section nav row, both
|
|
6321
|
+
* found by their shipped attributes and labels.
|
|
6322
|
+
* The last leg — the card itself — is ours: the module also carries a
|
|
6323
|
+
* short-lived in-bundle expand request that the settings-section card
|
|
6324
|
+
* consumes on mount, so that jump lands on the configuration already open.
|
|
6325
|
+
* EVERY step is individually guarded: a shell that doesn't match (different
|
|
6326
|
+
* layout, missing sidebar) degrades the whole jump to a silent no-op — this
|
|
6327
|
+
* path must never throw into the caller's render.
|
|
6328
|
+
*/
|
|
6329
|
+
let requestedAt = 0;
|
|
6330
|
+
/** Raise a short-lived request for the plugin's settings card to mount expanded. */
|
|
6331
|
+
function requestCardExpand(now = Date.now()) {
|
|
6332
|
+
requestedAt = now;
|
|
6333
|
+
}
|
|
6334
|
+
/** Consume the request once; true only while it is still fresh (younger than maxAgeMs). */
|
|
6335
|
+
function consumeCardExpand(now = Date.now(), maxAgeMs = 5e3) {
|
|
6336
|
+
const fresh = requestedAt > 0 && now - requestedAt < maxAgeMs;
|
|
6337
|
+
requestedAt = 0;
|
|
6338
|
+
return fresh;
|
|
6339
|
+
}
|
|
6340
|
+
/**
|
|
6341
|
+
* The shipped Plugins label in both locales — the main-panel entry's
|
|
6342
|
+
* aria-label and the settings section's nav row text are the same word.
|
|
6343
|
+
*/
|
|
6344
|
+
const PLUGIN_LABELS = /* @__PURE__ */ new Set(["Plugins", "插件"]);
|
|
6345
|
+
/** The bundle card's shipped list identity (locale-independent). */
|
|
6346
|
+
const PACKAGE_KEY = "dsh-context";
|
|
6347
|
+
/** How long the card poll follows the panel: 40 ticks at the 100ms tick, enough for the page's package load. */
|
|
6348
|
+
const POLL_TICKS = 40;
|
|
6349
|
+
/** Buttons the jump may operate on, in document order. */
|
|
6350
|
+
function buttonsOf(doc) {
|
|
6351
|
+
return [...doc.querySelectorAll("button")];
|
|
6352
|
+
}
|
|
6353
|
+
/** The Plugins main-panel entry, matched by its shipped aria-label. */
|
|
6354
|
+
function findPanelEntry(doc) {
|
|
6355
|
+
return buttonsOf(doc).find((b) => PLUGIN_LABELS.has(b.getAttribute("aria-label") ?? ""));
|
|
6356
|
+
}
|
|
6357
|
+
/**
|
|
6358
|
+
* The bundle card's open control: the one button inside the card that is not
|
|
6359
|
+
* the enable switch (the primitives switch carries `role="switch"`); the
|
|
6360
|
+
* title button's own aria-label is localized.
|
|
6361
|
+
*/
|
|
6362
|
+
function findCardOpenControl(doc) {
|
|
6363
|
+
const card = doc.querySelector(`[data-plugin-package="${PACKAGE_KEY}"]`);
|
|
6364
|
+
if (card === null) return void 0;
|
|
6365
|
+
const open = [...card.querySelectorAll("button")].filter((b) => b.getAttribute("role") !== "switch");
|
|
6366
|
+
return open.length === 1 ? open[0] : void 0;
|
|
6367
|
+
}
|
|
6368
|
+
/** The sidebar's settings triggers: dialog semantics plus an expanded flag. */
|
|
6369
|
+
function findTriggers(doc) {
|
|
6370
|
+
return buttonsOf(doc).filter((b) => b.getAttribute("aria-haspopup") === "dialog" && b.hasAttribute("aria-expanded"));
|
|
6371
|
+
}
|
|
6372
|
+
/** The Plugins section's nav row, matched by its shipped label text. */
|
|
6373
|
+
function findSectionRow(doc) {
|
|
6374
|
+
return buttonsOf(doc).find((b) => PLUGIN_LABELS.has(b.textContent.trim()));
|
|
6375
|
+
}
|
|
6376
|
+
function openPluginSettings(doc = document, schedule = (run, ms) => {
|
|
6377
|
+
window.setTimeout(run, ms);
|
|
6378
|
+
}) {
|
|
6379
|
+
try {
|
|
6380
|
+
const panel = findPanelEntry(doc);
|
|
6381
|
+
if (panel !== void 0) {
|
|
6382
|
+
panel.click();
|
|
6383
|
+
const poll = (left) => {
|
|
6384
|
+
try {
|
|
6385
|
+
const open = findCardOpenControl(doc);
|
|
6386
|
+
if (open !== void 0) {
|
|
6387
|
+
open.click();
|
|
6388
|
+
return;
|
|
6389
|
+
}
|
|
6390
|
+
} catch {}
|
|
6391
|
+
if (left > 0) schedule(() => {
|
|
6392
|
+
poll(left - 1);
|
|
6393
|
+
}, 100);
|
|
6394
|
+
};
|
|
6395
|
+
schedule(() => {
|
|
6396
|
+
poll(POLL_TICKS);
|
|
6397
|
+
}, 200);
|
|
6398
|
+
return;
|
|
6399
|
+
}
|
|
6400
|
+
const triggers = findTriggers(doc);
|
|
6401
|
+
if (triggers.find((b) => b.getAttribute("aria-expanded") === "true") === void 0 && triggers.length === 0) return;
|
|
6402
|
+
triggers.find((b) => b.getAttribute("aria-expanded") !== "true")?.click();
|
|
6403
|
+
requestCardExpand();
|
|
6404
|
+
schedule(() => {
|
|
6405
|
+
try {
|
|
6406
|
+
findSectionRow(doc)?.click();
|
|
6407
|
+
} catch {}
|
|
6408
|
+
}, 80);
|
|
6409
|
+
} catch {}
|
|
6410
|
+
}
|
|
6411
|
+
//#endregion
|
|
6293
6412
|
//#region src/client/balance.ts
|
|
6294
6413
|
const BALANCE_ROUTE = "/api/dsh-context/balance";
|
|
6295
6414
|
/** Where the last live figure is remembered across opens, per browser. */
|
|
@@ -6520,51 +6639,57 @@ window.__ModuleLoader__.load({
|
|
|
6520
6639
|
date.setDate(date.getDate() + delta);
|
|
6521
6640
|
return dayKeyOf(date.getTime());
|
|
6522
6641
|
}
|
|
6523
|
-
/** The
|
|
6524
|
-
function
|
|
6642
|
+
/** The Sunday (local) of the week containing `key` — the heatmap's column anchor. */
|
|
6643
|
+
function sundayOfWeek(key) {
|
|
6525
6644
|
if (!DAY_KEY_RE.test(key)) return null;
|
|
6526
6645
|
const y = Number(key.slice(0, 4));
|
|
6527
6646
|
const m = Number(key.slice(5, 7));
|
|
6528
6647
|
const d = Number(key.slice(8, 10));
|
|
6529
6648
|
const date = new Date(y, m - 1, d);
|
|
6530
6649
|
if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null;
|
|
6531
|
-
return shiftDayKey(key, -
|
|
6650
|
+
return shiftDayKey(key, -date.getDay());
|
|
6532
6651
|
}
|
|
6533
6652
|
//#endregion
|
|
6534
6653
|
//#region src/client/components/heatmap.tsx
|
|
6535
6654
|
/**
|
|
6536
6655
|
* The Context Dashboard's activity heatmap: a GitHub-style contribution grid
|
|
6537
|
-
* (weeks as columns,
|
|
6538
|
-
* column where
|
|
6539
|
-
*
|
|
6540
|
-
*
|
|
6656
|
+
* (weeks as columns, Sunday-first weekdays as rows, a month label over each
|
|
6657
|
+
* column where a month begins — the window's opening column always labeled —
|
|
6658
|
+
* and a Less→More key for the depth steps) over the merged daily
|
|
6659
|
+
* ledger (overview.ts). Cell depth is the selected metric's share of the
|
|
6660
|
+
* window's maximum — distinct active sessions or settlement steps; a session
|
|
6661
|
+
* can spread its steps thinly across many days while another day stacks a
|
|
6662
|
+
* run, so each metric scales on its OWN maximum — in four steps; a day with
|
|
6663
|
+
* data is a button whose click
|
|
6541
6664
|
* pins the session list to that day (click again to release). Cells tip
|
|
6542
6665
|
* through the harness's own Tooltip primitive (instant on hover; native
|
|
6543
|
-
* `title` lags a second behind), the bubble carrying the date
|
|
6544
|
-
* active sessions. The grid is computed from the injected
|
|
6666
|
+
* `title` lags a second behind), the bubble carrying the date, the day's
|
|
6667
|
+
* active sessions, and its steps. The grid is computed from the injected
|
|
6668
|
+
* `today` key, so
|
|
6545
6669
|
* the layout is deterministic in tests and follows the browser's local
|
|
6546
6670
|
* calendar at runtime.
|
|
6547
6671
|
*/
|
|
6548
6672
|
/**
|
|
6549
6673
|
* Lay out the grid: `weeks` columns ending at today's week, each seven
|
|
6550
|
-
*
|
|
6551
|
-
* a corrupt injected key degrades the card to its empty
|
|
6674
|
+
* Sunday-first cells (row 0 = Sunday). Returns null when `today` (or its
|
|
6675
|
+
* week math) fails — a corrupt injected key degrades the card to its empty
|
|
6676
|
+
* note.
|
|
6552
6677
|
*/
|
|
6553
6678
|
function gridOf(today, weeks) {
|
|
6554
|
-
const
|
|
6555
|
-
if (
|
|
6556
|
-
const
|
|
6557
|
-
if (
|
|
6679
|
+
const lastSunday = sundayOfWeek(today);
|
|
6680
|
+
if (lastSunday === null || weeks < 1) return null;
|
|
6681
|
+
const firstSunday = shiftDayKey(lastSunday, -7 * (weeks - 1));
|
|
6682
|
+
if (firstSunday === null) return null;
|
|
6558
6683
|
const columns = [];
|
|
6559
6684
|
for (let w = 0; w < weeks; w++) {
|
|
6560
|
-
const
|
|
6561
|
-
/* v8 ignore next --
|
|
6685
|
+
const sunday = shiftDayKey(firstSunday, 7 * w);
|
|
6686
|
+
/* v8 ignore next -- sunday is bounded by firstSunday and lastSunday (both
|
|
6562
6687
|
* proven valid), so it can never leave the representable range; kept as a
|
|
6563
6688
|
* guard so a future shiftDayKey change cannot leak a null into the grid. */
|
|
6564
|
-
if (
|
|
6689
|
+
if (sunday === null) return null;
|
|
6565
6690
|
const column = [];
|
|
6566
6691
|
for (let d = 0; d < 7; d++) {
|
|
6567
|
-
const key = shiftDayKey(
|
|
6692
|
+
const key = shiftDayKey(sunday, d);
|
|
6568
6693
|
if (key === null) return null;
|
|
6569
6694
|
column.push({
|
|
6570
6695
|
key,
|
|
@@ -6589,88 +6714,116 @@ window.__ModuleLoader__.load({
|
|
|
6589
6714
|
const { t } = kit;
|
|
6590
6715
|
return function Heatmap(props) {
|
|
6591
6716
|
const weeks = props.weeks ?? 8;
|
|
6717
|
+
const metric = props.metric ?? "steps";
|
|
6592
6718
|
const columns = gridOf(props.today, weeks);
|
|
6593
6719
|
if (columns === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6594
6720
|
className: "lc-empty",
|
|
6595
6721
|
children: t("ov.heat.empty")
|
|
6596
6722
|
});
|
|
6597
6723
|
const byKey = props.days;
|
|
6598
|
-
let
|
|
6724
|
+
let maxSessions = 0;
|
|
6725
|
+
let maxSteps = 0;
|
|
6599
6726
|
let any = false;
|
|
6600
6727
|
for (const column of columns) for (const cell of column) {
|
|
6601
6728
|
const entry = byKey[cell.key];
|
|
6602
6729
|
if (entry === void 0 || entry.tokens <= 0 && entry.requests <= 0) continue;
|
|
6603
6730
|
cell.entry = entry;
|
|
6604
6731
|
any = true;
|
|
6605
|
-
if (entry.
|
|
6732
|
+
if (entry.sessions > maxSessions) maxSessions = entry.sessions;
|
|
6733
|
+
if (entry.requests > maxSteps) maxSteps = entry.requests;
|
|
6606
6734
|
}
|
|
6607
6735
|
if (!any) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6608
6736
|
className: "lc-empty",
|
|
6609
6737
|
children: t("ov.heat.empty")
|
|
6610
6738
|
});
|
|
6611
|
-
const
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
t("ov.heat.wd.
|
|
6615
|
-
|
|
6739
|
+
const max = metric === "sessions" ? maxSessions : maxSteps;
|
|
6740
|
+
const metricValueOf = (entry) => metric === "sessions" ? entry.sessions : entry.requests;
|
|
6741
|
+
const weekdayLabels = {
|
|
6742
|
+
1: t("ov.heat.wd.1"),
|
|
6743
|
+
3: t("ov.heat.wd.3"),
|
|
6744
|
+
5: t("ov.heat.wd.5")
|
|
6745
|
+
};
|
|
6616
6746
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6617
|
-
className: "lc-heat",
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6747
|
+
className: "lc-heat-wrap",
|
|
6748
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6749
|
+
className: "lc-heat",
|
|
6750
|
+
role: "group",
|
|
6751
|
+
"aria-label": t("ov.heat.title"),
|
|
6752
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6753
|
+
className: "lc-heat-wds",
|
|
6754
|
+
"aria-hidden": "true",
|
|
6755
|
+
children: [
|
|
6756
|
+
0,
|
|
6757
|
+
1,
|
|
6758
|
+
2,
|
|
6759
|
+
3,
|
|
6760
|
+
4,
|
|
6761
|
+
5,
|
|
6762
|
+
6
|
|
6763
|
+
].map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6764
|
+
className: "lc-heat-wd",
|
|
6765
|
+
children: weekdayLabels[row] ?? ""
|
|
6766
|
+
}, row))
|
|
6767
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6768
|
+
className: "lc-heat-cols",
|
|
6769
|
+
children: columns.map((column, wi) => {
|
|
6770
|
+
const opens = wi === 0 || column[0].key.slice(0, 7) !== column[6].key.slice(0, 7) || column[0].key.slice(8, 10) === "01";
|
|
6771
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6772
|
+
className: "lc-heat-col",
|
|
6773
|
+
children: [opens && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6774
|
+
className: "lc-heat-mon",
|
|
6775
|
+
"aria-hidden": "true",
|
|
6776
|
+
children: t("ov.heat.mon." + column[6].key.slice(5, 7))
|
|
6777
|
+
}), column.map((cell) => {
|
|
6778
|
+
if (cell.future) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6779
|
+
className: "lc-heat-cell lc-heat-future",
|
|
6780
|
+
"aria-hidden": "true"
|
|
6781
|
+
}, cell.key);
|
|
6782
|
+
const level = cell.entry === void 0 ? 0 : levelOf(metricValueOf(cell.entry), max);
|
|
6783
|
+
if (cell.entry === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6784
|
+
label: cell.key,
|
|
6785
|
+
side: "top",
|
|
6786
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "lc-heat-cell lc-heat-0" })
|
|
6787
|
+
}, cell.key);
|
|
6788
|
+
const picked = props.selected === cell.key;
|
|
6789
|
+
const label = `${cell.key}\n${t("ov.heat.sessions", { n: cell.entry.sessions })}\n${t("ov.heat.steps", { n: cell.entry.requests })}`;
|
|
6790
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6791
|
+
label,
|
|
6792
|
+
side: "top",
|
|
6793
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6794
|
+
type: "button",
|
|
6795
|
+
className: `lc-heat-cell lc-heat-${String(level)}${picked ? " lc-heat-on" : ""}`,
|
|
6796
|
+
"aria-label": label,
|
|
6797
|
+
"aria-pressed": picked,
|
|
6798
|
+
onClick: () => {
|
|
6799
|
+
if (props.onSelect !== void 0) props.onSelect(picked ? null : cell.key);
|
|
6800
|
+
}
|
|
6801
|
+
})
|
|
6802
|
+
}, cell.key);
|
|
6803
|
+
})]
|
|
6804
|
+
}, wi);
|
|
6805
|
+
})
|
|
6806
|
+
})]
|
|
6807
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6808
|
+
className: "lc-heat-legend",
|
|
6622
6809
|
"aria-hidden": "true",
|
|
6623
6810
|
children: [
|
|
6624
|
-
0,
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
className: "lc-heat-col",
|
|
6641
|
-
children: [opens && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6642
|
-
className: "lc-heat-mon",
|
|
6643
|
-
"aria-hidden": "true",
|
|
6644
|
-
children: t("ov.heat.mon." + column[6].key.slice(5, 7))
|
|
6645
|
-
}), column.map((cell) => {
|
|
6646
|
-
if (cell.future) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6647
|
-
className: "lc-heat-cell lc-heat-future",
|
|
6648
|
-
"aria-hidden": "true"
|
|
6649
|
-
}, cell.key);
|
|
6650
|
-
const level = cell.entry === void 0 ? 0 : levelOf(cell.entry.tokens, max);
|
|
6651
|
-
if (cell.entry === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6652
|
-
label: cell.key,
|
|
6653
|
-
side: "top",
|
|
6654
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "lc-heat-cell lc-heat-0" })
|
|
6655
|
-
}, cell.key);
|
|
6656
|
-
const picked = props.selected === cell.key;
|
|
6657
|
-
const label = `${cell.key}\n${t("ov.heat.sessions", { n: cell.entry.sessions })}`;
|
|
6658
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
6659
|
-
label,
|
|
6660
|
-
side: "top",
|
|
6661
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6662
|
-
type: "button",
|
|
6663
|
-
className: `lc-heat-cell lc-heat-${String(level)}${picked ? " lc-heat-on" : ""}`,
|
|
6664
|
-
"aria-label": label,
|
|
6665
|
-
"aria-pressed": picked,
|
|
6666
|
-
onClick: () => {
|
|
6667
|
-
if (props.onSelect !== void 0) props.onSelect(picked ? null : cell.key);
|
|
6668
|
-
}
|
|
6669
|
-
})
|
|
6670
|
-
}, cell.key);
|
|
6671
|
-
})]
|
|
6672
|
-
}, wi);
|
|
6673
|
-
})
|
|
6811
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6812
|
+
className: "lc-heat-key",
|
|
6813
|
+
children: t("ov.heat.less")
|
|
6814
|
+
}),
|
|
6815
|
+
[
|
|
6816
|
+
0,
|
|
6817
|
+
1,
|
|
6818
|
+
2,
|
|
6819
|
+
3,
|
|
6820
|
+
4
|
|
6821
|
+
].map((level) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `lc-heat-cell lc-heat-${String(level)}` }, level)),
|
|
6822
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6823
|
+
className: "lc-heat-key",
|
|
6824
|
+
children: t("ov.heat.more")
|
|
6825
|
+
})
|
|
6826
|
+
]
|
|
6674
6827
|
})]
|
|
6675
6828
|
});
|
|
6676
6829
|
};
|
|
@@ -6917,11 +7070,11 @@ window.__ModuleLoader__.load({
|
|
|
6917
7070
|
* opening one log.
|
|
6918
7071
|
*
|
|
6919
7072
|
* The body is a 3:7 column pair: the insight column (the KPI 2×3 block over
|
|
6920
|
-
* the activity heatmap
|
|
6921
|
-
* the card grid); the heatmap keeps its own
|
|
6922
|
-
* list to a picked day (the panel's
|
|
6923
|
-
* click jumps to that session through
|
|
6924
|
-
* closes the panel.
|
|
7073
|
+
* the activity heatmap, then the preferences entry row) beside the session
|
|
7074
|
+
* column (search, group chips, and the card grid); the heatmap keeps its own
|
|
7075
|
+
* fixed 8-week window and PINs the list to a picked day (the panel's
|
|
7076
|
+
* drill-down gesture). A session card click jumps to that session through
|
|
7077
|
+
* the harness's own `sessions.open` and closes the panel.
|
|
6925
7078
|
*/
|
|
6926
7079
|
const RANGES = [
|
|
6927
7080
|
"24h",
|
|
@@ -6934,6 +7087,8 @@ window.__ModuleLoader__.load({
|
|
|
6934
7087
|
"tokens",
|
|
6935
7088
|
"context"
|
|
6936
7089
|
];
|
|
7090
|
+
/** The heatmap's depth metrics, in toggle order (steps is the default). */
|
|
7091
|
+
const METRICS = ["sessions", "steps"];
|
|
6937
7092
|
function makeOverviewPanel(ctx, kit) {
|
|
6938
7093
|
const { t, fmtDuration } = kit;
|
|
6939
7094
|
const Heatmap = makeHeatmap(kit);
|
|
@@ -6955,6 +7110,7 @@ window.__ModuleLoader__.load({
|
|
|
6955
7110
|
const [query, setQuery] = (0, react.useState)("");
|
|
6956
7111
|
const [group, setGroup] = (0, react.useState)(null);
|
|
6957
7112
|
const [sort, setSort] = (0, react.useState)("recent");
|
|
7113
|
+
const [metric, setMetric] = (0, react.useState)("steps");
|
|
6958
7114
|
const [page, setPage] = (0, react.useState)(0);
|
|
6959
7115
|
const close = () => {
|
|
6960
7116
|
overviewStore.set(false);
|
|
@@ -7052,134 +7208,168 @@ window.__ModuleLoader__.load({
|
|
|
7052
7208
|
className: "lc-ov-body",
|
|
7053
7209
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7054
7210
|
className: "lc-ov-left",
|
|
7055
|
-
children: [
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
className: "lc-card-
|
|
7169
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7170
|
-
className: "lc-card-title
|
|
7171
|
-
children:
|
|
7211
|
+
children: [
|
|
7212
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7213
|
+
className: "lc-ov-kpis",
|
|
7214
|
+
children: [
|
|
7215
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7216
|
+
className: "lc-stat lc-ov-kpi",
|
|
7217
|
+
children: [
|
|
7218
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7219
|
+
className: "lc-stat-label",
|
|
7220
|
+
children: t("ov.kpi.sessions")
|
|
7221
|
+
}),
|
|
7222
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7223
|
+
className: "lc-stat-value",
|
|
7224
|
+
children: kpi.sessions
|
|
7225
|
+
}),
|
|
7226
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7227
|
+
className: "lc-stat-sub",
|
|
7228
|
+
children: t("ov.kpi.ofTotal", { n: kpi.listed })
|
|
7229
|
+
})
|
|
7230
|
+
]
|
|
7231
|
+
}),
|
|
7232
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7233
|
+
className: "lc-stat lc-ov-kpi",
|
|
7234
|
+
children: [
|
|
7235
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7236
|
+
className: "lc-stat-label",
|
|
7237
|
+
children: t("ov.kpi.tokens")
|
|
7238
|
+
}),
|
|
7239
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7240
|
+
className: "lc-stat-value",
|
|
7241
|
+
children: fmt(kpi.tokens)
|
|
7242
|
+
}),
|
|
7243
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7244
|
+
className: "lc-stat-sub",
|
|
7245
|
+
children: [
|
|
7246
|
+
t("stats.turns"),
|
|
7247
|
+
" ",
|
|
7248
|
+
fmt(kpi.turns)
|
|
7249
|
+
]
|
|
7250
|
+
})
|
|
7251
|
+
]
|
|
7252
|
+
}),
|
|
7253
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7254
|
+
className: "lc-stat lc-ov-kpi",
|
|
7255
|
+
children: [
|
|
7256
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7257
|
+
className: "lc-stat-label",
|
|
7258
|
+
children: t("stats.cost")
|
|
7259
|
+
}),
|
|
7260
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7261
|
+
className: "lc-stat-value",
|
|
7262
|
+
children: kpi.cost === null ? "—" : formatCost(kpi.cost, currency)
|
|
7263
|
+
}),
|
|
7264
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7265
|
+
className: "lc-stat-sub",
|
|
7266
|
+
children: t("ov.kpi.sessionsSub", { n: kpi.costSessions })
|
|
7267
|
+
})
|
|
7268
|
+
]
|
|
7269
|
+
}),
|
|
7270
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7271
|
+
className: "lc-stat lc-ov-kpi",
|
|
7272
|
+
children: [
|
|
7273
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7274
|
+
className: "lc-stat-label",
|
|
7275
|
+
children: t("stats.cacheHit")
|
|
7276
|
+
}),
|
|
7277
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7278
|
+
className: "lc-stat-value",
|
|
7279
|
+
children: kpi.cacheHit === null ? "—" : kpi.cacheHit + "%"
|
|
7280
|
+
}),
|
|
7281
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7282
|
+
className: "lc-stat-sub",
|
|
7283
|
+
children: t("ov.kpi.sessionsSub", { n: kpi.usageSessions })
|
|
7284
|
+
})
|
|
7285
|
+
]
|
|
7286
|
+
}),
|
|
7287
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7288
|
+
className: "lc-stat lc-ov-kpi",
|
|
7289
|
+
children: [
|
|
7290
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7291
|
+
className: "lc-stat-label",
|
|
7292
|
+
children: t("stats.toolCalls")
|
|
7293
|
+
}),
|
|
7294
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7295
|
+
className: "lc-stat-value",
|
|
7296
|
+
children: fmt(kpi.toolCalls)
|
|
7297
|
+
}),
|
|
7298
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7299
|
+
className: "lc-stat-sub",
|
|
7300
|
+
children: t("ov.kpi.toolSub", { dur: fmtDuration(kpi.toolsMs) })
|
|
7301
|
+
})
|
|
7302
|
+
]
|
|
7303
|
+
}),
|
|
7304
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7305
|
+
className: "lc-stat lc-ov-kpi",
|
|
7306
|
+
children: [
|
|
7307
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7308
|
+
className: "lc-stat-label",
|
|
7309
|
+
children: t("timing.total")
|
|
7310
|
+
}),
|
|
7311
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7312
|
+
className: "lc-stat-value",
|
|
7313
|
+
children: fmtDuration(kpi.wallMs)
|
|
7314
|
+
}),
|
|
7315
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7316
|
+
className: "lc-stat-sub",
|
|
7317
|
+
children: t("ov.kpi.wallSub", { n: fmt(kpi.calls) })
|
|
7318
|
+
})
|
|
7319
|
+
]
|
|
7320
|
+
})
|
|
7321
|
+
]
|
|
7322
|
+
}),
|
|
7323
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7324
|
+
className: "lc-card lc-ov-heat-card",
|
|
7325
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7326
|
+
className: "lc-card-title",
|
|
7327
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7328
|
+
className: "lc-card-title-text",
|
|
7329
|
+
children: t("ov.heat.title")
|
|
7330
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7331
|
+
className: "lc-heat-ctl",
|
|
7332
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7333
|
+
className: "lc-card-sub",
|
|
7334
|
+
children: t("ov.heat.sub")
|
|
7335
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7336
|
+
className: "lc-gran",
|
|
7337
|
+
role: "group",
|
|
7338
|
+
"aria-label": t("ov.heat.metric"),
|
|
7339
|
+
children: METRICS.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7340
|
+
type: "button",
|
|
7341
|
+
className: "lc-gran-btn" + (metric === m ? " lc-gran-on" : ""),
|
|
7342
|
+
onClick: () => {
|
|
7343
|
+
setMetric(m);
|
|
7344
|
+
},
|
|
7345
|
+
children: t("ov.heat.metric." + m)
|
|
7346
|
+
}, m))
|
|
7347
|
+
})]
|
|
7348
|
+
})]
|
|
7349
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Heatmap, {
|
|
7350
|
+
days,
|
|
7351
|
+
metric,
|
|
7352
|
+
selected: day,
|
|
7353
|
+
onSelect: setDay,
|
|
7354
|
+
today: todayKey()
|
|
7355
|
+
})]
|
|
7356
|
+
}),
|
|
7357
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7358
|
+
type: "button",
|
|
7359
|
+
className: "lc-ov-settings",
|
|
7360
|
+
onClick: () => {
|
|
7361
|
+
openPluginSettings();
|
|
7362
|
+
close();
|
|
7363
|
+
},
|
|
7364
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7365
|
+
className: "lc-ov-settings-label",
|
|
7366
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconSettings, { size: 14 }), t("plugin.settings")]
|
|
7172
7367
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7173
|
-
className: "lc-
|
|
7174
|
-
children: t("
|
|
7368
|
+
className: "lc-ov-settings-hint",
|
|
7369
|
+
children: t("plugin.settingsOpen")
|
|
7175
7370
|
})]
|
|
7176
|
-
})
|
|
7177
|
-
|
|
7178
|
-
selected: day,
|
|
7179
|
-
onSelect: setDay,
|
|
7180
|
-
today: todayKey()
|
|
7181
|
-
})]
|
|
7182
|
-
})]
|
|
7371
|
+
})
|
|
7372
|
+
]
|
|
7183
7373
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7184
7374
|
className: "lc-ov-right",
|
|
7185
7375
|
children: [
|
|
@@ -7317,114 +7507,6 @@ window.__ModuleLoader__.load({
|
|
|
7317
7507
|
return cost === null ? "—" : formatCost(cost, currency);
|
|
7318
7508
|
}
|
|
7319
7509
|
//#endregion
|
|
7320
|
-
//#region src/client/settingsJump.ts
|
|
7321
|
-
/**
|
|
7322
|
-
* Best-effort jump to this plugin's preferences. Two generations of chrome:
|
|
7323
|
-
* - dsh 0.1.7+ (Config-form generation): the preferences live on the
|
|
7324
|
-
* bundle's page of the Plugins main panel — the jump clicks the panel's
|
|
7325
|
-
* sidebar entry (its shipped aria-label), then follows the page with a
|
|
7326
|
-
* bounded poll for the bundle card's open control, found by the shipped,
|
|
7327
|
-
* locale-independent `data-plugin-package` list identity: the card lists
|
|
7328
|
-
* once the page's package load settles, and inside it the one button
|
|
7329
|
-
* that is not the enable switch is the title that opens the page. A
|
|
7330
|
-
* poll that never finds the card (still loading, plugin absent, or the
|
|
7331
|
-
* page already open on the detail view — the list unmounts there)
|
|
7332
|
-
* degrades to the card list, and every step stays silent.
|
|
7333
|
-
* - older lines: Settings → Plugins → Plugin configuration — the settings
|
|
7334
|
-
* panel keeps its open state inside the shell component (no plugin-facing
|
|
7335
|
-
* open face exists), so the jump drives the real chrome: click the
|
|
7336
|
-
* sidebar's settings trigger, then the Plugins section nav row, both
|
|
7337
|
-
* found by their shipped attributes and labels.
|
|
7338
|
-
* The last leg — the card itself — is ours: the module also carries a
|
|
7339
|
-
* short-lived in-bundle expand request that the settings-section card
|
|
7340
|
-
* consumes on mount, so that jump lands on the configuration already open.
|
|
7341
|
-
* EVERY step is individually guarded: a shell that doesn't match (different
|
|
7342
|
-
* layout, missing sidebar) degrades the whole jump to a silent no-op — this
|
|
7343
|
-
* path must never throw into the caller's render.
|
|
7344
|
-
*/
|
|
7345
|
-
let requestedAt = 0;
|
|
7346
|
-
/** Raise a short-lived request for the plugin's settings card to mount expanded. */
|
|
7347
|
-
function requestCardExpand(now = Date.now()) {
|
|
7348
|
-
requestedAt = now;
|
|
7349
|
-
}
|
|
7350
|
-
/** Consume the request once; true only while it is still fresh (younger than maxAgeMs). */
|
|
7351
|
-
function consumeCardExpand(now = Date.now(), maxAgeMs = 5e3) {
|
|
7352
|
-
const fresh = requestedAt > 0 && now - requestedAt < maxAgeMs;
|
|
7353
|
-
requestedAt = 0;
|
|
7354
|
-
return fresh;
|
|
7355
|
-
}
|
|
7356
|
-
/**
|
|
7357
|
-
* The shipped Plugins label in both locales — the main-panel entry's
|
|
7358
|
-
* aria-label and the settings section's nav row text are the same word.
|
|
7359
|
-
*/
|
|
7360
|
-
const PLUGIN_LABELS = /* @__PURE__ */ new Set(["Plugins", "插件"]);
|
|
7361
|
-
/** The bundle card's shipped list identity (locale-independent). */
|
|
7362
|
-
const PACKAGE_KEY = "dsh-context";
|
|
7363
|
-
/** How long the card poll follows the panel: 40 ticks at the 100ms tick, enough for the page's package load. */
|
|
7364
|
-
const POLL_TICKS = 40;
|
|
7365
|
-
/** Buttons the jump may operate on, in document order. */
|
|
7366
|
-
function buttonsOf(doc) {
|
|
7367
|
-
return [...doc.querySelectorAll("button")];
|
|
7368
|
-
}
|
|
7369
|
-
/** The Plugins main-panel entry, matched by its shipped aria-label. */
|
|
7370
|
-
function findPanelEntry(doc) {
|
|
7371
|
-
return buttonsOf(doc).find((b) => PLUGIN_LABELS.has(b.getAttribute("aria-label") ?? ""));
|
|
7372
|
-
}
|
|
7373
|
-
/**
|
|
7374
|
-
* The bundle card's open control: the one button inside the card that is not
|
|
7375
|
-
* the enable switch (the primitives switch carries `role="switch"`); the
|
|
7376
|
-
* title button's own aria-label is localized.
|
|
7377
|
-
*/
|
|
7378
|
-
function findCardOpenControl(doc) {
|
|
7379
|
-
const card = doc.querySelector(`[data-plugin-package="${PACKAGE_KEY}"]`);
|
|
7380
|
-
if (card === null) return void 0;
|
|
7381
|
-
const open = [...card.querySelectorAll("button")].filter((b) => b.getAttribute("role") !== "switch");
|
|
7382
|
-
return open.length === 1 ? open[0] : void 0;
|
|
7383
|
-
}
|
|
7384
|
-
/** The sidebar's settings triggers: dialog semantics plus an expanded flag. */
|
|
7385
|
-
function findTriggers(doc) {
|
|
7386
|
-
return buttonsOf(doc).filter((b) => b.getAttribute("aria-haspopup") === "dialog" && b.hasAttribute("aria-expanded"));
|
|
7387
|
-
}
|
|
7388
|
-
/** The Plugins section's nav row, matched by its shipped label text. */
|
|
7389
|
-
function findSectionRow(doc) {
|
|
7390
|
-
return buttonsOf(doc).find((b) => PLUGIN_LABELS.has(b.textContent.trim()));
|
|
7391
|
-
}
|
|
7392
|
-
function openPluginSettings(doc = document, schedule = (run, ms) => {
|
|
7393
|
-
window.setTimeout(run, ms);
|
|
7394
|
-
}) {
|
|
7395
|
-
try {
|
|
7396
|
-
const panel = findPanelEntry(doc);
|
|
7397
|
-
if (panel !== void 0) {
|
|
7398
|
-
panel.click();
|
|
7399
|
-
const poll = (left) => {
|
|
7400
|
-
try {
|
|
7401
|
-
const open = findCardOpenControl(doc);
|
|
7402
|
-
if (open !== void 0) {
|
|
7403
|
-
open.click();
|
|
7404
|
-
return;
|
|
7405
|
-
}
|
|
7406
|
-
} catch {}
|
|
7407
|
-
if (left > 0) schedule(() => {
|
|
7408
|
-
poll(left - 1);
|
|
7409
|
-
}, 100);
|
|
7410
|
-
};
|
|
7411
|
-
schedule(() => {
|
|
7412
|
-
poll(POLL_TICKS);
|
|
7413
|
-
}, 200);
|
|
7414
|
-
return;
|
|
7415
|
-
}
|
|
7416
|
-
const triggers = findTriggers(doc);
|
|
7417
|
-
if (triggers.find((b) => b.getAttribute("aria-expanded") === "true") === void 0 && triggers.length === 0) return;
|
|
7418
|
-
triggers.find((b) => b.getAttribute("aria-expanded") !== "true")?.click();
|
|
7419
|
-
requestCardExpand();
|
|
7420
|
-
schedule(() => {
|
|
7421
|
-
try {
|
|
7422
|
-
findSectionRow(doc)?.click();
|
|
7423
|
-
} catch {}
|
|
7424
|
-
}, 80);
|
|
7425
|
-
} catch {}
|
|
7426
|
-
}
|
|
7427
|
-
//#endregion
|
|
7428
7510
|
//#region src/client/components/settingsCard.tsx
|
|
7429
7511
|
/**
|
|
7430
7512
|
* The dsh-context preference cards — two seats over the same six rows. The
|
|
@@ -7436,7 +7518,7 @@ window.__ModuleLoader__.load({
|
|
|
7436
7518
|
* `dsh-context` namespace and render nothing while it is unavailable (a
|
|
7437
7519
|
* deployment without the Host half, or a remote browser, shows no trace).
|
|
7438
7520
|
* The settings-section card mounts expanded when the Plugin Info card's
|
|
7439
|
-
* "Open
|
|
7521
|
+
* "Open plugin settings" jump left a fresh expand request (settingsJump.ts),
|
|
7440
7522
|
* scrolling itself into view.
|
|
7441
7523
|
*/
|
|
7442
7524
|
function PrefRow(props) {
|
|
@@ -9904,7 +9986,7 @@ window.__ModuleLoader__.load({
|
|
|
9904
9986
|
return function PluginInfo() {
|
|
9905
9987
|
const [latest, setLatest] = (0, react.useState)(null);
|
|
9906
9988
|
(0, react.useEffect)(() => {
|
|
9907
|
-
if ("0.
|
|
9989
|
+
if ("0.56.0".includes("-dev")) return;
|
|
9908
9990
|
let on = true;
|
|
9909
9991
|
fetchLatestVersion().then((v) => {
|
|
9910
9992
|
if (on && v) setLatest(v);
|
|
@@ -9913,8 +9995,8 @@ window.__ModuleLoader__.load({
|
|
|
9913
9995
|
on = false;
|
|
9914
9996
|
};
|
|
9915
9997
|
}, []);
|
|
9916
|
-
const update = latest !== null && isNewerVersion(latest, "0.
|
|
9917
|
-
const nameText = "dsh-context (v0.
|
|
9998
|
+
const update = latest !== null && isNewerVersion(latest, "0.56.0") ? latest : null;
|
|
9999
|
+
const nameText = "dsh-context (v0.56.0)";
|
|
9918
10000
|
const nameValue = [nameText];
|
|
9919
10001
|
if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9920
10002
|
className: "lc-pi-update",
|
|
@@ -11704,7 +11786,7 @@ window.__ModuleLoader__.load({
|
|
|
11704
11786
|
}
|
|
11705
11787
|
//#endregion
|
|
11706
11788
|
//#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/base.css.mjs
|
|
11707
|
-
const css$14 = ".lc-root{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);padding:16px 20px 32px;font-size:13px;overflow-y:auto}[data-sidebar-right-open] .lc-root,[data-sidebar-right-float-host] .lc-root{height:auto;padding:12px;overflow:visible}.lc-title-icon{flex:none}.lc-title-label{padding-right:30px}.lc-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;margin-bottom:14px;padding:14px 16px}.lc-root .lc-card{box-sizing:border-box;margin-bottom:7px;padding:7px 8px;container:lc-card/inline-size}.lc-root .lc-cols{gap:7px;margin-bottom:7px}.lc-card-title{flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:10px;font-weight:600;display:flex}.lc-card-title-text{white-space:nowrap;flex:none}.lc-gran,.lc-kinds{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-trend-ctl{align-items:center;gap:6px;margin-left:auto;display:flex}.lc-trend-ctl .lc-gran{margin-left:0}.lc-trend-adaptive{flex:none;margin-left:0}.lc-gran-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-gran-btn:hover{color:var(--dsw-alias-label-primary)}.lc-gran-on,.lc-gran-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-kind-n{font-variant-numeric:tabular-nums;opacity:.65;margin-left:4px}.lc-gran-on .lc-kind-n{opacity:.85}.lc-tip{z-index:6;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-shadow-lv3,0 2px 8px #0000002e);pointer-events:none;opacity:0;transition:opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;padding:6px 10px;font-size:12px;position:absolute}.lc-events,.lc-fa-list{flex-direction:column;gap:2px;height:320px;display:flex;overflow-y:auto}.lc-cols{flex-wrap:wrap;gap:14px;margin-bottom:14px;display:flex}.lc-cols>.lc-card,.lc-col>.lc-card:last-child{margin-bottom:0}.lc-col-browser{flex-direction:column;display:flex}.lc-col-browser>.lc-card{flex:1}.lc-head>.lc-card:has(.lc-stats){flex-direction:column;display:flex}.lc-head .lc-stats{flex:1;align-content:stretch}.lc-head .lc-stat{justify-content:center}.lc-empty{color:var(--dsw-alias-label-secondary);text-align:center;padding:18px 0}.lc-error{flex-direction:column;align-items:center;gap:8px;padding:40px 16px;display:flex}.lc-error-msg{font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow-wrap:anywhere;border-radius:6px;max-width:100%;padding:4px 8px;font-size:12px}.lc-error-retry{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;padding:4px 14px;font-size:12px}.lc-foot{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:12px}[data-conversation-scroll]:has(.lc-root)>[data-composer-seat]:not(:has([data-approval-key],[data-question-key],[data-plan-review-key])),[data-conversation-scroll]:has(.lc-root,.lc-modal-backdrop)~[data-width-handle]{display:none}";
|
|
11789
|
+
const css$14 = ".lc-root{box-sizing:border-box;height:100%;color:var(--dsw-alias-label-primary);padding:16px 20px 32px;font-size:13px;overflow-y:auto}[data-sidebar-right-open] .lc-root,[data-sidebar-right-float-host] .lc-root{height:auto;padding:12px;overflow:visible}.lc-title-icon{flex:none}.lc-title-label{padding-right:30px}.lc-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;margin-bottom:14px;padding:14px 16px}.lc-root .lc-card{box-sizing:border-box;margin-bottom:7px;padding:7px 8px;container:lc-card/inline-size}.lc-root .lc-cols{gap:7px;margin-bottom:7px}.lc-card-title{flex-wrap:wrap;align-items:baseline;gap:8px;margin-bottom:10px;font-weight:600;display:flex}.lc-card-title-text{white-space:nowrap;flex:none}.lc-gran,.lc-kinds{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;gap:2px;margin-left:auto;padding:1px;display:flex}.lc-trend-ctl,.lc-heat-ctl{align-items:center;gap:6px;margin-left:auto;display:flex}.lc-trend-ctl .lc-gran,.lc-heat-ctl .lc-gran,.lc-heat-ctl .lc-card-sub{margin-left:0}.lc-trend-adaptive{flex:none;margin-left:0}.lc-gran-btn{color:var(--dsw-alias-label-secondary);cursor:pointer;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border:0;border-radius:5px;padding:3px 8px;font-family:inherit;font-size:11px;line-height:1}.lc-gran-btn:hover{color:var(--dsw-alias-label-primary)}.lc-gran-on,.lc-gran-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.lc-kind-n{font-variant-numeric:tabular-nums;opacity:.65;margin-left:4px}.lc-gran-on .lc-kind-n{opacity:.85}.lc-tip{z-index:6;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);width:max-content;color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-shadow-lv3,0 2px 8px #0000002e);pointer-events:none;opacity:0;transition:opacity var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;padding:6px 10px;font-size:12px;position:absolute}.lc-events,.lc-fa-list{flex-direction:column;gap:2px;height:320px;display:flex;overflow-y:auto}.lc-cols{flex-wrap:wrap;gap:14px;margin-bottom:14px;display:flex}.lc-cols>.lc-card,.lc-col>.lc-card:last-child{margin-bottom:0}.lc-col-browser{flex-direction:column;display:flex}.lc-col-browser>.lc-card{flex:1}.lc-head>.lc-card:has(.lc-stats){flex-direction:column;display:flex}.lc-head .lc-stats{flex:1;align-content:stretch}.lc-head .lc-stat{justify-content:center}.lc-empty{color:var(--dsw-alias-label-secondary);text-align:center;padding:18px 0}.lc-error{flex-direction:column;align-items:center;gap:8px;padding:40px 16px;display:flex}.lc-error-msg{font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow-wrap:anywhere;border-radius:6px;max-width:100%;padding:4px 8px;font-size:12px}.lc-error-retry{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;padding:4px 14px;font-size:12px}.lc-foot{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:12px}[data-conversation-scroll]:has(.lc-root)>[data-composer-seat]:not(:has([data-approval-key],[data-question-key],[data-plan-review-key])),[data-conversation-scroll]:has(.lc-root,.lc-modal-backdrop)~[data-width-handle]{display:none}";
|
|
11708
11790
|
const tagId$14 = "dsh-context/base.css";
|
|
11709
11791
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$14) + "]") === null) {
|
|
11710
11792
|
const tag = document.createElement("style");
|
|
@@ -11858,7 +11940,7 @@ window.__ModuleLoader__.load({
|
|
|
11858
11940
|
}
|
|
11859
11941
|
//#endregion
|
|
11860
11942
|
//#region \0dsh-global-css:/home/runner/work/dsh-context/dsh-context/src/client/styles/overview.css.mjs
|
|
11861
|
-
const css = ".lc-ov-entry{box-sizing:border-box;width:calc(100% + 4px);height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:8px;margin:0 -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.lc-ov-entry:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-ov-entry-rail{border-radius:50%;flex:none;justify-content:center;gap:0;width:36px;height:36px;margin:0;padding:0}.lc-ov-entry-icon{flex:none}.lc-ov-entry-label{text-align:left;white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;overflow:hidden}.lc-ov-backdrop{z-index:200;background:var(--dsw-alias-bg-mask-1,#00000073);justify-content:center;align-items:center;display:flex;position:fixed;inset:0;container:lc-ov/inline-size}.lc-ov-card{box-sizing:border-box;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);width:min(1120px,100vw - 32px);max-height:min(86vh,900px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);color:var(--dsw-alias-label-primary);border-radius:12px;flex-direction:column;padding:16px 18px 18px;font-size:13px;display:flex;overflow:hidden}.lc-ov-head{flex-wrap:wrap;flex:none;align-items:center;gap:10px;margin-bottom:14px;display:flex}.lc-ov-head-icon{flex:none}.lc-ov-title{white-space:nowrap;font-size:15px;font-weight:600}.lc-ov-balance{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:100%;color:inherit;border-radius:999px;flex:none;align-items:center;gap:6px;padding:2px 10px;font-size:12px;line-height:18px;text-decoration:none;display:inline-flex}.lc-ov-balance:hover .lc-ov-balance-value{text-decoration:underline}.lc-ov-balance-label{color:var(--dsw-alias-label-secondary);white-space:nowrap}.lc-ov-balance-value{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600}.lc-ov-head .lc-modal-close{flex:none;margin-left:0}.lc-ov-body{flex:auto;grid-template-columns:minmax(0,3fr) minmax(0,7fr);gap:10px;min-height:0;display:grid}.lc-ov-left{scrollbar-gutter:stable;flex-direction:column;gap:10px;min-height:0;padding-right:8px;display:flex;overflow-y:auto}.lc-ov-right{scrollbar-gutter:stable;min-height:0;padding-right:8px;overflow-y:auto}@container lc-ov (width<=932px){.lc-ov-card{overflow-y:auto}.lc-ov-body{display:block}.lc-ov-left{margin-bottom:12px}.lc-ov-left,.lc-ov-right{min-height:auto;padding-right:0;overflow:visible}.lc-ov-heat-card{flex:none}}.lc-ov-left>.lc-card{box-sizing:border-box;min-width:0;margin-bottom:0}.lc-ov-kpis{flex:none;grid-template-rows:repeat(3,1fr);grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;display:grid}.lc-ov-kpi{align-items:center;padding:10px 8px}.lc-ov-kpi .lc-stat-value{font-size:20px}.lc-ov-heat-card{flex-direction:column;flex:1 0 auto;display:flex}.lc-heat{flex:1;justify-content:center;align-items:center;gap:4px;display:flex}.lc-heat-wds,.lc-heat-col{padding-top:13px}.lc-heat-wds{flex-direction:column;gap:3px;display:flex}.lc-heat-wd{width:10px;height:20px;color:var(--dsw-alias-label-secondary);text-align:center;flex:none;justify-content:center;align-items:center;font-size:9px;display:flex}.lc-heat-cols{gap:3px;display:flex}.lc-heat-col{flex-direction:column;gap:3px;display:flex;position:relative}.lc-heat-mon{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:9px;line-height:13px;position:absolute;top:0;left:0}.lc-heat-cell{box-sizing:border-box;background:var(--dsw-alias-bg-layer-2);cursor:default;border:0;border-radius:20%;width:20px;height:20px;padding:0}button.lc-heat-cell{cursor:pointer}button.lc-heat-cell:hover{box-shadow:0 0 0 1.5px color-mix(in srgb, var(--color-blue-500) 70%, transparent)}.lc-heat-future{background:0 0}.lc-heat-0{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 16%, transparent)}.lc-heat-1{background:color-mix(in srgb, var(--color-blue-500) 28%, transparent)}.lc-heat-2{background:color-mix(in srgb, var(--color-blue-500) 50%, transparent)}.lc-heat-3{background:color-mix(in srgb, var(--color-blue-500) 72%, transparent)}.lc-heat-4{background:color-mix(in srgb, var(--color-blue-500) 92%, transparent)}.lc-heat-on{box-shadow:0 0 0 1.5px var(--color-blue-500)}.lc-ov-list-head{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.lc-ov-list-title{white-space:nowrap;font-weight:600}.lc-ov-list-count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;background:var(--dsw-alias-bg-layer-2);border-radius:8px;padding:1px 7px;font-size:11px}.lc-ov-day-chip{border:1px solid color-mix(in srgb, var(--color-blue-500) 45%, transparent);color:var(--color-blue-500);background:color-mix(in srgb, var(--color-blue-500) 10%, transparent);cursor:pointer;white-space:nowrap;border-radius:999px;padding:1px 10px;font-family:inherit;font-size:11px;line-height:1.4}.lc-ov-search{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);min-width:110px;font:inherit;color:var(--dsw-alias-label-primary);transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;outline:none;flex:150px;padding:4px 10px;font-size:12px}.lc-ov-search:focus{border-color:var(--dsw-alias-label-secondary)}.lc-ov-search::placeholder{color:var(--dsw-alias-label-secondary)}.lc-ov-groups{flex-wrap:wrap;gap:6px;margin:-2px 0 10px;display:flex}.lc-ov-chip{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;text-overflow:ellipsis;max-width:220px;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border-radius:999px;align-items:baseline;gap:5px;padding:2px 10px;font-size:11px;line-height:1.5;display:inline-flex;overflow:hidden}.lc-ov-chip:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary)}.lc-ov-chip-on,.lc-ov-chip-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:#0000}.lc-ov-chip-n{font-variant-numeric:tabular-nums;opacity:.65;font-size:10px}.lc-ov-chip-on .lc-ov-chip-n{opacity:.85}.lc-ov-grid{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:10px;display:grid}.lc-ov-session{text-align:left;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;font:inherit;color:inherit;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}.lc-ov-session:hover{border-color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.lc-ov-session-current{border-color:color-mix(in srgb, var(--color-blue-500) 65%, transparent)}.lc-ov-session-head{align-items:flex-start;gap:6px;min-width:0;display:flex}.lc-ov-running{background:var(--color-green-500);border-radius:50%;flex:none;width:7px;height:7px}.lc-ov-session-title{-webkit-line-clamp:2;overflow-wrap:anywhere;-webkit-box-orient:vertical;flex:auto;min-width:0;font-weight:600;display:-webkit-box;overflow:hidden}.lc-ov-current{color:var(--color-blue-500);border:1px solid color-mix(in srgb, var(--color-blue-500) 45%, transparent);border-radius:4px;flex:none;padding:0 4px;font-size:10px;line-height:1.5}.lc-ov-session-times{flex-direction:column;flex:none;align-items:flex-end;gap:1px;display:flex}.lc-ov-session-time{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:11px}.lc-ov-session-created{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:10px;line-height:1.4}.lc-ov-session-crumb{min-width:0;color:var(--dsw-alias-label-secondary);white-space:nowrap;align-items:center;gap:5px;font-size:11px;display:flex;overflow:hidden}.lc-ov-crumb-group{text-overflow:ellipsis;flex:none;max-width:55%;overflow:hidden}.lc-ov-crumb-sep{opacity:.55;flex:none}.lc-ov-crumb-project{text-overflow:ellipsis;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 16%, transparent);border-radius:999px;flex:0 auto;padding:0 8px;font-size:10px;line-height:1.6;overflow:hidden}.lc-ov-session-body{align-items:center;gap:14px;min-width:0;display:flex}.lc-ov-mini-stats{flex-direction:column;flex:auto;gap:3px;min-width:0;display:flex}.lc-ov-mini-stat{justify-content:space-between;align-items:baseline;gap:10px;font-size:11px;display:flex}.lc-ov-mini-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:none}.lc-ov-mini-value{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600}.lc-ov-session-empty{color:var(--dsw-alias-label-secondary);padding:6px 0;font-size:11px;line-height:1.5}.lc-ov-session-preview{border-top:1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 60%, transparent);align-items:baseline;gap:6px;min-width:0;margin-top:auto;padding-top:6px;display:flex}.lc-ov-session-preview-label{color:var(--dsw-alias-label-secondary);flex:none;font-size:10px}.lc-ov-session-preview-text{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);flex:0 auto;font-size:11px;line-height:1.5;overflow:hidden}.lc-ov-pager{justify-content:center;align-items:center;gap:10px;margin-top:12px;display:flex}.lc-ov-pager-btn{border:1px solid var(--dsw-alias-border-l2);width:26px;height:22px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border-radius:6px;flex:none;justify-content:center;align-items:center;line-height:1;display:flex}.lc-ov-pager-btn:hover:enabled{border-color:var(--dsw-alias-label-secondary)}.lc-ov-pager-btn:disabled{opacity:.4;cursor:default}.lc-ov-pager-n{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:11px}";
|
|
11943
|
+
const css = ".lc-ov-entry{box-sizing:border-box;width:calc(100% + 4px);height:42px;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:8px;margin:0 -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;display:flex;overflow:hidden}.lc-ov-entry:hover{background:var(--dsw-alias-interactive-bg-hover)}.lc-ov-entry-rail{border-radius:50%;flex:none;justify-content:center;gap:0;width:36px;height:36px;margin:0;padding:0}.lc-ov-entry-icon{flex:none}.lc-ov-entry-label{text-align:left;white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;overflow:hidden}.lc-ov-backdrop{z-index:200;background:var(--dsw-alias-bg-mask-1,#00000073);justify-content:center;align-items:center;display:flex;position:fixed;inset:0;container:lc-ov/inline-size}.lc-ov-card{box-sizing:border-box;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);width:min(1120px,100vw - 32px);height:calc(100% - 80px);box-shadow:var(--dsw-shadow-lv3,0 12px 32px #0006);color:var(--dsw-alias-label-primary);border-radius:12px;flex-direction:column;padding:16px 18px 18px;font-size:13px;display:flex;overflow:hidden}.lc-ov-head{flex-wrap:wrap;flex:none;align-items:center;gap:10px;margin-bottom:14px;display:flex}.lc-ov-head-icon{flex:none}.lc-ov-title{white-space:nowrap;font-size:15px;font-weight:600}.lc-ov-balance{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:100%;color:inherit;border-radius:999px;flex:none;align-items:center;gap:6px;padding:2px 10px;font-size:12px;line-height:18px;text-decoration:none;display:inline-flex}.lc-ov-balance:hover .lc-ov-balance-value{text-decoration:underline}.lc-ov-balance-label{color:var(--dsw-alias-label-secondary);white-space:nowrap}.lc-ov-balance-value{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600}.lc-ov-head .lc-modal-close{flex:none;margin-left:0}.lc-ov-body{flex:auto;grid-template-columns:minmax(0,3fr) minmax(0,7fr);gap:10px;min-height:0;display:grid}.lc-ov-left{scrollbar-gutter:stable;flex-direction:column;gap:10px;min-height:0;padding-right:8px;display:flex;overflow-y:auto}.lc-ov-right{scrollbar-gutter:stable;min-height:0;padding-right:8px;overflow-y:auto}@container lc-ov (width<=932px){.lc-ov-card{overflow-y:auto}.lc-ov-body{display:block}.lc-ov-left{margin-bottom:12px}.lc-ov-left,.lc-ov-right{min-height:auto;padding-right:0;overflow:visible}.lc-ov-heat-card{flex:none}}.lc-ov-left>.lc-card{box-sizing:border-box;min-width:0;margin-bottom:0}.lc-ov-kpis{flex:none;grid-template-rows:repeat(3,1fr);grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;display:grid}.lc-ov-kpi{align-items:center;padding:10px 8px}.lc-ov-kpi .lc-stat-value{font-size:20px}.lc-ov-heat-card{flex-direction:column;flex:1 0 auto;display:flex}.lc-ov-settings{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:10px;flex:none;align-items:center;gap:8px;padding:9px 12px;font-size:12px;display:flex}.lc-ov-settings:hover{border-color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}.lc-ov-settings-label{white-space:nowrap;flex:none;align-items:center;gap:6px;display:inline-flex}.lc-ov-settings-hint{text-align:right;white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;overflow:hidden}.lc-heat-wrap{flex-direction:column;flex:1;display:flex}.lc-heat{flex:1;justify-content:center;align-items:center;gap:8px;display:flex}.lc-heat-wds,.lc-heat-col{padding-top:18px}.lc-heat-wds{flex-direction:column;gap:3px;display:flex}.lc-heat-wd{height:20px;color:var(--dsw-alias-label-secondary);text-align:center;white-space:nowrap;flex:none;justify-content:center;align-items:center;font-size:9px;display:flex}.lc-heat-cols{gap:3px;display:flex}.lc-heat-col{flex-direction:column;gap:3px;display:flex;position:relative}.lc-heat-mon{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:9px;line-height:18px;position:absolute;top:0;left:0}.lc-heat-cell{box-sizing:border-box;background:var(--dsw-alias-bg-layer-2);cursor:default;border:0;border-radius:20%;width:20px;height:20px;padding:0}button.lc-heat-cell{cursor:pointer}button.lc-heat-cell:hover{box-shadow:0 0 0 1.5px color-mix(in srgb, var(--color-blue-500) 70%, transparent)}.lc-heat-future{background:0 0}.lc-heat-0{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 16%, transparent)}.lc-heat-1{background:color-mix(in srgb, var(--color-blue-500) 28%, transparent)}.lc-heat-2{background:color-mix(in srgb, var(--color-blue-500) 50%, transparent)}.lc-heat-3{background:color-mix(in srgb, var(--color-blue-500) 72%, transparent)}.lc-heat-4{background:color-mix(in srgb, var(--color-blue-500) 92%, transparent)}.lc-heat-on{box-shadow:0 0 0 1.5px var(--color-blue-500)}.lc-heat-legend{justify-content:flex-end;align-items:center;gap:3px;padding-top:6px;display:flex}.lc-heat-key{color:var(--dsw-alias-label-secondary);font-size:9px}.lc-ov-list-head{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.lc-ov-list-title{white-space:nowrap;font-weight:600}.lc-ov-list-count{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;background:var(--dsw-alias-bg-layer-2);border-radius:8px;padding:1px 7px;font-size:11px}.lc-ov-day-chip{border:1px solid color-mix(in srgb, var(--color-blue-500) 45%, transparent);color:var(--color-blue-500);background:color-mix(in srgb, var(--color-blue-500) 10%, transparent);cursor:pointer;white-space:nowrap;border-radius:999px;padding:1px 10px;font-family:inherit;font-size:11px;line-height:1.4}.lc-ov-search{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);min-width:110px;font:inherit;color:var(--dsw-alias-label-primary);transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:6px;outline:none;flex:150px;padding:4px 10px;font-size:12px}.lc-ov-search:focus{border-color:var(--dsw-alias-label-secondary)}.lc-ov-search::placeholder{color:var(--dsw-alias-label-secondary)}.lc-ov-groups{flex-wrap:wrap;gap:6px;margin:-2px 0 10px;display:flex}.lc-ov-chip{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;text-overflow:ellipsis;max-width:220px;transition:color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border-radius:999px;align-items:baseline;gap:5px;padding:2px 10px;font-size:11px;line-height:1.5;display:inline-flex;overflow:hidden}.lc-ov-chip:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary)}.lc-ov-chip-on,.lc-ov-chip-on:hover{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border-color:#0000}.lc-ov-chip-n{font-variant-numeric:tabular-nums;opacity:.65;font-size:10px}.lc-ov-chip-on .lc-ov-chip-n{opacity:.85}.lc-ov-grid{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:10px;display:grid}.lc-ov-session{text-align:left;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;font:inherit;color:inherit;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out), background-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}.lc-ov-session:hover{border-color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.lc-ov-session-current{border-color:color-mix(in srgb, var(--color-blue-500) 65%, transparent)}.lc-ov-session-head{align-items:flex-start;gap:6px;min-width:0;display:flex}.lc-ov-running{background:var(--color-green-500);border-radius:50%;flex:none;width:7px;height:7px}.lc-ov-session-title{-webkit-line-clamp:2;overflow-wrap:anywhere;-webkit-box-orient:vertical;flex:auto;min-width:0;font-weight:600;display:-webkit-box;overflow:hidden}.lc-ov-current{color:var(--color-blue-500);border:1px solid color-mix(in srgb, var(--color-blue-500) 45%, transparent);border-radius:4px;flex:none;padding:0 4px;font-size:10px;line-height:1.5}.lc-ov-session-times{flex-direction:column;flex:none;align-items:flex-end;gap:1px;display:flex}.lc-ov-session-time{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:11px}.lc-ov-session-created{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:10px;line-height:1.4}.lc-ov-session-crumb{min-width:0;color:var(--dsw-alias-label-secondary);white-space:nowrap;align-items:center;gap:5px;font-size:11px;display:flex;overflow:hidden}.lc-ov-crumb-group{text-overflow:ellipsis;flex:none;max-width:55%;overflow:hidden}.lc-ov-crumb-sep{opacity:.55;flex:none}.lc-ov-crumb-project{text-overflow:ellipsis;min-width:0;font-family:var(--ds-font-family-code,ui-monospace, SFMono-Regular, Menlo, monospace);color:var(--dsw-alias-label-primary);background:color-mix(in srgb, var(--dsw-alias-label-secondary) 16%, transparent);border-radius:999px;flex:0 auto;padding:0 8px;font-size:10px;line-height:1.6;overflow:hidden}.lc-ov-session-body{align-items:center;gap:14px;min-width:0;display:flex}.lc-ov-mini-stats{flex-direction:column;flex:auto;gap:3px;min-width:0;display:flex}.lc-ov-mini-stat{justify-content:space-between;align-items:baseline;gap:10px;font-size:11px;display:flex}.lc-ov-mini-label{color:var(--dsw-alias-label-secondary);white-space:nowrap;flex:none}.lc-ov-mini-value{font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600}.lc-ov-session-empty{color:var(--dsw-alias-label-secondary);padding:6px 0;font-size:11px;line-height:1.5}.lc-ov-session-preview{border-top:1px solid color-mix(in srgb, var(--dsw-alias-border-l2) 60%, transparent);align-items:baseline;gap:6px;min-width:0;margin-top:auto;padding-top:6px;display:flex}.lc-ov-session-preview-label{color:var(--dsw-alias-label-secondary);flex:none;font-size:10px}.lc-ov-session-preview-text{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary);flex:0 auto;font-size:11px;line-height:1.5;overflow:hidden}.lc-ov-pager{justify-content:center;align-items:center;gap:10px;margin-top:12px;display:flex}.lc-ov-pager-btn{border:1px solid var(--dsw-alias-border-l2);width:26px;height:22px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;transition:border-color var(--ds-transition-duration,.2s) var(--ds-ease-in-out,ease-in-out);background:0 0;border-radius:6px;flex:none;justify-content:center;align-items:center;line-height:1;display:flex}.lc-ov-pager-btn:hover:enabled{border-color:var(--dsw-alias-label-secondary)}.lc-ov-pager-btn:disabled{opacity:.4;cursor:default}.lc-ov-pager-n{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:11px}";
|
|
11862
11944
|
const tagId = "dsh-context/overview.css";
|
|
11863
11945
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
11864
11946
|
const tag = document.createElement("style");
|