@weibaohui/context-razor 0.4.1 → 0.4.2
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/client/bundle.js +34 -27
- package/client/index.js +34 -27
- package/package.json +1 -1
package/client/bundle.js
CHANGED
|
@@ -68,9 +68,9 @@ window.__ModuleLoader__.load({
|
|
|
68
68
|
orderNote: '本插件不会改变上下文条目顺序,只会剔除选中条目。',
|
|
69
69
|
legendTitle: '按 token 量级筛选(点选高亮某一档)',
|
|
70
70
|
kindFilterLabel: '类型',
|
|
71
|
-
selectVisible: '
|
|
72
|
-
selectVisibleHint: '
|
|
73
|
-
clearSelect: '
|
|
71
|
+
selectVisible: '全选',
|
|
72
|
+
selectVisibleHint: '全选当前可见条目(配合类型/量级筛选)',
|
|
73
|
+
clearSelect: '取消全选',
|
|
74
74
|
deleteSelected: '删除选中',
|
|
75
75
|
selectedStats: '已选 {n} 条 / ≈{tokens} token',
|
|
76
76
|
stats: '{nodes} 条 · 合计 ≈{tokens} token{mode}',
|
|
@@ -110,9 +110,9 @@ window.__ModuleLoader__.load({
|
|
|
110
110
|
orderNote: 'This plugin never reorders context entries; it only removes the selected ones.',
|
|
111
111
|
legendTitle: 'Filter by token tier (click to isolate a band)',
|
|
112
112
|
kindFilterLabel: 'Type',
|
|
113
|
-
selectVisible: '
|
|
114
|
-
selectVisibleHint: 'Select
|
|
115
|
-
clearSelect: 'Clear
|
|
113
|
+
selectVisible: 'All',
|
|
114
|
+
selectVisibleHint: 'Select all currently visible entries (pairs with type/tier filters)',
|
|
115
|
+
clearSelect: 'Clear all',
|
|
116
116
|
deleteSelected: 'Delete selected',
|
|
117
117
|
selectedStats: '{n} selected / ≈{tokens} tokens',
|
|
118
118
|
stats: '{nodes} entries · total ≈{tokens} tokens{mode}',
|
|
@@ -271,6 +271,11 @@ window.__ModuleLoader__.load({
|
|
|
271
271
|
.rz-kindbtn:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}
|
|
272
272
|
.rz-kindbtn.on{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);font-weight:600}
|
|
273
273
|
.rz-kindcount{font-size:10px;opacity:.7}
|
|
274
|
+
.rz-thead{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:6px 12px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}
|
|
275
|
+
.rz-thead-l{display:inline-flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
276
|
+
.rz-sel-stats{color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}
|
|
277
|
+
.rz-col-tok{flex:0 0 62px;display:flex;justify-content:flex-end}
|
|
278
|
+
.rz-col-pct{flex:0 0 44px;text-align:right;color:var(--dsw-alias-label-tertiary);font-size:11px;white-space:nowrap}
|
|
274
279
|
.rz-list{display:flex;flex-direction:column;gap:6px}
|
|
275
280
|
.rz-row{display:flex;gap:10px;align-items:center;padding:8px 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l1);border-left:3px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);cursor:pointer;text-align:left;width:100%}
|
|
276
281
|
.rz-row:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -313,12 +318,10 @@ window.__ModuleLoader__.load({
|
|
|
313
318
|
|
|
314
319
|
const Chip = ({ kind, label, title }) => h('span', { className: 'rz-chip ' + kind, title }, label)
|
|
315
320
|
|
|
316
|
-
const TokenBadge = ({ entry
|
|
321
|
+
const TokenBadge = ({ entry }) => {
|
|
317
322
|
const tier = tierOf(entry)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return h('span', { className: 'rz-badge tier-' + tier, title },
|
|
321
|
-
'≈' + formatNum(entry.tokens) + (pct ? ' · ' + pct : ''))
|
|
323
|
+
return h('span', { className: 'rz-badge tier-' + tier, title: RAZOR_TIERS[tier].label + ' token' },
|
|
324
|
+
'≈' + formatNum(entry.tokens))
|
|
322
325
|
}
|
|
323
326
|
|
|
324
327
|
/** 分页列表:先渲染 pageSize 行,按需增长(大会话一次挂几千行会卡)。 */
|
|
@@ -335,12 +338,14 @@ window.__ModuleLoader__.load({
|
|
|
335
338
|
/** 单条全文弹窗(正文经 /entry 异步补全)。 */
|
|
336
339
|
function DetailModal({ detail, t, total, onClose }) {
|
|
337
340
|
if (!detail) return null
|
|
341
|
+
const pct = pctOf(detail.tokens, total)
|
|
338
342
|
return h('div', { className: 'rz-dlg-backdrop', onClick: onClose },
|
|
339
343
|
h('div', { className: 'rz-dlg', onClick: e => e.stopPropagation() },
|
|
340
344
|
h('h3', null, t('detailTitle') + ' · ' + t('seqLabel', { seq: detail.seq })),
|
|
341
345
|
h('div', { className: 'rz-stats', style: { marginBottom: 10 } },
|
|
342
346
|
h(Chip, { ...entryChip(detail, t) }),
|
|
343
|
-
h(TokenBadge, { entry: detail
|
|
347
|
+
h(TokenBadge, { entry: detail }),
|
|
348
|
+
pct && h('span', { className: 'rz-label', title: pct + ' of ≈' + formatNum(total) + ' token' }, pct),
|
|
344
349
|
h('span', { className: 'rz-label', title: 'seq ' + detail.seq }, formatDateTime(detail.time)),
|
|
345
350
|
h('span', { className: 'rz-label' }, t('detailChars', { chars: formatNum(detail.chars) })),
|
|
346
351
|
detail.usage && h('span', { className: 'rz-label' }, t('detailUsage', {
|
|
@@ -493,13 +498,7 @@ window.__ModuleLoader__.load({
|
|
|
493
498
|
h('span', { className: 'rz-legend' + (tierFilter.size > 0 ? ' filtering' : ''), title: t('legendTitle') },
|
|
494
499
|
RAZOR_TIERS.map((tr, i) => h('button', { key: i, className: 'rz-swatch tier-' + i + (tierFilter.has(i) ? ' on' : ''), title: tr.label + ' token', onClick: () => toggleTier(i) }, tr.label))),
|
|
495
500
|
h('span', { className: 'rz-spacer' }),
|
|
496
|
-
busy && h('span', { className: 'rz-badge' }, t('busyTag')),
|
|
497
|
-
h('button', { className: 'rz-btn', onClick: selectVisible, disabled: visible.length === 0 || busy, title: t('selectVisibleHint') },
|
|
498
|
-
t('selectVisible') + (visible.length ? ` (${visible.length})` : '')),
|
|
499
|
-
h('select', { className: 'rz-select', value: sortBy, onChange: e => setSortBy(e.target.value), title: t('sortLabel'), 'aria-label': t('sortLabel') },
|
|
500
|
-
h('option', { value: 'order' }, t('sortOrder')),
|
|
501
|
-
h('option', { value: 'tokens' }, t('sortTokens'))),
|
|
502
|
-
h('button', { className: 'rz-btn', onClick: refreshAll, title: t('refresh') }, t('refresh'))),
|
|
501
|
+
busy && h('span', { className: 'rz-badge' }, t('busyTag'))),
|
|
503
502
|
// 类型筛选:与 chip 同口径的可点选按钮(user/injected/assistant/tool:<名>),
|
|
504
503
|
// 多选 toggle,与 tier 量级筛选正交叠加。按钮带条数;hover 看 token 占比。
|
|
505
504
|
categories.length > 0 && h('div', { key: 'kinds', className: 'rz-kindsbar' },
|
|
@@ -513,25 +512,33 @@ window.__ModuleLoader__.load({
|
|
|
513
512
|
onClick: () => toggleKind(cat) },
|
|
514
513
|
categoryLabel(cat, t),
|
|
515
514
|
h('span', { className: 'rz-kindcount' }, count))))),
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
h('
|
|
519
|
-
|
|
520
|
-
h('button', { className: 'rz-btn', onClick:
|
|
521
|
-
|
|
515
|
+
// 表头(在类型筛选下方):左 刷新/全选,选中后追加 删除·取消全选;右 排序。
|
|
516
|
+
h('div', { key: 'thead', className: 'rz-thead' },
|
|
517
|
+
h('div', { className: 'rz-thead-l' },
|
|
518
|
+
h('button', { className: 'rz-btn', onClick: refreshAll, title: t('refresh') }, t('refresh')),
|
|
519
|
+
h('button', { className: 'rz-btn', onClick: selectVisible, disabled: visible.length === 0 || busy, title: t('selectVisibleHint') },
|
|
520
|
+
t('selectVisible') + (visible.length ? ` (${visible.length})` : '')),
|
|
521
|
+
selected.size > 0 && h('button', { className: 'rz-btn rz-btn-danger', disabled: !canDelete,
|
|
522
522
|
title: busy ? t('deleteBusyHint') : undefined,
|
|
523
523
|
onClick: () => setConfirming([...selected]) },
|
|
524
|
-
t('deleteSelected') + ` (${selected.size})`)
|
|
524
|
+
t('deleteSelected') + ` (${selected.size})`),
|
|
525
|
+
selected.size > 0 && h('button', { className: 'rz-btn', onClick: () => setSelected(new Set()) }, t('clearSelect'))),
|
|
526
|
+
h('span', { className: 'rz-spacer' }),
|
|
527
|
+
h('select', { className: 'rz-select', value: sortBy, onChange: e => setSortBy(e.target.value), title: t('sortLabel'), 'aria-label': t('sortLabel') },
|
|
528
|
+
h('option', { value: 'order' }, t('sortOrder')),
|
|
529
|
+
h('option', { value: 'tokens' }, t('sortTokens')))),
|
|
525
530
|
visible.length === 0
|
|
526
531
|
? h('div', { key: 'empty', className: 'rz-empty' }, t('emptyContext'))
|
|
527
532
|
: h('div', { key: 'list', className: 'rz-list' },
|
|
528
533
|
h(PagedList, { items: visible, t, render: entry => {
|
|
529
534
|
const tier = tierOf(entry)
|
|
535
|
+
const pct = pctOf(entry.tokens, context.totalTokens)
|
|
530
536
|
return h('div', { key: entry.seq, className: 'rz-row tier-' + tier + (selected.has(entry.seq) ? ' checked' : ''),
|
|
531
537
|
role: 'button', tabIndex: 0, onClick: () => toggleRow(entry.seq),
|
|
532
538
|
onKeyDown: e => e.key === 'Enter' && toggleRow(entry.seq) },
|
|
533
539
|
h('input', { type: 'checkbox', checked: selected.has(entry.seq), onClick: e => e.stopPropagation(), onChange: () => toggleRow(entry.seq) }),
|
|
534
|
-
h(
|
|
540
|
+
h('span', { className: 'rz-col-tok' }, h(TokenBadge, { entry })),
|
|
541
|
+
h('span', { className: 'rz-col-pct', title: pct ? pct + ' of ≈' + formatNum(context.totalTokens) + ' token' : '' }, pct || ''),
|
|
535
542
|
h(Chip, { ...entryChip(entry, t) }),
|
|
536
543
|
h('span', { className: 'rz-row-preview', title: entry.preview,
|
|
537
544
|
onClick: e => { e.stopPropagation(); openDetail(entry) } }, entry.preview || ' '),
|
package/client/index.js
CHANGED
|
@@ -58,9 +58,9 @@ const ZH = {
|
|
|
58
58
|
orderNote: '本插件不会改变上下文条目顺序,只会剔除选中条目。',
|
|
59
59
|
legendTitle: '按 token 量级筛选(点选高亮某一档)',
|
|
60
60
|
kindFilterLabel: '类型',
|
|
61
|
-
selectVisible: '
|
|
62
|
-
selectVisibleHint: '
|
|
63
|
-
clearSelect: '
|
|
61
|
+
selectVisible: '全选',
|
|
62
|
+
selectVisibleHint: '全选当前可见条目(配合类型/量级筛选)',
|
|
63
|
+
clearSelect: '取消全选',
|
|
64
64
|
deleteSelected: '删除选中',
|
|
65
65
|
selectedStats: '已选 {n} 条 / ≈{tokens} token',
|
|
66
66
|
stats: '{nodes} 条 · 合计 ≈{tokens} token{mode}',
|
|
@@ -100,9 +100,9 @@ const EN = {
|
|
|
100
100
|
orderNote: 'This plugin never reorders context entries; it only removes the selected ones.',
|
|
101
101
|
legendTitle: 'Filter by token tier (click to isolate a band)',
|
|
102
102
|
kindFilterLabel: 'Type',
|
|
103
|
-
selectVisible: '
|
|
104
|
-
selectVisibleHint: 'Select
|
|
105
|
-
clearSelect: 'Clear
|
|
103
|
+
selectVisible: 'All',
|
|
104
|
+
selectVisibleHint: 'Select all currently visible entries (pairs with type/tier filters)',
|
|
105
|
+
clearSelect: 'Clear all',
|
|
106
106
|
deleteSelected: 'Delete selected',
|
|
107
107
|
selectedStats: '{n} selected / ≈{tokens} tokens',
|
|
108
108
|
stats: '{nodes} entries · total ≈{tokens} tokens{mode}',
|
|
@@ -261,6 +261,11 @@ const STYLE = `<style>
|
|
|
261
261
|
.rz-kindbtn:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}
|
|
262
262
|
.rz-kindbtn.on{color:var(--dsw-alias-state-business-primary);border-color:var(--dsw-alias-state-business-primary);font-weight:600}
|
|
263
263
|
.rz-kindcount{font-size:10px;opacity:.7}
|
|
264
|
+
.rz-thead{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:6px 12px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}
|
|
265
|
+
.rz-thead-l{display:inline-flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
266
|
+
.rz-sel-stats{color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}
|
|
267
|
+
.rz-col-tok{flex:0 0 62px;display:flex;justify-content:flex-end}
|
|
268
|
+
.rz-col-pct{flex:0 0 44px;text-align:right;color:var(--dsw-alias-label-tertiary);font-size:11px;white-space:nowrap}
|
|
264
269
|
.rz-list{display:flex;flex-direction:column;gap:6px}
|
|
265
270
|
.rz-row{display:flex;gap:10px;align-items:center;padding:8px 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l1);border-left:3px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);cursor:pointer;text-align:left;width:100%}
|
|
266
271
|
.rz-row:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -303,12 +308,10 @@ const STYLE = `<style>
|
|
|
303
308
|
|
|
304
309
|
const Chip = ({ kind, label, title }) => h('span', { className: 'rz-chip ' + kind, title }, label)
|
|
305
310
|
|
|
306
|
-
const TokenBadge = ({ entry
|
|
311
|
+
const TokenBadge = ({ entry }) => {
|
|
307
312
|
const tier = tierOf(entry)
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return h('span', { className: 'rz-badge tier-' + tier, title },
|
|
311
|
-
'≈' + formatNum(entry.tokens) + (pct ? ' · ' + pct : ''))
|
|
313
|
+
return h('span', { className: 'rz-badge tier-' + tier, title: RAZOR_TIERS[tier].label + ' token' },
|
|
314
|
+
'≈' + formatNum(entry.tokens))
|
|
312
315
|
}
|
|
313
316
|
|
|
314
317
|
/** 分页列表:先渲染 pageSize 行,按需增长(大会话一次挂几千行会卡)。 */
|
|
@@ -325,12 +328,14 @@ function PagedList({ items, render, t }) {
|
|
|
325
328
|
/** 单条全文弹窗(正文经 /entry 异步补全)。 */
|
|
326
329
|
function DetailModal({ detail, t, total, onClose }) {
|
|
327
330
|
if (!detail) return null
|
|
331
|
+
const pct = pctOf(detail.tokens, total)
|
|
328
332
|
return h('div', { className: 'rz-dlg-backdrop', onClick: onClose },
|
|
329
333
|
h('div', { className: 'rz-dlg', onClick: e => e.stopPropagation() },
|
|
330
334
|
h('h3', null, t('detailTitle') + ' · ' + t('seqLabel', { seq: detail.seq })),
|
|
331
335
|
h('div', { className: 'rz-stats', style: { marginBottom: 10 } },
|
|
332
336
|
h(Chip, { ...entryChip(detail, t) }),
|
|
333
|
-
h(TokenBadge, { entry: detail
|
|
337
|
+
h(TokenBadge, { entry: detail }),
|
|
338
|
+
pct && h('span', { className: 'rz-label', title: pct + ' of ≈' + formatNum(total) + ' token' }, pct),
|
|
334
339
|
h('span', { className: 'rz-label', title: 'seq ' + detail.seq }, formatDateTime(detail.time)),
|
|
335
340
|
h('span', { className: 'rz-label' }, t('detailChars', { chars: formatNum(detail.chars) })),
|
|
336
341
|
detail.usage && h('span', { className: 'rz-label' }, t('detailUsage', {
|
|
@@ -483,13 +488,7 @@ function RazorPage({ t, fixedSessionId }) {
|
|
|
483
488
|
h('span', { className: 'rz-legend' + (tierFilter.size > 0 ? ' filtering' : ''), title: t('legendTitle') },
|
|
484
489
|
RAZOR_TIERS.map((tr, i) => h('button', { key: i, className: 'rz-swatch tier-' + i + (tierFilter.has(i) ? ' on' : ''), title: tr.label + ' token', onClick: () => toggleTier(i) }, tr.label))),
|
|
485
490
|
h('span', { className: 'rz-spacer' }),
|
|
486
|
-
busy && h('span', { className: 'rz-badge' }, t('busyTag')),
|
|
487
|
-
h('button', { className: 'rz-btn', onClick: selectVisible, disabled: visible.length === 0 || busy, title: t('selectVisibleHint') },
|
|
488
|
-
t('selectVisible') + (visible.length ? ` (${visible.length})` : '')),
|
|
489
|
-
h('select', { className: 'rz-select', value: sortBy, onChange: e => setSortBy(e.target.value), title: t('sortLabel'), 'aria-label': t('sortLabel') },
|
|
490
|
-
h('option', { value: 'order' }, t('sortOrder')),
|
|
491
|
-
h('option', { value: 'tokens' }, t('sortTokens'))),
|
|
492
|
-
h('button', { className: 'rz-btn', onClick: refreshAll, title: t('refresh') }, t('refresh'))),
|
|
491
|
+
busy && h('span', { className: 'rz-badge' }, t('busyTag'))),
|
|
493
492
|
// 类型筛选:与 chip 同口径的可点选按钮(user/injected/assistant/tool:<名>),
|
|
494
493
|
// 多选 toggle,与 tier 量级筛选正交叠加。按钮带条数;hover 看 token 占比。
|
|
495
494
|
categories.length > 0 && h('div', { key: 'kinds', className: 'rz-kindsbar' },
|
|
@@ -503,25 +502,33 @@ function RazorPage({ t, fixedSessionId }) {
|
|
|
503
502
|
onClick: () => toggleKind(cat) },
|
|
504
503
|
categoryLabel(cat, t),
|
|
505
504
|
h('span', { className: 'rz-kindcount' }, count))))),
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
h('
|
|
509
|
-
|
|
510
|
-
h('button', { className: 'rz-btn', onClick:
|
|
511
|
-
|
|
505
|
+
// 表头(在类型筛选下方):左 刷新/全选,选中后追加 删除·取消全选;右 排序。
|
|
506
|
+
h('div', { key: 'thead', className: 'rz-thead' },
|
|
507
|
+
h('div', { className: 'rz-thead-l' },
|
|
508
|
+
h('button', { className: 'rz-btn', onClick: refreshAll, title: t('refresh') }, t('refresh')),
|
|
509
|
+
h('button', { className: 'rz-btn', onClick: selectVisible, disabled: visible.length === 0 || busy, title: t('selectVisibleHint') },
|
|
510
|
+
t('selectVisible') + (visible.length ? ` (${visible.length})` : '')),
|
|
511
|
+
selected.size > 0 && h('button', { className: 'rz-btn rz-btn-danger', disabled: !canDelete,
|
|
512
512
|
title: busy ? t('deleteBusyHint') : undefined,
|
|
513
513
|
onClick: () => setConfirming([...selected]) },
|
|
514
|
-
t('deleteSelected') + ` (${selected.size})`)
|
|
514
|
+
t('deleteSelected') + ` (${selected.size})`),
|
|
515
|
+
selected.size > 0 && h('button', { className: 'rz-btn', onClick: () => setSelected(new Set()) }, t('clearSelect'))),
|
|
516
|
+
h('span', { className: 'rz-spacer' }),
|
|
517
|
+
h('select', { className: 'rz-select', value: sortBy, onChange: e => setSortBy(e.target.value), title: t('sortLabel'), 'aria-label': t('sortLabel') },
|
|
518
|
+
h('option', { value: 'order' }, t('sortOrder')),
|
|
519
|
+
h('option', { value: 'tokens' }, t('sortTokens')))),
|
|
515
520
|
visible.length === 0
|
|
516
521
|
? h('div', { key: 'empty', className: 'rz-empty' }, t('emptyContext'))
|
|
517
522
|
: h('div', { key: 'list', className: 'rz-list' },
|
|
518
523
|
h(PagedList, { items: visible, t, render: entry => {
|
|
519
524
|
const tier = tierOf(entry)
|
|
525
|
+
const pct = pctOf(entry.tokens, context.totalTokens)
|
|
520
526
|
return h('div', { key: entry.seq, className: 'rz-row tier-' + tier + (selected.has(entry.seq) ? ' checked' : ''),
|
|
521
527
|
role: 'button', tabIndex: 0, onClick: () => toggleRow(entry.seq),
|
|
522
528
|
onKeyDown: e => e.key === 'Enter' && toggleRow(entry.seq) },
|
|
523
529
|
h('input', { type: 'checkbox', checked: selected.has(entry.seq), onClick: e => e.stopPropagation(), onChange: () => toggleRow(entry.seq) }),
|
|
524
|
-
h(
|
|
530
|
+
h('span', { className: 'rz-col-tok' }, h(TokenBadge, { entry })),
|
|
531
|
+
h('span', { className: 'rz-col-pct', title: pct ? pct + ' of ≈' + formatNum(context.totalTokens) + ' token' : '' }, pct || ''),
|
|
525
532
|
h(Chip, { ...entryChip(entry, t) }),
|
|
526
533
|
h('span', { className: 'rz-row-preview', title: entry.preview,
|
|
527
534
|
onClick: e => { e.stopPropagation(); openDetail(entry) } }, entry.preview || ' '),
|