dsh-hyperliquid 0.4.2 → 0.4.3

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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.3 — 2026-10-17
4
+
5
+ - 趋势线可分别向左、向右延长(浮动工具条两个开关,agent 工具 `extendLeft` / `extendRight`);价格提醒按延长后的线判断,延长的线不参与屏幕外剔除。
6
+ - 「点击没反应」根因补充验证:0.1.0 两次点击间隔 300ms、450ms 同样漏画 20/20,550ms 0/20,分界与图表库 500ms 双击窗口一致;当前版本同样间隔 0 漏画。
7
+
3
8
  ## 0.4.2 — 2026-10-17
4
9
 
5
10
  - 画线对象属性对齐 TradingView:按周期显示(仅本周期,水平线的轴价格标签同样隐藏)、文本与标注气泡字号(10–32px)与粗体 / 斜体、矩形 / 圆 / 三角 / 通道 / 斐波那契 / 区间等的背景填充浓淡;浮动工具条、agent 工具参数、撤销与复制都支持。限定周期的画线在其他周期不绘制但保留在画线列表。
package/client.js CHANGED
@@ -17908,9 +17908,9 @@ function drawingLabel(kind, points2, price) {
17908
17908
  const when = new Date(first.time).toLocaleString(tr("zh-CN", "en-US"), { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false });
17909
17909
  return `${name} ${when}`;
17910
17910
  }
17911
- function clipLine(a, b, w, h, from) {
17911
+ function clipLine(a, b, w, h, from, to = Infinity) {
17912
17912
  const dx = b.x - a.x, dy = b.y - a.y;
17913
- let t0 = from, t1 = Infinity;
17913
+ let t0 = from, t1 = to;
17914
17914
  for (const [p, q] of [[-dx, a.x], [dx, w - a.x], [-dy, a.y], [dy, h - a.y]]) {
17915
17915
  if (p === 0) {
17916
17916
  if (q < 0) return null;
@@ -17992,7 +17992,7 @@ function guide(a, b, value, key3, text) {
17992
17992
  }
17993
17993
  var BADGE_PATHS = { alert: "M6 16V11a6 6 0 0 1 12 0v5l2 2H4zM10 20a2 2 0 0 0 4 0", shared: "M4 9h13l-3-3M20 15H7l3 3" };
17994
17994
  var DASH = { solid: void 0, dashed: "7 5", dotted: "1.5 4" };
17995
- var DrawingShape = React7.memo(function DrawingShape2({ kind, points: points2, label, text: textValue, className, view, anchors = false, interactive = false, color, lineWidth, lineStyle, id, alert, shared, rows, valueArea, levels, fontSize, bold, italic, fillOpacity }) {
17995
+ var DrawingShape = React7.memo(function DrawingShape2({ kind, points: points2, label, text: textValue, className, view, anchors = false, interactive = false, color, lineWidth, lineStyle, id, alert, shared, rows, valueArea, levels, fontSize, bold, italic, fillOpacity, extendLeft, extendRight }) {
17996
17996
  const k = (fontSize ?? 12) / 12;
17997
17997
  const badges = [...alert ? ["alert"] : [], ...shared ? ["shared"] : []];
17998
17998
  const { width: w, height: h } = view;
@@ -18014,9 +18014,17 @@ var DrawingShape = React7.memo(function DrawingShape2({ kind, points: points2, l
18014
18014
  body = /* @__PURE__ */ React7.createElement("line", { x1: p[0].x, x2: p[0].x, y1: "0", y2: h });
18015
18015
  handles = [{ x: p[0].x, y: Math.min(h - 12, Math.max(12, p[0].y)) }];
18016
18016
  break;
18017
- case "trend":
18018
- body = p[1] ? /* @__PURE__ */ React7.createElement("line", { x1: p[0].x, y1: p[0].y, x2: p[1].x, y2: p[1].y }) : null;
18017
+ case "trend": {
18018
+ if (!p[1]) break;
18019
+ if (!extendLeft && !extendRight) {
18020
+ body = /* @__PURE__ */ React7.createElement("line", { x1: p[0].x, y1: p[0].y, x2: p[1].x, y2: p[1].y });
18021
+ break;
18022
+ }
18023
+ const [l, r] = p[0].x <= p[1].x ? [p[0], p[1]] : [p[1], p[0]];
18024
+ const seg = clipLine(l, r, w, h, extendLeft ? -Infinity : 0, extendRight ? Infinity : 1);
18025
+ body = seg ? /* @__PURE__ */ React7.createElement("line", { x1: seg[0].x, y1: seg[0].y, x2: seg[1].x, y2: seg[1].y }) : null;
18019
18026
  break;
18027
+ }
18020
18028
  case "ray":
18021
18029
  case "extended": {
18022
18030
  if (!p[1]) break;
@@ -18435,7 +18443,7 @@ function DrawToolbar({ mark, globallyLocked, onEdit, onRemove, onClose, onClone,
18435
18443
  onClick: () => onEdit({ lineStyle: value })
18436
18444
  },
18437
18445
  /* @__PURE__ */ React8.createElement("svg", { viewBox: "0 0 18 18", width: "16", height: "16", "aria-hidden": "true" }, /* @__PURE__ */ React8.createElement("line", { x1: "2", x2: "16", y1: "9", y2: "9", stroke: "currentColor", strokeWidth: "2", strokeDasharray: value === "dashed" ? "4 3" : value === "dotted" ? "1 3" : void 0, strokeLinecap: "round" }))
18438
- ))) : null, FONT_KINDS.includes(mark.kind) || FILL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement("span", { className: "dhl-draw-toolbar-group", role: "group", "aria-label": tr("\u6587\u5B57\u4E0E\u586B\u5145", "Text and fill") }, FONT_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(Select, { "aria-label": tr("\u5B57\u53F7", "Font size"), title: tr("\u5B57\u53F7", "Font size"), value: String(mark.fontSize ?? 12), disabled: locked, onChange: (event) => onEdit({ fontSize: Number(event.target.value) }) }, [10, 12, 14, 18, 24, 32].map((size3) => /* @__PURE__ */ React8.createElement("option", { key: size3, value: size3 }, `${size3}px`))) : null, FONT_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.bold ? "on" : "", "aria-pressed": Boolean(mark.bold), disabled: locked, "aria-label": tr("\u7C97\u4F53", "Bold"), title: tr("\u7C97\u4F53", "Bold"), onClick: () => onEdit({ bold: !mark.bold }) }, /* @__PURE__ */ React8.createElement("b", null, "B")), /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.italic ? "on" : "", "aria-pressed": Boolean(mark.italic), disabled: locked, "aria-label": tr("\u659C\u4F53", "Italic"), title: tr("\u659C\u4F53", "Italic"), onClick: () => onEdit({ italic: !mark.italic }) }, /* @__PURE__ */ React8.createElement("i", null, "I"))) : null, FILL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(Select, { "aria-label": tr("\u80CC\u666F\u586B\u5145", "Background fill"), title: tr("\u80CC\u666F\u586B\u5145", "Background fill"), value: String(mark.fillOpacity ?? (mark.kind === "fib" ? 0.07 : 0.08)), disabled: locked, onChange: (event) => onEdit({ fillOpacity: Number(event.target.value) }) }, [[0, "\u65E0\u586B\u5145", "No fill"], [mark.kind === "fib" ? 0.07 : 0.08, "\u6DE1", "Light"], [0.18, "\u4E2D", "Medium"], [0.32, "\u6D53", "Strong"]].map(([value, zh, en]) => /* @__PURE__ */ React8.createElement("option", { key: String(value), value: String(value) }, tr(String(zh), String(en))))) : null) : null, FIB_LEVEL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement("span", { className: "dhl-draw-toolbar-group", role: "group", "aria-label": tr("\u6590\u6CE2\u90A3\u5951\u5C42\u7EA7", "Fibonacci levels") }, /* @__PURE__ */ React8.createElement(
18446
+ ))) : null, mark.kind === "trend" ? /* @__PURE__ */ React8.createElement("span", { className: "dhl-draw-toolbar-group", role: "group", "aria-label": tr("\u5EF6\u957F", "Extend") }, /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.extendLeft ? "on" : "", "aria-pressed": Boolean(mark.extendLeft), disabled: locked, "aria-label": tr("\u5411\u5DE6\u5EF6\u957F", "Extend left"), title: tr("\u5411\u5DE6\u5EF6\u957F", "Extend left"), onClick: () => onEdit({ extendLeft: !mark.extendLeft }) }, /* @__PURE__ */ React8.createElement("svg", { viewBox: "0 0 24 24", width: "15", height: "15", fill: "none", stroke: "currentColor", strokeWidth: "1.8", "aria-hidden": "true" }, /* @__PURE__ */ React8.createElement("path", { d: "M3 12h13", strokeDasharray: "2 2.5" }), /* @__PURE__ */ React8.createElement("path", { d: "M14 12h7" }), /* @__PURE__ */ React8.createElement("circle", { cx: "14", cy: "12", r: "1.8" }), /* @__PURE__ */ React8.createElement("path", { d: "M6 9l-3 3 3 3" }))), /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.extendRight ? "on" : "", "aria-pressed": Boolean(mark.extendRight), disabled: locked, "aria-label": tr("\u5411\u53F3\u5EF6\u957F", "Extend right"), title: tr("\u5411\u53F3\u5EF6\u957F", "Extend right"), onClick: () => onEdit({ extendRight: !mark.extendRight }) }, /* @__PURE__ */ React8.createElement("svg", { viewBox: "0 0 24 24", width: "15", height: "15", fill: "none", stroke: "currentColor", strokeWidth: "1.8", "aria-hidden": "true" }, /* @__PURE__ */ React8.createElement("path", { d: "M3 12h7" }), /* @__PURE__ */ React8.createElement("path", { d: "M10 12h11", strokeDasharray: "2 2.5" }), /* @__PURE__ */ React8.createElement("circle", { cx: "10", cy: "12", r: "1.8" }), /* @__PURE__ */ React8.createElement("path", { d: "M18 9l3 3-3 3" })))) : null, FONT_KINDS.includes(mark.kind) || FILL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement("span", { className: "dhl-draw-toolbar-group", role: "group", "aria-label": tr("\u6587\u5B57\u4E0E\u586B\u5145", "Text and fill") }, FONT_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(Select, { "aria-label": tr("\u5B57\u53F7", "Font size"), title: tr("\u5B57\u53F7", "Font size"), value: String(mark.fontSize ?? 12), disabled: locked, onChange: (event) => onEdit({ fontSize: Number(event.target.value) }) }, [10, 12, 14, 18, 24, 32].map((size3) => /* @__PURE__ */ React8.createElement("option", { key: size3, value: size3 }, `${size3}px`))) : null, FONT_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.bold ? "on" : "", "aria-pressed": Boolean(mark.bold), disabled: locked, "aria-label": tr("\u7C97\u4F53", "Bold"), title: tr("\u7C97\u4F53", "Bold"), onClick: () => onEdit({ bold: !mark.bold }) }, /* @__PURE__ */ React8.createElement("b", null, "B")), /* @__PURE__ */ React8.createElement("button", { type: "button", className: mark.italic ? "on" : "", "aria-pressed": Boolean(mark.italic), disabled: locked, "aria-label": tr("\u659C\u4F53", "Italic"), title: tr("\u659C\u4F53", "Italic"), onClick: () => onEdit({ italic: !mark.italic }) }, /* @__PURE__ */ React8.createElement("i", null, "I"))) : null, FILL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement(Select, { "aria-label": tr("\u80CC\u666F\u586B\u5145", "Background fill"), title: tr("\u80CC\u666F\u586B\u5145", "Background fill"), value: String(mark.fillOpacity ?? (mark.kind === "fib" ? 0.07 : 0.08)), disabled: locked, onChange: (event) => onEdit({ fillOpacity: Number(event.target.value) }) }, [[0, "\u65E0\u586B\u5145", "No fill"], [mark.kind === "fib" ? 0.07 : 0.08, "\u6DE1", "Light"], [0.18, "\u4E2D", "Medium"], [0.32, "\u6D53", "Strong"]].map(([value, zh, en]) => /* @__PURE__ */ React8.createElement("option", { key: String(value), value: String(value) }, tr(String(zh), String(en))))) : null) : null, FIB_LEVEL_KINDS.includes(mark.kind) ? /* @__PURE__ */ React8.createElement("span", { className: "dhl-draw-toolbar-group", role: "group", "aria-label": tr("\u6590\u6CE2\u90A3\u5951\u5C42\u7EA7", "Fibonacci levels") }, /* @__PURE__ */ React8.createElement(
18439
18447
  "input",
18440
18448
  {
18441
18449
  className: "dhl-draw-toolbar-text dhl-fib-levels",
@@ -19666,7 +19674,7 @@ function CandleChart({ candles, marks, indicators, expanded, resetToken, drawMod
19666
19674
  const cloneOf = React10.useCallback((mark) => {
19667
19675
  const line = timelineRef.current;
19668
19676
  const shifted = markPoints(mark).map((point) => ({ time: line.toTime(line.toLogical(point.time) + 5), price: point.price }));
19669
- const style = Object.fromEntries(Object.entries({ color: mark.color, lineWidth: mark.lineWidth, lineStyle: mark.lineStyle, levels: mark.levels, rows: mark.rows, valueArea: mark.valueArea, fontSize: mark.fontSize, bold: mark.bold, italic: mark.italic, fillOpacity: mark.fillOpacity, visibleIntervals: mark.visibleIntervals }).filter(([, value]) => value != null));
19677
+ const style = Object.fromEntries(Object.entries({ color: mark.color, lineWidth: mark.lineWidth, lineStyle: mark.lineStyle, levels: mark.levels, rows: mark.rows, valueArea: mark.valueArea, fontSize: mark.fontSize, bold: mark.bold, italic: mark.italic, extendLeft: mark.extendLeft, extendRight: mark.extendRight, fillOpacity: mark.fillOpacity, visibleIntervals: mark.visibleIntervals }).filter(([, value]) => value != null));
19670
19678
  return { kind: mark.kind, geometry: geometryPatch(mark.kind, shifted), style, label: mark.label };
19671
19679
  }, []);
19672
19680
  const clipboard = React10.useRef(null);
@@ -19915,7 +19923,7 @@ function CandleChart({ candles, marks, indicators, expanded, resetToken, drawMod
19915
19923
  const selected = selectedId === mark.id || group.includes(mark.id);
19916
19924
  if (interval && mark.visibleIntervals?.length && !mark.visibleIntervals.includes(interval)) return null;
19917
19925
  const clampedDecoration = !(mark.source === "user" || mark.kind === "level") || Boolean(mark.alert) || Boolean(mark.shared);
19918
- if (!selected && !clampedDecoration && FINITE_KINDS.has(mark.kind) && offscreen(shown, view)) return null;
19926
+ if (!selected && !clampedDecoration && !mark.extendLeft && !mark.extendRight && FINITE_KINDS.has(mark.kind) && offscreen(shown, view)) return null;
19919
19927
  return /* @__PURE__ */ React10.createElement(
19920
19928
  DrawingShape,
19921
19929
  {
@@ -19941,7 +19949,9 @@ function CandleChart({ candles, marks, indicators, expanded, resetToken, drawMod
19941
19949
  fontSize: mark.fontSize,
19942
19950
  bold: mark.bold,
19943
19951
  italic: mark.italic,
19944
- fillOpacity: mark.fillOpacity
19952
+ fillOpacity: mark.fillOpacity,
19953
+ extendLeft: mark.extendLeft,
19954
+ extendRight: mark.extendRight
19945
19955
  }
19946
19956
  );
19947
19957
  }), /* @__PURE__ */ React10.createElement("g", { className: "dhl-fills" }, fills.map((event) => {
@@ -20017,7 +20027,7 @@ function CandleChart({ candles, marks, indicators, expanded, resetToken, drawMod
20017
20027
  var React11 = __toESM(require("react"), 1);
20018
20028
  var HISTORY_LIMIT = 100;
20019
20029
  var GEOMETRY = ["price", "fromTime", "fromPrice", "toTime", "toPrice", "points"];
20020
- var STYLE = ["color", "lineWidth", "lineStyle", "locked", "hidden", "shared", "alert", "rows", "valueArea", "levels", "visibleIntervals", "fontSize", "fillOpacity", "bold", "italic"];
20030
+ var STYLE = ["color", "lineWidth", "lineStyle", "locked", "hidden", "shared", "alert", "rows", "valueArea", "levels", "visibleIntervals", "fontSize", "fillOpacity", "bold", "italic", "extendLeft", "extendRight"];
20021
20031
  var FLAGS = /* @__PURE__ */ new Set(["locked", "hidden", "shared", "alert"]);
20022
20032
  function recreateRequest(mark) {
20023
20033
  const out = { kind: mark.kind, label: mark.label, role: mark.role, coin: mark.coin, interval: mark.interval };
@@ -1,6 +1,6 @@
1
1
  export type DrawingKind = 'level' | 'hray' | 'vline' | 'text' | 'trend' | 'ray' | 'extended' | 'fib' | 'rect' | 'measure' | 'channel' | 'long' | 'short' | 'fibext' | 'fibchannel' | 'fibtime' | 'gannfan' | 'pitchfork' | 'regression' | 'vprofile' | 'arrow' | 'callout' | 'circle' | 'triangle' | 'brush' | 'crossline' | 'pricelabel' | 'infoline' | 'trendangle' | 'pricerange' | 'daterange' | 'elliott' | 'elliottabc' | 'xabcd' | 'abcd' | 'headshoulders' | 'gannbox' | 'gannsquare' | 'schiff' | 'modschiff' | 'icon'
2
2
  export type LineStyleName = 'solid' | 'dashed' | 'dotted'
3
- export interface DrawingStyle { visibleIntervals?: string[]; fontSize?: number; bold?: boolean; italic?: boolean; fillOpacity?: number; levels?: number[]; rows?: number; valueArea?: number; color?: string; lineWidth?: number; lineStyle?: LineStyleName; locked?: boolean; hidden?: boolean; shared?: boolean; alert?: boolean }
3
+ export interface DrawingStyle { visibleIntervals?: string[]; fontSize?: number; bold?: boolean; italic?: boolean; extendLeft?: boolean; extendRight?: boolean; fillOpacity?: number; levels?: number[]; rows?: number; valueArea?: number; color?: string; lineWidth?: number; lineStyle?: LineStyleName; locked?: boolean; hidden?: boolean; shared?: boolean; alert?: boolean }
4
4
  export declare const DRAWING_POINTS: Record<DrawingKind, number>
5
5
  export declare const DRAWING_KINDS: DrawingKind[]
6
6
  export declare const DRAWING_CLICKS: Record<DrawingKind, number>
@@ -106,7 +106,8 @@ export function linePriceAt(mark, time) {
106
106
  if (!a) return null
107
107
  if (mark.kind === 'hray') return time >= a.time ? a.price : null
108
108
  if (!b || b.time === a.time) return null
109
- if (mark.kind === 'trend' && (time < Math.min(a.time, b.time) || time > Math.max(a.time, b.time))) return null
109
+ // A trend line can be extended left and/or right (TradingView's per-line extend option).
110
+ if (mark.kind === 'trend' && ((!mark.extendLeft && time < Math.min(a.time, b.time)) || (!mark.extendRight && time > Math.max(a.time, b.time)))) return null
110
111
  if (mark.kind === 'ray' && (time - a.time) * (b.time - a.time) < 0) return null
111
112
  return a.price + (b.price - a.price) * (time - a.time) / (b.time - a.time)
112
113
  }
@@ -206,6 +207,12 @@ export function drawingStyle(request) {
206
207
  if (!Number.isInteger(size) || size < 10 || size > 32) throw new Error('字号必须为 10-32 的整数')
207
208
  style.fontSize = size
208
209
  }
210
+ for (const flag of ['extendLeft', 'extendRight']) {
211
+ if (request?.[flag] == null) continue
212
+ if (request?.kind != null && request.kind !== 'trend') throw new Error(`${flag} 只适用于 trend`)
213
+ if (typeof request[flag] !== 'boolean') throw new Error(`${flag} 必须为布尔值`)
214
+ style[flag] = request[flag]
215
+ }
209
216
  for (const flag of ['bold', 'italic']) {
210
217
  if (request?.[flag] == null) continue
211
218
  if (request?.kind != null && !FONT_KINDS.includes(request.kind)) throw new Error(`${flag} 只适用于 ${FONT_KINDS.join('/')}`)
package/lib/remote.js CHANGED
@@ -575,7 +575,7 @@ export class HyperRemote extends TypertRemoteService {
575
575
  const fields = { ...drawingStyle({ ...patch, kind: current.kind }) }
576
576
  if (patch?.alert === true) fields.alertTriggeredAt = undefined
577
577
  // null clears a style back to its default (undo of a first restyle relies on this).
578
- for (const key of ['color', 'lineWidth', 'lineStyle', 'rows', 'valueArea', 'levels', 'visibleIntervals', 'fontSize', 'fillOpacity', 'bold', 'italic']) if (key in patch && patch[key] === null) fields[key] = undefined
578
+ for (const key of ['color', 'lineWidth', 'lineStyle', 'rows', 'valueArea', 'levels', 'visibleIntervals', 'fontSize', 'fillOpacity', 'bold', 'italic', 'extendLeft', 'extendRight']) if (key in patch && patch[key] === null) fields[key] = undefined
579
579
  if (geometryKeys.some((key) => key in patch)) Object.assign(fields, drawingGeometry(current.kind, merged))
580
580
  if ('label' in patch) {
581
581
  const label = String(patch.label ?? '').trim()
package/lib/tools.js CHANGED
@@ -254,6 +254,7 @@ function buildTools(remote) {
254
254
  lineWidth: { type: 'number', description: '画线线宽 1-4' },
255
255
  visibleIntervals: { type: 'array', items: { type: 'string' }, description: '只在这些周期显示(如 ["4h","1d"]);省略=所有周期' },
256
256
  fontSize: { type: 'number', description: 'kind=text/callout:字号 10-32' },
257
+ extendLeft: { type: 'boolean', description: 'kind=trend:向左延长' }, extendRight: { type: 'boolean', description: 'kind=trend:向右延长' },
257
258
  bold: { type: 'boolean', description: 'kind=text/callout:粗体' }, italic: { type: 'boolean', description: 'kind=text/callout:斜体' },
258
259
  fillOpacity: { type: 'number', description: '矩形/圆/三角形/通道/斐波那契/区间等的背景填充透明度 0-0.6(0=无填充)' },
259
260
  levels: { type: 'array', items: { type: 'number' }, description: 'kind=fib/fibext/fibchannel:自定义斐波那契层级,如 [0,0.382,0.5,0.618,1,1.618]' },
@@ -310,7 +311,7 @@ function buildTools(remote) {
310
311
  return { text: `已移除均线:${maLabel(removed)}(${removed.id})`, line: removed }
311
312
  }
312
313
  if (args?.action === 'update') {
313
- const patch = Object.fromEntries(['points', 'price', 'fromTime', 'fromPrice', 'toTime', 'toPrice', 'label', 'color', 'lineWidth', 'lineStyle', 'locked', 'hidden', 'shared', 'alert', 'rows', 'valueArea', 'levels', 'visibleIntervals', 'fontSize', 'fillOpacity', 'bold', 'italic'].filter((key) => args?.[key] != null).map((key) => [key, args[key]]))
314
+ const patch = Object.fromEntries(['points', 'price', 'fromTime', 'fromPrice', 'toTime', 'toPrice', 'label', 'color', 'lineWidth', 'lineStyle', 'locked', 'hidden', 'shared', 'alert', 'rows', 'valueArea', 'levels', 'visibleIntervals', 'fontSize', 'fillOpacity', 'bold', 'italic', 'extendLeft', 'extendRight'].filter((key) => args?.[key] != null).map((key) => [key, args[key]]))
314
315
  const mark = remote.editChartMark(args?.id, patch, sessionId)
315
316
  return { text: `已更新${DRAWING_NAMES[mark.kind] ?? mark.kind}:${mark.label}(${mark.id})`, mark }
316
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-hyperliquid",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Hyperliquid trading desk for the DeepSeek Harness (dsh) - market workspace, native agent conversation and guarded live / paper trading over the Hyperliquid API.",
5
5
  "icon": "./icon.svg",
6
6
  "type": "module",