dsh-input-traffic 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -15,6 +15,10 @@
15
15
 
16
16
  A cordis client plugin assembled via the `dsh plugin` command and a bundle patch — no dsh source changes, no PR required.
17
17
 
18
+ > 💡 **Why "Freeze session" is recommended**: DeepSeek moved to **peak/off-peak billing** on 2026-08-17 — the peak window (Beijing time 09:00-12:00, 14:00-18:00) costs **2×** the off-peak rate (all other hours, including lunch, night, weekends and holidays). If a long-running session spans the expensive window, manually freezing pauses API consumption and resuming off-peak can save up to **50%**.
19
+ >
20
+ > **Suggested pairing for now**: use it together with a **reminder** plugin (e.g. [dsh-notify](https://github.com/zhengjy01/dsh-notify), desktop notifications when it is time to freeze/resume) and a **billing/usage** plugin (e.g. [dsh-deepseek-usage](https://github.com/yyb16yyb-hub/dsh-deepseek-usage), [dsh-cost-tracker](https://github.com/yflmq001/dsh-cost-tracker), [dsh-billing-balance](https://github.com/YZz-S/dsh-billing-balance), to verify actual spend around a freeze) — a "remind → freeze → resume off-peak → verify" saving loop.
21
+
18
22
  ## What it does
19
23
 
20
24
  - **Three tiers coexist**: while the agent is busy, every input lands in a waiting area first, then you choose when it enters the conversation — no longer a single "interrupt" or a single "queue":
@@ -27,6 +31,7 @@ A cordis client plugin assembled via the `dsh plugin` command and a bundle patch
27
31
  - **Edits are never lost**: if saving an edit fails (the agent already claimed the message), the edited content automatically moves back to the composer; an occupied draft is never overwritten.
28
32
  - **Peak-hour freeze**: a "Freeze session" button on the composer's right — near DeepSeek peak pricing hours (09:00-12:00, 14:00-18:00) it pauses API consumption: the current turn finishes naturally, then the unsent queue is frozen; "Resume session" continues during off-peak hours.
29
33
  - **Official behavior takeover**: while the plugin is mounted, the official "busy-Enter behavior" settings row is hidden (Enter stays queue-later).
34
+ - **Day/night auto-adapt**: the dock and the freeze button use dsh's official semantic tokens (`--dsw-alias-*`) exclusively, so they follow the system dark mode / dsh dark theme automatically — in dark mode they switch to a **dark-gray surface with inverted (white) text**, with no configuration (see "Day/night mode").
30
35
 
31
36
  ## UI preview
32
37
 
@@ -55,7 +60,11 @@ Layout sketch of the waiting area and the freeze button in a session page:
55
60
 
56
61
  > Why red is cancel + remove + resend: the harness inbox rejects inserting a message that is already pending; steering the original message after an interrupt would be rejected and strand the message (see FAQ).
57
62
 
58
- ## Session freeze / resume (peak-hour pause)
63
+ ## Session freeze / resume (peak-hour pause) ⭐ Recommended
64
+
65
+ > **Cost-saving role**: this is the plugin's **core recommended feature** for DeepSeek's peak/off-peak billing (effective 2026-08-17) — the peak window (09:00-12:00, 14:00-18:00) costs double, off-peak is half price. Freezing pauses non-urgent work until off-peak hours, directly avoiding the expensive window; long-running sessions can save up to half the cost.
66
+ >
67
+ > **Suggested pairing**: a **reminder** plugin (e.g. [dsh-notify](https://github.com/zhengjy01/dsh-notify)) notifies you to freeze/resume when entering or leaving the peak window; a **billing/usage** plugin (e.g. [dsh-deepseek-usage](https://github.com/yyb16yyb-hub/dsh-deepseek-usage), [dsh-cost-tracker](https://github.com/yflmq001/dsh-cost-tracker), [dsh-billing-balance](https://github.com/YZz-S/dsh-billing-balance)) verifies the actual spend around a freeze.
59
68
 
60
69
  The "Freeze session / Resume session" button on the composer's right (beside the send button) pauses API consumption near DeepSeek peak pricing hours:
61
70
 
@@ -87,6 +96,14 @@ When editing a queued message (inline):
87
96
  - **Shortcuts**: `Enter` saves, `Shift+Enter` inserts a newline, `Esc` cancels (composition input is protected from accidental saves);
88
97
  - **Failure fallback**: if the save fails because the agent already claimed the message (e.g. "started sending"), the edited content automatically moves back to the composer with a notice — **nothing is lost**; the back-fill only happens when the composer is empty, so an existing draft is never overwritten.
89
98
 
99
+ ## Day/night mode (automatic dark adaptation)
100
+
101
+ The dock and the freeze button **no longer use hand-drawn colors** — they reference dsh's official semantic tokens (`--dsw-alias-*`: `bg-layer-*` / `border-l*` / `label-*` / `interactive-bg-hover` / `state-success|warn|error-primary`) maintained by the dsh theme system:
102
+
103
+ - **Automatic follow**: dsh's default theme preference is "system" — when the OS switches to dark mode (or you pick a dark theme in dsh settings), `body[data-ds-dark-theme]` takes effect and the tokens switch to the dark palette, so the dock becomes a **dark-gray surface with inverted (white) text** and the tier colors use the official dark-adapted values (contrast is guaranteed by dsh);
104
+ - **No configuration**: the plugin does not watch the system and adds no settings — light/dark is fully delegated to the dsh theme; the day appearance is unchanged;
105
+ - **Scope**: the waiting-area dock (including the frozen banner / frozen list) and the "Freeze session" button on the composer's right.
106
+
90
107
  ## Installation
91
108
 
92
109
  ```sh
@@ -149,7 +166,7 @@ npm run lint:fix # auto-fix what can be fixed
149
166
  - 🔴 Red = interrupt — stop the current action, the message is processed right away;
150
167
  - 🟢 Green = keep queued (the default); on an already-steered message, green revokes it back to the queue;
151
168
  3. Reorder / re-edit: use move up/down, "Edit in composer", or the multi-line inline editor (Enter saves, Shift+Enter newline);
152
- 4. Near peak hours: press "Freeze session" on the composer's right; the session pauses after the current turn; press "Resume session" during off-peak hours to continue.
169
+ 4. **Cost-saving key (recommended)**: near the peak window (09:00-12:00, 14:00-18:00), press "Freeze session" on the composer's right; the session pauses after the current turn, avoiding the expensive window; press "Resume session" off-peak to continue. Pair with reminder / billing plugins (see "Recommended" above).
153
170
 
154
171
  ## FAQ
155
172
 
package/README.md CHANGED
@@ -15,6 +15,10 @@
15
15
 
16
16
  无需修改 dsh 源码、无需提 PR:`dsh plugin` 命令组装 + bundle patch 装配的 cordis client 插件。
17
17
 
18
+ > 💡 **为什么推荐「冻结会话」**:DeepSeek 已于 2026-08-17 实行**峰谷计费**——高峰时段(北京时间 9:00-12:00、14:00-18:00)单价为闲时(其余时段,含午间、夜间、周末与节假日)的 **2 倍**。长跑型会话若跨越高价窗口,手动冻结暂停 API 消耗、错峰再恢复,费用最多可省 **50%**。
19
+ >
20
+ > **目前建议搭配**:配合**一般提醒**插件(如 [dsh-notify](https://github.com/zhengjy01/dsh-notify),到点桌面提醒「该冻结/该恢复」)与**计费统计**插件(如 [dsh-deepseek-usage](https://github.com/yyb16yyb-hub/dsh-deepseek-usage)、[dsh-cost-tracker](https://github.com/yflmq001/dsh-cost-tracker)、[dsh-billing-balance](https://github.com/YZz-S/dsh-billing-balance),核对冻结前后的实际花费),形成「提醒 → 冻结 → 错峰恢复 → 对账」的省钱闭环。
21
+
18
22
  ## 它能做什么
19
23
 
20
24
  - **三档插入并存**:智能体忙碌时,每一条输入都先进入等待区,再按需选择何时进入对话——不再只有一个"打断"或只有一个"排队":
@@ -27,6 +31,7 @@
27
31
  - **编辑不丢内容**:编辑保存失败(消息已被 agent 认领)时,编辑内容自动退回主输入框,不会丢失;主输入框已有内容时不覆盖。
28
32
  - **高峰期冻结**:输入框右侧「冻结会话」按钮——邻近 DeepSeek 高峰收费时段(9:00-12:00、14:00-18:00)时主动暂停 API 消耗:当前轮次自然完成后暂停,未发送队列冻结保存;「恢复会话」后在非高价时间继续处理。
29
33
  - **接管官方行为**:插件生效时,官方设置面板的「繁忙时 Enter 键行为」设置行不再显示(Enter 行为固定为绿色排队)。
34
+ - **日夜自动适配**:队列框与冻结按钮全部改用 dsh 官方语义 token(`--dsw-alias-*`),自动跟随系统深色模式 / dsh 暗色主题——深色下自动变为**深灰底 + 白色反色字**,无需任何设置(见「日夜模式」)。
30
35
 
31
36
  ## 界面预览
32
37
 
@@ -55,7 +60,11 @@
55
60
 
56
61
  > 红色为什么是 cancel + remove + resend:harness 的 inbox 禁止重复插入同一条消息,打断后直接 steer 会被拒绝导致消息滞留(详见「常见问题」)。
57
62
 
58
- ## 会话冻结 / 恢复(高峰期暂停)
63
+ ## 会话冻结 / 恢复(高峰期暂停)⭐ 推荐
64
+
65
+ > **省钱定位**:这是本插件面向 DeepSeek 峰谷计费(2026-08-17 生效)的**核心推荐功能**——高峰时段(9:00-12:00、14:00-18:00)单价翻倍、闲时半价。手动冻结把不紧急的生成「暂停」到闲时再恢复,直接规避高价窗口,长跑型会话最多省一半费用。
66
+ >
67
+ > **建议搭配**:**一般提醒**插件(如 [dsh-notify](https://github.com/zhengjy01/dsh-notify))在进入/离开高峰时段时提醒你手动冻结/恢复;**计费统计**插件(如 [dsh-deepseek-usage](https://github.com/yyb16yyb-hub/dsh-deepseek-usage)、[dsh-cost-tracker](https://github.com/yflmq001/dsh-cost-tracker)、[dsh-billing-balance](https://github.com/YZz-S/dsh-billing-balance))在冻结前后核对实际花费。
59
68
 
60
69
  输入框右侧(发送按钮旁)的「冻结会话 / 恢复会话」按钮,用于即将进入 DeepSeek 高峰收费时段时暂停 API 消耗:
61
70
 
@@ -87,6 +96,14 @@
87
96
  - **快捷键**:`Enter` 保存,`Shift+Enter` 换行,`Esc` 取消(中文输入法组合期间不会误保存);
88
97
  - **失败兜底**:保存时若消息已被 agent 认领(如「已经开始发送」),编辑内容自动退回主输入框并提示,**不会丢失**;仅当主输入框为空时回填,已有草稿不被覆盖。
89
98
 
99
+ ## 日夜模式(自动适配深色)
100
+
101
+ 队列框与冻结按钮的配色**不再使用自绘颜色**,全部改为引用 dsh 官方语义 token(`--dsw-alias-*`:`bg-layer-*` / `border-l*` / `label-*` / `interactive-bg-hover` / `state-success|warn|error-primary`)。这些 token 由 dsh 主题系统统一维护:
102
+
103
+ - **自动跟随**:dsh 默认主题偏好为「跟随系统」——系统切到深色模式(或在 dsh 设置里手动选暗色主题)时,`body[data-ds-dark-theme]` 生效,token 自动切换为深色盘,队列框变为**深灰底 + 白色反色字**,三档色用官方暗色适配值(对比度由 dsh 保证);
104
+ - **无需配置**:插件本身不监听系统、不新增设置项——深浅完全交给 dsh 主题,白天外观保持不变;
105
+ - **范围**:等待区 dock(含冻结横幅 / 冻结列表)与输入框右侧「冻结会话」按钮。
106
+
90
107
  ## 安装
91
108
 
92
109
  ```sh
@@ -149,7 +166,7 @@ npm run lint:fix # 自动修复可修复项
149
166
  - 🔴 红色 = 打断——立即中断当前动作,消息随后被处理;
150
167
  - 🟢 绿色 = 保持排队(当前默认态);对已插话的消息点绿 = 收回排队;
151
168
  3. 需要调整顺序 / 修改内容:用上移下移、打回输入框编辑或多行编辑(Enter 保存、Shift+Enter 换行);
152
- 4. 邻近高峰时段:点击输入框右侧「冻结会话」,当前轮次完成后自动暂停;非高价时间点「恢复会话」继续。
169
+ 4. **省钱关键(推荐)**:邻近高峰时段(9:00-12:00、14:00-18:00)点击输入框右侧「冻结会话」,当前轮次完成后自动暂停,避开高价窗口;闲时点「恢复会话」继续。可配合提醒 / 计费统计插件使用(见上文「推荐」)。
153
170
 
154
171
  ## 常见问题
155
172
 
package/lib/client.js CHANGED
@@ -195,7 +195,7 @@ window.__ModuleLoader__.load({
195
195
  }
196
196
  //#endregion
197
197
  //#region \0dsh-css:E:\test\rewrite-agently\dsh-input-traffic\src\client\steer-queue-dock.module.css.mjs
198
- const css$1 = ".cev0eq_dock{width:100%}.cev0eq_panel{background:var(--ds-color-surface,#fffc);border:1px solid var(--ds-color-border,#00000014);border-radius:10px;overflow:hidden}.cev0eq_toolbar{border-bottom:1px solid var(--ds-color-border,#0000000f);align-items:center;gap:8px;padding:4px 8px;display:flex}.cev0eq_header{color:var(--ds-color-text-secondary,#6b7280);cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:2px 6px;font-size:12px;display:inline-flex}.cev0eq_header:disabled{cursor:default}.cev0eq_lead{color:var(--ds-color-text-tertiary,#9ca3af);display:inline-flex}.cev0eq_count{font-weight:600}.cev0eq_chevron{color:var(--ds-color-text-tertiary,#9ca3af);display:inline-flex}.cev0eq_toolbarActions{margin-left:auto}.cev0eq_clear{color:var(--ds-color-text-secondary,#6b7280);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_freeze{border:1px solid var(--ds-color-border,#0000001f);color:var(--ds-color-text-secondary,#6b7280);cursor:pointer;background:0 0;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_freeze[aria-pressed=true]{border-color:var(--ds-steer-green,#30a46c);color:var(--ds-steer-green,#30a46c)}.cev0eq_freeze:hover:not(:disabled){background:var(--ds-color-surface-hover,#0000000a)}.cev0eq_freeze:disabled{opacity:.5;cursor:default}.cev0eq_frozenBanner{border-bottom:1px solid var(--ds-color-border,#0000000f);background:color-mix(in srgb, var(--ds-steer-green,#30a46c) 8%, transparent);color:var(--ds-steer-green,#30a46c);padding:4px 10px;font-size:12px}.cev0eq_frozenList{margin:0;padding:4px;list-style:none}.cev0eq_frozenRow{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.cev0eq_frozenMark{color:var(--ds-color-text-tertiary,#9ca3af);flex:none;margin-left:auto;font-size:11px}.cev0eq_clear:hover:not(:disabled){border-color:var(--ds-color-border,#0000001f);background:var(--ds-color-surface-hover,#0000000a)}.cev0eq_clear:disabled{opacity:.5;cursor:default}.cev0eq_clearConfirm{border-color:var(--ds-steer-red,#e5484d);color:var(--ds-steer-red,#e5484d)}.cev0eq_clearConfirm:hover:not(:disabled){border-color:var(--ds-steer-red,#e5484d);background:color-mix(in srgb, var(--ds-steer-red,#e5484d) 8%, transparent)}.cev0eq_clearCancel{color:var(--ds-color-text-secondary,#6b7280);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_clearCancel:hover:not(:disabled){background:var(--ds-color-surface-hover,#0000000a)}.cev0eq_clearLabel{font-size:12px}.cev0eq_list{margin:0;padding:4px;list-style:none}.cev0eq_row{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.cev0eq_row[draggable=true]{cursor:grab}.cev0eq_row[draggable=true]:active{cursor:grabbing}.cev0eq_rowDragOver{outline:2px dashed var(--ds-color-border-strong,#00000040);outline-offset:-2px;background:var(--ds-color-surface-hover,#0000000d)}.cev0eq_row:hover{background:var(--ds-color-surface-hover,#00000008)}.cev0eq_row[data-editing]{align-items:flex-start}.cev0eq_preview{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--ds-color-text,#1f2937);flex:1;font-size:13px;overflow:hidden}.cev0eq_badge{white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 6px;font-size:11px;line-height:16px;display:inline-flex}.cev0eq_badgeLabel{color:inherit}.cev0eq_badgeNow{color:var(--ds-steer-red,#e5484d);background:color-mix(in srgb, var(--ds-steer-red,#e5484d) 10%, transparent)}.cev0eq_badgeNext{color:var(--ds-steer-yellow,#e8a33d);background:color-mix(in srgb, var(--ds-steer-yellow,#e8a33d) 12%, transparent)}.cev0eq_badgeLater{color:var(--ds-steer-green,#30a46c);background:color-mix(in srgb, var(--ds-steer-green,#30a46c) 12%, transparent)}.cev0eq_badgeNow .cev0eq_dot{background:var(--ds-steer-red,#e5484d)}.cev0eq_badgeNext .cev0eq_dot{background:var(--ds-steer-yellow,#e8a33d)}.cev0eq_badgeLater .cev0eq_dot{background:var(--ds-steer-green,#30a46c)}.cev0eq_steeringList{margin:0;padding:0 4px 4px;list-style:none}.cev0eq_steeringList .cev0eq_row{opacity:.85}.cev0eq_editor{border:1px solid var(--ds-color-border,#00000026);background:var(--ds-color-surface,#fff);resize:none;border-radius:6px;flex:1;min-width:0;max-height:160px;padding:4px 6px;font-size:13px;line-height:20px;overflow-y:auto}.cev0eq_actions{align-items:center;gap:2px;display:inline-flex}.cev0eq_action{width:24px;height:24px;color:var(--ds-color-text-tertiary,#9ca3af);cursor:pointer;background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.cev0eq_action:hover:not(:disabled){background:var(--ds-color-surface-hover,#0000000d);color:var(--ds-color-text,#1f2937)}.cev0eq_action:disabled{opacity:.4;cursor:default}.cev0eq_plan{border-left:1px solid var(--ds-color-border,#00000014);align-items:center;gap:2px;margin-left:4px;padding-left:6px;display:inline-flex}.cev0eq_tier{cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;justify-content:center;align-items:center;width:20px;height:20px;padding:0;display:inline-flex}.cev0eq_tier:hover:not(:disabled){border-color:var(--ds-color-border,#0003)}.cev0eq_tier:disabled{cursor:default}.cev0eq_tierLater{border-color:var(--ds-steer-green,#30a46c);background:color-mix(in srgb, var(--ds-steer-green,#30a46c) 12%, transparent)}.cev0eq_dot{border-radius:50%;width:10px;height:10px}.cev0eq_tierNow .cev0eq_dot{background:var(--ds-steer-red,#e5484d)}.cev0eq_tierNext .cev0eq_dot{background:var(--ds-steer-yellow,#e8a33d)}.cev0eq_tierLater .cev0eq_dot{background:var(--ds-steer-green,#30a46c)}";
198
+ const css$1 = ".cev0eq_dock{width:100%}.cev0eq_panel{background:var(--dsw-alias-bg-layer-1,#fffc);border:1px solid var(--dsw-alias-border-l2,#00000014);border-radius:10px;overflow:hidden}.cev0eq_toolbar{border-bottom:1px solid var(--dsw-alias-border-l2,#0000000f);align-items:center;gap:8px;padding:4px 8px;display:flex}.cev0eq_header{color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:2px 6px;font-size:12px;display:inline-flex}.cev0eq_header:disabled{cursor:default}.cev0eq_lead{color:var(--dsw-alias-label-tertiary,#9ca3af);display:inline-flex}.cev0eq_count{font-weight:600}.cev0eq_chevron{color:var(--dsw-alias-label-tertiary,#9ca3af);display:inline-flex}.cev0eq_toolbarActions{margin-left:auto}.cev0eq_clear{color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_freeze{border:1px solid var(--dsw-alias-border-l3,#0000001f);color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_freeze[aria-pressed=true]{border-color:var(--dsw-alias-state-success-primary,#30a46c);color:var(--dsw-alias-state-success-primary,#30a46c)}.cev0eq_freeze:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.cev0eq_freeze:disabled{opacity:.5;cursor:default}.cev0eq_frozenBanner{border-bottom:1px solid var(--dsw-alias-border-l2,#0000000f);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 8%, transparent);color:var(--dsw-alias-state-success-primary,#30a46c);padding:4px 10px;font-size:12px}.cev0eq_frozenList{margin:0;padding:4px;list-style:none}.cev0eq_frozenRow{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.cev0eq_frozenMark{color:var(--dsw-alias-label-tertiary,#9ca3af);flex:none;margin-left:auto;font-size:11px}.cev0eq_clear:hover:not(:disabled){border-color:var(--dsw-alias-border-l3,#0000001f);background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.cev0eq_clear:disabled{opacity:.5;cursor:default}.cev0eq_clearConfirm{border-color:var(--dsw-alias-state-error-primary,#e5484d);color:var(--dsw-alias-state-error-primary,#e5484d)}.cev0eq_clearConfirm:hover:not(:disabled){border-color:var(--dsw-alias-state-error-primary,#e5484d);background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#e5484d) 8%, transparent)}.cev0eq_clearCancel{color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:4px;padding:3px 8px;font-size:12px;display:inline-flex}.cev0eq_clearCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.cev0eq_clearLabel{font-size:12px}.cev0eq_list{margin:0;padding:4px;list-style:none}.cev0eq_row{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.cev0eq_row[draggable=true]{cursor:grab}.cev0eq_row[draggable=true]:active{cursor:grabbing}.cev0eq_rowDragOver{outline:2px dashed var(--dsw-alias-border-l4,#00000040);outline-offset:-2px;background:var(--dsw-alias-interactive-bg-hover,#0000000d)}.cev0eq_row:hover{background:var(--dsw-alias-interactive-bg-hover,#00000008)}.cev0eq_row[data-editing]{align-items:flex-start}.cev0eq_preview{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary,#1f2937);flex:1;font-size:13px;overflow:hidden}.cev0eq_badge{white-space:nowrap;border-radius:999px;flex:none;align-items:center;gap:4px;padding:1px 6px;font-size:11px;line-height:16px;display:inline-flex}.cev0eq_badgeLabel{color:inherit}.cev0eq_badgeNow{color:var(--dsw-alias-state-error-primary,#e5484d);background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#e5484d) 10%, transparent)}.cev0eq_badgeNext{color:var(--dsw-alias-state-warn-primary,#e8a33d);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#e8a33d) 12%, transparent)}.cev0eq_badgeLater{color:var(--dsw-alias-state-success-primary,#30a46c);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 12%, transparent)}.cev0eq_badgeNow .cev0eq_dot{background:var(--dsw-alias-state-error-primary,#e5484d)}.cev0eq_badgeNext .cev0eq_dot{background:var(--dsw-alias-state-warn-primary,#e8a33d)}.cev0eq_badgeLater .cev0eq_dot{background:var(--dsw-alias-state-success-primary,#30a46c)}.cev0eq_steeringList{margin:0;padding:0 4px 4px;list-style:none}.cev0eq_steeringList .cev0eq_row{opacity:.85}.cev0eq_editor{border:1px solid var(--dsw-alias-border-l3,#00000026);background:var(--dsw-alias-bg-layer-2,#fff);resize:none;border-radius:6px;flex:1;min-width:0;max-height:160px;padding:4px 6px;font-size:13px;line-height:20px;overflow-y:auto}.cev0eq_actions{align-items:center;gap:2px;display:inline-flex}.cev0eq_action{width:24px;height:24px;color:var(--dsw-alias-label-tertiary,#9ca3af);cursor:pointer;background:0 0;border:0;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.cev0eq_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2937)}.cev0eq_action:disabled{opacity:.4;cursor:default}.cev0eq_plan{border-left:1px solid var(--dsw-alias-border-l2,#00000014);align-items:center;gap:2px;margin-left:4px;padding-left:6px;display:inline-flex}.cev0eq_tier{cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;justify-content:center;align-items:center;width:20px;height:20px;padding:0;display:inline-flex}.cev0eq_tier:hover:not(:disabled){border-color:var(--dsw-alias-border-l4,#0003)}.cev0eq_tier:disabled{cursor:default}.cev0eq_tierLater{border-color:var(--dsw-alias-state-success-primary,#30a46c);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 12%, transparent)}.cev0eq_dot{border-radius:50%;width:10px;height:10px}.cev0eq_tierNow .cev0eq_dot{background:var(--dsw-alias-state-error-primary,#e5484d)}.cev0eq_tierNext .cev0eq_dot{background:var(--dsw-alias-state-warn-primary,#e8a33d)}.cev0eq_tierLater .cev0eq_dot{background:var(--dsw-alias-state-success-primary,#30a46c)}";
199
199
  const tagId$1 = "dsh-input-traffic/steer-queue-dock.module.css";
200
200
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
201
201
  const tag = document.createElement("style");
@@ -205,42 +205,42 @@ window.__ModuleLoader__.load({
205
205
  document.head.appendChild(tag);
206
206
  }
207
207
  var steer_queue_dock_module_css_default = {
208
- "count": "cev0eq_count",
209
- "action": "cev0eq_action",
210
- "actions": "cev0eq_actions",
211
- "tier": "cev0eq_tier",
212
- "tierLater": "cev0eq_tierLater",
213
- "tierNext": "cev0eq_tierNext",
214
208
  "chevron": "cev0eq_chevron",
215
209
  "clearCancel": "cev0eq_clearCancel",
216
- "frozenRow": "cev0eq_frozenRow",
217
- "frozenList": "cev0eq_frozenList",
210
+ "dock": "cev0eq_dock",
211
+ "badgeNow": "cev0eq_badgeNow",
218
212
  "toolbar": "cev0eq_toolbar",
219
- "freeze": "cev0eq_freeze",
213
+ "frozenRow": "cev0eq_frozenRow",
220
214
  "badge": "cev0eq_badge",
221
- "header": "cev0eq_header",
222
- "toolbarActions": "cev0eq_toolbarActions",
223
- "badgeNext": "cev0eq_badgeNext",
224
- "editor": "cev0eq_editor",
225
- "lead": "cev0eq_lead",
226
215
  "badgeLabel": "cev0eq_badgeLabel",
227
- "clearConfirm": "cev0eq_clearConfirm",
228
- "dock": "cev0eq_dock",
229
- "badgeNow": "cev0eq_badgeNow",
230
- "preview": "cev0eq_preview",
231
- "panel": "cev0eq_panel",
232
- "frozenBanner": "cev0eq_frozenBanner",
233
- "row": "cev0eq_row",
216
+ "freeze": "cev0eq_freeze",
234
217
  "steeringList": "cev0eq_steeringList",
235
- "clearLabel": "cev0eq_clearLabel",
236
- "tierNow": "cev0eq_tierNow",
237
218
  "badgeLater": "cev0eq_badgeLater",
219
+ "action": "cev0eq_action",
220
+ "tierNow": "cev0eq_tierNow",
238
221
  "dot": "cev0eq_dot",
222
+ "frozenList": "cev0eq_frozenList",
223
+ "frozenBanner": "cev0eq_frozenBanner",
239
224
  "list": "cev0eq_list",
240
- "plan": "cev0eq_plan",
225
+ "toolbarActions": "cev0eq_toolbarActions",
226
+ "clear": "cev0eq_clear",
227
+ "preview": "cev0eq_preview",
228
+ "tier": "cev0eq_tier",
229
+ "clearLabel": "cev0eq_clearLabel",
230
+ "badgeNext": "cev0eq_badgeNext",
231
+ "row": "cev0eq_row",
232
+ "clearConfirm": "cev0eq_clearConfirm",
233
+ "tierNext": "cev0eq_tierNext",
234
+ "editor": "cev0eq_editor",
235
+ "count": "cev0eq_count",
241
236
  "frozenMark": "cev0eq_frozenMark",
242
- "rowDragOver": "cev0eq_rowDragOver",
243
- "clear": "cev0eq_clear"
237
+ "lead": "cev0eq_lead",
238
+ "header": "cev0eq_header",
239
+ "actions": "cev0eq_actions",
240
+ "tierLater": "cev0eq_tierLater",
241
+ "panel": "cev0eq_panel",
242
+ "plan": "cev0eq_plan",
243
+ "rowDragOver": "cev0eq_rowDragOver"
244
244
  };
245
245
  //#endregion
246
246
  //#region src/client/steer-queue-dock.tsx
@@ -1169,7 +1169,7 @@ window.__ModuleLoader__.load({
1169
1169
  }
1170
1170
  //#endregion
1171
1171
  //#region \0dsh-css:E:\test\rewrite-agently\dsh-input-traffic\src\client\freeze-button.module.css.mjs
1172
- const css = ".Klmgza_freeze{border:1px solid var(--ds-color-border,#0000001f);height:24px;color:var(--ds-color-text-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border-radius:6px;align-items:center;gap:4px;padding:0 8px;font-size:12px;display:inline-flex}.Klmgza_freeze:hover:not(:disabled){background:var(--ds-color-surface-hover,#0000000a)}.Klmgza_freeze[aria-pressed=true]{border-color:var(--ds-steer-green,#30a46c);color:var(--ds-steer-green,#30a46c);background:color-mix(in srgb, var(--ds-steer-green,#30a46c) 8%, transparent)}.Klmgza_label{font-size:12px}";
1172
+ const css = ".Klmgza_freeze{border:1px solid var(--dsw-alias-border-l3,#0000001f);height:24px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border-radius:6px;align-items:center;gap:4px;padding:0 8px;font-size:12px;display:inline-flex}.Klmgza_freeze:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.Klmgza_freeze[aria-pressed=true]{border-color:var(--dsw-alias-state-success-primary,#30a46c);color:var(--dsw-alias-state-success-primary,#30a46c);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 8%, transparent)}.Klmgza_label{font-size:12px}";
1173
1173
  const tagId = "dsh-input-traffic/freeze-button.module.css";
1174
1174
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1175
1175
  const tag = document.createElement("style");
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Auto-continue core — 平台无关的纯逻辑, 吸收自 dsh-auto-continue
3
+ * (https://github.com/HsiangNianian/dsh-auto-continue, MIT, v0.8.1 的
4
+ * src/shared/core.ts), 按 input-traffic 的纯 client 定位裁剪:
5
+ *
6
+ * - 只吸收「错误分类 / 自适应退避 / 幂等护栏 / 模板填充」这些无宿主依赖的纯函数;
7
+ * - 不吸收宿主引擎(host firehose / agent.followup / SSE 桥)——那会破坏本插件
8
+ * 「纯浏览器侧、不改官方源码」的定位, 且与「冻结会话省钱」方向相反(见 README 兼容性);
9
+ * - 全部函数无任何 @deepseek-ai/* 值导入, 通过 client bundle purity gate。
10
+ *
11
+ * 应用场景: dock 的「续跑」——检测到会话停下但排队消息未处理完(疑似中断)时,
12
+ * 分类失败、按退避节奏重发, 永久性错误则停止并提示人工介入。
13
+ */
14
+ /** 一次发送失败的可分类事实(从 send 的 reject error 里提取)。 */
15
+ export interface FailureFacts {
16
+ /** 稳定机器路由码(如 UPSTREAM、RATE_LIMIT_EXCEEDED)。 */
17
+ code?: string;
18
+ /** 人类可读的失败描述。 */
19
+ message: string;
20
+ /** 供应商 HTTP 状态码(可用时)。 */
21
+ status?: number;
22
+ }
23
+ /**
24
+ * 错误分类: 该失败是否值得重试续跑。
25
+ * 永久性失败(认证/余额/模型不存在/上下文超限等)重试也不会成功, 应停止并提示用户;
26
+ * 其余(网络、超时、5xx、429 等)视为临时性失败, 允许自动重发。
27
+ */
28
+ export declare function isTransientFailure(failure: FailureFacts): boolean;
29
+ /**
30
+ * 消息文本分类: 仅明确属于网络/传输类的临时错误才值得重试。
31
+ * 其余(序列化失败、配置/宿主内部错误等)视为永久性——重试无益。
32
+ */
33
+ export declare function isTransientAgentError(message: string): boolean;
34
+ /** 自适应退避: 同一会话连续失败时的有效重试间隔。 */
35
+ export declare function effectiveCooldown(consecutive: number, base: number, factor: number, max: number): number;
36
+ /** 模板填充所需上下文(全部可选, 缺失的占位符填为空串)。 */
37
+ export interface TemplateContext {
38
+ /** 失败事实(错误码/消息/HTTP 状态), 对应 {code}/{message}/{status}。 */
39
+ facts?: FailureFacts;
40
+ /** 失败前最后一次工具调用的名称, 对应 {tool}。 */
41
+ tool?: string;
42
+ /** 连续失败次数(含本次), 对应 {errorCount}。 */
43
+ errorCount?: number;
44
+ /** 自失败发生以来的毫秒数, 对应 {elapsed}。 */
45
+ elapsedMs?: number;
46
+ /** 上一步工具结果摘要(截断), 对应 {result}(护栏模板用)。 */
47
+ result?: string;
48
+ }
49
+ /** 把毫秒格式化为人类可读的经过时长(如 65s → 1m5s)。 */
50
+ export declare function formatElapsed(ms: number | undefined): string;
51
+ /** 用失败事实填充续跑模板占位符({code}/{message}/{status}/{tool}/{errorCount}/{elapsed}/{result})。 */
52
+ export declare function fillTemplate(template: string, ctx: TemplateContext): string;
53
+ /** 上一步工具调用的判定结果: 是否已确认完成, 以及文本摘要。 */
54
+ export interface ToolResultFacts {
55
+ /** 工具是否成功完成(内部失败或 isError 视为未成功)。 */
56
+ ok: boolean;
57
+ /** 工具输出的文本摘要(截断)。 */
58
+ excerpt: string;
59
+ }
60
+ /** 从 tool/result 事件载荷提取成功与否与文本摘要(幂等护栏: 续跑时提示别重复执行)。 */
61
+ export declare function toolResultFacts(data: {
62
+ error?: {
63
+ name?: string;
64
+ code?: string;
65
+ };
66
+ message?: {
67
+ content?: Array<{
68
+ type?: string;
69
+ content?: unknown;
70
+ isError?: boolean;
71
+ }>;
72
+ };
73
+ }): ToolResultFacts;
74
+ /** 续跑配置(全部可选, 解析时回落默认值)。 */
75
+ export interface AutoContinueSettings {
76
+ /** 续跑时自动发送的消息文本(可含模板占位符)。 */
77
+ continueText?: string;
78
+ /** 宽限期: 停下多久后视为中断再自动重发(ms)。 */
79
+ graceMs?: number;
80
+ /** 同一会话两次自动续跑的最小间隔(ms)。 */
81
+ cooldownMs?: number;
82
+ /** 连续自动续跑上限; 超过后停止, 直到用户介入或成功回合。 */
83
+ maxConsecutive?: number;
84
+ /** 连续失败时的退避系数。 */
85
+ backoffFactor?: number;
86
+ /** 自适应退避的上限(ms)。 */
87
+ backoffMaxMs?: number;
88
+ /**
89
+ * 自动续跑: 检测到疑似中断时自动重发排队消息。
90
+ * 默认关闭——纯 client 拿不到 turn/end reason, 无法区分「用户主动停止」与
91
+ * 「非人为中断」, 故默认只提示不擅自续跑(与 auto-continue 的 paused 不同)。
92
+ */
93
+ autoResume?: boolean;
94
+ /** 全局暂停续跑(如冻结期间)。 */
95
+ paused?: boolean;
96
+ }
97
+ /** 完全解析后的续跑配置(内置默认值 + 用户覆盖)。 */
98
+ export type AutoContinueConfig = Required<AutoContinueSettings>;
99
+ /** 内置默认值(与 dock 的 localStorage 持久化键一致)。 */
100
+ export declare const DEFAULT_CONFIG: AutoContinueConfig;
101
+ /** 把(可能不完整的)配置解析为完整配置(合法数字/布尔校验 + 兜底默认)。 */
102
+ export declare function resolveConfig(section: AutoContinueSettings | undefined): AutoContinueConfig;
103
+ //# sourceMappingURL=auto-continue-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-continue-core.d.ts","sourceRoot":"","sources":["../../../src/client/auto-continue-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAWjE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,+BAA+B;AAC/B,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,CAIR;AAED,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,sCAAsC;AACtC,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM5D;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,MAAM,CAS3E;AA0BD,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,OAAO,CAAC;YAAC,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAA;CACvF,GAAG,eAAe,CAGlB;AAED,4BAA4B;AAC5B,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kBAAkB;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,qBAAqB;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,gCAAgC;AAChC,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAA;AAE/D,2CAA2C;AAC3C,eAAO,MAAM,cAAc,EAAE,kBAS5B,CAAA;AAUD,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,SAAS,GAAG,kBAAkB,CAgB3F"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Auto-continue core — 平台无关的纯逻辑, 吸收自 dsh-auto-continue
3
+ * (https://github.com/HsiangNianian/dsh-auto-continue, MIT, v0.8.1 的
4
+ * src/shared/core.ts), 按 input-traffic 的纯 client 定位裁剪:
5
+ *
6
+ * - 只吸收「错误分类 / 自适应退避 / 幂等护栏 / 模板填充」这些无宿主依赖的纯函数;
7
+ * - 不吸收宿主引擎(host firehose / agent.followup / SSE 桥)——那会破坏本插件
8
+ * 「纯浏览器侧、不改官方源码」的定位, 且与「冻结会话省钱」方向相反(见 README 兼容性);
9
+ * - 全部函数无任何 @deepseek-ai/* 值导入, 通过 client bundle purity gate。
10
+ *
11
+ * 应用场景: dock 的「续跑」——检测到会话停下但排队消息未处理完(疑似中断)时,
12
+ * 分类失败、按退避节奏重发, 永久性错误则停止并提示人工介入。
13
+ */
14
+ /**
15
+ * 错误分类: 该失败是否值得重试续跑。
16
+ * 永久性失败(认证/余额/模型不存在/上下文超限等)重试也不会成功, 应停止并提示用户;
17
+ * 其余(网络、超时、5xx、429 等)视为临时性失败, 允许自动重发。
18
+ */
19
+ export function isTransientFailure(failure) {
20
+ const haystack = `${failure.code ?? ''} ${failure.message}`.toLowerCase();
21
+ const status = failure.status;
22
+ if (status !== undefined && (status === 401 || status === 403))
23
+ return false;
24
+ const permanent = /auth|unauthor|forbidden|credential|api[_-]?key|permission/i.test(haystack) ||
25
+ /insufficient.*(balance|quota)|billing|payment|quota.*exceeded.*(?!retry)/i.test(haystack) ||
26
+ /model[^a-z]*not[^a-z]*found|unknown[_-]?model|not.*support.*model/i.test(haystack) ||
27
+ /context.*(length|limit|overflow|exceed)|token.*limit|max.*context/i.test(haystack) ||
28
+ /invalid[_-]?request|bad[_-]?request/i.test(haystack);
29
+ return !permanent;
30
+ }
31
+ /**
32
+ * 消息文本分类: 仅明确属于网络/传输类的临时错误才值得重试。
33
+ * 其余(序列化失败、配置/宿主内部错误等)视为永久性——重试无益。
34
+ */
35
+ export function isTransientAgentError(message) {
36
+ return /network|timeout|timed ?out|econn|etimedout|socket|5\d\d|\b429\b|upstream|temporar/i.test(message);
37
+ }
38
+ /** 自适应退避: 同一会话连续失败时的有效重试间隔。 */
39
+ export function effectiveCooldown(consecutive, base, factor, max) {
40
+ // consecutive = 已连续自动重发的次数; 第 1 次后开始按 factor 递增
41
+ const multiplier = Math.pow(factor, consecutive);
42
+ return Math.min(Math.max(base, base * multiplier), Math.max(base, max));
43
+ }
44
+ /** 把毫秒格式化为人类可读的经过时长(如 65s → 1m5s)。 */
45
+ export function formatElapsed(ms) {
46
+ if (ms === undefined || !Number.isFinite(ms) || ms < 0)
47
+ return '';
48
+ if (ms < 1000)
49
+ return `${Math.round(ms)}ms`;
50
+ const s = Math.round(ms / 1000);
51
+ if (s < 60)
52
+ return `${s}s`;
53
+ return `${Math.floor(s / 60)}m${s % 60 > 0 ? `${s % 60}s` : ''}`;
54
+ }
55
+ /** 用失败事实填充续跑模板占位符({code}/{message}/{status}/{tool}/{errorCount}/{elapsed}/{result})。 */
56
+ export function fillTemplate(template, ctx) {
57
+ return template
58
+ .replace(/\{code\}/g, ctx.facts?.code ?? '')
59
+ .replace(/\{message\}/g, ctx.facts?.message ?? '')
60
+ .replace(/\{status\}/g, ctx.facts?.status !== undefined ? String(ctx.facts.status) : '')
61
+ .replace(/\{tool\}/g, ctx.tool ?? '')
62
+ .replace(/\{errorCount\}/g, ctx.errorCount !== undefined ? String(ctx.errorCount) : '')
63
+ .replace(/\{elapsed\}/g, formatElapsed(ctx.elapsedMs))
64
+ .replace(/\{result\}/g, ctx.result ?? '');
65
+ }
66
+ /** 工具结果摘要的最大长度(护栏模板 {result} 用)。 */
67
+ const TOOL_RESULT_CAP = 160;
68
+ /** 从任意内容块里递归收集文本(结果为模型可见的工具输出)。 */
69
+ function extractText(blocks, cap) {
70
+ let out = '';
71
+ const walk = (value) => {
72
+ if (out.length >= cap)
73
+ return;
74
+ if (Array.isArray(value)) {
75
+ for (const item of value)
76
+ walk(item);
77
+ return;
78
+ }
79
+ if (typeof value !== 'object' || value === null)
80
+ return;
81
+ const record = value;
82
+ if (record['type'] === 'text' && typeof record['text'] === 'string') {
83
+ out += record['text'];
84
+ return;
85
+ }
86
+ for (const child of Object.values(record))
87
+ walk(child);
88
+ };
89
+ walk(blocks);
90
+ return out.slice(0, cap);
91
+ }
92
+ /** 从 tool/result 事件载荷提取成功与否与文本摘要(幂等护栏: 续跑时提示别重复执行)。 */
93
+ export function toolResultFacts(data) {
94
+ const failed = data.error !== undefined || data.message?.content?.[0]?.isError === true;
95
+ return { ok: !failed, excerpt: extractText(data.message?.content?.[0]?.content, TOOL_RESULT_CAP) };
96
+ }
97
+ /** 内置默认值(与 dock 的 localStorage 持久化键一致)。 */
98
+ export const DEFAULT_CONFIG = {
99
+ continueText: '继续',
100
+ graceMs: 3000,
101
+ cooldownMs: 20000,
102
+ maxConsecutive: 3,
103
+ backoffFactor: 2,
104
+ backoffMaxMs: 300000,
105
+ autoResume: false,
106
+ paused: false,
107
+ };
108
+ function numberOr(value, fallback) {
109
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : fallback;
110
+ }
111
+ function booleanOr(value, fallback) {
112
+ return typeof value === 'boolean' ? value : fallback;
113
+ }
114
+ /** 把(可能不完整的)配置解析为完整配置(合法数字/布尔校验 + 兜底默认)。 */
115
+ export function resolveConfig(section) {
116
+ const value = section ?? {};
117
+ const text = typeof value.continueText === 'string' && value.continueText.trim() !== ''
118
+ ? value.continueText
119
+ : DEFAULT_CONFIG.continueText;
120
+ return {
121
+ continueText: text,
122
+ graceMs: numberOr(value.graceMs, DEFAULT_CONFIG.graceMs),
123
+ cooldownMs: numberOr(value.cooldownMs, DEFAULT_CONFIG.cooldownMs),
124
+ maxConsecutive: Math.max(1, numberOr(value.maxConsecutive, DEFAULT_CONFIG.maxConsecutive)),
125
+ backoffFactor: Math.max(1, numberOr(value.backoffFactor, DEFAULT_CONFIG.backoffFactor)),
126
+ backoffMaxMs: numberOr(value.backoffMaxMs, DEFAULT_CONFIG.backoffMaxMs),
127
+ autoResume: booleanOr(value.autoResume, DEFAULT_CONFIG.autoResume),
128
+ paused: booleanOr(value.paused, DEFAULT_CONFIG.paused),
129
+ };
130
+ }
131
+ //# sourceMappingURL=auto-continue-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-continue-core.js","sourceRoot":"","sources":["../../../src/client/auto-continue-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Auto-continue store — 中断检测与续跑配置的共享状态。
3
+ *
4
+ * 与 freeze-store 同构(无运行时依赖、稳定 identity per mount、可测试):
5
+ * - interrupted: 检测到「会话停下但排队消息未处理完」(疑似非人为中断)时置位,
6
+ * dock 据此显示续跑提示条;
7
+ * - 续跑配置持久化到 localStorage(键 `dsh-input-traffic:auto-continue`),
8
+ * 自动续跑默认关闭(纯 client 拿不到 turn/end reason, 无法与用户主动停止
9
+ * 区分, 故默认只提示、不擅自续跑)。
10
+ */
11
+ import { type AutoContinueConfig, type AutoContinueSettings } from './auto-continue-core.ts';
12
+ /** localStorage 持久化键(续跑配置)。 */
13
+ export declare const CONFIG_KEY = "dsh-input-traffic:auto-continue";
14
+ export interface AutoContinueState {
15
+ /** 是否检测到疑似中断(提示条可见性)。 */
16
+ interrupted: boolean;
17
+ /** 连续自动续跑次数(按配置上限封顶)。 */
18
+ consecutive: number;
19
+ /** 上次续跑尝试时间戳(退避节流用)。 */
20
+ lastAttemptAt: number;
21
+ }
22
+ /** 最小快照 store(与 freeze-store 同构)。 */
23
+ export declare const autoContinueStore: {
24
+ getSnapshot(): AutoContinueState;
25
+ subscribe(listener: () => void): () => void;
26
+ };
27
+ /** 当前解析后的续跑配置。 */
28
+ export declare function readAutoContinueConfig(): AutoContinueConfig;
29
+ /** 持久化续跑配置(部分覆盖, 缺失回落默认)。 */
30
+ export declare function setAutoContinueConfig(patch: AutoContinueSettings): void;
31
+ /** 标记检测到疑似中断(dock 显示提示条)。 */
32
+ export declare function markInterrupted(): void;
33
+ /** 清除中断标志(用户手动续跑 / 队列清空 / 会话重新运行)。 */
34
+ export declare function clearInterrupted(): void;
35
+ /** 记录一次续跑尝试(推进连续计数与退避节流)。 */
36
+ export declare function noteRetry(consecutive: number): void;
37
+ /** 重置续跑状态(成功回合 / 用户介入后)。 */
38
+ export declare function resetAutoContinue(): void;
39
+ /** 测试重置。 */
40
+ export declare function resetAutoContinueStore(): void;
41
+ //# sourceMappingURL=auto-continue-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-continue-store.d.ts","sourceRoot":"","sources":["../../../src/client/auto-continue-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAiB,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAE3G,+BAA+B;AAC/B,eAAO,MAAM,UAAU,oCAAoC,CAAA;AAE3D,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,WAAW,EAAE,OAAO,CAAA;IACpB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,wBAAwB;IACxB,aAAa,EAAE,MAAM,CAAA;CACtB;AAsBD,qCAAqC;AACrC,eAAO,MAAM,iBAAiB;mBACb,iBAAiB;wBAGZ,MAAM,IAAI,GAAG,MAAM,IAAI;CAI5C,CAAA;AAED,kBAAkB;AAClB,wBAAgB,sBAAsB,IAAI,kBAAkB,CAE3D;AAED,6BAA6B;AAC7B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAUvE;AAED,6BAA6B;AAC7B,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAED,sCAAsC;AACtC,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC;AAED,6BAA6B;AAC7B,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,4BAA4B;AAC5B,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED,YAAY;AACZ,wBAAgB,sBAAsB,IAAI,IAAI,CAS7C"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Auto-continue store — 中断检测与续跑配置的共享状态。
3
+ *
4
+ * 与 freeze-store 同构(无运行时依赖、稳定 identity per mount、可测试):
5
+ * - interrupted: 检测到「会话停下但排队消息未处理完」(疑似非人为中断)时置位,
6
+ * dock 据此显示续跑提示条;
7
+ * - 续跑配置持久化到 localStorage(键 `dsh-input-traffic:auto-continue`),
8
+ * 自动续跑默认关闭(纯 client 拿不到 turn/end reason, 无法与用户主动停止
9
+ * 区分, 故默认只提示、不擅自续跑)。
10
+ */
11
+ import { resolveConfig } from "./auto-continue-core.js";
12
+ /** localStorage 持久化键(续跑配置)。 */
13
+ export const CONFIG_KEY = 'dsh-input-traffic:auto-continue';
14
+ const listeners = new Set();
15
+ let state = { interrupted: false, consecutive: 0, lastAttemptAt: 0 };
16
+ let config = readConfig();
17
+ /** 读取(可能不完整的)localStorage 配置并解析为完整配置。 */
18
+ function readConfig() {
19
+ let raw;
20
+ try {
21
+ const stored = localStorage.getItem(CONFIG_KEY);
22
+ if (stored !== null)
23
+ raw = JSON.parse(stored);
24
+ }
25
+ catch {
26
+ /* storage 不可用或损坏: 回落默认 */
27
+ }
28
+ return resolveConfig(raw);
29
+ }
30
+ function emit() {
31
+ for (const listener of listeners)
32
+ listener();
33
+ }
34
+ /** 最小快照 store(与 freeze-store 同构)。 */
35
+ export const autoContinueStore = {
36
+ getSnapshot() {
37
+ return state;
38
+ },
39
+ subscribe(listener) {
40
+ listeners.add(listener);
41
+ return () => { listeners.delete(listener); };
42
+ },
43
+ };
44
+ /** 当前解析后的续跑配置。 */
45
+ export function readAutoContinueConfig() {
46
+ return config;
47
+ }
48
+ /** 持久化续跑配置(部分覆盖, 缺失回落默认)。 */
49
+ export function setAutoContinueConfig(patch) {
50
+ config = resolveConfig({ ...config, ...patch });
51
+ try {
52
+ localStorage.setItem(CONFIG_KEY, JSON.stringify(config));
53
+ }
54
+ catch {
55
+ /* storage 不可用: 仅内存生效 */
56
+ }
57
+ // 强制快照引用变化: useSyncExternalStore 依赖引用对比决定是否重渲染。
58
+ state = { ...state };
59
+ emit();
60
+ }
61
+ /** 标记检测到疑似中断(dock 显示提示条)。 */
62
+ export function markInterrupted() {
63
+ state = { ...state, interrupted: true };
64
+ emit();
65
+ }
66
+ /** 清除中断标志(用户手动续跑 / 队列清空 / 会话重新运行)。 */
67
+ export function clearInterrupted() {
68
+ state = { ...state, interrupted: false };
69
+ emit();
70
+ }
71
+ /** 记录一次续跑尝试(推进连续计数与退避节流)。 */
72
+ export function noteRetry(consecutive) {
73
+ state = { ...state, consecutive, lastAttemptAt: Date.now() };
74
+ emit();
75
+ }
76
+ /** 重置续跑状态(成功回合 / 用户介入后)。 */
77
+ export function resetAutoContinue() {
78
+ state = { interrupted: false, consecutive: 0, lastAttemptAt: 0 };
79
+ emit();
80
+ }
81
+ /** 测试重置。 */
82
+ export function resetAutoContinueStore() {
83
+ state = { interrupted: false, consecutive: 0, lastAttemptAt: 0 };
84
+ try {
85
+ localStorage.removeItem(CONFIG_KEY);
86
+ }
87
+ catch {
88
+ /* storage 不可用 */
89
+ }
90
+ config = readConfig();
91
+ emit();
92
+ }
93
+ //# sourceMappingURL=auto-continue-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-continue-store.js","sourceRoot":"","sources":["../../../src/client/auto-continue-store.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,104 +1,104 @@
1
- {
2
- "name": "dsh-input-traffic",
3
- "version": "0.2.6",
4
- "type": "module",
5
- "description": "Busy-time input queue for the DeepSeek Harness web GUI: three-tier (now/next/later) planning, queue editing with drag-to-reorder and concurrency protection, interject (steer) and interrupt, batch clear with confirm, session freeze - a cordis client plugin, no dsh source changes, no PR required",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/drscrewdriver/dsh-input-traffic.git"
9
- },
10
- "main": "lib/index.js",
11
- "types": "lib/types/index.d.ts",
12
- "exports": {
13
- ".": {
14
- "types": "./lib/types/index.d.ts",
15
- "default": "./lib/index.js"
16
- },
17
- "./client": {
18
- "types": "./lib/types/client/index.d.ts",
19
- "default": "./lib/client.js"
20
- },
21
- "./package.json": "./package.json"
22
- },
23
- "files": [
24
- "lib/",
25
- "cordis.patch.yml",
26
- "README.md"
27
- ],
28
- "dsh": {
29
- "bundle": {
30
- "patch": "./cordis.patch.yml"
31
- },
32
- "client": {
33
- "inject": [
34
- "@deepseek-ai/dsh-client-locale",
35
- "@deepseek-ai/dsh-client-ui-conversation"
36
- ],
37
- "platform": "web"
38
- }
39
- },
40
- "scripts": {
41
- "build": "tsc -p tsconfig.json && tsdown",
42
- "test": "vitest run",
43
- "clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
44
- "lint": "eslint src tests",
45
- "lint:fix": "eslint src tests --fix",
46
- "tdd": "vitest",
47
- "verify": "npm run lint && npm run test && npm run build && node examples/verify-assembly.mjs"
48
- },
49
- "engines": {
50
- "node": ">=20"
51
- },
52
- "license": "MIT",
53
- "peerDependencies": {
54
- "@deepseek-ai/cordis": "^4.0.1",
55
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.5",
56
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.5",
57
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.5",
58
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.5",
59
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.5",
60
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.5"
61
- },
62
- "peerDependenciesMeta": {
63
- "@deepseek-ai/cordis": {
64
- "optional": true
65
- },
66
- "@deepseek-ai/dsh-client-locale": {
67
- "optional": true
68
- },
69
- "@deepseek-ai/dsh-client-runtime": {
70
- "optional": true
71
- },
72
- "@deepseek-ai/dsh-client-ui-conversation": {
73
- "optional": true
74
- },
75
- "@deepseek-ai/dsh-client-ui-primitives": {
76
- "optional": true
77
- },
78
- "@deepseek-ai/dsh-client-ui-settings": {
79
- "optional": true
80
- },
81
- "@deepseek-ai/dsh-client-ui-slots": {
82
- "optional": true
83
- }
84
- },
85
- "devDependencies": {
86
- "@deepseek-ai/cordis": "^4.0.1",
87
- "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
88
- "@testing-library/dom": "^10.4.1",
89
- "@testing-library/react": "^16.3.2",
90
- "@types/node": "^22.20.0",
91
- "@types/react": "~18.3.1",
92
- "@types/react-dom": "~18.3.1",
93
- "eslint": "^9.39.5",
94
- "eslint-plugin-react": "^7.37.5",
95
- "eslint-plugin-react-hooks": "^5.2.0",
96
- "jsdom": "^29.1.1",
97
- "lightningcss": "^1.32.0",
98
- "react": "^18.2.0",
99
- "tsdown": "^0.22.2",
100
- "typescript": "^6.0.3",
101
- "typescript-eslint": "^8.67.0",
102
- "vitest": "^4.1.8"
103
- }
104
- }
1
+ {
2
+ "name": "dsh-input-traffic",
3
+ "version": "0.2.8",
4
+ "type": "module",
5
+ "description": "Busy-time input queue for the DeepSeek Harness web GUI: three-tier (now/next/later) planning, queue editing with drag-to-reorder and concurrency protection, interject (steer) and interrupt, batch clear with confirm, session freeze - a cordis client plugin, no dsh source changes, no PR required",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/drscrewdriver/dsh-input-traffic.git"
9
+ },
10
+ "main": "lib/index.js",
11
+ "types": "lib/types/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./lib/types/index.d.ts",
15
+ "default": "./lib/index.js"
16
+ },
17
+ "./client": {
18
+ "types": "./lib/types/client/index.d.ts",
19
+ "default": "./lib/client.js"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib/",
25
+ "cordis.patch.yml",
26
+ "README.md"
27
+ ],
28
+ "dsh": {
29
+ "bundle": {
30
+ "patch": "./cordis.patch.yml"
31
+ },
32
+ "client": {
33
+ "inject": [
34
+ "@deepseek-ai/dsh-client-locale",
35
+ "@deepseek-ai/dsh-client-ui-conversation"
36
+ ],
37
+ "platform": "web"
38
+ }
39
+ },
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.json && tsdown",
42
+ "test": "vitest run",
43
+ "clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
44
+ "lint": "eslint src tests",
45
+ "lint:fix": "eslint src tests --fix",
46
+ "tdd": "vitest",
47
+ "verify": "npm run lint && npm run test && npm run build && node examples/verify-assembly.mjs"
48
+ },
49
+ "engines": {
50
+ "node": ">=20"
51
+ },
52
+ "license": "MIT",
53
+ "peerDependencies": {
54
+ "@deepseek-ai/cordis": "^4.0.1",
55
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.5",
56
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.5",
57
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.5",
58
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.5",
59
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.5",
60
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.5"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@deepseek-ai/cordis": {
64
+ "optional": true
65
+ },
66
+ "@deepseek-ai/dsh-client-locale": {
67
+ "optional": true
68
+ },
69
+ "@deepseek-ai/dsh-client-runtime": {
70
+ "optional": true
71
+ },
72
+ "@deepseek-ai/dsh-client-ui-conversation": {
73
+ "optional": true
74
+ },
75
+ "@deepseek-ai/dsh-client-ui-primitives": {
76
+ "optional": true
77
+ },
78
+ "@deepseek-ai/dsh-client-ui-settings": {
79
+ "optional": true
80
+ },
81
+ "@deepseek-ai/dsh-client-ui-slots": {
82
+ "optional": true
83
+ }
84
+ },
85
+ "devDependencies": {
86
+ "@deepseek-ai/cordis": "^4.0.1",
87
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
88
+ "@testing-library/dom": "^10.4.1",
89
+ "@testing-library/react": "^16.3.2",
90
+ "@types/node": "^22.20.0",
91
+ "@types/react": "~18.3.1",
92
+ "@types/react-dom": "~18.3.1",
93
+ "eslint": "^9.39.5",
94
+ "eslint-plugin-react": "^7.37.5",
95
+ "eslint-plugin-react-hooks": "^5.2.0",
96
+ "jsdom": "^29.1.1",
97
+ "lightningcss": "^1.32.0",
98
+ "react": "^18.2.0",
99
+ "tsdown": "^0.22.2",
100
+ "typescript": "^6.0.3",
101
+ "typescript-eslint": "^8.67.0",
102
+ "vitest": "^4.1.8"
103
+ }
104
+ }