dsh-flash-ctx-mon 0.0.0-stage → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +243 -2
- package/README.zh-CN.md +214 -0
- package/cordis.patch.yml +8 -0
- package/dist/index.js +47 -0
- package/lib/client.js +3237 -0
- package/package.json +43 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,244 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-flash-ctx-mon
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> The **context monitor** companion plugin for
|
|
4
|
+
> [dock-flash](https://gitee.com/lenin.guo/dock-flash) — it registers its own alert
|
|
5
|
+
> provider and its own panel switch instead of living inside dock-flash's `apply()`.
|
|
6
|
+
|
|
7
|
+
Apache-2.0
|
|
8
|
+
|
|
9
|
+
**[中文](./README.zh-CN.md)**
|
|
10
|
+
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
Two capabilities, one in each half of the plugin:
|
|
14
|
+
|
|
15
|
+
1. **Context monitor** — reads the **precise** token usage DSH already reports on its
|
|
16
|
+
session event stream and turns pressure on the model's context window into
|
|
17
|
+
dock-flash alerts, at three rising thresholds.
|
|
18
|
+
2. **Session skills chip** — a chip in the conversation header listing the skills the
|
|
19
|
+
current session has actually loaded, resolved against the skill catalog.
|
|
20
|
+
|
|
21
|
+
The monitor is **on by default** — only an explicit "off" turns it off — and it is
|
|
22
|
+
**entirely client-side**.
|
|
23
|
+
|
|
24
|
+
## What it registers
|
|
25
|
+
|
|
26
|
+
### Host half — `src/index.ts` → `dist/index.js`
|
|
27
|
+
|
|
28
|
+
A Cordis plugin named `dsh-flash-ctx-mon`.
|
|
29
|
+
|
|
30
|
+
| Thing | Detail |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Settings namespace | `dsh-flash-ctx-mon` |
|
|
33
|
+
| Fields | `ctxApproxWindow`, `ctxThresholdInfo`, `ctxThresholdWarning`, `ctxThresholdError`, `ctxPollBase`, `ctxPollMin`, `modelContextWindows`, `modelContextWindowSources` |
|
|
34
|
+
| Routes | **none** |
|
|
35
|
+
| Host-side services | **none** (`inject: []`) |
|
|
36
|
+
|
|
37
|
+
**The host half exists only to hold the settings namespace and its schema.** There is no
|
|
38
|
+
collector and no route, because there is nothing to collect on the host: token usage
|
|
39
|
+
arrives through DSH session events (`ctx.get('sessions')`), the model catalog through
|
|
40
|
+
`remote.session.modelCatalog()`, and the skill catalog through `remote.skills.list()` —
|
|
41
|
+
all of it in the browser.
|
|
42
|
+
|
|
43
|
+
### Browser half — `lib/client.js` (no build step)
|
|
44
|
+
|
|
45
|
+
| Registration | Through |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| Alert provider `dsh-flash-ctx-mon:context-alert` | `ctx.get('dockFlashAlerts').registerProvider()` |
|
|
48
|
+
| Panel switch `dsh-flash-ctx-mon:monitor-context` | `ctx.get('quickControl').registerSwitch()` |
|
|
49
|
+
| Session header chip `dsh-flash-ctx-mon-skills` | `ctx.inject(['slots'])` → `conversation.session.header.actions` |
|
|
50
|
+
|
|
51
|
+
Switch properties: `type: 'toggle'`, `group: 'system'`, `cluster: 'system-alerts'`,
|
|
52
|
+
`order: 59`, `icon: 'message'`, plus a **Configure** button. Its visibility follows
|
|
53
|
+
dock-flash's `dock-flash:system-alerts` master toggle — with the alert registry switched
|
|
54
|
+
off there is nothing for this switch to drive. It deliberately carries **no `subtitle`**:
|
|
55
|
+
the live "model · 12%" readout it used to print on the row is already the first thing in
|
|
56
|
+
the panel the Configure button opens.
|
|
57
|
+
|
|
58
|
+
> **Dual discovery, plus a fallback poll.** `ctx.get('quickControl')` /
|
|
59
|
+
> `ctx.get('dockFlashAlerts')` resolve asynchronously, so registration has three routes:
|
|
60
|
+
> the `dock-flash:ready` event (dock-flash loaded after us), a synchronous `ctx.get()`
|
|
61
|
+
> check (it loaded before us), and a fallback poll of up to 15 attempts 200 ms apart.
|
|
62
|
+
> The first to succeed sets `_registered`, so nothing registers twice.
|
|
63
|
+
|
|
64
|
+
## The switch
|
|
65
|
+
|
|
66
|
+
In dock-flash's quick panel, under **⚙️ System → System Alerts**, find **Context
|
|
67
|
+
Monitor**:
|
|
68
|
+
|
|
69
|
+
- turning it **off** writes `'0'` to `localStorage['dsh-flash-ctx-mon:monitor-context']`
|
|
70
|
+
and calls `setProviderEnabled(…, false)` on the alert registry, so the provider stops
|
|
71
|
+
producing alerts;
|
|
72
|
+
- turning it **on** restores both.
|
|
73
|
+
|
|
74
|
+
**Who wins.** The browser key is the authority, and **absence means on**
|
|
75
|
+
(`getItem(key) !== '0'`). The host's own fields are all `volatile()`, so DSH resets them
|
|
76
|
+
to their defaults on every restart — the browser is what remembers your choice.
|
|
77
|
+
|
|
78
|
+
## The config modal
|
|
79
|
+
|
|
80
|
+
**Configure** beside the switch opens the context monitor panel:
|
|
81
|
+
|
|
82
|
+
| Control | Range | Step | Default |
|
|
83
|
+
| --- | --- | --- | --- |
|
|
84
|
+
| Context Window Size `ctxApproxWindow` | 64000–512000 tokens | 8000 | 128000 |
|
|
85
|
+
| Info Threshold `ctxThresholdInfo` | 30–80 % | 1 | 70 |
|
|
86
|
+
| Warning Threshold `ctxThresholdWarning` | 50–92 % | 1 | 85 |
|
|
87
|
+
| Error Threshold `ctxThresholdError` | 70–98 % | 1 | 95 |
|
|
88
|
+
| Context Poll Base Interval `ctxPollBase` | 5000–60000 ms | 1000 | 20000 |
|
|
89
|
+
| Context Poll Min Interval `ctxPollMin` | 1000–10000 ms | 500 | 2000 |
|
|
90
|
+
|
|
91
|
+
Below the sliders the panel reports the live state — **Current Model**, **Window Size**,
|
|
92
|
+
**Window Source** (Session Event / Model Catalog / Error Parsed / Manual / Built-in /
|
|
93
|
+
Fuzzy Match / Fallback), **Data Source** (Precise / Awaiting data), **Input Tokens** and
|
|
94
|
+
**Context Pressure** — and carries the **Model Window Map** editor, a **Refresh
|
|
95
|
+
Catalog** action, and a preview of what the alert messages look like.
|
|
96
|
+
|
|
97
|
+
## Alerts
|
|
98
|
+
|
|
99
|
+
Emitted only when the token source is `precise`; with no session-event usage data the
|
|
100
|
+
monitor reports "Awaiting data" and **emits nothing** — it does not guess from message
|
|
101
|
+
counts.
|
|
102
|
+
|
|
103
|
+
| Level | At | Title |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| ℹ️ info | ≥ `ctxThresholdInfo` (70 %) | Session context getting long |
|
|
106
|
+
| 🟡 warning | ≥ `ctxThresholdWarning` (85 %) | Session context nearly exhausted |
|
|
107
|
+
| 🔴 error | ≥ `ctxThresholdError` (95 %) | Session context almost exhausted |
|
|
108
|
+
|
|
109
|
+
Each message carries the percentage and the reading it came from — `model ·
|
|
110
|
+
12.4K/128K` in precise mode. Alerts are `dismissible` and flow through dock-flash's
|
|
111
|
+
registry, so they appear in the panel's alert list and as toasts like any other.
|
|
112
|
+
|
|
113
|
+
## How a model's window is resolved
|
|
114
|
+
|
|
115
|
+
`_resolveWindow(model)` reads `modelContextWindows` — the **user-mapped** table in the
|
|
116
|
+
settings namespace — and labels each answer with its provenance from
|
|
117
|
+
`modelContextWindowSources`. A model that is not in the map resolves to `null`, and the
|
|
118
|
+
caller falls back to `ctxApproxWindow` (the "Fallback" source).
|
|
119
|
+
|
|
120
|
+
**The built-in window table has been retired.** `_KNOWN_WINDOWS` is empty and the
|
|
121
|
+
catalog auto-fill is a documented no-op, so today the map is the only source of a real
|
|
122
|
+
window size — which is why the panel's Model Window Map editor is how you teach it about
|
|
123
|
+
a model it gets wrong.
|
|
124
|
+
|
|
125
|
+
> Both map fields are `volatile()`, and that is **not** a statement that they are
|
|
126
|
+
> transient. The settings service rejects any patched path that is not under a volatile
|
|
127
|
+
> node (`Config field "…" is not volatile`), so a non-volatile `modelContextWindows`
|
|
128
|
+
> meant every mapping the panel wrote was rejected, rolled back and lost — a mapped
|
|
129
|
+
> model kept falling back to `ctxApproxWindow`. Volatile is what makes the write legal;
|
|
130
|
+
> the value still lands in the profile patch and survives a restart.
|
|
131
|
+
|
|
132
|
+
## Polling
|
|
133
|
+
|
|
134
|
+
The monitor samples on an adaptive interval: `ctxPollBase` is the **ceiling** used while
|
|
135
|
+
usage is low, and the interval tightens as usage rises, never below `ctxPollMin`. In
|
|
136
|
+
precise mode the base interval is doubled automatically, because the event source pushes
|
|
137
|
+
updates rather than being polled. A skill being used forces an immediate poll, so its
|
|
138
|
+
notice is claimed while the use is still fresh.
|
|
139
|
+
|
|
140
|
+
## The skills chip
|
|
141
|
+
|
|
142
|
+
A chip in the conversation header, registered into `conversation.session.header.actions`
|
|
143
|
+
as `dsh-flash-ctx-mon-skills` (order 15). It lists the skills **the current session** has
|
|
144
|
+
loaded — subagents and other sessions are excluded, because the slot hands the component
|
|
145
|
+
the id of the session it renders for.
|
|
146
|
+
|
|
147
|
+
Detection uses DSH's own marker: the `<skill_content name="X">` block emitted when a
|
|
148
|
+
skill body is loaded. It arrives on two paths — the model calling the `skill` tool, and a
|
|
149
|
+
user typing `/name` in the composer (which produces **no** tool call of its own) — and a
|
|
150
|
+
failed call carries no block, so failures are not counted. Names are resolved against the
|
|
151
|
+
skill catalog (`remote.skills.list()`), and the popup shows uses, first/last use and the
|
|
152
|
+
catalog description, with **Open in sidebar**.
|
|
153
|
+
|
|
154
|
+
The tracker is deliberately **independent of the monitor switch**: the chip keeps working
|
|
155
|
+
with the context monitor switched off.
|
|
156
|
+
|
|
157
|
+
## Settings
|
|
158
|
+
|
|
159
|
+
| Field | Default | Notes |
|
|
160
|
+
| --- | --- | --- |
|
|
161
|
+
| `ctxApproxWindow` | 128000 | Fallback window for a model the map does not know |
|
|
162
|
+
| `ctxThresholdInfo` | 70 | % of the window |
|
|
163
|
+
| `ctxThresholdWarning` | 85 | % — must exceed the info threshold |
|
|
164
|
+
| `ctxThresholdError` | 95 | % — must exceed the warning threshold |
|
|
165
|
+
| `ctxPollBase` | 20000 | ms, the low-usage ceiling |
|
|
166
|
+
| `ctxPollMin` | 2000 | ms, the floor |
|
|
167
|
+
| `modelContextWindows` | `{}` | model id → window size |
|
|
168
|
+
| `modelContextWindowSources` | `{}` | model id → provenance tag |
|
|
169
|
+
|
|
170
|
+
## Dependencies
|
|
171
|
+
|
|
172
|
+
| Package | Type | Purpose |
|
|
173
|
+
| --- | --- | --- |
|
|
174
|
+
| `@deepseek-ai/cordis` | peer | the plugin framework |
|
|
175
|
+
| `dock-flash` `>=1.5.0-0 <2.0.0-0 \|\| >=2.0.0-0 <3.0.0-0` | peer | supplies the `quickControl` and `dockFlashAlerts` services and the `dock-flash:ready` event |
|
|
176
|
+
| `dock-base` `>=0.1.2-0 <1.0.0-0 \|\| >=0.2.0-0 <1.0.0-0` | peer, optional | workbench mode only |
|
|
177
|
+
| `@deepseek-ai/schemastery` | dependency | the settings schema (`volatile()`) |
|
|
178
|
+
|
|
179
|
+
There is **no hard dependency** on dock-flash: every service is resolved through
|
|
180
|
+
`ctx.get(...)`, and compatibility is declared by the **peer range** — the same shape
|
|
181
|
+
dock-flash itself uses towards dock-base. The range carries one branch per tuple whose
|
|
182
|
+
prereleases must resolve, so both the 1.x and 2.x lines are accepted, prereleases
|
|
183
|
+
included.
|
|
184
|
+
|
|
185
|
+
## Install
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
dsh plugin --profile <profile> add <path-to-this-checkout>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`cordis.patch.yml` inserts the host row. Its `name` is a **package name**, resolved
|
|
192
|
+
through the profile's `node_modules` — **never a relative path**.
|
|
193
|
+
|
|
194
|
+
The browser half needs no row: the module loader discovers it from `package.json`'s
|
|
195
|
+
`exports["./client"]` plus `dsh.client` and serves it at
|
|
196
|
+
`/plugins/dsh-flash-ctx-mon/client.js`.
|
|
197
|
+
|
|
198
|
+
## Build
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
pnpm install
|
|
202
|
+
pnpm run build # tsc → dist/index.js (host half only)
|
|
203
|
+
pnpm run typecheck
|
|
204
|
+
node scripts/verify-config-volatile.mjs ./dist/index.js
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`dist/index.js` is **tracked on purpose**, for the same reason dock-flash tracks its own:
|
|
208
|
+
a git install fetches sources and runs no build script, so a repository without `dist/`
|
|
209
|
+
would arrive missing the host entry point that `main` and `exports["."]` point at.
|
|
210
|
+
`lib/client.js` is a single file edited directly; it has no build step and takes effect
|
|
211
|
+
on page refresh.
|
|
212
|
+
|
|
213
|
+
`scripts/verify-config-volatile.mjs` loads the built host half and re-runs the settings
|
|
214
|
+
service's own volatile-path test against it — the invariant the two map fields must
|
|
215
|
+
satisfy, or every write to them is rejected.
|
|
216
|
+
|
|
217
|
+
## Layout
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
src/index.ts HOST half → tsc → dist/index.js
|
|
221
|
+
lib/client.js BROWSER half → no build, edited directly
|
|
222
|
+
dist/index.js compiled host half — tracked on purpose
|
|
223
|
+
cordis.patch.yml bundle layer: inserts the host row into the profile
|
|
224
|
+
scripts/ verify-config-volatile.mjs — the volatile-schema check
|
|
225
|
+
.github/workflows/sync-from-gitee.yml — the Gitee → GitHub mirror
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Gitee is the authoritative repository; GitHub (`github.com/tcgbp/dsh-flash-ctx-mon`) is a
|
|
229
|
+
mirror of it and the host of the release tarball.
|
|
230
|
+
|
|
231
|
+
## Privacy and limits (deliberate)
|
|
232
|
+
|
|
233
|
+
- **Nothing leaves the machine.** The monitor reads DSH's own session events and two
|
|
234
|
+
client remotes; it has no host route, no collector and no outbound request.
|
|
235
|
+
- **Precise or nothing.** With no session-event usage data the monitor shows "Awaiting
|
|
236
|
+
data" and raises no alert, rather than estimating from message counts.
|
|
237
|
+
- **Per-session skills only.** The chip counts the current session; subagent sessions and
|
|
238
|
+
other conversations are excluded. A session that is no longer retained reports "Skill
|
|
239
|
+
catalog unavailable" with a Retry.
|
|
240
|
+
- **Bounded tracking.** Tracked skills are capped at 200 per session (defensive), and a
|
|
241
|
+
skill notice is only announced for a use within the last 15 seconds, so replaying a
|
|
242
|
+
session's history does not fire a burst of notices.
|
|
243
|
+
- **UI language**: the panel and the alert text carry both Chinese and English, and
|
|
244
|
+
follow DSH's language setting.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# dsh-flash-ctx-mon
|
|
2
|
+
|
|
3
|
+
> [dock-flash](https://gitee.com/lenin.guo/dock-flash) 的**上下文监控**配套插件 —— 它自己注册
|
|
4
|
+
> 告警提供者与面板开关,而不是住在 dock-flash 的 `apply()` 里。
|
|
5
|
+
|
|
6
|
+
Apache-2.0
|
|
7
|
+
|
|
8
|
+
**[English](./README.md)**
|
|
9
|
+
|
|
10
|
+
## 它做什么
|
|
11
|
+
|
|
12
|
+
两个能力,分别落在插件的两半:
|
|
13
|
+
|
|
14
|
+
1. **上下文监控** —— 直接读取 DSH 会话事件流里已有的**精确** token 用量,把模型上下文窗口的
|
|
15
|
+
压力按三档递进的阈值变成 dock-flash 告警。
|
|
16
|
+
2. **会话技能芯片** —— 会话标题栏上的一枚芯片,列出**当前会话**真正加载过的技能,并用技能
|
|
17
|
+
目录补全信息。
|
|
18
|
+
|
|
19
|
+
监控**默认开启**(只有显式关闭才会关掉),并且**完全在客户端**。
|
|
20
|
+
|
|
21
|
+
## 它注册了什么
|
|
22
|
+
|
|
23
|
+
### 宿主半 —— `src/index.ts` → `dist/index.js`
|
|
24
|
+
|
|
25
|
+
一个名为 `dsh-flash-ctx-mon` 的 Cordis 插件。
|
|
26
|
+
|
|
27
|
+
| 项目 | 说明 |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| 设置命名空间 | `dsh-flash-ctx-mon` |
|
|
30
|
+
| 字段 | `ctxApproxWindow`、`ctxThresholdInfo`、`ctxThresholdWarning`、`ctxThresholdError`、`ctxPollBase`、`ctxPollMin`、`modelContextWindows`、`modelContextWindowSources` |
|
|
31
|
+
| 路由 | **无** |
|
|
32
|
+
| 宿主侧服务 | **无**(`inject: []`) |
|
|
33
|
+
|
|
34
|
+
**宿主半存在的唯一目的是承载设置命名空间与它的 schema。** 没有采集器、没有路由,因为宿主侧
|
|
35
|
+
本来就无可采集:token 用量来自 DSH 会话事件(`ctx.get('sessions')`),模型目录来自
|
|
36
|
+
`remote.session.modelCatalog()`,技能目录来自 `remote.skills.list()` —— 全都在浏览器里。
|
|
37
|
+
|
|
38
|
+
### 浏览器半 —— `lib/client.js`(无构建步骤)
|
|
39
|
+
|
|
40
|
+
| 注册项 | 经由 |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| 告警提供者 `dsh-flash-ctx-mon:context-alert` | `ctx.get('dockFlashAlerts').registerProvider()` |
|
|
43
|
+
| 面板开关 `dsh-flash-ctx-mon:monitor-context` | `ctx.get('quickControl').registerSwitch()` |
|
|
44
|
+
| 会话标题芯片 `dsh-flash-ctx-mon-skills` | `ctx.inject(['slots'])` → `conversation.session.header.actions` |
|
|
45
|
+
|
|
46
|
+
开关属性:`type: 'toggle'`、`group: 'system'`、`cluster: 'system-alerts'`、`order: 59`、
|
|
47
|
+
`icon: 'message'`,外加一个**配置**按钮。它的可见性跟随 dock-flash 的
|
|
48
|
+
`dock-flash:system-alerts` 总开关 —— 告警注册表关掉之后,这个开关没有东西可驱动。它故意
|
|
49
|
+
**不带 `subtitle`**:过去印在行上的 "模型 · 12%" 实时读数,现在就在「配置」按钮打开的
|
|
50
|
+
面板第一屏。
|
|
51
|
+
|
|
52
|
+
> **双路发现,外加兜底轮询。** `ctx.get('quickControl')` / `ctx.get('dockFlashAlerts')` 是
|
|
53
|
+
> 异步解析的,所以注册有三条路径:`dock-flash:ready` 事件(dock-flash 比我们晚加载)、同步
|
|
54
|
+
> `ctx.get()` 检查(它比我们早加载)、以及最多 15 次、每次间隔 200 ms 的兜底轮询。先成功
|
|
55
|
+
> 的那个会置上 `_registered`,所以不会重复注册。
|
|
56
|
+
|
|
57
|
+
## 开关
|
|
58
|
+
|
|
59
|
+
在 dock-flash 快捷面板的 **⚙️ 系统 → 系统告警** 下,找到 **上下文监控**:
|
|
60
|
+
|
|
61
|
+
- **关**:向 `localStorage['dsh-flash-ctx-mon:monitor-context']` 写入 `'0'`,并对告警注册表
|
|
62
|
+
调用 `setProviderEnabled(…, false)`,提供者随之停止产出告警;
|
|
63
|
+
- **开**:两者一起恢复。
|
|
64
|
+
|
|
65
|
+
**谁说了算。** 浏览器里那个键是权威,且**键不存在即为开**(`getItem(key) !== '0'`)。宿主
|
|
66
|
+
侧的字段全部是 `volatile()`,每次重启 DSH 都会把它们重置为默认值 —— 记住你选择的是浏览器。
|
|
67
|
+
|
|
68
|
+
## 配置面板
|
|
69
|
+
|
|
70
|
+
开关旁的**配置**按钮打开上下文监控面板:
|
|
71
|
+
|
|
72
|
+
| 控件 | 范围 | 步长 | 默认 |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| 上下文窗口大小 `ctxApproxWindow` | 64000–512000 token | 8000 | 128000 |
|
|
75
|
+
| 信息阈值 `ctxThresholdInfo` | 30–80 % | 1 | 70 |
|
|
76
|
+
| 警告阈值 `ctxThresholdWarning` | 50–92 % | 1 | 85 |
|
|
77
|
+
| 错误阈值 `ctxThresholdError` | 70–98 % | 1 | 95 |
|
|
78
|
+
| 上下文轮询基础间隔 `ctxPollBase` | 5000–60000 ms | 1000 | 20000 |
|
|
79
|
+
| 上下文轮询最小间隔 `ctxPollMin` | 1000–10000 ms | 500 | 2000 |
|
|
80
|
+
|
|
81
|
+
滑块下方是实时状态:**当前模型**、**窗口大小**、**窗口来源**(会话事件 / 模型目录 / 错误
|
|
82
|
+
解析 / 手动配置 / 内置表 / 模糊匹配 / 估算默认)、**数据来源**(精确 / 等待数据)、
|
|
83
|
+
**输入Token** 与 **上下文压力**;此外还有**模型窗口映射**编辑器、**刷新目录**动作,以及
|
|
84
|
+
告警消息样式的预览。
|
|
85
|
+
|
|
86
|
+
## 告警
|
|
87
|
+
|
|
88
|
+
仅在 token 来源为 `precise` 时产出;没有会话事件用量数据时,监控显示「等待数据」并且
|
|
89
|
+
**什么都不发** —— 它不会拿消息条数去猜。
|
|
90
|
+
|
|
91
|
+
| 级别 | 触发 | 标题 |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| ℹ️ 信息 | ≥ `ctxThresholdInfo`(70 %) | 会话上下文较长 |
|
|
94
|
+
| 🟡 警告 | ≥ `ctxThresholdWarning`(85 %) | 会话上下文即将用尽 |
|
|
95
|
+
| 🔴 错误 | ≥ `ctxThresholdError`(95 %) | 会话上下文几乎用尽 |
|
|
96
|
+
|
|
97
|
+
每条消息都带上百分比与它所依据的读数 —— 精确模式下形如 `模型 · 12.4K/128K`。告警是
|
|
98
|
+
`dismissible` 的,并且走 dock-flash 的注册表,所以它们和其它告警一样出现在面板告警列表与
|
|
99
|
+
弹窗通知里。
|
|
100
|
+
|
|
101
|
+
## 模型窗口是怎么解析出来的
|
|
102
|
+
|
|
103
|
+
`_resolveWindow(model)` 读取 `modelContextWindows` —— 设置命名空间里那张**用户映射**表 —— 并
|
|
104
|
+
用 `modelContextWindowSources` 给每个结果标上来源。表里没有的模型解析结果为 `null`,调用方
|
|
105
|
+
回退到 `ctxApproxWindow`(即「估算默认」来源)。
|
|
106
|
+
|
|
107
|
+
**内置窗口表已经退役。** `_KNOWN_WINDOWS` 为空,目录自动填充是一个有文档说明的空实现,所以
|
|
108
|
+
今天映射表是真实窗口大小的唯一来源 —— 这也正是「模型窗口映射」编辑器存在的意义:教会它某个
|
|
109
|
+
它算错的模型。
|
|
110
|
+
|
|
111
|
+
> 两个映射字段都是 `volatile()`,而这不代表它们是**临时**的。设置服务会拒绝任何不在 volatile
|
|
112
|
+
> 节点下的写入路径(`Config field "…" is not volatile`),所以 `modelContextWindows` 曾经因为
|
|
113
|
+
> 不是 volatile,导致面板写下的每一条映射都被宿主拒绝、被客户端回滚、然后丢失 —— 被映射过的
|
|
114
|
+
> 模型依旧回退到 `ctxApproxWindow`。volatile 是让写入合法的前提;值本身照旧落在 profile patch
|
|
115
|
+
> 里,重启后仍在。
|
|
116
|
+
|
|
117
|
+
## 轮询
|
|
118
|
+
|
|
119
|
+
监控按自适应间隔采样:`ctxPollBase` 是占比低时使用的**天花板**,占比越高间隔越密,但不会低于
|
|
120
|
+
`ctxPollMin`。精确模式下基础间隔会自动加倍,因为事件源是主动推送而不是被轮询。有技能被使用时
|
|
121
|
+
会立刻触发一次采样,好让它的提示在「新鲜」窗口内被认领。
|
|
122
|
+
|
|
123
|
+
## 技能芯片
|
|
124
|
+
|
|
125
|
+
会话标题栏上的一枚芯片,以 `dsh-flash-ctx-mon-skills`(order 15)注册进
|
|
126
|
+
`conversation.session.header.actions`。它列出**当前会话**加载过的技能 —— 子代理与其它会话被
|
|
127
|
+
排除在外,因为 slot 会把「它正在为哪个会话渲染」的 id 交给组件。
|
|
128
|
+
|
|
129
|
+
检测用的是 DSH 自己的标记:技能正文被加载时输出的 `<skill_content name="X">` 块。它从两条
|
|
130
|
+
路径到达 —— 模型调用 `skill` 工具,以及用户在输入框敲 `/name`(这条路径**不产生**工具调用)
|
|
131
|
+
—— 而失败的调用不带这个块,所以失败不会被计入。名字会用技能目录(`remote.skills.list()`)
|
|
132
|
+
解析,弹层显示调用次数、首次/最近使用时间与目录描述,并提供**在侧栏打开**。
|
|
133
|
+
|
|
134
|
+
该追踪器刻意**独立于监控开关**:上下文监控关掉之后,芯片照常工作。
|
|
135
|
+
|
|
136
|
+
## 设置项
|
|
137
|
+
|
|
138
|
+
| 字段 | 默认 | 说明 |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `ctxApproxWindow` | 128000 | 映射表不认识的模型所用的回退窗口 |
|
|
141
|
+
| `ctxThresholdInfo` | 70 | 占窗口百分比 |
|
|
142
|
+
| `ctxThresholdWarning` | 85 | % —— 必须大于信息阈值 |
|
|
143
|
+
| `ctxThresholdError` | 95 | % —— 必须大于警告阈值 |
|
|
144
|
+
| `ctxPollBase` | 20000 | ms,占比低时的天花板 |
|
|
145
|
+
| `ctxPollMin` | 2000 | ms,地板 |
|
|
146
|
+
| `modelContextWindows` | `{}` | 模型 id → 窗口大小 |
|
|
147
|
+
| `modelContextWindowSources` | `{}` | 模型 id → 来源标记 |
|
|
148
|
+
|
|
149
|
+
## 依赖
|
|
150
|
+
|
|
151
|
+
| 包 | 类型 | 用途 |
|
|
152
|
+
| --- | --- | --- |
|
|
153
|
+
| `@deepseek-ai/cordis` | peer | 插件框架 |
|
|
154
|
+
| `dock-flash` `>=1.5.0-0 <2.0.0-0 \|\| >=2.0.0-0 <3.0.0-0` | peer | 提供 `quickControl`、`dockFlashAlerts` 服务与 `dock-flash:ready` 事件 |
|
|
155
|
+
| `dock-base` `>=0.1.2-0 <1.0.0-0 \|\| >=0.2.0-0 <1.0.0-0` | peer,可选 | 仅 workbench 模式 |
|
|
156
|
+
| `@deepseek-ai/schemastery` | dependency | 设置 schema(`volatile()`) |
|
|
157
|
+
|
|
158
|
+
对 dock-flash **没有硬依赖**:所有服务都通过 `ctx.get(...)` 解析,兼容性由 **peer 范围**声明
|
|
159
|
+
—— 与 dock-flash 自己对 dock-base 的写法同形。该范围按「预发布必须能解析的 tuple」逐条分支,
|
|
160
|
+
因此 1.x 与 2.x 两条线都被接受,预发布版本也算在内。
|
|
161
|
+
|
|
162
|
+
## 安装
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
dsh plugin --profile <profile> add <path-to-this-checkout>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`cordis.patch.yml` 负责插入宿主行。它的 `name` 是**包名**,经 profile 的 `node_modules`
|
|
169
|
+
解析 —— **绝不是相对路径**。
|
|
170
|
+
|
|
171
|
+
浏览器半不需要任何行:模块加载器从 `package.json` 的 `exports["./client"]` 配合 `dsh.client`
|
|
172
|
+
发现它,并在 `/plugins/dsh-flash-ctx-mon/client.js` 提供。
|
|
173
|
+
|
|
174
|
+
## 构建
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
pnpm install
|
|
178
|
+
pnpm run build # tsc → dist/index.js (仅宿主半)
|
|
179
|
+
pnpm run typecheck
|
|
180
|
+
node scripts/verify-config-volatile.mjs ./dist/index.js
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`dist/index.js` 是**有意纳入版本控制**的,理由与 dock-flash 相同:git 安装只取源码、不跑任何
|
|
184
|
+
构建脚本,所以没有 `dist/` 的仓库会缺少 `main` 与 `exports["."]` 指向的宿主入口。
|
|
185
|
+
`lib/client.js` 是单文件直接编辑,无构建步骤,刷新页面即生效。
|
|
186
|
+
|
|
187
|
+
`scripts/verify-config-volatile.mjs` 会加载构建好的宿主半,并对它重跑设置服务自己的
|
|
188
|
+
volatile 路径检查 —— 也就是那两个映射字段必须满足的不变量,不满足则每次写入都会被拒绝。
|
|
189
|
+
|
|
190
|
+
## 目录结构
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
src/index.ts HOST half → tsc → dist/index.js
|
|
194
|
+
lib/client.js BROWSER half → no build, edited directly
|
|
195
|
+
dist/index.js compiled host half — tracked on purpose
|
|
196
|
+
cordis.patch.yml bundle layer: inserts the host row into the profile
|
|
197
|
+
scripts/ verify-config-volatile.mjs — the volatile-schema check
|
|
198
|
+
.github/workflows/sync-from-gitee.yml — the Gitee → GitHub mirror
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Gitee 是权威仓库;GitHub(`github.com/tcgbp/dsh-flash-ctx-mon`)是它的镜像,也是发布用
|
|
202
|
+
tarball 的托管处。
|
|
203
|
+
|
|
204
|
+
## 隐私与边界(有意为之)
|
|
205
|
+
|
|
206
|
+
- **不出本机。** 监控只读 DSH 自己的会话事件与两个客户端 remote;它没有宿主路由、没有采集器、
|
|
207
|
+
也没有任何对外请求。
|
|
208
|
+
- **精确,否则不发。** 没有会话事件用量数据时显示「等待数据」且不发告警,而不是拿消息条数
|
|
209
|
+
估算。
|
|
210
|
+
- **技能仅限本会话。** 芯片只统计当前会话;子代理会话与其它对话排除在外。已不再保留的会话
|
|
211
|
+
会显示「技能目录读取失败」并给出重试。
|
|
212
|
+
- **有界追踪。** 每个会话最多追踪 200 个技能(防御性上限);只有当某次使用发生在最近 15 秒内
|
|
213
|
+
时才会发出提示,所以重放一个会话的历史不会一次爆出一串提示。
|
|
214
|
+
- **界面语言**:面板与告警文案同时提供中英文,并跟随 DSH 的语言设置。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# dsh-flash-ctx-mon bundle layer — registers the HOST half into a profile.
|
|
2
|
+
#
|
|
3
|
+
# The BROWSER half needs no row here: the module loader auto-discovers the
|
|
4
|
+
# client bundle from package.json `exports["./client"]` + `dsh.client` and
|
|
5
|
+
# serves it at /plugins/<pkg>/client.js.
|
|
6
|
+
- insert:
|
|
7
|
+
- id: dsh-flash-ctx-mon
|
|
8
|
+
name: dsh-flash-ctx-mon
|