dsh-brief-sidebar 0.9.5 → 0.9.6

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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-brief-sidebar",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "main": "./lib/index.mjs",
5
5
  "description": "会话简报侧栏页(brief):把会话的 todo 列表(`todos` 投影的进展看板)、产物列表(`dshSummaryDeliverables` 投影的实时产出文件)与记忆槽位(`memorySlots` 投影,来自 dsh-prime-memory,开关可关)一起渲染成右侧栏的一个「概要」tab,并遮蔽 DSH 官方那条 composer 上方的 todo 面板。只读展示,不做写回。",
6
6
  "engines": {
package/lib/client.js CHANGED
@@ -253,7 +253,7 @@ window.__ModuleLoader__.load({
253
253
  display: "flex",
254
254
  flexDirection: "column"
255
255
  };
256
- const ROW_STYLE$6 = {
256
+ const ROW_STYLE$5 = {
257
257
  display: "flex",
258
258
  alignItems: "flex-start",
259
259
  gap: 8,
@@ -305,7 +305,7 @@ window.__ModuleLoader__.load({
305
305
  /** One task row. */
306
306
  function TodoRow(props) {
307
307
  const { item, t } = props;
308
- return (0, react.createElement)("li", { style: ROW_STYLE$6 }, (0, react.createElement)("span", { style: pillStyle(item.status) }, t(statusKey(item.status))), (0, react.createElement)("span", { style: contentStyle(item.status) }, item.content));
308
+ return (0, react.createElement)("li", { style: ROW_STYLE$5 }, (0, react.createElement)("span", { style: pillStyle(item.status) }, t(statusKey(item.status))), (0, react.createElement)("span", { style: contentStyle(item.status) }, item.content));
309
309
  }
310
310
  /**
311
311
  * The progress section. The subscription is unconditional (a plain listener,
@@ -1363,7 +1363,7 @@ window.__ModuleLoader__.load({
1363
1363
  display: "flex",
1364
1364
  flexDirection: "column"
1365
1365
  };
1366
- const ROW_STYLE$5 = {
1366
+ const ROW_STYLE$4 = {
1367
1367
  display: "flex",
1368
1368
  alignItems: "flex-start",
1369
1369
  gap: 8,
@@ -1409,11 +1409,11 @@ window.__ModuleLoader__.load({
1409
1409
  const title = plan === null ? path : `${t("deliverable.codeplanTag")}: ${plan.task} · ${path}`;
1410
1410
  const label = basename(path);
1411
1411
  const content = plan === null ? null : (0, react.createElement)("span", { style: TAG_STYLE$2 }, t("deliverable.codeplanTag"));
1412
- if (open === void 0) return (0, react.createElement)("li", { style: ROW_STYLE$5 }, content, (0, react.createElement)("span", {
1412
+ if (open === void 0) return (0, react.createElement)("li", { style: ROW_STYLE$4 }, content, (0, react.createElement)("span", {
1413
1413
  style: PATH_STYLE,
1414
1414
  title
1415
1415
  }, label));
1416
- return (0, react.createElement)("li", { style: ROW_STYLE$5 }, content, (0, react.createElement)("button", {
1416
+ return (0, react.createElement)("li", { style: ROW_STYLE$4 }, content, (0, react.createElement)("button", {
1417
1417
  style: BUTTON_STYLE,
1418
1418
  title,
1419
1419
  onClick: () => {
@@ -2004,7 +2004,7 @@ window.__ModuleLoader__.load({
2004
2004
  display: "flex",
2005
2005
  flexDirection: "column"
2006
2006
  };
2007
- const ROW_STYLE$4 = {
2007
+ const ROW_STYLE$3 = {
2008
2008
  display: "flex",
2009
2009
  alignItems: "baseline",
2010
2010
  gap: 8,
@@ -2072,7 +2072,7 @@ window.__ModuleLoader__.load({
2072
2072
  marker: "skill-usage-invoked-group"
2073
2073
  }), (0, react.createElement)("ul", { style: LIST_STYLE$3 }, view.session.map((entry) => (0, react.createElement)("li", {
2074
2074
  key: entry.name,
2075
- style: ROW_STYLE$4,
2075
+ style: ROW_STYLE$3,
2076
2076
  "data-dsh-brief-sidebar": "skill-usage-row"
2077
2077
  }, (0, react.createElement)("span", { style: NAME_STYLE$1 }, entry.name), (0, react.createElement)("span", { style: COUNT_STYLE }, expandPair(t("skillUsage.uses"), entry.count, entry.count)), latestNames.includes(entry.name) && (0, react.createElement)("span", { style: TAG_STYLE$1 }, t("skillUsage.latestTag"))))), rest.length > 0 && (0, react.createElement)(FoldToggle, {
2078
2078
  label: expandCount(t("skillUsage.availableGroup"), rest.length),
@@ -2086,7 +2086,7 @@ window.__ModuleLoader__.load({
2086
2086
  marker: "skill-usage-available-capped"
2087
2087
  }), availableOpen && (0, react.createElement)("ul", { style: LIST_STYLE$3 }, rest.map((name) => (0, react.createElement)("li", {
2088
2088
  key: name,
2089
- style: ROW_STYLE$4,
2089
+ style: ROW_STYLE$3,
2090
2090
  "data-dsh-brief-sidebar": "skill-usage-available-row"
2091
2091
  }, (0, react.createElement)("span", { style: NAME_STYLE$1 }, name)))), view.session.length > 0 && (0, react.createElement)("div", { style: FOOTER_STYLE$3 }, expandPair(t("skillUsage.count"), view.callTotal, view.sessionTotal)));
2092
2092
  }
@@ -2096,15 +2096,19 @@ window.__ModuleLoader__.load({
2096
2096
  * The search-reference section: the `dshSummarySearchRefs` projection drawn as
2097
2097
  * one tab of the references section.
2098
2098
  *
2099
- * It answers "what did this session pull in from outside": the queries it ran
2100
- * — via the harness's `web_search` or the user's own `advanced_search` — and the
2101
- * sources those searches returned. Each query row carries its tool name, because
2102
- * which of the two answered is a fact the reader asks about. Two groups, because
2103
- * they are two different facts — a query says what was asked, a source says what
2104
- * came back, and an older `dsh-free-search` without `presentationMeta` produces
2105
- * queries with no sources at all. That degraded case is stated rather than
2106
- * hidden, because an empty source list would otherwise read as "the search found
2107
- * nothing".
2099
+ * It answers "what did this session pull in from outside", and it answers it the
2100
+ * way the conversation to its left does: **one left-aligned bubble per source**,
2101
+ * title as a link, host and provider snippet under it. No group headers, no list
2102
+ * of query titles — that wall duplicated what the transcript already shows, and a
2103
+ * reader who opens this tab is looking for the results, not for a restatement of
2104
+ * the questions.
2105
+ *
2106
+ * The fold still records which query and which tool (`web_search` or the user's
2107
+ * own `advanced_search`) surfaced each source; that data stays in the frame for
2108
+ * any surface that wants it, it is just no longer drawn here. An older
2109
+ * `dsh-free-search` without `presentationMeta` yields queries with no sources —
2110
+ * that degraded case is stated (`searchRefs.noSourcesHint`) rather than left as
2111
+ * an empty pane, because an empty list reads as "the search found nothing".
2108
2112
  *
2109
2113
  * Optional on both sides: no registry, or a host half that never registered the
2110
2114
  * unit, means the client reads capability absence and the section hides.
@@ -2130,31 +2134,45 @@ window.__ModuleLoader__.load({
2130
2134
  const LIST_STYLE$2 = {
2131
2135
  listStyle: "none",
2132
2136
  margin: 0,
2133
- padding: "6px 0",
2134
- display: "flex",
2135
- flexDirection: "column"
2136
- };
2137
- const ROW_STYLE$3 = {
2137
+ padding: "8px 12px 10px",
2138
2138
  display: "flex",
2139
+ flexDirection: "column",
2139
2140
  alignItems: "flex-start",
2140
- gap: 8,
2141
- padding: "6px 12px"
2141
+ gap: 8
2142
2142
  };
2143
- const QUERY_STYLE = {
2143
+ /**
2144
+ * One result, drawn as a chat bubble: left-aligned, background-filled, rounded,
2145
+ * and narrower than the column. The reader reads this tab the way they read the
2146
+ * conversation to its left — each bubble is one thing the session pulled in — so
2147
+ * the list chrome (row rules, group headers, per-query title lines) is dropped
2148
+ * rather than restyled.
2149
+ *
2150
+ * `alignItems: flex-start` on the list is what keeps bubbles hugging the left
2151
+ * edge; without it a flex child stretches to the full column and the bubble
2152
+ * reads as a plain card.
2153
+ */
2154
+ const BUBBLE_STYLE$1 = {
2155
+ maxWidth: "92%",
2156
+ padding: "8px 10px",
2157
+ borderRadius: 10,
2158
+ background: "var(--dsw-alias-bg-layer-3)",
2159
+ border: "1px solid var(--dsw-alias-border-l2)",
2160
+ color: "var(--dsw-alias-label-primary)",
2161
+ fontSize: 12,
2162
+ lineHeight: "17px",
2144
2163
  minWidth: 0,
2145
- flex: "1 1 auto",
2146
- overflowWrap: "anywhere",
2147
- color: "var(--dsw-alias-label-secondary)"
2164
+ display: "flex",
2165
+ flexDirection: "column",
2166
+ gap: 2
2148
2167
  };
2149
- /** The source title, one line: the host and URL carry the identification. */
2168
+ /** The source title, up to three lines: inside a bubble it IS the content. */
2150
2169
  const TITLE_STYLE$2 = {
2151
2170
  minWidth: 0,
2152
- flex: "1 1 auto",
2171
+ overflowWrap: "anywhere",
2153
2172
  display: "-webkit-box",
2154
- WebkitLineClamp: 2,
2173
+ WebkitLineClamp: 3,
2155
2174
  WebkitBoxOrient: "vertical",
2156
- overflow: "hidden",
2157
- color: "var(--dsw-alias-label-secondary)"
2175
+ overflow: "hidden"
2158
2176
  };
2159
2177
  const SNIPPET_STYLE = {
2160
2178
  margin: 0,
@@ -2164,12 +2182,19 @@ window.__ModuleLoader__.load({
2164
2182
  fontSize: 11,
2165
2183
  lineHeight: "16px"
2166
2184
  };
2167
- const META_STYLE$2 = {
2168
- flexShrink: 0,
2185
+ const HOST_STYLE = {
2169
2186
  color: "var(--dsw-alias-label-tertiary)",
2170
2187
  fontSize: 11,
2171
- lineHeight: "18px",
2172
- whiteSpace: "nowrap"
2188
+ lineHeight: "16px",
2189
+ overflowWrap: "anywhere"
2190
+ };
2191
+ /** The bubble's own footer strip — where the "本轮" pill lives now. */
2192
+ const BUBBLE_FOOT_STYLE = {
2193
+ display: "flex",
2194
+ alignItems: "center",
2195
+ gap: 6,
2196
+ marginTop: 2,
2197
+ minWidth: 0
2173
2198
  };
2174
2199
  /** The "本轮" pill: same form as the skill tag, tertiary emphasis. */
2175
2200
  const TAG_STYLE = {
@@ -2214,52 +2239,29 @@ window.__ModuleLoader__.load({
2214
2239
  color: "var(--dsw-alias-label-secondary)"
2215
2240
  } }, t("searchRefs.empty")), (0, react.createElement)("div", null, t("searchRefs.emptyHint"))));
2216
2241
  const body = [];
2217
- if (view.queries.length > 0) {
2218
- body.push((0, react.createElement)(GroupHeader, {
2219
- key: "qh",
2220
- text: expandCount(t("searchRefs.queryGroup"), view.queries.length),
2221
- marker: "search-refs-query-group"
2222
- }));
2223
- body.push((0, react.createElement)("ul", {
2224
- key: "ql",
2225
- style: LIST_STYLE$2
2226
- }, view.queries.map((row) => (0, react.createElement)("li", {
2227
- key: `${row.turn}:${row.query}`,
2228
- style: ROW_STYLE$3,
2229
- "data-dsh-brief-sidebar": "search-refs-query"
2230
- }, (0, react.createElement)("span", { style: QUERY_STYLE }, row.query), (0, react.createElement)("span", { style: TAG_STYLE }, row.tool), (0, react.createElement)("span", { style: META_STYLE$2 }, expandCount(t("searchRefs.hits"), row.hits))))));
2231
- }
2232
- if (view.sources.length > 0) {
2233
- body.push((0, react.createElement)(GroupHeader, {
2234
- key: "sh",
2235
- text: expandCount(t("searchRefs.sourceGroup"), view.sources.length),
2236
- marker: "search-refs-source-group"
2237
- }));
2238
- body.push((0, react.createElement)("ul", {
2239
- key: "sl",
2240
- style: LIST_STYLE$2
2241
- }, view.sources.map((item) => {
2242
- const href = safeHref(item.url);
2243
- const label = item.title ?? item.url;
2244
- const link = href === void 0 ? (0, react.createElement)("span", { style: TITLE_STYLE$2 }, label) : (0, react.createElement)("a", {
2245
- style: TITLE_STYLE$2,
2246
- href,
2247
- target: "_blank",
2248
- rel: "noreferrer noopener"
2249
- }, label);
2250
- return (0, react.createElement)("li", {
2251
- key: item.url,
2252
- style: ROW_STYLE$3,
2253
- "data-dsh-brief-sidebar": "search-refs-source"
2254
- }, (0, react.createElement)("div", { style: {
2255
- minWidth: 0,
2256
- flex: "1 1 auto",
2257
- display: "flex",
2258
- flexDirection: "column",
2259
- gap: 2
2260
- } }, link, (0, react.createElement)("span", { style: META_STYLE$2 }, item.host), item.snippet !== void 0 && (0, react.createElement)("p", { style: SNIPPET_STYLE }, item.snippet)), isLatestSource(view, item.url) && (0, react.createElement)("span", { style: TAG_STYLE }, t("searchRefs.latestTag")));
2261
- })));
2262
- } else body.push((0, react.createElement)("div", {
2242
+ if (view.sources.length > 0) body.push((0, react.createElement)("ul", {
2243
+ key: "sl",
2244
+ style: LIST_STYLE$2
2245
+ }, view.sources.map((item) => {
2246
+ const href = safeHref(item.url);
2247
+ const label = item.title ?? item.url;
2248
+ const link = href === void 0 ? (0, react.createElement)("span", { style: TITLE_STYLE$2 }, label) : (0, react.createElement)("a", {
2249
+ style: TITLE_STYLE$2,
2250
+ href,
2251
+ target: "_blank",
2252
+ rel: "noreferrer noopener"
2253
+ }, label);
2254
+ const latest = isLatestSource(view, item.url);
2255
+ return (0, react.createElement)("li", {
2256
+ key: item.url,
2257
+ style: { minWidth: 0 },
2258
+ "data-dsh-brief-sidebar": "search-refs-source"
2259
+ }, (0, react.createElement)("div", {
2260
+ style: BUBBLE_STYLE$1,
2261
+ "data-dsh-brief-sidebar": "search-refs-bubble"
2262
+ }, link, (0, react.createElement)("span", { style: HOST_STYLE }, item.host), item.snippet !== void 0 && (0, react.createElement)("p", { style: SNIPPET_STYLE }, item.snippet), (latest || item.count > 1) && (0, react.createElement)("div", { style: BUBBLE_FOOT_STYLE }, latest && (0, react.createElement)("span", { style: TAG_STYLE }, t("searchRefs.latestTag")), item.count > 1 && (0, react.createElement)("span", { style: HOST_STYLE }, `\u00d7${item.count}`))));
2263
+ })));
2264
+ else body.push((0, react.createElement)("div", {
2263
2265
  key: "ns",
2264
2266
  style: FOOTER_STYLE$2,
2265
2267
  "data-dsh-brief-sidebar": "search-refs-no-sources"