@dan-ai-studio/dshopencodego 0.1.87 → 0.1.88

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/lib/client.js CHANGED
@@ -209,6 +209,7 @@ var networkRemote = {
209
209
  };
210
210
 
211
211
  // src/request-log/store.ts
212
+ var MAX_TOOL_CALLS = 32;
212
213
  var MAX_STREAM_MARKS = 200;
213
214
  var MIN_STREAM_MS_FOR_RATE = 100;
214
215
 
@@ -239,6 +240,7 @@ function parseEntry(value) {
239
240
  const shape = row["shape"];
240
241
  const headers = row["headers"];
241
242
  const protocol = row["protocol"];
243
+ const toolCalls = row["toolCalls"] === void 0 ? void 0 : parseToolCalls(row["toolCalls"]);
242
244
  return {
243
245
  seq: count("seq", row),
244
246
  atMs: count("atMs", row),
@@ -266,6 +268,10 @@ function parseEntry(value) {
266
268
  ...row["decodeMs"] === void 0 ? {} : { decodeMs: count("decodeMs", row) },
267
269
  ...row["streamMs"] === void 0 ? {} : { streamMs: count("streamMs", row) },
268
270
  ...row["tps"] === void 0 ? {} : { tps: rate("tps", row) },
271
+ ...toolCalls === void 0 || toolCalls.length === 0 ? {} : { toolCalls },
272
+ ...row["estimatedInputTokens"] === void 0 ? {} : { estimatedInputTokens: count("estimatedInputTokens", row) },
273
+ ...row["fittedMaxTokens"] === void 0 ? {} : { fittedMaxTokens: count("fittedMaxTokens", row) },
274
+ ...row["maxTokensClamped"] === true ? { maxTokensClamped: true } : {},
269
275
  // Running rows cross the wire too: a viewer opened mid-request must
270
276
  // see them. Older snapshots predate the flag and read as finished.
271
277
  ...row["running"] === true ? { running: true } : {},
@@ -303,6 +309,20 @@ function rate(key, row) {
303
309
  }
304
310
  return entry;
305
311
  }
312
+ function parseToolCalls(value) {
313
+ if (!Array.isArray(value)) return [];
314
+ const kept = [];
315
+ for (const item of value) {
316
+ if (kept.length >= MAX_TOOL_CALLS) break;
317
+ if (item === null || typeof item !== "object") continue;
318
+ const row = item;
319
+ if (typeof row["name"] !== "string" || row["name"].length === 0) continue;
320
+ const callCount = row["count"];
321
+ if (typeof callCount !== "number" || !Number.isInteger(callCount) || callCount < 1) continue;
322
+ kept.push({ name: row["name"], count: callCount });
323
+ }
324
+ return kept;
325
+ }
306
326
  function parsePoolEvent(value) {
307
327
  if (value === null || typeof value !== "object") throw new Error("invalid request-log pool event");
308
328
  const row = value;
@@ -589,6 +609,12 @@ var en = {
589
609
  requestLogTimelineBurst: "Delivered in one burst",
590
610
  requestLogColStream: "Content span",
591
611
  requestLogColFirstToken: "First token",
612
+ requestLogColPhase: "Phase",
613
+ requestLogColPhaseHint: "Share of time by phase: prep / wait / stream",
614
+ requestLogColTools: "Tools",
615
+ requestLogColToolsHint: "Tools this request actually invoked, with call counts",
616
+ requestLogColContext: "Context",
617
+ requestLogColContextHint: "Estimated input before send and the fitted output cap; an arrow marks a clamped request",
592
618
  requestLogColStatus: "Status",
593
619
  requestLogDetailRequest: "Request",
594
620
  requestLogDetailTiming: "Timing",
@@ -794,6 +820,12 @@ var zh = {
794
820
  requestLogTimelineBurst: "\u6574\u8F6E\u4E00\u6B21\u9001\u8FBE",
795
821
  requestLogColStream: "\u5185\u5BB9\u8DE8\u5EA6",
796
822
  requestLogColFirstToken: "\u9996\u5B57",
823
+ requestLogColPhase: "\u9636\u6BB5",
824
+ requestLogColPhaseHint: "\u5404\u9636\u6BB5\u8017\u65F6\u5360\u6BD4\uFF1A\u51C6\u5907 / \u7B49\u5F85 / \u8F93\u51FA",
825
+ requestLogColTools: "\u5DE5\u5177",
826
+ requestLogColToolsHint: "\u672C\u8F6E\u5B9E\u9645\u8C03\u7528\u7684\u5DE5\u5177\u53CA\u6B21\u6570",
827
+ requestLogColContext: "\u4E0A\u4E0B\u6587",
828
+ requestLogColContextHint: "\u53D1\u9001\u524D\u4F30\u7B97\u7684\u8F93\u5165\u4E0E\u88C5\u914D\u540E\u7684\u8F93\u51FA\u4E0A\u9650\uFF0C\u7BAD\u5934\u8868\u793A\u88AB\u6536\u7F29\u8FC7",
797
829
  requestLogColStatus: "\u72B6\u6001",
798
830
  requestLogDetailRequest: "\u8BF7\u6C42",
799
831
  requestLogDetailTiming: "\u8017\u65F6",
@@ -2213,10 +2245,10 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
2213
2245
  const style = document.createElement("style");
2214
2246
  style.dataset.plugin = "@dan-ai-studio/dshopencodego";
2215
2247
  style.dataset.pluginCss = id2;
2216
- 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:1px solid var(--dsw-alias-border-l1);border-radius:999px;height:12px;position:relative}.Lx7MOq_timelineMidTick{background:var(--dsw-alias-label-tertiary);opacity:.7;width:1px;position:absolute;top:2px;bottom:2px;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{border-radius:4px;min-width:2px;position:absolute;top:2px;bottom:2px}.Lx7MOq_timelinePrep{background:var(--dsw-alias-state-idle-primary)}.Lx7MOq_timelineWait{background:var(--dsw-alias-state-warn-primary)}.Lx7MOq_timelineStream{background:var(--dsw-alias-state-success-primary);opacity:.45}.Lx7MOq_timelineStreamAlt{background:var(--dsw-alias-state-success-primary);opacity:.95}.Lx7MOq_timelineLive{background-image:linear-gradient(100deg,#0000 30%,#ffffff80 50%,#0000 70%);background-size:200% 100%;animation:1.6s linear infinite Lx7MOq_timelineShimmer}@keyframes Lx7MOq_timelineShimmer{0%{background-position:200% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){.Lx7MOq_timelineLive{animation:none}}.Lx7MOq_timelineRespTick{background:var(--dsw-alias-label-primary);width:2px;box-shadow:0 0 6px var(--dsw-alias-label-primary);border-radius:2px;position:absolute;top:-3px;bottom:-3px}.Lx7MOq_timelineTick{background:var(--dsw-alias-label-primary);border-radius:2px;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;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:999px;align-items:center;gap:6px;padding:2px 10px;display:inline-flex}.Lx7MOq_timelineSwatch{border-radius:50%;width:8px;height:8px}.Lx7MOq_timelineSwatchPrep{background:var(--dsw-alias-state-idle-primary)}.Lx7MOq_timelineSwatchWait{background:var(--dsw-alias-state-warn-primary)}.Lx7MOq_timelineSwatchStream{background:var(--dsw-alias-state-success-primary)}.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{width:88px;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)}";
2248
+ 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:1px solid var(--dsw-alias-border-l1);border-radius:999px;height:12px;position:relative}.Lx7MOq_timelineMidTick{background:var(--dsw-alias-label-tertiary);opacity:.7;width:1px;position:absolute;top:2px;bottom:2px;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{border-radius:4px;min-width:2px;position:absolute;top:2px;bottom:2px}.Lx7MOq_timelinePrep{background:var(--dsw-alias-state-idle-primary)}.Lx7MOq_timelineWait{background:var(--dsw-alias-state-warn-primary)}.Lx7MOq_timelineStream{background:var(--dsw-alias-state-success-primary);opacity:.45}.Lx7MOq_timelineStreamAlt{background:var(--dsw-alias-state-success-primary);opacity:.95}.Lx7MOq_timelineLive{background-image:linear-gradient(100deg,#0000 30%,#ffffff80 50%,#0000 70%);background-size:200% 100%;animation:1.6s linear infinite Lx7MOq_timelineShimmer}@keyframes Lx7MOq_timelineShimmer{0%{background-position:200% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){.Lx7MOq_timelineLive{animation:none}}.Lx7MOq_timelineRespTick{background:var(--dsw-alias-label-primary);width:2px;box-shadow:0 0 6px var(--dsw-alias-label-primary);border-radius:2px;position:absolute;top:-3px;bottom:-3px}.Lx7MOq_timelineTick{background:var(--dsw-alias-label-primary);border-radius:2px;width:2px;margin-left:-2px;position:absolute;top:-2px;bottom:-2px;left:100%}.Lx7MOq_phaseBar{background:var(--dsw-alias-bg-layer-1);border-radius:999px;min-width:110px;height:8px;position:relative}.Lx7MOq_phaseBar .Lx7MOq_timelineSeg{border-radius:3px;top:1px;bottom:1px}.Lx7MOq_phaseBar .Lx7MOq_timelineRespTick{top:-2px;bottom:-2px}.Lx7MOq_toolChips{flex-wrap:wrap;gap:4px;max-width:220px;display:inline-flex}.Lx7MOq_toolChip{white-space:nowrap;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:999px;align-items:center;gap:4px;padding:0 8px;font-size:12px;display:inline-flex}.Lx7MOq_toolChipCount{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums}.Lx7MOq_toolChipMore{white-space:nowrap;color:var(--dsw-alias-label-secondary);border:1px dashed var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;border-radius:999px;align-items:center;padding:0 8px;font-size:12px;display:inline-flex}.Lx7MOq_fitClamped{color:var(--dsw-alias-state-warn-primary)}.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;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:999px;align-items:center;gap:6px;padding:2px 10px;display:inline-flex}.Lx7MOq_timelineSwatch{border-radius:50%;width:8px;height:8px}.Lx7MOq_timelineSwatchPrep{background:var(--dsw-alias-state-idle-primary)}.Lx7MOq_timelineSwatchWait{background:var(--dsw-alias-state-warn-primary)}.Lx7MOq_timelineSwatchStream{background:var(--dsw-alias-state-success-primary)}.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{width:88px;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)}";
2217
2249
  document.head.appendChild(style);
2218
2250
  }
2219
- 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", "timelineLive": "Lx7MOq_timelineLive", "timelineMid": "Lx7MOq_timelineMid", "timelineMidTick": "Lx7MOq_timelineMidTick", "timelinePrep": "Lx7MOq_timelinePrep", "timelineRespTick": "Lx7MOq_timelineRespTick", "timelineSeg": "Lx7MOq_timelineSeg", "timelineShimmer": "Lx7MOq_timelineShimmer", "timelineStream": "Lx7MOq_timelineStream", "timelineStreamAlt": "Lx7MOq_timelineStreamAlt", "timelineSwatch": "Lx7MOq_timelineSwatch", "timelineSwatchPrep": "Lx7MOq_timelineSwatchPrep", "timelineSwatchStream": "Lx7MOq_timelineSwatchStream", "timelineSwatchWait": "Lx7MOq_timelineSwatchWait", "timelineTick": "Lx7MOq_timelineTick", "timelineTickSwatch": "Lx7MOq_timelineTickSwatch", "timelineTrack": "Lx7MOq_timelineTrack", "timelineTrackWrap": "Lx7MOq_timelineTrackWrap", "timelineWait": "Lx7MOq_timelineWait", "title": "Lx7MOq_title", "toolbar": "Lx7MOq_toolbar" };
2251
+ 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", "fitClamped": "Lx7MOq_fitClamped", "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", "phaseBar": "Lx7MOq_phaseBar", "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", "timelineLive": "Lx7MOq_timelineLive", "timelineMid": "Lx7MOq_timelineMid", "timelineMidTick": "Lx7MOq_timelineMidTick", "timelinePrep": "Lx7MOq_timelinePrep", "timelineRespTick": "Lx7MOq_timelineRespTick", "timelineSeg": "Lx7MOq_timelineSeg", "timelineShimmer": "Lx7MOq_timelineShimmer", "timelineStream": "Lx7MOq_timelineStream", "timelineStreamAlt": "Lx7MOq_timelineStreamAlt", "timelineSwatch": "Lx7MOq_timelineSwatch", "timelineSwatchPrep": "Lx7MOq_timelineSwatchPrep", "timelineSwatchStream": "Lx7MOq_timelineSwatchStream", "timelineSwatchWait": "Lx7MOq_timelineSwatchWait", "timelineTick": "Lx7MOq_timelineTick", "timelineTickSwatch": "Lx7MOq_timelineTickSwatch", "timelineTrack": "Lx7MOq_timelineTrack", "timelineTrackWrap": "Lx7MOq_timelineTrackWrap", "timelineWait": "Lx7MOq_timelineWait", "title": "Lx7MOq_title", "toolChip": "Lx7MOq_toolChip", "toolChipCount": "Lx7MOq_toolChipCount", "toolChipMore": "Lx7MOq_toolChipMore", "toolChips": "Lx7MOq_toolChips", "toolbar": "Lx7MOq_toolbar" };
2220
2252
 
2221
2253
  // src/client/RequestLogPage.tsx
2222
2254
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -2232,6 +2264,7 @@ var SORT_DEFAULT_DIR = {
2232
2264
  prepMs: "desc",
2233
2265
  waitMs: "desc",
2234
2266
  firstTokenMs: "desc",
2267
+ estimatedInputTokens: "desc",
2235
2268
  durationMs: "desc",
2236
2269
  status: "asc"
2237
2270
  };
@@ -2259,6 +2292,8 @@ function sortValue(entry, key) {
2259
2292
  return waitMs(entry) ?? -1;
2260
2293
  case "firstTokenMs":
2261
2294
  return entry.firstTokenMs ?? -1;
2295
+ case "estimatedInputTokens":
2296
+ return entry.estimatedInputTokens ?? -1;
2262
2297
  case "durationMs":
2263
2298
  return entry.durationMs ?? -1;
2264
2299
  case "status":
@@ -2497,6 +2532,97 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2497
2532
  label,
2498
2533
  sortKey === key ? sortDir === "asc" ? " \u25B2" : " \u25BC" : ""
2499
2534
  ] });
2535
+ const plainHead = (label, hint) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { title: hint, children: label });
2536
+ const kindClass = (kind) => kind === "prep" ? request_log_default.timelinePrep : kind === "wait" ? request_log_default.timelineWait : kind === "stream" ? request_log_default.timelineStream : request_log_default.timelineStreamAlt;
2537
+ const phaseSummary = (timeline) => {
2538
+ const totals = /* @__PURE__ */ new Map();
2539
+ const order = [];
2540
+ for (const block of timeline.blocks) {
2541
+ const key = block.kind === "streamAlt" ? "stream" : block.kind;
2542
+ const known = totals.get(key);
2543
+ if (known === void 0) {
2544
+ totals.set(key, { label: block.label, total: block.to - block.from });
2545
+ order.push(key);
2546
+ } else {
2547
+ known.total += block.to - block.from;
2548
+ }
2549
+ }
2550
+ const parts = [];
2551
+ for (const key of order) {
2552
+ const group = totals.get(key);
2553
+ if (group !== void 0) parts.push(`${group.label} ${duration(group.total)}`);
2554
+ }
2555
+ if (timeline.responseAt !== void 0) {
2556
+ parts.push(`${t("requestLogTimelineFirstByte")} ${duration(timeline.responseAt)}`);
2557
+ }
2558
+ return parts.join(", ");
2559
+ };
2560
+ const phaseBlocks = (timeline, live) => {
2561
+ const percent2 = (at) => `${(at / timeline.end * 100).toFixed(2)}%`;
2562
+ const liveIndex = live ? timeline.blocks.findLastIndex((block) => block.kind === "stream" || block.kind === "streamAlt") : -1;
2563
+ const out = timeline.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2564
+ "div",
2565
+ {
2566
+ className: `${request_log_default.timelineSeg} ${kindClass(block.kind)}${index === liveIndex ? ` ${request_log_default.timelineLive}` : ""}`,
2567
+ style: {
2568
+ left: percent2(block.from),
2569
+ width: percent2(Math.max(0, block.to - block.from))
2570
+ },
2571
+ title: `${block.label} ${duration(block.to - block.from)}`
2572
+ },
2573
+ `${block.kind}-${index}`
2574
+ ));
2575
+ if (timeline.responseAt !== void 0) {
2576
+ out.push(
2577
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2578
+ "div",
2579
+ {
2580
+ className: request_log_default.timelineRespTick,
2581
+ style: { left: percent2(Math.min(timeline.responseAt, timeline.end)) },
2582
+ title: `${t("requestLogTimelineFirstByte")} ${duration(timeline.responseAt)}`
2583
+ },
2584
+ "response"
2585
+ )
2586
+ );
2587
+ }
2588
+ return out;
2589
+ };
2590
+ const MAX_ROW_TOOLS = 3;
2591
+ const toolChips = (entry) => {
2592
+ const calls = entry.toolCalls ?? [];
2593
+ if (calls.length === 0) return "\u2014";
2594
+ const full = calls.map((call) => `${call.name} \xD7${call.count}`).join(", ");
2595
+ const shown = calls.slice(0, MAX_ROW_TOOLS);
2596
+ const extra = calls.length - shown.length;
2597
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.toolChips, title: full, children: [
2598
+ shown.map((call) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.toolChip, title: `${call.name} \xD7${call.count}`, children: [
2599
+ call.name,
2600
+ " ",
2601
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.toolChipCount, children: [
2602
+ "\xD7",
2603
+ call.count
2604
+ ] })
2605
+ ] }, call.name)),
2606
+ extra > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: request_log_default.toolChipMore, title: full, children: [
2607
+ "+",
2608
+ extra
2609
+ ] })
2610
+ ] });
2611
+ };
2612
+ const fitText = (entry) => {
2613
+ if (entry.estimatedInputTokens === void 0) return "\u2014";
2614
+ const estimate = `~${compactCount(Math.round(entry.estimatedInputTokens))}`;
2615
+ if (entry.maxTokensClamped === true && entry.fittedMaxTokens !== void 0) {
2616
+ return `${estimate} \u2192 ${compactCount(entry.fittedMaxTokens)}`;
2617
+ }
2618
+ return estimate;
2619
+ };
2620
+ const fitTitle = (entry) => {
2621
+ if (entry.estimatedInputTokens === void 0) return t("requestLogColContextHint");
2622
+ const estimate = `~${count2(Math.round(entry.estimatedInputTokens))}`;
2623
+ const fitted = entry.maxTokensClamped === true && entry.fittedMaxTokens !== void 0 ? ` \u2192 ${count2(entry.fittedMaxTokens)}` : "";
2624
+ return `${t("requestLogColContextHint")}: ${estimate}${fitted}`;
2625
+ };
2500
2626
  const rows = () => {
2501
2627
  const out = [];
2502
2628
  let lastGroup;
@@ -2505,7 +2631,7 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2505
2631
  if (group !== void 0 && group !== lastGroup) {
2506
2632
  lastGroup = group;
2507
2633
  out.push(
2508
- /* @__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}`)
2634
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.group, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 16, children: groupBy === "session" ? sessionLabel(group).text : groupBy === "result" ? resultGroupLabel(group) : group }) }, `group-${group}-${entry.seq}`)
2509
2635
  );
2510
2636
  }
2511
2637
  const state = entry.running === true ? "rowRunning" : !entry.ok ? "rowFail" : entry.tps !== void 0 && entry.tps < 5 ? "rowSlow" : "rowOk";
@@ -2548,6 +2674,20 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2548
2674
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.prepMs) }),
2549
2675
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(waitMs(entry)) }),
2550
2676
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: duration(entry.firstTokenMs) }),
2677
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: (() => {
2678
+ const timeline = timelineOf(entry, t);
2679
+ if (timeline === void 0) return "\u2014";
2680
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.phaseBar, role: "img", "aria-label": phaseSummary(timeline), children: phaseBlocks(timeline, false) });
2681
+ })() }),
2682
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: toolChips(entry) }),
2683
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2684
+ "td",
2685
+ {
2686
+ className: entry.maxTokensClamped === true ? request_log_default.fitClamped : void 0,
2687
+ title: fitTitle(entry),
2688
+ children: fitText(entry)
2689
+ }
2690
+ ),
2551
2691
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: entry.running === true ? duration(Math.max(0, Date.now() - entry.atMs)) : duration(entry.durationMs) }),
2552
2692
  /* @__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" })
2553
2693
  ]
@@ -2557,11 +2697,10 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2557
2697
  );
2558
2698
  if (expanded === entry.seq) {
2559
2699
  out.push(
2560
- /* @__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: [
2700
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { className: request_log_default.detail, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { colSpan: 16, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.detailGrid, children: [
2561
2701
  (() => {
2562
2702
  const timeline = timelineOf(entry, t);
2563
2703
  if (timeline === void 0) return null;
2564
- const kindClass = (kind) => kind === "prep" ? request_log_default.timelinePrep : kind === "wait" ? request_log_default.timelineWait : kind === "stream" ? request_log_default.timelineStream : request_log_default.timelineStreamAlt;
2565
2704
  const legendSwatch = (key) => key === "prep" ? request_log_default.timelineSwatchPrep : key === "wait" ? request_log_default.timelineSwatchWait : key === "stream" ? request_log_default.timelineSwatchStream : request_log_default.timelineTickSwatch;
2566
2705
  const legend = [];
2567
2706
  const legendKey = (kind) => kind === "streamAlt" ? "stream" : kind;
@@ -2591,31 +2730,10 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2591
2730
  text: `${t("requestLogColLatency")} ${duration(timeline.end)}`
2592
2731
  });
2593
2732
  const spoken = legend.map((item) => item.text).join(", ");
2594
- const percent2 = (at) => `${(at / timeline.end * 100).toFixed(2)}%`;
2595
- const liveIndex = entry.running === true ? timeline.blocks.findLastIndex((block) => block.kind === "stream" || block.kind === "streamAlt") : -1;
2596
2733
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timeline, role: "img", "aria-label": spoken, children: [
2597
2734
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timelineTrackWrap, children: [
2598
2735
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: request_log_default.timelineTrack, children: [
2599
- timeline.blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2600
- "div",
2601
- {
2602
- className: `${request_log_default.timelineSeg} ${kindClass(block.kind)}${index === liveIndex ? ` ${request_log_default.timelineLive}` : ""}`,
2603
- style: {
2604
- left: percent2(block.from),
2605
- width: percent2(Math.max(0, block.to - block.from))
2606
- },
2607
- title: `${block.label} ${duration(block.to - block.from)}`
2608
- },
2609
- `${block.kind}-${index}`
2610
- )),
2611
- timeline.responseAt !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2612
- "div",
2613
- {
2614
- className: request_log_default.timelineRespTick,
2615
- style: { left: percent2(Math.min(timeline.responseAt, timeline.end)) },
2616
- title: `${t("requestLogTimelineFirstByte")} ${duration(timeline.responseAt)}`
2617
- }
2618
- ),
2736
+ phaseBlocks(timeline, entry.running === true),
2619
2737
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.timelineMidTick }),
2620
2738
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: request_log_default.timelineTick, title: duration(timeline.end) })
2621
2739
  ] }),
@@ -2902,6 +3020,9 @@ function RequestLogPage({ readLog, enabled, canOpenSession, openSession, t, getL
2902
3020
  head("prepMs", t("requestLogColPrep")),
2903
3021
  head("waitMs", t("requestLogColWait")),
2904
3022
  head("firstTokenMs", t("requestLogColFirstToken")),
3023
+ plainHead(t("requestLogColPhase"), t("requestLogColPhaseHint")),
3024
+ plainHead(t("requestLogColTools"), t("requestLogColToolsHint")),
3025
+ head("estimatedInputTokens", t("requestLogColContext"), t("requestLogColContextHint")),
2905
3026
  head("durationMs", t("requestLogColLatency")),
2906
3027
  head("status", t("requestLogColStatus"))
2907
3028
  ] }) }),
package/lib/index.js CHANGED
@@ -78360,17 +78360,23 @@ var OpencodeGoAdapter = class extends LlmAdapter {
78360
78360
  const ceiling = config.modelLimits[model.id]?.maxTokens;
78361
78361
  const requested = options.maxTokens === void 0 || ceiling === null || ceiling === void 0 ? options.maxTokens : Math.min(options.maxTokens, ceiling);
78362
78362
  let maxTokens;
78363
+ const estimatedInputTokens = estimateInputTokens(options);
78363
78364
  try {
78364
78365
  maxTokens = resolveFittedMaxTokens({
78365
78366
  modelId: model.id,
78366
78367
  contextWindow: model.contextWindow,
78367
78368
  routeMaxTokens: model.maxTokens,
78368
78369
  requestedMaxTokens: requested,
78369
- estimatedInputTokens: estimateInputTokens(options)
78370
+ estimatedInputTokens
78370
78371
  });
78371
78372
  } catch (error) {
78372
78373
  failSpan(error);
78373
78374
  }
78375
+ span?.fit(
78376
+ estimatedInputTokens,
78377
+ maxTokens,
78378
+ requested !== void 0 && maxTokens !== void 0 && maxTokens < requested
78379
+ );
78374
78380
  const apiKey = await this.options.resolveApiKey();
78375
78381
  if (apiKey === void 0 || apiKey.length === 0) {
78376
78382
  const error = new LlmError10("dshopencodego: no credential resolved for the opencode-go route", "MISSING_CREDENTIAL");
@@ -78461,6 +78467,9 @@ var OpencodeGoAdapter = class extends LlmAdapter {
78461
78467
  return;
78462
78468
  }
78463
78469
  if (span !== void 0 && isTokenDelta(result.value)) span.token();
78470
+ if (span !== void 0 && result.value.type === "block-end" && result.value.block.type === "tool-call") {
78471
+ span.toolCall(result.value.block.name);
78472
+ }
78464
78473
  if (result.value.type === "usage") {
78465
78474
  pendingUsage = result.value.usage;
78466
78475
  this.options.onUsage?.({
@@ -78700,6 +78709,7 @@ var networkRemote = {
78700
78709
 
78701
78710
  // src/request-log/store.ts
78702
78711
  var MAX_POOL_EVENTS = 20;
78712
+ var MAX_TOOL_CALLS = 32;
78703
78713
  var STREAM_MARK_EVERY = 10;
78704
78714
  var MAX_STREAM_MARKS = 200;
78705
78715
  var MIN_STREAM_MS_FOR_RATE = 100;
@@ -78770,12 +78780,33 @@ var RequestLog = class {
78770
78780
  let lastTokenAt;
78771
78781
  let tokenDeltas = 0;
78772
78782
  const marks = [];
78783
+ const toolList = [];
78784
+ const toolSeen = /* @__PURE__ */ new Map();
78773
78785
  let reported = false;
78774
78786
  let finished = false;
78775
78787
  return {
78776
78788
  identify: (protocol) => {
78777
78789
  if (record2.protocol === void 0) record2.protocol = protocol;
78778
78790
  },
78791
+ toolCall: (name2) => {
78792
+ if (name2.length === 0) return;
78793
+ const at = toolSeen.get(name2);
78794
+ const known = at === void 0 ? void 0 : toolList[at];
78795
+ if (known !== void 0) {
78796
+ known.count += 1;
78797
+ } else {
78798
+ if (toolList.length >= MAX_TOOL_CALLS) return;
78799
+ toolSeen.set(name2, toolList.length);
78800
+ toolList.push({ name: name2, count: 1 });
78801
+ }
78802
+ record2.toolCalls = toolList;
78803
+ },
78804
+ fit: (inputTokens, maxTokens, clamped) => {
78805
+ if (record2.estimatedInputTokens !== void 0) return;
78806
+ record2.estimatedInputTokens = inputTokens;
78807
+ if (maxTokens !== void 0) record2.fittedMaxTokens = maxTokens;
78808
+ if (clamped) record2.maxTokensClamped = true;
78809
+ },
78779
78810
  token: () => {
78780
78811
  const now = Date.now();
78781
78812
  if (firstTokenAt === void 0) {
@@ -78825,6 +78856,12 @@ var RequestLog = class {
78825
78856
  ...record2.prepMs === void 0 ? {} : { prepMs: record2.prepMs },
78826
78857
  ...record2.responseMs === void 0 ? {} : { responseMs: record2.responseMs },
78827
78858
  ...record2.streamMarksMs === void 0 ? {} : { streamMarksMs: [...record2.streamMarksMs] },
78859
+ ...record2.toolCalls === void 0 || record2.toolCalls.length === 0 ? {} : {
78860
+ toolCalls: record2.toolCalls.map((call) => ({ name: call.name, count: call.count }))
78861
+ },
78862
+ ...record2.estimatedInputTokens === void 0 ? {} : { estimatedInputTokens: record2.estimatedInputTokens },
78863
+ ...record2.fittedMaxTokens === void 0 ? {} : { fittedMaxTokens: record2.fittedMaxTokens },
78864
+ ...record2.maxTokensClamped === true ? { maxTokensClamped: true } : {},
78828
78865
  ...usage === void 0 ? {} : {
78829
78866
  inputTokens: usage.inputTokens,
78830
78867
  outputTokens: usage.outputTokens,
@@ -78918,6 +78955,7 @@ function parseEntry(value) {
78918
78955
  const shape = row["shape"];
78919
78956
  const headers = row["headers"];
78920
78957
  const protocol = row["protocol"];
78958
+ const toolCalls = row["toolCalls"] === void 0 ? void 0 : parseToolCalls(row["toolCalls"]);
78921
78959
  return {
78922
78960
  seq: count("seq", row),
78923
78961
  atMs: count("atMs", row),
@@ -78945,6 +78983,10 @@ function parseEntry(value) {
78945
78983
  ...row["decodeMs"] === void 0 ? {} : { decodeMs: count("decodeMs", row) },
78946
78984
  ...row["streamMs"] === void 0 ? {} : { streamMs: count("streamMs", row) },
78947
78985
  ...row["tps"] === void 0 ? {} : { tps: rate("tps", row) },
78986
+ ...toolCalls === void 0 || toolCalls.length === 0 ? {} : { toolCalls },
78987
+ ...row["estimatedInputTokens"] === void 0 ? {} : { estimatedInputTokens: count("estimatedInputTokens", row) },
78988
+ ...row["fittedMaxTokens"] === void 0 ? {} : { fittedMaxTokens: count("fittedMaxTokens", row) },
78989
+ ...row["maxTokensClamped"] === true ? { maxTokensClamped: true } : {},
78948
78990
  // Running rows cross the wire too: a viewer opened mid-request must
78949
78991
  // see them. Older snapshots predate the flag and read as finished.
78950
78992
  ...row["running"] === true ? { running: true } : {},
@@ -78982,6 +79024,20 @@ function rate(key, row) {
78982
79024
  }
78983
79025
  return entry;
78984
79026
  }
79027
+ function parseToolCalls(value) {
79028
+ if (!Array.isArray(value)) return [];
79029
+ const kept = [];
79030
+ for (const item of value) {
79031
+ if (kept.length >= MAX_TOOL_CALLS) break;
79032
+ if (item === null || typeof item !== "object") continue;
79033
+ const row = item;
79034
+ if (typeof row["name"] !== "string" || row["name"].length === 0) continue;
79035
+ const callCount = row["count"];
79036
+ if (typeof callCount !== "number" || !Number.isInteger(callCount) || callCount < 1) continue;
79037
+ kept.push({ name: row["name"], count: callCount });
79038
+ }
79039
+ return kept;
79040
+ }
78985
79041
  function parsePoolEvent(value) {
78986
79042
  if (value === null || typeof value !== "object") throw new Error("invalid request-log pool event");
78987
79043
  const row = value;
@@ -79590,7 +79646,7 @@ function createUpdateChecker(deps) {
79590
79646
  }
79591
79647
 
79592
79648
  // src/update/version.ts
79593
- var PLUGIN_VERSION = true ? "0.1.87" : "0.0.0-dev";
79649
+ var PLUGIN_VERSION = true ? "0.1.88" : "0.0.0-dev";
79594
79650
 
79595
79651
  // src/update/service.ts
79596
79652
  import { TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
@@ -125,6 +125,36 @@ export interface RequestLogEntry {
125
125
  * misreport a buffered reply as infinitely quick.
126
126
  */
127
127
  readonly tps?: number;
128
+ /**
129
+ * Tools this request actually invoked, in first-seen order with call
130
+ * counts. Declarations live in `shape.tools`; this names what ran, so a
131
+ * row reads like the Harness's own per-turn execution summary. Absent
132
+ * when the request invoked nothing. Capped — a pathological turn cannot
133
+ * grow a bounded row.
134
+ */
135
+ readonly toolCalls?: ReadonlyArray<{
136
+ readonly name: string;
137
+ readonly count: number;
138
+ }>;
139
+ /**
140
+ * Conservative input estimate the adapter fitted against, in tokens. An
141
+ * upper bound, not a count: the gateway's tokenizer is unknown, so the
142
+ * estimate only ever overstates. Absent when the request failed before
143
+ * fitting ran.
144
+ */
145
+ readonly estimatedInputTokens?: number;
146
+ /**
147
+ * The output cap actually sent on the wire, in tokens. Absent when the
148
+ * call sent none (caller and route both silent) or failed before
149
+ * fitting ran.
150
+ */
151
+ readonly fittedMaxTokens?: number;
152
+ /**
153
+ * Present only when the fitted cap sits below what was asked: the input
154
+ * plus the requested output would not fit the window, so this call went
155
+ * out smaller instead of taking a gateway 400.
156
+ */
157
+ readonly maxTokensClamped?: boolean;
128
158
  /**
129
159
  * Whether the request is still in flight. Present only while it runs:
130
160
  * `finish` removes it. A running row always reads `ok: false` with no
@@ -191,6 +221,12 @@ export interface RequestLogGates {
191
221
  /** How many entries to keep; the ring trims to it on every append. */
192
222
  readonly maxEntries: () => number;
193
223
  }
224
+ /**
225
+ * How many distinct tool names one row keeps. Past the cap extra tools
226
+ * are still executed — only the record stops naming them — so a turn
227
+ * that fans out across dozens of tools cannot grow a bounded row.
228
+ */
229
+ export declare const MAX_TOOL_CALLS = 32;
194
230
  /**
195
231
  * How many streaming timestamps one row keeps at most. Past the cap the
196
232
  * trail simply stops growing: the newest marks matter more than the oldest
@@ -249,6 +285,24 @@ export interface RequestSpan {
249
285
  * `finish`; a second call keeps the first.
250
286
  */
251
287
  identify(protocol: WireProtocol): void;
288
+ /**
289
+ * Count one invoked tool by name, in first-seen order. Called once per
290
+ * completed tool call the stream carries; a second sighting of the same
291
+ * name bumps its count instead of appending. Past the distinct-name cap
292
+ * extra tools are ignored by the record, never by the request.
293
+ */
294
+ toolCall(name: string): void;
295
+ /**
296
+ * Record the context fit this request was sent under. Called once, with
297
+ * the estimate and the cap the adapter actually sent; first call wins,
298
+ * like the wire line. A clamped cap is flagged so the row explains a
299
+ * shorter-than-asked reply.
300
+ * @param inputTokens - the conservative input estimate, in tokens.
301
+ * @param maxTokens - the output cap sent on the wire, or undefined when
302
+ * the call sent none.
303
+ * @param clamped - whether the cap sits below what was asked.
304
+ */
305
+ fit(inputTokens: number, maxTokens: number | undefined, clamped: boolean): void;
252
306
  /**
253
307
  * Close the span and complete its running row in place.
254
308
  * @param ok - whether the request completed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dan-ai-studio/dshopencodego",
3
- "version": "0.1.87",
3
+ "version": "0.1.88",
4
4
  "description": "OpenCode Go provider for DeepSeek Harness: live gateway catalog, per-conversation session header, usage",
5
5
  "type": "module",
6
6
  "license": "MIT",