dsh-input-traffic 0.2.9 → 0.2.10-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.ja.md +78 -0
- package/CHANGELOG.ko.md +78 -0
- package/CHANGELOG.md +102 -0
- package/INSTALL.ja.md +151 -0
- package/INSTALL.ko.md +151 -0
- package/INSTALL.md +152 -0
- package/INSTALL.zh.md +151 -0
- package/README.en.md +37 -2
- package/README.ja.md +187 -0
- package/README.ko.md +181 -0
- package/README.md +49 -4
- package/dsh.plugin.json +13 -0
- package/lib/client.js +64 -50
- package/lib/client.js.map +1 -1
- package/lib/types/client/freeze-button.d.ts +10 -3
- package/lib/types/client/freeze-button.d.ts.map +1 -1
- package/lib/types/client/freeze-button.js +3 -2
- package/lib/types/client/freeze-button.js.map +1 -1
- package/lib/types/client/index.d.ts +23 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +16 -2
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/locales.d.ts +5 -1
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/locales.js +109 -5
- package/lib/types/client/locales.js.map +1 -1
- package/package.json +15 -7
package/README.ko.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<strong>DeepSeek Harness Web GUI용 3단계 입력 트래픽 제어</strong>
|
|
3
|
+
</p>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="README.en.md">English</a> · <a href="README.md">中文</a> · <a href="README.ja.md">日本語</a> · <strong>한국어</strong>
|
|
6
|
+
</p>
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-263146?style=flat-square"></a>
|
|
9
|
+
<img src="https://camo.githubusercontent.com/2c11fb2e0e14bb9985c5acbe61123a7441c5ee63aa27fa6e04e2a707ebfd6022/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6473682d2d706c7567696e2d72656164792d3437384342463f6c6f676f3d646565707365656b266c6f676f436f6c6f723d7768697465" alt="dsh-plugin" style="max-width: 100%;">
|
|
10
|
+
<img alt="Public beta" src="https://img.shields.io/badge/status-public%20beta-7da1de?style=flat-square">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
# dsh-input-traffic
|
|
14
|
+
|
|
15
|
+
- [English README](./README.en.md)
|
|
16
|
+
- [中文 README](./README.md)
|
|
17
|
+
- [日本語 README](./README.ja.md)
|
|
18
|
+
- [한국어 README](./README.ko.md)
|
|
19
|
+
- [Installation guide](./INSTALL.md)
|
|
20
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
21
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
22
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
23
|
+
- [Changelog](./CHANGELOG.md)
|
|
24
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
25
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
26
|
+
|
|
27
|
+
> **호환성 참고:** `ja`와 `ko` 사전이 포함되어 있지만, 현재 공식 DSH 릴리스는 `LocaleRuntime`을 통해 `zh`와 `en`만 제공합니다. 순정 DSH에서 `ja` 또는 `ko`를 선택하면 `locale "<id>" is not registered` 오류가 발생합니다. 공식 DSH가 해당 locale ID를 추가할 때까지 사용할 수 없습니다. 고급 사용자는 DSH 포크를 유지하면서 `packages/client/locale/src/locale-settings.ts`의 `LOCALE_IDS`와 `packages/client/locale/src/client/index.ts`의 `LOCALES` 라벨을 업데이트하고 핵심 사전과 테스트를 추가한 뒤 다시 빌드하여 실행할 수 있습니다. 이 플러그인만으로는 DSH의 전역 locale 목록을 확장할 수 없습니다.
|
|
28
|
+
|
|
29
|
+
> 에이전트가 바쁠 때 "중단" 또는 "대기" 둘 중 하나가 아닙니다: 빨간색은 즉시 중단 후 전송, 노란색은 다음 턴에 삽입, 초록색은 끝까지 대기 — 3단계가 공존합니다. DeepSeek 피크 과금 시간대가临近하면 원클릭으로 세션을 동결하고 오피크에 재개합니다.
|
|
30
|
+
|
|
31
|
+
`dsh plugin` 명령으로 조립 + 번들 패치로 장착하는 cordis 클라이언트 플러그인. dsh 소스 변경이나 PR이 필요 없습니다.
|
|
32
|
+
|
|
33
|
+
> 💡 **"세션 동결"이 권장되는 이유**: DeepSeek는 2026-08-17부터 **피크/오피크 과금**을 시행합니다 — 피크 시간대(베이징 시간 9:00-12:00, 14:00-18:00) 단가는 오피크(나머지 시간대, 주간·야간·주말·공휴일 포함)의 **2배**입니다. 장시간 실행되는 세션이 비싼 시간대를跨越하면, 수동으로 동결하여 API 소비를 일시 정지하고 오피크에 재개하면 비용을 최대 **50%** 절감할 수 있습니다.
|
|
34
|
+
>
|
|
35
|
+
> **권장 구성**: **알림** 플러그인([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), 동결 전후 실제 지출 확인)을 함께 사용하여 "알림 → 동결 → 오피크 재개 → 정산" 절약 루ープ를 실현합니다.
|
|
36
|
+
|
|
37
|
+
## 기능概要
|
|
38
|
+
|
|
39
|
+
- **3단계 삽입 공존**: 에이전트가 바쁠 때 모든 입력은 먼저 대기 영역에 들어가고, 대화에 들어가는 시기를 선택할 수 있습니다 — "중단" 또는 "대기" 단일 선택이 아닙니다:
|
|
40
|
+
- 🔴 **빨간색(now)**: 현재 턴을 중단하고 즉시 전송 — 실행 중인 생성이 중지되고 메시지가 에이전트에 의해 즉시 처리되어 응답됩니다;
|
|
41
|
+
- 🟡 **노란색(next)**: 다음 자연스러운 턴에 삽입 — 현재 액션(도구 호출/실행 중인 생성)이 완료된 후 삽입;
|
|
42
|
+
- 🟢 **초록색(later)**: 논리 전체 실행 후 입력 — 대기열에서 이전 입력의 모든 액션이 완료된 후 처리(기본값).
|
|
43
|
+
- **노란색은 취소 가능**: 이미 삽입된(노란색) 메시지에 초록 버튼을 누르면 삽입을 취소하고 대기열로 되돌릴 수 있습니다.
|
|
44
|
+
- **대기열 내용 편집 가능**: 대기열에 있는 메시지를 직접 편집할 수 있습니다 — 멀티라인 에디터가 내용에 따라 자동 확장되어 긴 메시지도 완전히 표시됩니다(Enter 저장 / Shift+Enter 줄바꿈 / Esc 취소).
|
|
45
|
+
- **대기열 관리**: 대기영역의 메시지는 **위로/아래로 이동**하여 순서 변경, 삭제, "취소 후 전체 지우기"가 가능합니다.
|
|
46
|
+
- **편집 시 내용 손실 없음**: 저장 실패 시(에이전트가 이미 메시지를 가져간 경우), 편집 내용은 자동으로 컴포저로 돌아갑니다.
|
|
47
|
+
- **피크 시간 동결**: 입력창 우측 "세션 동결" 버튼 — DeepSeek 피크 과금 시간대(9:00-12:00, 14:00-18:00)에 가까워지면 API 소비를 일시 정지: 현재 턴이 자연스럽게 완료된 후 일시 정지, 미전송 대기열은 동결 저장; "세션 재개"로 오피크에 처리 계속.
|
|
48
|
+
- **세션 격리 동결**: 동결 대기열은 **sessionId로 격리** — 한 세션의 동결은 다른 세션에 영향을 주지 않습니다.
|
|
49
|
+
- **공식 동작 오버라이드**: 플러그인 활성 시 공식 설정 패널의 "바쁜 동안 Enter 키 동작" 설정 행이 숨겨집니다(Enter 동작은 초록 대기열로 고정).
|
|
50
|
+
- **주야 자동 적응**: 대기열 프레임과 동결 버튼은 모두 dsh 공식 시맨틱 토큰(`--dsw-alias-*`)을 사용하며 시스템 다크모드 / dsh 다크 테마를 자동 추적합니다.
|
|
51
|
+
|
|
52
|
+
## 3단계 의미론
|
|
53
|
+
|
|
54
|
+
| 단계 | 색상 | 의미론 | 하위 메커니즘(dsh 기존 RPC 조합) |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| **later** (기본값) | 초록 | 대기: 이전 입력의 모든 액션이 완료된 후 처리; 삽입된(노란색) 메시지에 초록 = **삽입 취소, 대기열로 복귀** | Enter 기본 queue → `agent.followup()` (next-turn); 취소 = `updateQueue(remove)` + `send(text)` |
|
|
57
|
+
| **next** | 노랑 | 다음 자연스러운 턴에 삽입: 현재 액션 완료 후 | `updateQueue(id, { kind: 'steer' })` → `agent.steer()` (next-step 경계) |
|
|
58
|
+
| **now** | 빨강 | 중단 후 전송: 현재 턴 중지, 메시지 즉시 처리 | `cancel()` → `updateQueue(remove)` (inbox 중복 삽입 거부 회피) → `send(text)` (재전송, 드라이버 즉시 깨우기) |
|
|
59
|
+
|
|
60
|
+
## 세션 동결 / 재개 (피크 시간대 일시정지) ⭐ 권장
|
|
61
|
+
|
|
62
|
+
> **절약 포지셔닝**: 본 플러그인의 DeepSeek 피크/오피크 과금(2026-08-17 시행)에 대한 **핵심 권장 기능**입니다 — 피크 시간대 단가 2배, 오피크는 반값. 수동 동결로 긴급하지 않은 생성을 "일시정지"하고 오피크에 재개하면 비싼 시간대를 직접 회피합니다.
|
|
63
|
+
>
|
|
64
|
+
> **권장 구성**: **알림** 플러그인([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)) 동결 전후 실제 지출 확인.
|
|
65
|
+
|
|
66
|
+
- **동결**: 현재 턴은 **중단되지 않고** 자연스럽게 완료된 후 일시정지; 대기열은 동결과 **분리** — 동결은 에이전트 소비(실행/삽입/추가)만 중지하고 대기 영역은 표시된 채 **완전히 조작 가능**;
|
|
67
|
+
- **재개**: (수정된) 대기열이 재전송되고 **각 항목은 예정된 단계로 실행** (빨강=중단 후 즉시 처리, 노랑=삽입, 초록=대기열); 에이전트는 FIFO 계속;
|
|
68
|
+
- **세션 격리**: 동결 상태와 분리된 대기열은 **sessionId로 격리** — 세션 A의 동결은 세션 B의 배너/버튼/대기열에 영향 없음;
|
|
69
|
+
- **엔진**: 동결 = `updateQueue/remove)`로 각 행 분리(단계별 복사본은 플러그인 store에 세션별 저장), 현재 턴이 pending 없이 자연 정지; 재개 = 먼저 `sessionGuard.resume(sessionId)`, 그 후 `send(text)`로 재전송하여 드라이버 깨우기(빨간 단계는 `cancel()` 후 전송);
|
|
70
|
+
- 주의: 이미지 등 비텍스트 내용이 포함된 대기열 메시지는 재전송 불가하며, 동결 시 대기열에서 해제됩니다(복원되지 않음).
|
|
71
|
+
|
|
72
|
+
## 대기열 관리
|
|
73
|
+
|
|
74
|
+
대기영역 각 행(미동결 시)은 다음 작업을 제공:
|
|
75
|
+
|
|
76
|
+
| 작업 | 설명 |
|
|
77
|
+
|---|---|
|
|
78
|
+
| 위로/아래로 이동 | FIFO 순서 재구성(이미지 메시지가 대기열에 있으면 비활성화) |
|
|
79
|
+
| **드래그로 재정렬** | 행을 드래그하여 대상 위치로 이동(네이티브 HTML5 DnD) |
|
|
80
|
+
| 컴포저로 되돌려 편집 | 메시지 내용을 컴포저 초안으로 복귀 |
|
|
81
|
+
| 편집/삭제 | 멀티라인 에디터로 직접 편집/취소 |
|
|
82
|
+
| 빨간/노란/초록 계획 | "3단계 의미론" 참조 |
|
|
83
|
+
| 취소 후 전체 지우기 | 2단계 확인 후 실행 중지 + 전체 대기열 삭제 |
|
|
84
|
+
|
|
85
|
+
## 주야 모드(자동 다크 적응)
|
|
86
|
+
|
|
87
|
+
대기열 프레임과 동결 버튼은 모두 dsh 공식 시맨틱 토큰(`--dsw-alias-*`)을 사용하며, 다크모드에서 **다크그레이 배경 + 흰색 반전 텍스트**로 자동 전환. 설정 불필요.
|
|
88
|
+
|
|
89
|
+
## 설치
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
# 방법 1: npm에서 설치(권장, 안정 버전)
|
|
93
|
+
dsh plugin --profile web add dsh-input-traffic -w
|
|
94
|
+
|
|
95
|
+
# 방법 2: GitHub에서 직접 설치(drscrewdriver 포크 전용)
|
|
96
|
+
dsh plugin --profile web add github:drscrewdriver/dsh-input-traffic#main
|
|
97
|
+
|
|
98
|
+
# 방법 3: 로컬 경로로 조립
|
|
99
|
+
# dsh plugin --profile web add /absolute/path/to/dsh-input-traffic -w
|
|
100
|
+
|
|
101
|
+
# 확인
|
|
102
|
+
dsh web --dump-config | grep -B1 -A2 'input-traffic'
|
|
103
|
+
|
|
104
|
+
# dsh web 재시작(필수!)
|
|
105
|
+
dsh web
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> ⚠️ **GitHub 네트워크 도달성**: github: 직접 설치는 github.com 연결이 필요합니다. 네트워크 제한이 있는 경우 프록시 또는 미러 가속기를 설정하세요.
|
|
109
|
+
|
|
110
|
+
상세는 [INSTALL.ko.md](./INSTALL.ko.md)를 참조하세요.
|
|
111
|
+
|
|
112
|
+
## 개발(TDD + Lint)
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
npm run tdd # vitest watch: 변경 시 재실행, 빨강→초록 루프
|
|
116
|
+
npm run lint # ESLint flat config
|
|
117
|
+
npm run lint:fix # 자동 수정
|
|
118
|
+
npm run verify # 통합 게이트: lint + test + build + verify-assembly
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 사용법
|
|
122
|
+
|
|
123
|
+
1. 에이전트가 바쁠 때 직접 입력하여 전송 — 메시지는 **대기 영역에 진입**(기본 초록 대기열);
|
|
124
|
+
2. 메시지에 계획 버튼을 누릅니다:
|
|
125
|
+
- 🟡 노랑 = 삽입 — 현재 액션 완료 후 삽입;
|
|
126
|
+
- 🔴 빨강 = 중단 — 현재 액션을 즉시 중지, 메시지가 즉시 처리;
|
|
127
|
+
- 🟢 초록 = 대기 유지(기본값); 삽입된 메시지에 초록 = 취소하여 대기열로 복귀;
|
|
128
|
+
3. 순서 변경/재편집: 위로/아래로 이동, 컴포저로 되돌리기, 또는 멀티라인 인라인 에디터(Enter 저장, Shift+Enter 줄바꿈);
|
|
129
|
+
4. **절약 핵심(권장)**: 피크 시간대(9:00-12:00, 14:00-18:00)에 가까워지면 "세션 동결"을 눌러 일시정지; 오피크에 "세션 재개"로 계속.
|
|
130
|
+
|
|
131
|
+
## 자주 묻는 질문
|
|
132
|
+
|
|
133
|
+
### 중단 후 메시지에 응답이 없음 / 대화 정지
|
|
134
|
+
|
|
135
|
+
과거 문제(수정 완료). 원인: harness inbox는 이미 대기 중인 메시지의 중복 삽입을 거부합니다. 중단 후 원본 메시지를 직접 steer하면 `"message is already pending"`으로 거부되어 메시지가 대기열에 고정되고 에이전트가 정지합니다. 현재 구현은 `cancel → remove → resend`(새 메시지로 재전송)입니다. 여전히 발생하면 플러그인을 최신 빌드하고 dsh web을 재시작하세요.
|
|
136
|
+
|
|
137
|
+
### 편집 저장 실패 후 내용은 어디로?
|
|
138
|
+
|
|
139
|
+
손실되지 않습니다. 저장 실패 시(에이전트가 이미 메시지를 가져간 경우), 편집 내용은 자동으로 컴포저로 돌아가 "편집 실패, 내용이 컴포저로 돌아갔습니다" 알림이 표시됩니다. 컴포저에 이미 초안이 있으면 덮어쓰지 않습니다.
|
|
140
|
+
|
|
141
|
+
### 설정 패널에 "바쁜 동안 Enter 키 동작"이 없음
|
|
142
|
+
|
|
143
|
+
정상입니다 — 플러그인이 오버라이드한 후 해당 설정 행이 숨겨지고 Enter 동작은 초록 대기열로 고정됩니다.
|
|
144
|
+
|
|
145
|
+
### 동결 후 대기열 메시지가 사라짐
|
|
146
|
+
|
|
147
|
+
정상입니다 — 동결은 대기열을 플러그인 store에 저장합니다(세션별 격리, 대기 영역에서 동결 리스트로 이동). 재개 후 다시 표시됩니다. **페이지 새로고침 시 동결 대기열은 손실됩니다** — 동결 중 새로고침하지 마세요.
|
|
148
|
+
|
|
149
|
+
### 위로/아래로 버튼 사용 불가
|
|
150
|
+
|
|
151
|
+
대기열에 이미지 등 비텍스트 메시지가 포함되어 있으면 재정렬이 비활성화됩니다(이미지 메시지는 재전송 불가). 컴포저로 되돌려 편집도 마찬가지.
|
|
152
|
+
|
|
153
|
+
## 제거
|
|
154
|
+
|
|
155
|
+
```sh
|
|
156
|
+
dsh plugin --profile web remove dsh-input-traffic
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
재시작 후 공식 대기열 dock과 "바쁜 동안 Enter 키 동작" 설정 행이 복원됩니다.
|
|
160
|
+
|
|
161
|
+
## 호환성 및 개인정보
|
|
162
|
+
|
|
163
|
+
- DeepSeek Harness와 web 프로필이 필요합니다. Windows/macOS/Linux dsh web에서 검증 완료.
|
|
164
|
+
- 플러그인은 브라우저 측(클라이언트) 전용 — 모든 작업은 dsh 기존 RPC를 통해 수행되며 **공식 소스를 변경하지 않습니다**.
|
|
165
|
+
- 플러그인은 세션 내용 이외의 데이터를 읽거나 업로드하지 않습니다. 동결 대기열은 브라우저 메모리에만 저장됩니다.
|
|
166
|
+
|
|
167
|
+
## drscrewdriver DSH Plugin Family
|
|
168
|
+
|
|
169
|
+
본 프로젝트는 [drscrewdriver](https://github.com/drscrewdriver)가 유지보수하는 DSH 플러그인 시리즈의 하나입니다:
|
|
170
|
+
|
|
171
|
+
| 플러그인 | 한 줄 설명 |
|
|
172
|
+
|---|---|
|
|
173
|
+
| **[dsh-input-traffic](https://github.com/drscrewdriver/dsh-input-traffic)** | DSH Web GUI 바쁜 시간 입력 대기열: 3단계 트래픽 제어, 드래그 재정렬, 세션 동결 |
|
|
174
|
+
| **[dsh-session-guard](https://github.com/drscrewdriver/dsh-session-guard)** | 피크 자동 세션 게이트: 주말 모드 + 피크 자동 일시정지 + 세션급 잠금 + 백엔드 자동 재시도 |
|
|
175
|
+
| [dsh-thinking-levels](https://github.com/drscrewdriver/dsh-thinking-levels) | 라운드별 reasoning_effort 제어: Auto 스케줄링 또는 수동 고정 |
|
|
176
|
+
| [dsh-seatbelt-sandbox](https://github.com/drscrewdriver/dsh-seatbelt-sandbox) | macOS Seatbelt 샌드박스 어댑터 |
|
|
177
|
+
| [dsh-switch-search](https://github.com/drscrewdriver/dsh-switch-search) | 사이드바 대화 검색 강화 |
|
|
178
|
+
|
|
179
|
+
## 라이선스
|
|
180
|
+
|
|
181
|
+
MIT
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<strong>给 DeepSeek Harness Web GUI 一个三档输入交通管制</strong>
|
|
3
3
|
</p>
|
|
4
4
|
<p align="center">
|
|
5
|
-
<strong>中文</strong> · <a href="README.
|
|
5
|
+
<a href="README.en.md">English</a> · <strong>中文</strong> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a>
|
|
6
6
|
</p>
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-263146?style=flat-square"></a>
|
|
@@ -13,6 +13,30 @@
|
|
|
13
13
|
|
|
14
14
|
# dsh-input-traffic
|
|
15
15
|
|
|
16
|
+
- [English README](./README.en.md)
|
|
17
|
+
- [中文 README](./README.md)
|
|
18
|
+
- [日本語 README](./README.ja.md)
|
|
19
|
+
- [한국어 README](./README.ko.md)
|
|
20
|
+
- [Installation guide](./INSTALL.md)
|
|
21
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
22
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
23
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
24
|
+
- [Changelog](./CHANGELOG.md)
|
|
25
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
26
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
27
|
+
|
|
28
|
+
> **▼ DSH 版本适配**
|
|
29
|
+
> | DSH 版本 | 队列条 / 冻结按钮 | 繁忙时 Enter 钉住 | 关键差异 |
|
|
30
|
+
> | --- | --- | --- | --- |
|
|
31
|
+
> | 0.1.1-rc.2 | ✅ | ✅ | `conversation.input.right` 仍带 `InputZone` owner(插件已不依赖) |
|
|
32
|
+
> | 0.1.2-rc.1 | ✅ | ✅ | 该槽改为无 owner(`InputBar.tsx:466` 传 `{}`);冻结按钮改读会话标准件 `useSession` |
|
|
33
|
+
>
|
|
34
|
+
> - **单一产物,运行时自适应**:同一份 `lib/client.js` 在两个版本都可用。客户端 bundle 只 `require` `react` / `react/jsx-runtime` / `@deepseek-ai/dsh-client-ui-primitives`,三者在两版的共享模块表内,不涉及 `dsh-client-runtime` → `dsh-client-store` 的改名。
|
|
35
|
+
> - **只消费两版共享面**:队列条在 `conversation.input.dock`(两版都带 `InputZone` owner,`input.draft` 两版都有);冻结按钮在 `conversation.input.right`,该槽 0.1.2 起不再传 owner,因此组件只读 `useSession` / `sessionId`——两者在两版 `SessionStandardProps` 中都有。
|
|
36
|
+
> - **队列条位置**:注册 `order: 1000`,排在 `conversation.input.dock` 带内所有已知条目(todo 0 / goal 10 / 官方 queue 20 / dsh-perm-gate 提示 30)之后,紧贴输入卡片。DSH 没有 "last" 语义,这是约定而非结构性保证——第三方插件若注册更大的 `order` 仍可能插到它下面。
|
|
37
|
+
|
|
38
|
+
> **兼容性说明:** v0.2.9 已包含日语(`ja`)和韩语(`ko`)字典,但当前官方 DSH 只通过 `LocaleRuntime` 提供 `zh` 和 `en`。在原版 DSH 中选择 `ja` 或 `ko` 会失败,并提示 `locale "<id>" is not registered`。需要等待官方 DSH 增加对应 locale ID 后才能正常使用。高级用户可以维护 DSH fork,在 `packages/client/locale/src/locale-settings.ts` 更新 `LOCALE_IDS`,在 `packages/client/locale/src/client/index.ts` 更新 `LOCALES` 标签,并补齐核心字典和测试,然后重新构建并运行 fork 版本。仅修改本插件无法扩展 DSH 的全局 locale 列表。
|
|
39
|
+
|
|
16
40
|
> 智能体忙碌时不再只有"打断"或"排队"二选一:红色打断立即输入、黄色下一轮插入、绿色排队到最后,三档并存;邻近 DeepSeek 高峰收费时段可一键冻结会话,错峰再恢复继续。
|
|
17
41
|
|
|
18
42
|
无需修改 dsh 源码、无需提 PR:`dsh plugin` 命令组装 + bundle patch 装配的 cordis client 插件。
|
|
@@ -22,8 +46,18 @@
|
|
|
22
46
|
> **目前建议搭配**:配合**一般提醒**插件(如 [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),核对冻结前后的实际花费),形成「提醒 → 冻结 → 错峰恢复 → 对账」的省钱闭环。
|
|
23
47
|
|
|
24
48
|
## 它能做什么
|
|
25
|
-
|
|
26
|
-
|
|
49
|
+
|
|
50
|
+
> 实际运行截屏(Windows,dsh web):
|
|
51
|
+
|
|
52
|
+
<figure>
|
|
53
|
+
<img width="1600" alt="深色模式下的会话页:上方排队等待区显示『1 条排队消息』(🟢 排队 test1)与『取消并清空』;中央为花边样式输入框,提示 Cmd/Ctrl+Enter 插话发送全部排队消息;输入行右侧为『冻结会话』按钮、DeepSeek-V4-Flash 模型选择与发送控件" src="assets/dark-mode.png" />
|
|
54
|
+
<figcaption>深色模式(自动跟随系统 / dsh 暗色主题):排队等待区 + 输入行右侧「冻结会话」按钮。</figcaption>
|
|
55
|
+
</figure>
|
|
56
|
+
|
|
57
|
+
<figure>
|
|
58
|
+
<img width="1400" alt="浅色模式且会话已冻结的会话页:排队等待区出现『已冻结:当前轮次完成后暂停,排队消息将在恢复后继续』横幅及『取消并清空』;队列含测试1(🟢 排队)、测试2/测试3(🟡 插话中);输入行按钮切换为『恢复会话』" src="assets/light-mode.png" />
|
|
59
|
+
<figcaption>浅色模式 + 已冻结状态:高峰时段冻结后队列被冻结保存,输入行按钮切换为「恢复会话」,错峰再行处理。</figcaption>
|
|
60
|
+
</figure>
|
|
27
61
|
|
|
28
62
|
- **三档插入并存**:智能体忙碌时,每一条输入都先进入等待区,再按需选择何时进入对话——不再只有一个"打断"或只有一个"排队":
|
|
29
63
|
- 🔴 **红色(now)**:打断当前轮次并立即输入——当前生成停止,消息作为新输入被 agent 立刻处理并回复;
|
|
@@ -89,7 +123,18 @@
|
|
|
89
123
|
- `src/client/freeze-store.ts` — 会话级冻结状态 store(`Map<sessionId, {frozen, pending}>`,供按钮 ↔ dock 共享);
|
|
90
124
|
- `src/client/session-guard-bridge.ts` — session-guard RPC 透传(fail-open,未装则静默);
|
|
91
125
|
- `src/client/index.ts` — slot 注册 + composer block 注入(`conversation.blocks.set`)。
|
|
92
|
-
- **作用域对比**:本插件冻结按钮 = **会话级**(按 sessionId 锁那一个会话);session-guard
|
|
126
|
+
- **作用域对比**:本插件冻结按钮 = **会话级**(按 sessionId 锁那一个会话);session-guard 的高峰自动门 / step 门 = **全局或会话级暂停**(入峰拉门、退峰自动放行)。
|
|
127
|
+
|
|
128
|
+
**分工(重要):本插件只负责「排」,session-guard 只负责「停」**
|
|
129
|
+
|
|
130
|
+
| | 本插件(input-traffic) | session-guard |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| 职责 | 用户输入进**哪条队列、什么档位、何时被消费** | **何时允许推进**(step / 回合 / 请求) |
|
|
133
|
+
| DSH 原语 | `next-step` / `next-turn` 两条待处理队列 + `updateQueue(steer\|remove\|edit)` / `send` / `cancel` | `agent/pre-step`(step 门)、`agent.cancel({keepInbox:true})` + `goals.pause`、`agent/request` hold |
|
|
134
|
+
| 冻结 | 摘 `queued` + `steering` 行(**保留档位**)+ composer block | `stopNextTurn`:**先释放 step 门**再做回合级暂停(否则两边互等) |
|
|
135
|
+
| 恢复 | 按档位重投(红 cancel+send / 黄 steer / 绿 send) | `resume`:从暂停点续跑 |
|
|
136
|
+
|
|
137
|
+
两条队列的物理含义:`next-step` = 「与**工具返回同级**的下一个 step,仍在同一个 turn 内」;`next-turn` = 「新的回合」。所以黄档是「插到当前回合的下一步」,绿档是「等回合结束后再开一轮」——这正是三档能被 API 在同一次 turn 中途看到的原因。
|
|
93
138
|
|
|
94
139
|
## 队列管理
|
|
95
140
|
|
package/dsh.plugin.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "dsh-external/dsh-input-traffic",
|
|
3
|
+
"version": "0.2.10-beta.2",
|
|
4
|
+
"main": "./lib/index.js",
|
|
5
|
+
"description": "Busy-time input queue: three-tier planning, drag-to-reorder, interject/interrupt, batch clear, session freeze.",
|
|
6
|
+
"contributes": {
|
|
7
|
+
"tools": [],
|
|
8
|
+
"skills": []
|
|
9
|
+
},
|
|
10
|
+
"client": {
|
|
11
|
+
"main": "./lib/client.js"
|
|
12
|
+
}
|
|
13
|
+
}
|
package/lib/client.js
CHANGED
|
@@ -8,7 +8,7 @@ window.__ModuleLoader__.load({
|
|
|
8
8
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
9
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
//#region src/client/locales.ts
|
|
11
|
-
/** `steer`
|
|
11
|
+
/** `steer` client dictionaries (zh / en / ja / ko). */
|
|
12
12
|
/** Dictionary namespace owned by this plugin. */
|
|
13
13
|
const NS = "steer";
|
|
14
14
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
@@ -55,8 +55,8 @@ window.__ModuleLoader__.load({
|
|
|
55
55
|
"steer.clear.cancel": "取消清空",
|
|
56
56
|
"steer.clear.aria": "取消当前执行并清空全部排队消息",
|
|
57
57
|
"steer.clearFailed": "取消并清空失败,请重试。",
|
|
58
|
-
"steer.freeze": "
|
|
59
|
-
"steer.resume": "
|
|
58
|
+
"steer.freeze": "冻结追加",
|
|
59
|
+
"steer.resume": "恢复追加",
|
|
60
60
|
"steer.frozen": "已冻结:当前轮次完成后暂停,排队消息将在恢复后继续",
|
|
61
61
|
"steer.frozenInput": "已冻结:输入已暂停,恢复后继续",
|
|
62
62
|
"steer.frozenBadge": "已冻结",
|
|
@@ -107,8 +107,8 @@ window.__ModuleLoader__.load({
|
|
|
107
107
|
"steer.clear.cancel": "Cancel clearing",
|
|
108
108
|
"steer.clear.aria": "Cancel the current run and clear all queued messages",
|
|
109
109
|
"steer.clearFailed": "Cancel and clear failed, please retry.",
|
|
110
|
-
"steer.freeze": "Freeze
|
|
111
|
-
"steer.resume": "Resume
|
|
110
|
+
"steer.freeze": "Freeze & append",
|
|
111
|
+
"steer.resume": "Resume & append",
|
|
112
112
|
"steer.frozen": "Frozen: the current turn finishes, then the queue pauses until resumed",
|
|
113
113
|
"steer.frozenInput": "Frozen: input paused, resume to continue",
|
|
114
114
|
"steer.frozenBadge": "frozen",
|
|
@@ -204,8 +204,8 @@ window.__ModuleLoader__.load({
|
|
|
204
204
|
for (const listener of listeners) listener();
|
|
205
205
|
}
|
|
206
206
|
//#endregion
|
|
207
|
-
//#region \0dsh-css:E:\test\rewrite-agently\dsh-input-traffic\src\client\steer-queue-dock.module.css.mjs
|
|
208
|
-
const css$1 = ".
|
|
207
|
+
//#region \0dsh-css:E:\test\rewrite-agently\mine-dsh-plugins\dsh-input-traffic\src\client\steer-queue-dock.module.css.mjs
|
|
208
|
+
const css$1 = ".FNESVa_dock{width:100%}.FNESVa_panel{background:var(--dsw-alias-bg-layer-1,#fffc);border:1px solid var(--dsw-alias-border-l2,#00000014);border-radius:10px;overflow:hidden}.FNESVa_toolbar{border-bottom:1px solid var(--dsw-alias-border-l2,#0000000f);align-items:center;gap:8px;padding:4px 8px;display:flex}.FNESVa_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}.FNESVa_header:disabled{cursor:default}.FNESVa_lead{color:var(--dsw-alias-label-tertiary,#9ca3af);display:inline-flex}.FNESVa_count{font-weight:600}.FNESVa_chevron{color:var(--dsw-alias-label-tertiary,#9ca3af);display:inline-flex}.FNESVa_toolbarActions{margin-left:auto}.FNESVa_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}.FNESVa_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}.FNESVa_freeze[aria-pressed=true]{border-color:var(--dsw-alias-state-success-primary,#30a46c);color:var(--dsw-alias-state-success-primary,#30a46c)}.FNESVa_freeze:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.FNESVa_freeze:disabled{opacity:.5;cursor:default}.FNESVa_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}.FNESVa_frozenList{margin:0;padding:4px;list-style:none}.FNESVa_frozenRow{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.FNESVa_frozenMark{color:var(--dsw-alias-label-tertiary,#9ca3af);flex:none;margin-left:auto;font-size:11px}.FNESVa_clear:hover:not(:disabled){border-color:var(--dsw-alias-border-l3,#0000001f);background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.FNESVa_clear:disabled{opacity:.5;cursor:default}.FNESVa_clearConfirm{border-color:var(--dsw-alias-state-error-primary,#e5484d);color:var(--dsw-alias-state-error-primary,#e5484d)}.FNESVa_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)}.FNESVa_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}.FNESVa_clearCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.FNESVa_clearLabel{font-size:12px}.FNESVa_list{margin:0;padding:4px;list-style:none}.FNESVa_row{border-radius:6px;align-items:center;gap:8px;padding:4px 6px;display:flex}.FNESVa_row[draggable=true]{cursor:grab}.FNESVa_row[draggable=true]:active{cursor:grabbing}.FNESVa_rowDragOver{outline:2px dashed var(--dsw-alias-border-l4,#00000040);outline-offset:-2px;background:var(--dsw-alias-interactive-bg-hover,#0000000d)}.FNESVa_row:hover{background:var(--dsw-alias-interactive-bg-hover,#00000008)}.FNESVa_row[data-editing]{align-items:flex-start}.FNESVa_preview{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-primary,#1f2937);flex:1;font-size:13px;overflow:hidden}.FNESVa_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}.FNESVa_badgeLabel{color:inherit}.FNESVa_badgeNow{color:var(--dsw-alias-state-error-primary,#e5484d);background:color-mix(in srgb, var(--dsw-alias-state-error-primary,#e5484d) 10%, transparent)}.FNESVa_badgeNext{color:var(--dsw-alias-state-warn-primary,#e8a33d);background:color-mix(in srgb, var(--dsw-alias-state-warn-primary,#e8a33d) 12%, transparent)}.FNESVa_badgeLater{color:var(--dsw-alias-state-success-primary,#30a46c);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 12%, transparent)}.FNESVa_badgeNow .FNESVa_dot{background:var(--dsw-alias-state-error-primary,#e5484d)}.FNESVa_badgeNext .FNESVa_dot{background:var(--dsw-alias-state-warn-primary,#e8a33d)}.FNESVa_badgeLater .FNESVa_dot{background:var(--dsw-alias-state-success-primary,#30a46c)}.FNESVa_steeringList{margin:0;padding:0 4px 4px;list-style:none}.FNESVa_steeringList .FNESVa_row{opacity:.85}.FNESVa_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}.FNESVa_actions{align-items:center;gap:2px;display:inline-flex}.FNESVa_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}.FNESVa_action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2937)}.FNESVa_action:disabled{opacity:.4;cursor:default}.FNESVa_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}.FNESVa_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}.FNESVa_tier:hover:not(:disabled){border-color:var(--dsw-alias-border-l4,#0003)}.FNESVa_tier:disabled{cursor:default}.FNESVa_tierLater{border-color:var(--dsw-alias-state-success-primary,#30a46c);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#30a46c) 12%, transparent)}.FNESVa_dot{border-radius:50%;width:10px;height:10px}.FNESVa_tierNow .FNESVa_dot{background:var(--dsw-alias-state-error-primary,#e5484d)}.FNESVa_tierNext .FNESVa_dot{background:var(--dsw-alias-state-warn-primary,#e8a33d)}.FNESVa_tierLater .FNESVa_dot{background:var(--dsw-alias-state-success-primary,#30a46c)}";
|
|
209
209
|
const tagId$1 = "dsh-input-traffic/steer-queue-dock.module.css";
|
|
210
210
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
211
211
|
const tag = document.createElement("style");
|
|
@@ -215,42 +215,42 @@ window.__ModuleLoader__.load({
|
|
|
215
215
|
document.head.appendChild(tag);
|
|
216
216
|
}
|
|
217
217
|
var steer_queue_dock_module_css_default = {
|
|
218
|
-
"
|
|
219
|
-
"
|
|
220
|
-
"
|
|
221
|
-
"
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
"
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"
|
|
236
|
-
"
|
|
237
|
-
"
|
|
238
|
-
"
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
243
|
-
"
|
|
244
|
-
"
|
|
245
|
-
"
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
253
|
-
"
|
|
218
|
+
"editor": "FNESVa_editor",
|
|
219
|
+
"rowDragOver": "FNESVa_rowDragOver",
|
|
220
|
+
"lead": "FNESVa_lead",
|
|
221
|
+
"count": "FNESVa_count",
|
|
222
|
+
"clear": "FNESVa_clear",
|
|
223
|
+
"list": "FNESVa_list",
|
|
224
|
+
"steeringList": "FNESVa_steeringList",
|
|
225
|
+
"badgeNow": "FNESVa_badgeNow",
|
|
226
|
+
"tierNow": "FNESVa_tierNow",
|
|
227
|
+
"tier": "FNESVa_tier",
|
|
228
|
+
"frozenList": "FNESVa_frozenList",
|
|
229
|
+
"badgeLabel": "FNESVa_badgeLabel",
|
|
230
|
+
"clearCancel": "FNESVa_clearCancel",
|
|
231
|
+
"row": "FNESVa_row",
|
|
232
|
+
"dock": "FNESVa_dock",
|
|
233
|
+
"header": "FNESVa_header",
|
|
234
|
+
"actions": "FNESVa_actions",
|
|
235
|
+
"badgeLater": "FNESVa_badgeLater",
|
|
236
|
+
"chevron": "FNESVa_chevron",
|
|
237
|
+
"tierLater": "FNESVa_tierLater",
|
|
238
|
+
"badgeNext": "FNESVa_badgeNext",
|
|
239
|
+
"panel": "FNESVa_panel",
|
|
240
|
+
"preview": "FNESVa_preview",
|
|
241
|
+
"frozenRow": "FNESVa_frozenRow",
|
|
242
|
+
"tierNext": "FNESVa_tierNext",
|
|
243
|
+
"clearConfirm": "FNESVa_clearConfirm",
|
|
244
|
+
"plan": "FNESVa_plan",
|
|
245
|
+
"toolbarActions": "FNESVa_toolbarActions",
|
|
246
|
+
"frozenMark": "FNESVa_frozenMark",
|
|
247
|
+
"freeze": "FNESVa_freeze",
|
|
248
|
+
"badge": "FNESVa_badge",
|
|
249
|
+
"frozenBanner": "FNESVa_frozenBanner",
|
|
250
|
+
"dot": "FNESVa_dot",
|
|
251
|
+
"clearLabel": "FNESVa_clearLabel",
|
|
252
|
+
"action": "FNESVa_action",
|
|
253
|
+
"toolbar": "FNESVa_toolbar"
|
|
254
254
|
};
|
|
255
255
|
//#endregion
|
|
256
256
|
//#region src/client/steer-queue-dock.tsx
|
|
@@ -1218,8 +1218,8 @@ window.__ModuleLoader__.load({
|
|
|
1218
1218
|
globalThis.__DSH_SESSION_GUARD_BRIDGE__ = true;
|
|
1219
1219
|
} catch {}
|
|
1220
1220
|
//#endregion
|
|
1221
|
-
//#region \0dsh-css:E:\test\rewrite-agently\dsh-input-traffic\src\client\freeze-button.module.css.mjs
|
|
1222
|
-
const css = ".
|
|
1221
|
+
//#region \0dsh-css:E:\test\rewrite-agently\mine-dsh-plugins\dsh-input-traffic\src\client\freeze-button.module.css.mjs
|
|
1222
|
+
const css = ".BUSMDW_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}.BUSMDW_freeze:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#0000000a)}.BUSMDW_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)}.BUSMDW_label{font-size:12px}";
|
|
1223
1223
|
const tagId = "dsh-input-traffic/freeze-button.module.css";
|
|
1224
1224
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1225
1225
|
const tag = document.createElement("style");
|
|
@@ -1229,8 +1229,8 @@ window.__ModuleLoader__.load({
|
|
|
1229
1229
|
document.head.appendChild(tag);
|
|
1230
1230
|
}
|
|
1231
1231
|
var freeze_button_module_css_default = {
|
|
1232
|
-
"
|
|
1233
|
-
"
|
|
1232
|
+
"label": "BUSMDW_label",
|
|
1233
|
+
"freeze": "BUSMDW_freeze"
|
|
1234
1234
|
};
|
|
1235
1235
|
//#endregion
|
|
1236
1236
|
//#region src/client/freeze-button.tsx
|
|
@@ -1255,11 +1255,12 @@ window.__ModuleLoader__.load({
|
|
|
1255
1255
|
* Freeze/resume toggle for the peak-hour scenario.
|
|
1256
1256
|
* @param props - slot props; the session snapshot drives the detach list.
|
|
1257
1257
|
*/
|
|
1258
|
-
function FreezeButton({
|
|
1258
|
+
function FreezeButton({ useSession, updateQueue, cancel, send, sendSteer, sessionId, setComposerBlock, notify, t }) {
|
|
1259
1259
|
const sid = sessionId ?? "";
|
|
1260
1260
|
const { frozen } = (0, react.useSyncExternalStore)(freezeStore.subscribe, () => freezeStore.getSnapshot(sid));
|
|
1261
|
+
const queue = useSession((s) => s.queue);
|
|
1261
1262
|
const freeze = async () => {
|
|
1262
|
-
const rows =
|
|
1263
|
+
const rows = queue.filter((row) => row.placement === "queued" || row.placement === "steering");
|
|
1263
1264
|
const pending = rows.flatMap((row) => row.text === null ? [] : [{
|
|
1264
1265
|
text: row.text,
|
|
1265
1266
|
tier: row.placement === "steering" ? "safe_point" : "queue"
|
|
@@ -1319,6 +1320,18 @@ window.__ModuleLoader__.load({
|
|
|
1319
1320
|
/** Busy-Enter field inside that namespace; the plugin pins it to queue. */
|
|
1320
1321
|
const BUSY_ENTER_FIELD = "busyEnter";
|
|
1321
1322
|
/**
|
|
1323
|
+
* Display order of the queue strip inside `conversation.input.dock`.
|
|
1324
|
+
*
|
|
1325
|
+
* List rows render sorted by `order` ascending, so a value above every other
|
|
1326
|
+
* contributor keeps the strip as the bottom-most entry of the band — directly
|
|
1327
|
+
* on top of the composer card. Known contributors in both 0.1.1-rc.2 and
|
|
1328
|
+
* 0.1.2-rc.1: `todo` 0, `goal` 10, official `queue` 20, `dsh-perm-gate.notice`
|
|
1329
|
+
* 30. DSH has no "last" slot semantics, so this is a convention, not a
|
|
1330
|
+
* structural guarantee: a third party registering a larger value could still
|
|
1331
|
+
* land below us.
|
|
1332
|
+
*/
|
|
1333
|
+
const QUEUE_DOCK_ORDER = 1e3;
|
|
1334
|
+
/**
|
|
1322
1335
|
* Deliver one plain-text message into the session's next step. The exposed
|
|
1323
1336
|
* conversation `send` verb only queues into the next turn, so resume steers
|
|
1324
1337
|
* through the session face's steer-mode prompt instead (no harness change).
|
|
@@ -1353,7 +1366,7 @@ window.__ModuleLoader__.load({
|
|
|
1353
1366
|
ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
1354
1367
|
name: "conversation.input.dock",
|
|
1355
1368
|
id: "queue",
|
|
1356
|
-
order:
|
|
1369
|
+
order: QUEUE_DOCK_ORDER,
|
|
1357
1370
|
priority: -1,
|
|
1358
1371
|
locale: NS,
|
|
1359
1372
|
inject: (sessionId) => {
|
|
@@ -1411,6 +1424,7 @@ window.__ModuleLoader__.load({
|
|
|
1411
1424
|
}, HideEnterRow));
|
|
1412
1425
|
}
|
|
1413
1426
|
//#endregion
|
|
1427
|
+
exports.QUEUE_DOCK_ORDER = QUEUE_DOCK_ORDER;
|
|
1414
1428
|
exports.apply = apply;
|
|
1415
1429
|
exports.inject = inject;
|
|
1416
1430
|
return module.exports;
|