@dan-ai-studio/dshopencodego 0.1.80 → 0.1.82
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.en.md +1 -1
- package/README.md +1 -1
- package/lib/client.js +110 -5
- package/lib/index.js +1 -1
- package/lib/types/request-log/store.d.ts +13 -0
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -144,7 +144,7 @@ The API key comes from the Harness credential store (reference name `OPENCODE_GO
|
|
|
144
144
|
- **Two entries, one page**:
|
|
145
145
|
- **A sidebar icon → a full page in the main column**: every request across sessions. The log is a process-wide thing, so the sidebar is where it belongs — a fixed, always-visible spot, and the same pattern the Harness's own plugin manager uses.
|
|
146
146
|
- **A "Request log" View inside the conversation**: this session's requests, in place — answering "why was that turn slow" without leaving the chat.
|
|
147
|
-
- It is a page, not a floating card: the head, the summary (requests / failures / mean latency / mean first token / mean tok/s / mean cache hit / connection reuse) and the filters stay put while the table scrolls. Each row carries time, model, session, input/output/cache, **cache hit**, **tok/s**, first token, latency and status; clicking one expands its HTTP detail (method, protocol, URL, body size, **preparation**, redacted headers, request shape, result and usage, reasoning split, cache writes, per-request cost, content span). **Preparation** is the local time from request start to the HTTP send — large means the slowness is local (cold catalog / images / history conversion); small with a large first token means the gateway / model side is slow. Filters: model, result, slow requests, session; groups: session, model, result; **click a column head to sort by it**, click again to flip.
|
|
147
|
+
- It is a page, not a floating card: the head, the summary (requests / failures / mean latency / mean first token / mean tok/s / mean cache hit / connection reuse) and the filters stay put while the table scrolls. Each row carries time, model, session, input/output/cache, **cache hit**, **tok/s**, first token, latency and status; clicking one expands its HTTP detail (first a **request timeline** — preparation → waiting for first token → streaming, plus the end tick, with per-segment milliseconds in the legend; then method, protocol, URL, body size, **preparation**, redacted headers, request shape, result and usage, reasoning split, cache writes, per-request cost, content span). **Preparation** is the local time from request start to the HTTP send — large means the slowness is local (cold catalog / images / history conversion); small with a large first token means the gateway / model side is slow. A dedicated sortable `Prep` column sits next to first token. Filters: model, result, slow requests, session; groups: session, model, result; **click a column head to sort by it**, click again to flip.
|
|
148
148
|
- **tok/s** is the output rate over the decode window (first token to the end), on the same scale as the Harness's own per-turn reading (reasoning tokens included). A request that produced no token has no rate — none is invented. **A burst delivery has no rate either**: when the gateway holds a whole turn and flushes it at the end (common with reasoning models: 8 seconds of thinking invisible on the wire, then a hundred tokens in a few milliseconds), a sub-100ms content span is delivery shape, not generation speed — it shows as — and stays out of the mean.
|
|
149
149
|
- The session column names the **session title** (from the session catalog; falls back to the id, whose full spelling stays one hover away). The session filter matches titles and ids; session groups are headed the same way. **Clicking a title opens that session** (an archived one refuses, and says so).
|
|
150
150
|
- **Cache hit** is the share of input tokens served from cache (cache reads over uncached input plus cache reads). No reported input means no share — none is invented either.
|
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
143
143
|
- **两个入口,同一个页面**:
|
|
144
144
|
- **侧边栏图标 → 主区域整页**:跨会话看全部请求。日志是进程级的数据,放在侧边栏最合理——位置固定、常驻可见,和 DSH 自己的插件管理器同一个范式。
|
|
145
145
|
- **会话里的「请求日志」标签页**:就地看**本会话**的请求,回答"刚才那轮为什么慢"不用离开对话。
|
|
146
|
-
- 页面是一整页而不是浮层:标题、统计(请求数/失败数/平均耗时/平均首字/平均 tok/s/平均缓存命中/连接复用率)、筛选栏固定在上方,只有表格自己滚动。每行含时间、模型、会话、输入/输出/缓存、**缓存命中**、**tok/s**、首字、耗时与状态;点一行展开 HTTP
|
|
146
|
+
- 页面是一整页而不是浮层:标题、统计(请求数/失败数/平均耗时/平均首字/平均 tok/s/平均缓存命中/连接复用率)、筛选栏固定在上方,只有表格自己滚动。每行含时间、模型、会话、输入/输出/缓存、**缓存命中**、**tok/s**、首字、耗时与状态;点一行展开 HTTP 明细(第一行是**请求时间线**:准备 → 等待首字 → 输出三段加结束刻度,图例带每段毫秒数;方法、协议、地址、请求体大小、**准备耗时**、脱敏后的请求头、请求构成、结果与用量、推理拆分、缓存写入、单轮花费、内容跨度)。**准备耗时**是从请求开始到 HTTP 发出的本地耗时——它大是本地(目录冷启动/图片/历史转换)慢,它小但首字大是网关/模型侧慢;另有独立的 `准备` 列可点击排序。筛选有模型/结果/慢请求/会话,分组有会话/模型/结果;**点列头按该列排序**,再点一次反向。
|
|
147
147
|
- **tok/s** 是**首字到结束**这段解码窗口上的输出速率,口径与 Harness 自己的每轮读数一致(含推理 token)。没有 token 的请求没有速率——不编数。**突发推送同样没有速率**:网关把一整轮攒到最后一次性推过来时(推理模型常见:8 秒思考在 wire 上不可见,然后上百个 token 几毫秒内到达),内容跨度不足 100ms,算出来的"每秒几万 token"不是生成速度——显示为 —,也不计入平均。
|
|
148
148
|
- 会话列显示**会话标题**(标题来自会话目录;拿不到时回退显示 id,悬停可见完整 id)。会话筛选同时匹配标题与 id;按会话分组的组头同样显示标题。**点标题直接打开那个会话**(归档的打不开,会明说)。
|
|
149
149
|
- **缓存命中**是输入 token 里走缓存的占比(缓存读取/(未缓存输入+缓存读取))。网关没报输入就没有占比——同样不编数。
|
package/lib/client.js
CHANGED
|
@@ -565,6 +565,11 @@ var en = {
|
|
|
565
565
|
requestLogColCacheRate: "Cache hit",
|
|
566
566
|
requestLogColLatency: "Latency",
|
|
567
567
|
requestLogColTps: "tok/s",
|
|
568
|
+
requestLogColPrep: "Prep",
|
|
569
|
+
requestLogColWait: "Wait",
|
|
570
|
+
requestLogTimelineWait: "Waiting for first token",
|
|
571
|
+
requestLogTimelineStream: "Streaming",
|
|
572
|
+
requestLogTimelineBurst: "Delivered in one burst",
|
|
568
573
|
requestLogColStream: "Content span",
|
|
569
574
|
requestLogColFirstToken: "First token",
|
|
570
575
|
requestLogColStatus: "Status",
|
|
@@ -765,6 +770,11 @@ var zh = {
|
|
|
765
770
|
requestLogColCacheRate: "\u7F13\u5B58\u547D\u4E2D",
|
|
766
771
|
requestLogColLatency: "\u8017\u65F6",
|
|
767
772
|
requestLogColTps: "tok/s",
|
|
773
|
+
requestLogColPrep: "\u51C6\u5907",
|
|
774
|
+
requestLogColWait: "\u7B49\u5F85",
|
|
775
|
+
requestLogTimelineWait: "\u7B49\u5F85\u9996\u5B57",
|
|
776
|
+
requestLogTimelineStream: "\u8F93\u51FA\u4E2D",
|
|
777
|
+
requestLogTimelineBurst: "\u6574\u8F6E\u4E00\u6B21\u9001\u8FBE",
|
|
768
778
|
requestLogColStream: "\u5185\u5BB9\u8DE8\u5EA6",
|
|
769
779
|
requestLogColFirstToken: "\u9996\u5B57",
|
|
770
780
|
requestLogColStatus: "\u72B6\u6001",
|
|
@@ -2142,16 +2152,19 @@ function Section({ controller, t, getLocale, openRequestLog }) {
|
|
|
2142
2152
|
var import_react2 = require("react");
|
|
2143
2153
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
2144
2154
|
|
|
2155
|
+
// src/request-log/store.ts
|
|
2156
|
+
var MIN_STREAM_MS_FOR_RATE = 100;
|
|
2157
|
+
|
|
2145
2158
|
// plugin-css:/home/runner/work/dshopencodego/dshopencodego/src/client/request-log.module.css
|
|
2146
2159
|
var id2 = "@dan-ai-studio/dshopencodego/request-log.module.css";
|
|
2147
2160
|
if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]")) {
|
|
2148
2161
|
const style = document.createElement("style");
|
|
2149
2162
|
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
2150
2163
|
style.dataset.pluginCss = id2;
|
|
2151
|
-
style.textContent = ".Lx7MOq_page{box-sizing:border-box;background:var(--dsw-alias-bg-base);height:100%;min-height:0;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex}.Lx7MOq_pageLoose{height:auto}.Lx7MOq_pageLoose .Lx7MOq_tableWrap{overflow:visible}.Lx7MOq_pageLoose .Lx7MOq_stuck{z-index:3;background:var(--dsw-alias-bg-base);position:sticky;top:0}.Lx7MOq_pageLoose .Lx7MOq_table th{top:var(--request-log-stuck,0px)}.Lx7MOq_pageLoose .Lx7MOq_foot{z-index:2;background:var(--dsw-alias-bg-base);position:sticky;bottom:0}.Lx7MOq_head{flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:20px clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_headText{min-width:0}.Lx7MOq_title{margin:0;font-size:20px;font-weight:500;line-height:28px}.Lx7MOq_subtitle{color:var(--dsw-alias-label-secondary);margin:4px 0 0;font-size:13px;line-height:20px}.Lx7MOq_headActions{flex:none;align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_button{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;align-items:center;gap:6px;padding:0 12px;font-size:13px;display:inline-flex}.Lx7MOq_button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_button:disabled{cursor:default;opacity:.5}.Lx7MOq_summary{flex-wrap:wrap;flex:none;gap:8px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_card{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex-direction:column;gap:2px;min-width:104px;padding:8px 12px;display:flex}.Lx7MOq_cardLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.Lx7MOq_cardValue{font-variant-numeric:tabular-nums;font-size:16px;font-weight:500;line-height:22px}.Lx7MOq_cardError .Lx7MOq_cardValue{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_cardWarn .Lx7MOq_cardValue{color:var(--dsw-alias-state-warn-primary)}.Lx7MOq_toolbar{flex-wrap:wrap;flex:none;align-items:center;gap:8px 12px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_field{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:13px;line-height:20px;display:inline-flex}.Lx7MOq_select,.Lx7MOq_input{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;padding:0 8px;font-size:13px}.Lx7MOq_input{width:160px}.Lx7MOq_inputNumber{width:72px}.Lx7MOq_checkbox{accent-color:var(--dsw-alias-brand-primary)}.Lx7MOq_sessionLink{color:var(--dsw-alias-link);font:inherit;text-align:left;cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0}.Lx7MOq_sessionLink:hover{text-decoration:underline}.Lx7MOq_sessionText{text-overflow:ellipsis;vertical-align:bottom;max-width:340px;display:inline-block;overflow:hidden}.Lx7MOq_modelText{text-overflow:ellipsis;vertical-align:bottom;max-width:220px;display:inline-block;overflow:hidden}.Lx7MOq_tableWrap{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex:1;min-height:0;margin:0 clamp(16px,3vw,32px);overflow:auto}.Lx7MOq_table{border-collapse:separate;border-spacing:0;width:100%;min-width:940px;font-size:13px;line-height:20px}.Lx7MOq_table th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);text-align:left;white-space:nowrap;padding:8px 10px;font-size:12px;font-weight:500;position:sticky;top:0}.Lx7MOq_thSortable{cursor:pointer;user-select:none}.Lx7MOq_thSortable:hover{color:var(--dsw-alias-label-primary)}.Lx7MOq_table td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:nowrap;font-variant-numeric:tabular-nums;padding:6px 10px}.Lx7MOq_table tbody tr:last-child td{border-bottom:none}.Lx7MOq_row{cursor:pointer}.Lx7MOq_row:hover td{background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_rowOk td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-border-l3)}.Lx7MOq_rowSlow td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-warn-primary)}.Lx7MOq_rowFail td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-error-primary)}.Lx7MOq_rowRunning td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-brand-primary)}.Lx7MOq_rowFail td:last-child,.Lx7MOq_rowSlow td:last-child{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_group td{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);padding-top:12px;font-weight:500}.Lx7MOq_detail td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:normal;background:var(--dsw-alias-bg-layer-2);padding:12px 10px 16px}.Lx7MOq_detailGrid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:6px 24px;display:grid}.Lx7MOq_detailItem{gap:8px;min-width:0;font-size:13px;line-height:20px;display:flex}.Lx7MOq_detailLabel{color:var(--dsw-alias-label-tertiary);flex:none}.Lx7MOq_detailValue{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary)}.Lx7MOq_mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.Lx7MOq_empty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:48px 16px}.Lx7MOq_foot{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:12px clamp(16px,3vw,32px) 20px;font-size:12px;display:flex}.Lx7MOq_pager{align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_notice{color:var(--dsw-alias-label-secondary);padding:0 clamp(16px,3vw,32px) 12px;font-size:13px;line-height:20px}.Lx7MOq_noticeError{color:var(--dsw-alias-state-error-primary)}";
|
|
2164
|
+
style.textContent = ".Lx7MOq_page{box-sizing:border-box;background:var(--dsw-alias-bg-base);height:100%;min-height:0;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex}.Lx7MOq_pageLoose{height:auto}.Lx7MOq_pageLoose .Lx7MOq_tableWrap{overflow:visible}.Lx7MOq_pageLoose .Lx7MOq_stuck{z-index:3;background:var(--dsw-alias-bg-base);position:sticky;top:0}.Lx7MOq_pageLoose .Lx7MOq_table th{top:var(--request-log-stuck,0px)}.Lx7MOq_pageLoose .Lx7MOq_foot{z-index:2;background:var(--dsw-alias-bg-base);position:sticky;bottom:0}.Lx7MOq_head{flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:20px clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_headText{min-width:0}.Lx7MOq_title{margin:0;font-size:20px;font-weight:500;line-height:28px}.Lx7MOq_subtitle{color:var(--dsw-alias-label-secondary);margin:4px 0 0;font-size:13px;line-height:20px}.Lx7MOq_headActions{flex:none;align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_button{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;align-items:center;gap:6px;padding:0 12px;font-size:13px;display:inline-flex}.Lx7MOq_button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_button:disabled{cursor:default;opacity:.5}.Lx7MOq_summary{flex-wrap:wrap;flex:none;gap:8px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_card{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex-direction:column;gap:2px;min-width:104px;padding:8px 12px;display:flex}.Lx7MOq_cardLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:16px}.Lx7MOq_cardValue{font-variant-numeric:tabular-nums;font-size:16px;font-weight:500;line-height:22px}.Lx7MOq_cardError .Lx7MOq_cardValue{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_cardWarn .Lx7MOq_cardValue{color:var(--dsw-alias-state-warn-primary)}.Lx7MOq_toolbar{flex-wrap:wrap;flex:none;align-items:center;gap:8px 12px;padding:0 clamp(16px,3vw,32px) 12px;display:flex}.Lx7MOq_field{color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;font-size:13px;line-height:20px;display:inline-flex}.Lx7MOq_select,.Lx7MOq_input{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-bg-layer-1);height:28px;color:var(--dsw-alias-label-primary);font:inherit;padding:0 8px;font-size:13px}.Lx7MOq_input{width:160px}.Lx7MOq_inputNumber{width:72px}.Lx7MOq_checkbox{accent-color:var(--dsw-alias-brand-primary)}.Lx7MOq_sessionLink{color:var(--dsw-alias-link);font:inherit;text-align:left;cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:0}.Lx7MOq_sessionLink:hover{text-decoration:underline}.Lx7MOq_sessionText{text-overflow:ellipsis;vertical-align:bottom;max-width:340px;display:inline-block;overflow:hidden}.Lx7MOq_modelText{text-overflow:ellipsis;vertical-align:bottom;max-width:220px;display:inline-block;overflow:hidden}.Lx7MOq_tableWrap{border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);flex:1;min-height:0;margin:0 clamp(16px,3vw,32px);overflow:auto}.Lx7MOq_table{border-collapse:separate;border-spacing:0;width:100%;min-width:940px;font-size:13px;line-height:20px}.Lx7MOq_table th{z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);text-align:left;white-space:nowrap;padding:8px 10px;font-size:12px;font-weight:500;position:sticky;top:0}.Lx7MOq_thSortable{cursor:pointer;user-select:none}.Lx7MOq_thSortable:hover{color:var(--dsw-alias-label-primary)}.Lx7MOq_table td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:nowrap;font-variant-numeric:tabular-nums;padding:6px 10px}.Lx7MOq_table tbody tr:last-child td{border-bottom:none}.Lx7MOq_row{cursor:pointer}.Lx7MOq_row:hover td{background:var(--dsw-alias-interactive-bg-hover)}.Lx7MOq_rowOk td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-border-l3)}.Lx7MOq_rowSlow td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-warn-primary)}.Lx7MOq_rowFail td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-state-error-primary)}.Lx7MOq_rowRunning td:first-child{box-shadow:inset 3px 0 0 var(--dsw-alias-brand-primary)}.Lx7MOq_rowFail td:last-child,.Lx7MOq_rowSlow td:last-child{color:var(--dsw-alias-state-error-primary)}.Lx7MOq_group td{border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);padding-top:12px;font-weight:500}.Lx7MOq_detail td{border-bottom:1px solid var(--dsw-alias-border-l1);white-space:normal;background:var(--dsw-alias-bg-layer-2);padding:12px 10px 16px}.Lx7MOq_detailGrid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:6px 24px;display:grid}.Lx7MOq_timeline{flex-direction:column;grid-column:1/-1;gap:6px;padding:4px 0 8px;display:flex}.Lx7MOq_timelineTrackWrap{padding-bottom:18px;position:relative}.Lx7MOq_timelineTrack{background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:10px;position:relative;overflow:hidden}.Lx7MOq_timelineMidTick{background:var(--dsw-alias-label-tertiary);opacity:.7;width:1px;position:absolute;top:0;bottom:0;left:50%}.Lx7MOq_timelineMid{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;line-height:16px;position:absolute;top:100%;transform:translate(-50%)}.Lx7MOq_timelineSeg{min-width:2px;position:absolute;top:0;bottom:0}.Lx7MOq_timelinePrep{background:var(--dsw-alias-brand-primary)}.Lx7MOq_timelineWait{background:var(--dsw-alias-state-warn-primary)}.Lx7MOq_timelineStream{background:var(--dsw-alias-brand-primary);opacity:.45}.Lx7MOq_timelineTick{background:var(--dsw-alias-label-primary);width:2px;margin-left:-2px;position:absolute;top:-2px;bottom:-2px;left:100%}.Lx7MOq_timelineLegend{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex-wrap:wrap;gap:4px 16px;font-size:12px;display:flex}.Lx7MOq_timelineItem{white-space:nowrap;align-items:center;gap:6px;display:inline-flex}.Lx7MOq_timelineSwatch{border-radius:2px;width:8px;height:8px}.Lx7MOq_timelineTickSwatch{background:var(--dsw-alias-label-primary)}.Lx7MOq_detailItem{gap:8px;min-width:0;font-size:13px;line-height:20px;display:flex}.Lx7MOq_detailLabel{color:var(--dsw-alias-label-tertiary);flex:none}.Lx7MOq_detailValue{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-primary)}.Lx7MOq_mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.Lx7MOq_empty{text-align:center;color:var(--dsw-alias-label-tertiary);padding:48px 16px}.Lx7MOq_foot{color:var(--dsw-alias-label-tertiary);flex-wrap:wrap;flex:none;align-items:center;gap:12px;padding:12px clamp(16px,3vw,32px) 20px;font-size:12px;display:flex}.Lx7MOq_pager{align-items:center;gap:8px;margin-left:auto;display:flex}.Lx7MOq_notice{color:var(--dsw-alias-label-secondary);padding:0 clamp(16px,3vw,32px) 12px;font-size:13px;line-height:20px}.Lx7MOq_noticeError{color:var(--dsw-alias-state-error-primary)}";
|
|
2152
2165
|
document.head.appendChild(style);
|
|
2153
2166
|
}
|
|
2154
|
-
var request_log_default = { "button": "Lx7MOq_button", "card": "Lx7MOq_card", "cardError": "Lx7MOq_cardError", "cardLabel": "Lx7MOq_cardLabel", "cardValue": "Lx7MOq_cardValue", "cardWarn": "Lx7MOq_cardWarn", "checkbox": "Lx7MOq_checkbox", "detail": "Lx7MOq_detail", "detailGrid": "Lx7MOq_detailGrid", "detailItem": "Lx7MOq_detailItem", "detailLabel": "Lx7MOq_detailLabel", "detailValue": "Lx7MOq_detailValue", "empty": "Lx7MOq_empty", "field": "Lx7MOq_field", "foot": "Lx7MOq_foot", "group": "Lx7MOq_group", "head": "Lx7MOq_head", "headActions": "Lx7MOq_headActions", "headText": "Lx7MOq_headText", "input": "Lx7MOq_input", "inputNumber": "Lx7MOq_inputNumber", "modelText": "Lx7MOq_modelText", "mono": "Lx7MOq_mono", "notice": "Lx7MOq_notice", "noticeError": "Lx7MOq_noticeError", "page": "Lx7MOq_page", "pageLoose": "Lx7MOq_pageLoose", "pager": "Lx7MOq_pager", "row": "Lx7MOq_row", "rowFail": "Lx7MOq_rowFail", "rowOk": "Lx7MOq_rowOk", "rowRunning": "Lx7MOq_rowRunning", "rowSlow": "Lx7MOq_rowSlow", "select": "Lx7MOq_select", "sessionLink": "Lx7MOq_sessionLink", "sessionText": "Lx7MOq_sessionText", "stuck": "Lx7MOq_stuck", "subtitle": "Lx7MOq_subtitle", "summary": "Lx7MOq_summary", "table": "Lx7MOq_table", "tableWrap": "Lx7MOq_tableWrap", "thSortable": "Lx7MOq_thSortable", "title": "Lx7MOq_title", "toolbar": "Lx7MOq_toolbar" };
|
|
2167
|
+
var request_log_default = { "button": "Lx7MOq_button", "card": "Lx7MOq_card", "cardError": "Lx7MOq_cardError", "cardLabel": "Lx7MOq_cardLabel", "cardValue": "Lx7MOq_cardValue", "cardWarn": "Lx7MOq_cardWarn", "checkbox": "Lx7MOq_checkbox", "detail": "Lx7MOq_detail", "detailGrid": "Lx7MOq_detailGrid", "detailItem": "Lx7MOq_detailItem", "detailLabel": "Lx7MOq_detailLabel", "detailValue": "Lx7MOq_detailValue", "empty": "Lx7MOq_empty", "field": "Lx7MOq_field", "foot": "Lx7MOq_foot", "group": "Lx7MOq_group", "head": "Lx7MOq_head", "headActions": "Lx7MOq_headActions", "headText": "Lx7MOq_headText", "input": "Lx7MOq_input", "inputNumber": "Lx7MOq_inputNumber", "modelText": "Lx7MOq_modelText", "mono": "Lx7MOq_mono", "notice": "Lx7MOq_notice", "noticeError": "Lx7MOq_noticeError", "page": "Lx7MOq_page", "pageLoose": "Lx7MOq_pageLoose", "pager": "Lx7MOq_pager", "row": "Lx7MOq_row", "rowFail": "Lx7MOq_rowFail", "rowOk": "Lx7MOq_rowOk", "rowRunning": "Lx7MOq_rowRunning", "rowSlow": "Lx7MOq_rowSlow", "select": "Lx7MOq_select", "sessionLink": "Lx7MOq_sessionLink", "sessionText": "Lx7MOq_sessionText", "stuck": "Lx7MOq_stuck", "subtitle": "Lx7MOq_subtitle", "summary": "Lx7MOq_summary", "table": "Lx7MOq_table", "tableWrap": "Lx7MOq_tableWrap", "thSortable": "Lx7MOq_thSortable", "timeline": "Lx7MOq_timeline", "timelineItem": "Lx7MOq_timelineItem", "timelineLegend": "Lx7MOq_timelineLegend", "timelineMid": "Lx7MOq_timelineMid", "timelineMidTick": "Lx7MOq_timelineMidTick", "timelinePrep": "Lx7MOq_timelinePrep", "timelineSeg": "Lx7MOq_timelineSeg", "timelineStream": "Lx7MOq_timelineStream", "timelineSwatch": "Lx7MOq_timelineSwatch", "timelineTick": "Lx7MOq_timelineTick", "timelineTickSwatch": "Lx7MOq_timelineTickSwatch", "timelineTrack": "Lx7MOq_timelineTrack", "timelineTrackWrap": "Lx7MOq_timelineTrackWrap", "timelineWait": "Lx7MOq_timelineWait", "title": "Lx7MOq_title", "toolbar": "Lx7MOq_toolbar" };
|
|
2155
2168
|
|
|
2156
2169
|
// src/client/RequestLogPage.tsx
|
|
2157
2170
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -2164,6 +2177,8 @@ var SORT_DEFAULT_DIR = {
|
|
|
2164
2177
|
cacheReadTokens: "desc",
|
|
2165
2178
|
cacheRate: "desc",
|
|
2166
2179
|
tps: "desc",
|
|
2180
|
+
prepMs: "desc",
|
|
2181
|
+
waitMs: "desc",
|
|
2167
2182
|
firstTokenMs: "desc",
|
|
2168
2183
|
durationMs: "desc",
|
|
2169
2184
|
status: "asc"
|
|
@@ -2186,6 +2201,10 @@ function sortValue(entry, key) {
|
|
|
2186
2201
|
return cacheRate(entry) ?? -1;
|
|
2187
2202
|
case "tps":
|
|
2188
2203
|
return entry.tps ?? -1;
|
|
2204
|
+
case "prepMs":
|
|
2205
|
+
return entry.prepMs ?? -1;
|
|
2206
|
+
case "waitMs":
|
|
2207
|
+
return waitMs(entry) ?? -1;
|
|
2189
2208
|
case "firstTokenMs":
|
|
2190
2209
|
return entry.firstTokenMs ?? -1;
|
|
2191
2210
|
case "durationMs":
|
|
@@ -2226,9 +2245,46 @@ function cacheRate(entry) {
|
|
|
2226
2245
|
const total = entry.inputTokens + cached;
|
|
2227
2246
|
return total > 0 ? cached / total : void 0;
|
|
2228
2247
|
}
|
|
2248
|
+
function timelineOf(entry, t) {
|
|
2249
|
+
const running = entry.running === true;
|
|
2250
|
+
const end = entry.durationMs ?? (running ? Math.max(0, Date.now() - entry.atMs) : void 0);
|
|
2251
|
+
if (end === void 0 || end <= 0) return void 0;
|
|
2252
|
+
const prep = entry.prepMs;
|
|
2253
|
+
const first = entry.firstTokenMs;
|
|
2254
|
+
if (prep === void 0 && first === void 0) return void 0;
|
|
2255
|
+
const start = prep ?? 0;
|
|
2256
|
+
const slices = [];
|
|
2257
|
+
if (prep !== void 0 && prep > 0) {
|
|
2258
|
+
slices.push({ kind: "prep", label: t("requestLogDetailPrep"), from: 0, to: Math.min(prep, end) });
|
|
2259
|
+
}
|
|
2260
|
+
if (first !== void 0) {
|
|
2261
|
+
if (first > start) {
|
|
2262
|
+
slices.push({
|
|
2263
|
+
kind: "wait",
|
|
2264
|
+
label: t("requestLogTimelineWait"),
|
|
2265
|
+
from: Math.min(start, end),
|
|
2266
|
+
to: Math.min(first, end)
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
if (entry.streamMs !== void 0 && entry.streamMs > 0) {
|
|
2270
|
+
const last = Math.min(first + entry.streamMs, end);
|
|
2271
|
+
if (last > first) slices.push({ kind: "stream", label: t("requestLogTimelineStream"), from: first, to: last });
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
if (slices.length === 0) return void 0;
|
|
2275
|
+
return {
|
|
2276
|
+
slices,
|
|
2277
|
+
end,
|
|
2278
|
+
burst: !running && first !== void 0 && (entry.streamMs === void 0 || entry.streamMs < MIN_STREAM_MS_FOR_RATE)
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2229
2281
|
function percent(value) {
|
|
2230
2282
|
return value === void 0 ? "\u2014" : `${(value * 100).toFixed(0)}%`;
|
|
2231
2283
|
}
|
|
2284
|
+
function waitMs(entry) {
|
|
2285
|
+
if (entry.firstTokenMs === void 0) return void 0;
|
|
2286
|
+
return Math.max(0, entry.firstTokenMs - (entry.prepMs ?? 0));
|
|
2287
|
+
}
|
|
2232
2288
|
function average(values) {
|
|
2233
2289
|
if (values.length === 0) return void 0;
|
|
2234
2290
|
let sum = 0;
|
|
@@ -2317,7 +2373,7 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
|
|
|
2317
2373
|
if (!hasRunning) return;
|
|
2318
2374
|
const timer = setInterval(() => {
|
|
2319
2375
|
void load();
|
|
2320
|
-
},
|
|
2376
|
+
}, 2e3);
|
|
2321
2377
|
return () => {
|
|
2322
2378
|
clearInterval(timer);
|
|
2323
2379
|
};
|
|
@@ -2378,7 +2434,7 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
|
|
|
2378
2434
|
if (group !== void 0 && group !== lastGroup) {
|
|
2379
2435
|
lastGroup = group;
|
|
2380
2436
|
out.push(
|
|
2381
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.group, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan:
|
|
2437
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.group, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 13, children: groupBy === "session" ? sessionLabel(group).text : groupBy === "result" ? resultGroupLabel(group) : group }) }, `group-${group}-${entry.seq}`)
|
|
2382
2438
|
);
|
|
2383
2439
|
}
|
|
2384
2440
|
const state = entry.running === true ? "rowRunning" : !entry.ok ? "rowFail" : entry.tps !== void 0 && entry.tps < 5 ? "rowSlow" : "rowOk";
|
|
@@ -2418,6 +2474,8 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
|
|
|
2418
2474
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: count2(entry.cacheReadTokens) }),
|
|
2419
2475
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: percent(cacheRate(entry)) }),
|
|
2420
2476
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: rate2(entry.tps) }),
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.prepMs) }),
|
|
2478
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(waitMs(entry)) }),
|
|
2421
2479
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.firstTokenMs) }),
|
|
2422
2480
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: entry.running === true ? duration(Math.max(0, Date.now() - entry.atMs)) : duration(entry.durationMs) }),
|
|
2423
2481
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: entry.running === true ? `${t("requestLogRunning")} \xB7 ${duration(Math.max(0, Date.now() - entry.atMs))}` : entry.ok ? entry.status === void 0 ? "\u2713" : String(entry.status) : entry.code ?? "\u2717" })
|
|
@@ -2428,7 +2486,52 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
|
|
|
2428
2486
|
);
|
|
2429
2487
|
if (expanded === entry.seq) {
|
|
2430
2488
|
out.push(
|
|
2431
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.detail, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan:
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.detail, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 13, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailGrid, children: [
|
|
2490
|
+
(() => {
|
|
2491
|
+
const timeline = timelineOf(entry, t);
|
|
2492
|
+
if (timeline === void 0) return null;
|
|
2493
|
+
const kindClass = (kind) => kind === "prep" ? request_log_default.timelinePrep : kind === "wait" ? request_log_default.timelineWait : request_log_default.timelineStream;
|
|
2494
|
+
const spoken = [
|
|
2495
|
+
...timeline.slices.map((slice) => `${slice.label} ${duration(slice.to - slice.from)}`),
|
|
2496
|
+
`${t("requestLogColLatency")} ${duration(timeline.end)}`
|
|
2497
|
+
].join(", ");
|
|
2498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timeline, role: "img", "aria-label": spoken, children: [
|
|
2499
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timelineTrackWrap, children: [
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timelineTrack, children: [
|
|
2501
|
+
timeline.slices.map((slice) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2502
|
+
"div",
|
|
2503
|
+
{
|
|
2504
|
+
className: `${request_log_default.timelineSeg} ${kindClass(slice.kind)}`,
|
|
2505
|
+
style: {
|
|
2506
|
+
left: `${(slice.from / timeline.end * 100).toFixed(2)}%`,
|
|
2507
|
+
width: `${Math.max(0, (slice.to - slice.from) / timeline.end * 100).toFixed(2)}%`
|
|
2508
|
+
},
|
|
2509
|
+
title: `${slice.label} ${duration(slice.to - slice.from)}`
|
|
2510
|
+
},
|
|
2511
|
+
slice.kind
|
|
2512
|
+
)),
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.timelineMidTick }),
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.timelineTick, title: duration(timeline.end) })
|
|
2515
|
+
] }),
|
|
2516
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.timelineMid, title: duration(timeline.end / 2), children: duration(timeline.end / 2) })
|
|
2517
|
+
] }),
|
|
2518
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timelineLegend, children: [
|
|
2519
|
+
timeline.slices.map((slice) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.timelineItem, children: [
|
|
2520
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.timelineSwatch} ${kindClass(slice.kind)}` }),
|
|
2521
|
+
slice.label,
|
|
2522
|
+
" ",
|
|
2523
|
+
duration(slice.to - slice.from)
|
|
2524
|
+
] }, slice.kind)),
|
|
2525
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.timelineItem, children: [
|
|
2526
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.timelineSwatch} ${request_log_default.timelineTickSwatch}` }),
|
|
2527
|
+
t("requestLogColLatency"),
|
|
2528
|
+
" ",
|
|
2529
|
+
duration(timeline.end)
|
|
2530
|
+
] }),
|
|
2531
|
+
timeline.burst && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.timelineItem, children: t("requestLogTimelineBurst") })
|
|
2532
|
+
] })
|
|
2533
|
+
] });
|
|
2534
|
+
})(),
|
|
2432
2535
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailItem, children: [
|
|
2433
2536
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: request_log_default.detailLabel, children: t("requestLogDetailMethod") }),
|
|
2434
2537
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${request_log_default.detailValue} ${request_log_default.mono}`, children: entry.method })
|
|
@@ -2698,6 +2801,8 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
|
|
|
2698
2801
|
head("cacheReadTokens", t("requestLogColCache"), t("requestLogColCacheHint")),
|
|
2699
2802
|
head("cacheRate", t("requestLogColCacheRate")),
|
|
2700
2803
|
head("tps", t("requestLogColTps")),
|
|
2804
|
+
head("prepMs", t("requestLogColPrep")),
|
|
2805
|
+
head("waitMs", t("requestLogColWait")),
|
|
2701
2806
|
head("firstTokenMs", t("requestLogColFirstToken")),
|
|
2702
2807
|
head("durationMs", t("requestLogColLatency")),
|
|
2703
2808
|
head("status", t("requestLogColStatus"))
|
package/lib/index.js
CHANGED
|
@@ -78134,7 +78134,7 @@ function createUpdateChecker(deps) {
|
|
|
78134
78134
|
}
|
|
78135
78135
|
|
|
78136
78136
|
// src/update/version.ts
|
|
78137
|
-
var PLUGIN_VERSION = true ? "0.1.
|
|
78137
|
+
var PLUGIN_VERSION = true ? "0.1.82" : "0.0.0-dev";
|
|
78138
78138
|
|
|
78139
78139
|
// src/update/service.ts
|
|
78140
78140
|
import { TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
|
|
@@ -175,6 +175,19 @@ export interface RequestLogGates {
|
|
|
175
175
|
/** How many entries to keep; the ring trims to it on every append. */
|
|
176
176
|
readonly maxEntries: () => number;
|
|
177
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Minimum content span for a meaningful rate, in milliseconds.
|
|
180
|
+
*
|
|
181
|
+
* A rate needs a window, and a sub-100ms arrival spread is delivery shape,
|
|
182
|
+
* not generation speed: wall-clock timers resolve to a millisecond, one
|
|
183
|
+
* network flush fans its events out across several event-loop turns, and no
|
|
184
|
+
* served LLM sustains thousands of tokens per second. Below this line the
|
|
185
|
+
* tokens arrived in one burst — the reply's speed on the wire is unknown,
|
|
186
|
+
* so no rate is reported rather than a fabricated one. The viewer reuses
|
|
187
|
+
* the same line to name that shape instead of leaving the missing output
|
|
188
|
+
* slice unexplained.
|
|
189
|
+
*/
|
|
190
|
+
export declare const MIN_STREAM_MS_FOR_RATE = 100;
|
|
178
191
|
/**
|
|
179
192
|
* An in-flight request, handed back only when the log is enabled.
|
|
180
193
|
*
|
package/package.json
CHANGED