deepseek-harness-wallet 0.1.4 → 0.1.5
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/CHANGELOG.md +8 -1
- package/README.md +27 -17
- package/lib/client.js +108 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to this project are documented
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.1.5 - 2026-08-18
|
|
6
|
+
|
|
7
|
+
- 修复输入框内的余额标签被固定压缩成 44px 极简显示的问题,现在按实际可用空间在完整 / 紧凑 / 极简三档间自动切换。 / Fixed the composer chip always collapsing to its 44px compact value; it now switches between full, fit, and compact layouts by measured space.
|
|
8
|
+
- 修复缩放比例不等于 100% 时被误判为空间不足的问题。 / Fixed compact mode being mis-triggered whenever the scale was not 100%.
|
|
9
|
+
- 修复芯片拖到输入框旁悬浮时被其他面板遮挡的问题。 / Fixed docked chips being covered by neighbouring host panels.
|
|
10
|
+
- 输入框内缩放上限调整为 120%,悬浮 / 侧边停靠时仍可到 125%。 / The scale slider is capped at 120% in the composer row; floating and side docks keep the full 75–125% range.
|
|
4
11
|
|
|
5
12
|
## 0.1.4 - 2026-08-17
|
|
6
13
|
|
package/README.md
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
# DeepSeek Harness Control Center
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/deepseek-harness-wallet)
|
|
4
|
+
[](https://github.com/feibi-mochi/deepseek-harness-control-center/releases)
|
|
5
|
+
[](https://github.com/feibi-mochi/deepseek-harness-control-center/actions/workflows/validate.yml)
|
|
6
|
+
[](https://github.com/deepseek-ai/DeepSeek-Harness)
|
|
7
|
+
[](./LICENSE)
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
**DeepSeek Harness monitoring, alerts, recharge, and session control center.**
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
`Balance ¥5.89 · Session ¥0.72 · Official 18.8M | Third-party 800K · ↗ Recharge`
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
[English](./README.md) · [简体中文](https://github.com/feibi-mochi/deepseek-harness-control-center/blob/main/docs/i18n/README.zh-CN.md) · [Install](#install) · [Compatibility](#browser-desktop-and-os-compatibility) · [Changelog](./CHANGELOG.md)
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
The resident chip combines the live DeepSeek balance, the open conversation's estimated official spend, official token usage, third-party token totals, and the official recharge shortcut. Accounting is isolated twice—by conversation and by provider—so one conversation cannot borrow another conversation's counters, and third-party traffic cannot become DeepSeek spend. Official cost is accumulated when each usage event arrives using the price active at that moment; later peak/off-peak changes therefore do not rewrite historical estimates. The detail panel expands this summary into per-currency balance rows, token splits, session spend, refresh controls, and a configurable CNY low-balance threshold.
|
|
14
|
-
|
|
15
|
-
Monitoring is paired with deliberate actions. A low balance changes the wallet's visual state and emits one alert until the balance recovers. The recharge shortcut always targets DeepSeek's fixed official top-up URL, and the first use shows the destination before leaving Harness. Completion reminders cover a different kind of waiting: they can remain until manually dismissed or close after a selected delay, combine simultaneous completions into a queue, coordinate across tabs, and open the relevant conversation when clicked. If a system notification cannot be shown, the same event falls back to an in-page notice instead of disappearing silently.
|
|
16
|
-
|
|
17
|
-
The interface is meant to live with the user's workspace rather than occupy it. The chip may remain in the composer, move freely, preview and snap to supported page edges or regions, switch between compact horizontal and vertical arrangements, scale from the control panel, or minimize directly to a movable dot. If the composer becomes too narrow for the full home chip, it keeps a clickable balance/token value instead of overflowing underneath the model selector. Official and third-party data can be shown independently while preventing an empty all-hidden state. The details panel itself is draggable and remembers its last position, and saved positions are fitted back into the viewport when the window changes.
|
|
18
|
-
|
|
19
|
-
Session controls keep two very different operations separate. **Clear current-session wallet data** removes only this plugin's balance-derived spend and token counters for the open conversation; it does not delete the conversation. **Permanent session deletion** is an optional host integration, not a deletion engine supplied by this npm package. It appears only when the current DSH host advertises a real deletion path, remains opt-in, and still requires confirmation; unsupported hosts keep the setting disabled. This boundary prevents a decorative switch from promising an operation the surrounding application cannot perform.
|
|
20
|
-
|
|
21
|
-
The trust model is intentionally narrow. The plugin registers no model tools, injects no prompt text, and adds no model-token overhead. Its host-side accounting is kept in the local DSH storage, while layout and reminder preferences use browser-compatible local storage. The existing DSH credential is used only for the official balance request, and recharge navigation is fixed to the official DeepSeek domain. The plugin does not collect payment details, estimate third-party money values without a price source, or merge balances across currencies.
|
|
22
|
-
|
|
23
|
-
Compatibility is based on capabilities rather than operating-system names. A normal DSH Web environment uses standards-based browser behavior; restricted Electron, Tauri, or other desktop shells can provide a small adapter for notifications, storage, and external links without changing accounting or UI logic. Optional features degrade visibly when a capability is absent. This keeps the project useful as a broader Harness monitoring and session-control center while leaving room for future provider adapters, history views, and other management features without changing the established npm package identity.
|
|
15
|
+
> A local-first companion that keeps account status, per-conversation usage, completion reminders, official recharge, flexible layout, and host-gated session controls beside the DSH composer.
|
|
24
16
|
|
|
25
17
|
> If DeepSeek Harness Control Center helps you, please consider leaving a ⭐ Star. Thank you!
|
|
26
18
|
|
|
@@ -41,6 +33,24 @@ Compatibility is based on capabilities rather than operating-system names. A nor
|
|
|
41
33
|
- **Theme-native UI** — built entirely on `--dsw-alias-*` theme variables, so light and dark themes both render correctly; the panel closes when you click outside and flips open-direction near screen edges.
|
|
42
34
|
- **Clear current-session wallet data** — one button clears only the open conversation's token/cost records; it does not delete the conversation, and every other conversation is untouched.
|
|
43
35
|
|
|
36
|
+
## Project overview
|
|
37
|
+
|
|
38
|
+
### One place for the signals that matter
|
|
39
|
+
|
|
40
|
+
DeepSeek Harness can keep several conversations and model providers active at once, but balance, usage, background-task status, and session actions normally live in different places. Control Center brings the information worth checking repeatedly beside the composer, so the current workflow can answer three questions at a glance: **How much official balance remains? What has this conversation used? Does anything need attention?**
|
|
41
|
+
|
|
42
|
+
### Present when needed, quiet when not
|
|
43
|
+
|
|
44
|
+
The project is designed around quick reading and in-context action rather than another full-page dashboard. Its compact surface expands only when needed, adapts to the available space, and leaves layout and reminder behavior under the user's control. Accounting remains separated by conversation and provider, while wallet-data cleanup and permanent session deletion remain intentionally different operations.
|
|
45
|
+
|
|
46
|
+
### Extensible without hiding the boundaries
|
|
47
|
+
|
|
48
|
+
The npm package handles monitoring and interface behavior; optional host powers are enabled only when DSH actually provides them. That capability-based boundary keeps unsupported actions visibly unavailable and gives browsers or desktop wrappers a small, reviewable adaptation surface. Future providers and controls can therefore be added without changing the established `deepseek-harness-wallet` package identity or silently expanding what the plugin is trusted to do.
|
|
49
|
+
|
|
50
|
+
> **Want permanent session deletion?** It cannot be enabled by configuring the plugin alone. Give the [integration guide](./integrations/dsh-session-delete/README.md) and [Agent adaptation prompt](./integrations/dsh-session-delete/AGENT_PROMPT.md) to an Agent with access to the buildable DSH source. The control-panel switch becomes available only after the host implementation is built, tested, and advertises the capability.
|
|
51
|
+
|
|
52
|
+
Details: [compatibility](#browser-desktop-and-os-compatibility) · [data and trust](#data--trust) · [pricing](#pricing-timeline)
|
|
53
|
+
|
|
44
54
|
## Install
|
|
45
55
|
|
|
46
56
|
From npm:
|
package/lib/client.js
CHANGED
|
@@ -250,7 +250,8 @@ window.__ModuleLoader__.load({
|
|
|
250
250
|
|
|
251
251
|
var css = [
|
|
252
252
|
'.dshw_anchor{display:inline-flex;align-items:center;min-height:22px;min-width:0;vertical-align:middle}',
|
|
253
|
-
'.dshw_anchorHome{
|
|
253
|
+
'.dshw_anchorHome{overflow:hidden;min-width:44px}',
|
|
254
|
+
'.dshw_chipLift{z-index:80!important}',
|
|
254
255
|
'.dshw_anchorHome>.dshw_chip{box-sizing:border-box;max-width:100%;min-width:0;overflow:hidden}',
|
|
255
256
|
'.dshw_chip{border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.15));background:transparent;height:22px;color:var(--dsw-alias-label-primary,#1f2328);white-space:nowrap;border-radius:999px;align-items:stretch;font-size:12px;line-height:1;display:inline-flex;position:relative;touch-action:none;user-select:none;cursor:grab}',
|
|
256
257
|
'.dshw_chip:hover,.dshw_chip:focus-within{border-color:var(--dsw-alias-brand-primary,#4aa3ff)}',
|
|
@@ -307,8 +308,13 @@ window.__ModuleLoader__.load({
|
|
|
307
308
|
'.dshw_notice{box-sizing:border-box;width:100%;display:flex;align-items:flex-start;gap:8px;padding:10px 10px 10px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.15));border-radius:9px;background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-primary,#1f2328);box-shadow:0 6px 20px rgba(0,0,0,.2);font-size:12px;line-height:1.45;pointer-events:auto;cursor:pointer}',
|
|
308
309
|
'.dshw_noticeCopy{min-width:0;display:flex;flex:1;flex-direction:column;gap:2px}.dshw_noticeCopy span{white-space:pre-line;overflow-wrap:anywhere}',
|
|
309
310
|
'.dshw_noticeClose{flex:none;width:24px;height:24px;border:0;border-radius:5px;background:transparent;color:inherit;font-size:18px;line-height:1;cursor:pointer}.dshw_noticeClose:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.06))}',
|
|
310
|
-
|
|
311
|
-
|
|
311
|
+
// Home-fit and compact modes are toggled by measured space (see the
|
|
312
|
+
// home-space effect in WalletChip), not by container queries:
|
|
313
|
+
// container-type:inline-size on a content-sized flex item detaches its
|
|
314
|
+
// width from the chip, so flex layouts resolve it to min-width (44px)
|
|
315
|
+
// even when the row has room.
|
|
316
|
+
'.dshw_anchorHome.dshw_fit .dshw_chipMain>span:not(.dshw_homePrimary){display:none}',
|
|
317
|
+
'.dshw_anchorHome.dshw_compact .dshw_chip{width:100%}.dshw_anchorHome.dshw_compact .dshw_chipMain{box-sizing:border-box;width:100%;min-width:0;overflow:hidden;justify-content:center;padding:0 3px}.dshw_anchorHome.dshw_compact .dshw_chipMain>span{display:none}.dshw_anchorHome.dshw_compact .dshw_chipMain>.dshw_homePrimary{display:inline;min-width:0;overflow:hidden;text-overflow:ellipsis}.dshw_anchorHome.dshw_compact .dshw_homePrimaryLabel{display:none}.dshw_anchorHome.dshw_compact .dshw_recharge{display:none}',
|
|
312
318
|
'@media (max-width:420px){.dshw_chipDocked:not(.dshw_chipVertical){max-width:calc(100vw - 4px);font-size:10px}.dshw_chipDocked:not(.dshw_chipVertical) .dshw_chipMain{gap:3px;padding:0 4px}.dshw_chipDocked:not(.dshw_chipVertical) .dshw_recharge{padding:0 4px}}'
|
|
313
319
|
].join('')
|
|
314
320
|
|
|
@@ -687,6 +693,18 @@ window.__ModuleLoader__.load({
|
|
|
687
693
|
return node || null
|
|
688
694
|
}
|
|
689
695
|
|
|
696
|
+
function isStackingContext(style) {
|
|
697
|
+
if (!style) return false
|
|
698
|
+
if (style.position === 'fixed' || style.position === 'sticky') return true
|
|
699
|
+
if (style.zIndex !== 'auto' && style.position !== 'static') return true
|
|
700
|
+
if (style.transform !== 'none' || style.filter !== 'none' || style.perspective !== 'none') return true
|
|
701
|
+
if (style.willChange === 'transform' || style.willChange === 'filter' || style.willChange === 'opacity' || style.willChange === 'z-index') return true
|
|
702
|
+
if (style.contain && style.contain !== 'none') return true
|
|
703
|
+
if (style.isolation === 'isolate') return true
|
|
704
|
+
if (style.opacity !== '1') return true
|
|
705
|
+
return false
|
|
706
|
+
}
|
|
707
|
+
|
|
690
708
|
function findComposerRect(node, viewportWidth, viewportHeight) {
|
|
691
709
|
var composer = findComposerNode(node, viewportWidth, viewportHeight)
|
|
692
710
|
return composer && typeof composer.getBoundingClientRect === 'function' ? composer.getBoundingClientRect() : null
|
|
@@ -799,6 +817,8 @@ window.__ModuleLoader__.load({
|
|
|
799
817
|
var [chipScale, setChipScale] = React.useState(function () {
|
|
800
818
|
try { return normalizeChipScale(compatibility.storage.getItem(CHIP_SCALE_KEY)) } catch (e) { return 1 }
|
|
801
819
|
})
|
|
820
|
+
var [homeMode, setHomeMode] = React.useState('full')
|
|
821
|
+
var chipLiftHostRef = React.useRef(null)
|
|
802
822
|
var [dataVisibility, setDataVisibility] = React.useState(function () {
|
|
803
823
|
try {
|
|
804
824
|
var savedVisibility = compatibility.storage.getItem(DATA_VISIBILITY_KEY)
|
|
@@ -855,6 +875,8 @@ window.__ModuleLoader__.load({
|
|
|
855
875
|
|
|
856
876
|
function saveChipScale(next) {
|
|
857
877
|
next = normalizeChipScale(next)
|
|
878
|
+
var cap = chipLayoutRef.current.dock === 'home' ? 1.2 : 1.25
|
|
879
|
+
if (next > cap) next = cap
|
|
858
880
|
chipScaleRef.current = next
|
|
859
881
|
setChipScale(next)
|
|
860
882
|
try { compatibility.storage.setItem(CHIP_SCALE_KEY, String(next)) } catch (e) { /* ignore */ }
|
|
@@ -1211,6 +1233,35 @@ window.__ModuleLoader__.load({
|
|
|
1211
1233
|
if (event.preventDefault) event.preventDefault()
|
|
1212
1234
|
}
|
|
1213
1235
|
|
|
1236
|
+
// A docked chip is position:fixed, but it still renders inside the host
|
|
1237
|
+
// composer subtree; hosts commonly wrap that subtree in a low stacking
|
|
1238
|
+
// context (dsh uses z-index:1), which caps the chip under neighbouring
|
|
1239
|
+
// top-level panels. The node must stay in place so React's delegated
|
|
1240
|
+
// events keep working, so instead lift the outermost trapping ancestor
|
|
1241
|
+
// context while any dock mode is active.
|
|
1242
|
+
useLayoutEffect(function () {
|
|
1243
|
+
if (chipLayout.dock === 'home') return
|
|
1244
|
+
var node = chipAnchorRef.current
|
|
1245
|
+
if (node === null || typeof window === 'undefined' || !window.getComputedStyle) return
|
|
1246
|
+
var outermost = null
|
|
1247
|
+
while (node && node !== document.body) {
|
|
1248
|
+
if (isStackingContext(window.getComputedStyle(node))) outermost = node
|
|
1249
|
+
node = node.parentElement
|
|
1250
|
+
}
|
|
1251
|
+
chipLiftHostRef.current = outermost
|
|
1252
|
+
if (outermost && outermost.classList) outermost.classList.add('dshw_chipLift')
|
|
1253
|
+
return function () {
|
|
1254
|
+
if (outermost && outermost.classList) outermost.classList.remove('dshw_chipLift')
|
|
1255
|
+
if (chipLiftHostRef.current === outermost) chipLiftHostRef.current = null
|
|
1256
|
+
}
|
|
1257
|
+
}, [chipLayout.dock])
|
|
1258
|
+
|
|
1259
|
+
// A stored 125% from a floating/side dock must come back down when the
|
|
1260
|
+
// chip returns to the space-constrained home row.
|
|
1261
|
+
React.useEffect(function () {
|
|
1262
|
+
if (chipLayout.dock === 'home' && chipScaleRef.current > 1.2) saveChipScale(1.2)
|
|
1263
|
+
}, [chipLayout.dock])
|
|
1264
|
+
|
|
1214
1265
|
useLayoutEffect(function () {
|
|
1215
1266
|
var node = chipRef.current
|
|
1216
1267
|
if (node === null) return
|
|
@@ -1218,6 +1269,55 @@ window.__ModuleLoader__.load({
|
|
|
1218
1269
|
var measured = { width: rect.width, height: rect.height, scale: chipScaleRef.current }
|
|
1219
1270
|
if (node.classList && node.classList.contains('dshw_chipVertical')) chipSizeRef.current.vertical = measured
|
|
1220
1271
|
else chipSizeRef.current.horizontal = measured
|
|
1272
|
+
}, [chipLayout.dock, chipScale, data, showOfficial, showThird, homeMode])
|
|
1273
|
+
|
|
1274
|
+
useLayoutEffect(function () {
|
|
1275
|
+
if (chipLayout.dock !== 'home') return
|
|
1276
|
+
var anchor = chipAnchorRef.current
|
|
1277
|
+
var chip = chipRef.current
|
|
1278
|
+
if (!anchor || !chip) return
|
|
1279
|
+
|
|
1280
|
+
function measureHomeMode() {
|
|
1281
|
+
var current = chipAnchorRef.current
|
|
1282
|
+
var chipNode = chipRef.current
|
|
1283
|
+
if (!current || !chipNode) return null
|
|
1284
|
+
// Try each tier in place and let the composer row's own flex pressure
|
|
1285
|
+
// accept or squeeze it: a tier fits when the chip's allocated width
|
|
1286
|
+
// matches its content width. All readings come from the chip itself
|
|
1287
|
+
// so the scale slider's zoom factor cancels out; the anchor's
|
|
1288
|
+
// parent slot wrapper can be display:contents, so measuring
|
|
1289
|
+
// ancestors is not reliable.
|
|
1290
|
+
var compact = current.classList.contains('dshw_compact')
|
|
1291
|
+
current.classList.remove('dshw_compact')
|
|
1292
|
+
current.classList.remove('dshw_fit')
|
|
1293
|
+
var mode
|
|
1294
|
+
if (chipNode.clientWidth >= chipNode.scrollWidth - 1) {
|
|
1295
|
+
mode = 'full'
|
|
1296
|
+
} else {
|
|
1297
|
+
current.classList.add('dshw_fit')
|
|
1298
|
+
mode = chipNode.clientWidth >= chipNode.scrollWidth - 1 ? 'fit' : 'compact'
|
|
1299
|
+
current.classList.remove('dshw_fit')
|
|
1300
|
+
}
|
|
1301
|
+
if (compact) current.classList.add('dshw_compact')
|
|
1302
|
+
return mode
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
function evaluateHomeSpace() {
|
|
1306
|
+
var next = measureHomeMode()
|
|
1307
|
+
if (next) setHomeMode(next)
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
evaluateHomeSpace()
|
|
1311
|
+
window.addEventListener('resize', evaluateHomeSpace)
|
|
1312
|
+
var observer = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(evaluateHomeSpace) : null
|
|
1313
|
+
if (observer) {
|
|
1314
|
+
observer.observe(anchor)
|
|
1315
|
+
observer.observe(chip)
|
|
1316
|
+
}
|
|
1317
|
+
return function () {
|
|
1318
|
+
window.removeEventListener('resize', evaluateHomeSpace)
|
|
1319
|
+
if (observer) observer.disconnect()
|
|
1320
|
+
}
|
|
1221
1321
|
}, [chipLayout.dock, chipScale, data, showOfficial, showThird])
|
|
1222
1322
|
|
|
1223
1323
|
useLayoutEffect(function () {
|
|
@@ -1377,6 +1477,9 @@ window.__ModuleLoader__.load({
|
|
|
1377
1477
|
var thirdTokens = third.tokens ? totalTokens(third.tokens) : 0
|
|
1378
1478
|
var low = showOfficial && snapshot.lowBalance === true
|
|
1379
1479
|
var chipDock = chipLayout.dock
|
|
1480
|
+
// The home toolbar row cannot fit the widest scale on narrow windows, so
|
|
1481
|
+
// cap the slider there; floating and side docks keep the full range.
|
|
1482
|
+
var scaleMaxPercent = chipDock === 'home' ? 120 : 125
|
|
1380
1483
|
var chipVertical = chipDock === 'left' || chipDock === 'right' || chipDock === 'content-left'
|
|
1381
1484
|
var chipClass = low ? 'dshw_chip dshw_chipLow' : 'dshw_chip'
|
|
1382
1485
|
var cssZoom = compatibility.supportsCssZoom()
|
|
@@ -1455,7 +1558,7 @@ window.__ModuleLoader__.load({
|
|
|
1455
1558
|
onClick: onRechargeClick
|
|
1456
1559
|
}, '\u2197\u5145') : null)
|
|
1457
1560
|
|
|
1458
|
-
var chipHost = React.createElement('span', { ref: chipAnchorRef, className: chipDock === 'home' ? 'dshw_anchor dshw_anchorHome' : 'dshw_anchor' }, chip)
|
|
1561
|
+
var chipHost = React.createElement('span', { ref: chipAnchorRef, className: chipDock === 'home' ? 'dshw_anchor dshw_anchorHome' + (homeMode === 'compact' ? ' dshw_compact' : homeMode === 'fit' ? ' dshw_fit' : '') : 'dshw_anchor' }, chip)
|
|
1459
1562
|
var snapPreviewElement = snapPreview ? React.createElement('div', {
|
|
1460
1563
|
className: snapPreview.vertical ? 'dshw_snapPreview dshw_snapPreviewVertical' : 'dshw_snapPreview',
|
|
1461
1564
|
style: { left: snapPreview.x, top: snapPreview.y, width: snapPreview.width, height: snapPreview.height },
|
|
@@ -1531,7 +1634,7 @@ window.__ModuleLoader__.load({
|
|
|
1531
1634
|
className: 'dshw_scaleInput',
|
|
1532
1635
|
type: 'range',
|
|
1533
1636
|
min: '75',
|
|
1534
|
-
max:
|
|
1637
|
+
max: String(scaleMaxPercent),
|
|
1535
1638
|
step: '5',
|
|
1536
1639
|
value: String(Math.round(chipScale * 100)),
|
|
1537
1640
|
'aria-label': '钱包芯片比例',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepseek-harness-wallet",
|
|
3
3
|
"description": "Local-first account monitoring, usage accounting, official recharge, completion reminders, flexible layout, and host-gated session controls for DeepSeek Harness.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"exports": {
|