@rezti/dsh-rez-suite 0.1.3 → 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/lib/style.css CHANGED
@@ -1,110 +1,83 @@
1
- [data-pane="conversation"] {
2
- position: relative;
1
+ .WRGRRW_shell {
2
+ flex-direction: column;
3
+ gap: 12px;
4
+ min-width: 0;
5
+ display: flex;
3
6
  }
4
7
 
5
- [data-dsh-rez-view] {
6
- z-index: 60;
7
- background: var(--dsw-alias-bg-base);
8
- display: none;
9
- position: absolute;
10
- inset: 0;
8
+ .WRGRRW_card {
9
+ border: 1px solid var(--dsw-alias-border-l2);
10
+ background: var(--dsw-alias-bg-layer-3);
11
+ border-radius: 12px;
12
+ list-style: none;
13
+ transition: border-color .16s, background .16s;
11
14
  }
12
15
 
13
- html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-dsh-rez-view] {
14
- display: block;
16
+ .WRGRRW_card:hover {
17
+ border-color: var(--dsw-alias-label-dimmed);
15
18
  }
16
19
 
17
- html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-pane="conversation"] > :not([data-dsh-rez-view]), html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [class*="centerCol"] > :not([data-dsh-rez-view]) {
18
- display: none !important;
20
+ .WRGRRW_cardOpen {
21
+ background: var(--dsw-alias-bg-layer-2);
22
+ border-color: var(--dsw-alias-label-dimmed);
19
23
  }
20
24
 
21
- .WRGRRW_entry {
25
+ .WRGRRW_header {
26
+ appearance: none;
22
27
  width: 100%;
23
- height: 32px;
24
- color: var(--dsw-alias-label-secondary);
28
+ font: inherit;
29
+ color: inherit;
30
+ text-align: left;
25
31
  cursor: pointer;
26
- white-space: nowrap;
27
32
  background: none;
28
- border: none;
29
- border-radius: 8px;
33
+ border: 0;
34
+ border-radius: 12px;
30
35
  align-items: center;
31
- gap: 8px;
32
- padding: 0 12px;
33
- font-size: 13px;
36
+ gap: 12px;
37
+ padding: 14px 16px;
34
38
  display: flex;
35
39
  }
36
40
 
37
- .WRGRRW_entry:hover {
38
- background: var(--dsw-specific-sidebar-nav-item-hover);
39
- color: var(--dsw-alias-label-primary);
40
- }
41
-
42
- .WRGRRW_entryIcon {
43
- flex: none;
44
- justify-content: center;
45
- align-items: center;
46
- display: inline-flex;
47
- }
48
-
49
- .WRGRRW_entryLabel {
50
- text-overflow: ellipsis;
51
- overflow: hidden;
52
- }
53
-
54
- [data-dsh-frame][data-sidebar-collapsed] .WRGRRW_entry {
55
- justify-content: center;
56
- width: 100%;
57
- padding: 0;
58
- }
59
-
60
- [data-dsh-frame][data-sidebar-collapsed] .WRGRRW_entryLabel {
61
- display: none;
41
+ .WRGRRW_header:focus-visible {
42
+ outline: 2px solid var(--dsw-alias-brand-primary);
43
+ outline-offset: -2px;
62
44
  }
63
45
 
64
- .WRGRRW_view {
65
- overflow: hidden;
46
+ .WRGRRW_headText {
47
+ flex-direction: column;
48
+ flex: 1;
49
+ gap: 4px;
50
+ min-width: 0;
51
+ display: flex;
66
52
  }
67
53
 
68
- .WRGRRW_panel {
69
- background: var(--dsw-alias-bg-base);
70
- min-width: 0;
71
- height: 100%;
72
- min-height: 0;
54
+ .WRGRRW_name {
73
55
  color: var(--dsw-alias-label-primary);
74
- font-family: var(--dsw-font-family);
75
- flex-direction: column;
76
- gap: 10px;
77
- padding: 14px 16px 16px;
78
- display: flex;
56
+ font-size: 15px;
57
+ font-weight: 600;
58
+ line-height: 1.4;
79
59
  }
80
60
 
81
- .WRGRRW_panelHeader {
82
- flex: none;
83
- align-items: center;
84
- gap: 10px;
85
- display: flex;
61
+ .WRGRRW_description {
62
+ color: var(--dsw-alias-label-tertiary);
63
+ font-size: 13px;
64
+ line-height: 1.5;
86
65
  }
87
66
 
88
- .WRGRRW_panelTitle {
89
- flex: 1;
90
- margin: 0;
91
- font-size: 16px;
92
- font-weight: 700;
67
+ .WRGRRW_chevron {
68
+ color: var(--dsw-alias-label-tertiary);
69
+ flex: none;
70
+ transition: transform .16s;
93
71
  }
94
72
 
95
- .WRGRRW_iconButton {
96
- color: var(--dsw-alias-label-secondary);
97
- cursor: pointer;
98
- background: none;
99
- border: none;
100
- border-radius: 6px;
101
- padding: 4px 8px;
102
- font-size: 14px;
73
+ .WRGRRW_chevronOpen {
74
+ transform: rotate(180deg);
103
75
  }
104
76
 
105
- .WRGRRW_iconButton:hover {
106
- background: var(--dsw-alias-interactive-bg-hover);
107
- color: var(--dsw-alias-label-primary);
77
+ .WRGRRW_body {
78
+ border-top: 1px solid var(--dsw-alias-border-l2);
79
+ margin: 0 16px 12px;
80
+ padding-top: 8px;
108
81
  }
109
82
 
110
83
  .WRGRRW_tabBar {
@@ -136,21 +109,12 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
136
109
  font-weight: 600;
137
110
  }
138
111
 
139
- .WRGRRW_panelContent {
140
- flex-direction: column;
141
- flex: 1;
142
- min-height: 0;
143
- display: flex;
144
- overflow: hidden;
145
- }
146
-
147
112
  .WRGRRW_tabBody {
148
113
  flex-direction: column;
149
- flex: 1;
150
114
  gap: 12px;
151
- min-height: 0;
115
+ min-width: 0;
116
+ padding: 12px 0 4px;
152
117
  display: flex;
153
- overflow-y: auto;
154
118
  }
155
119
 
156
120
  .WRGRRW_section {
@@ -164,16 +128,17 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
164
128
  }
165
129
 
166
130
  .WRGRRW_sectionTitle {
131
+ color: var(--dsw-alias-label-primary);
167
132
  margin: 0;
168
133
  font-size: 13px;
169
134
  font-weight: 600;
170
135
  }
171
136
 
172
137
  .WRGRRW_field {
173
- grid-template-columns: 140px 1fr;
174
- align-items: center;
175
- gap: 8px;
176
- display: grid;
138
+ flex-direction: column;
139
+ align-items: stretch;
140
+ gap: 4px;
141
+ display: flex;
177
142
  }
178
143
 
179
144
  .WRGRRW_label {
@@ -183,7 +148,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
183
148
 
184
149
  .WRGRRW_input, .WRGRRW_select {
185
150
  color: var(--dsw-alias-label-primary);
186
- background: var(--dsw-specific-input-major);
151
+ background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));
187
152
  border: 1px solid var(--dsw-alias-border-l2);
188
153
  border-radius: 8px;
189
154
  outline: none;
@@ -207,7 +172,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
207
172
 
208
173
  .WRGRRW_button {
209
174
  border: 1px solid var(--dsw-alias-border-l2);
210
- background: var(--dsw-specific-input-major);
175
+ background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));
211
176
  color: var(--dsw-alias-label-primary);
212
177
  cursor: pointer;
213
178
  border-radius: 8px;
@@ -215,23 +180,19 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
215
180
  font-size: 13px;
216
181
  }
217
182
 
218
- .WRGRRW_button:hover {
183
+ .WRGRRW_button:hover:not(:disabled) {
219
184
  background: var(--dsw-alias-interactive-bg-hover);
220
185
  }
221
186
 
222
- .WRGRRW_qr {
223
- background: #fff;
224
- border-radius: 8px;
225
- width: 240px;
226
- height: 240px;
227
- margin: 8px 0;
228
- display: block;
187
+ .WRGRRW_button:disabled {
188
+ opacity: .4;
189
+ cursor: default;
229
190
  }
230
191
 
231
192
  .WRGRRW_primaryButton {
232
- background: var(--dsw-alias-state-business-primary);
233
- border-color: var(--dsw-alias-state-business-primary);
234
- color: #fff;
193
+ background: var(--dsw-alias-label-primary);
194
+ border-color: var(--dsw-alias-label-primary);
195
+ color: var(--dsw-alias-bg-layer-3);
235
196
  }
236
197
 
237
198
  .WRGRRW_dangerButton {
@@ -240,9 +201,20 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
240
201
  color: #fff;
241
202
  }
242
203
 
204
+ .WRGRRW_qr {
205
+ background: #fff;
206
+ border-radius: 8px;
207
+ width: 200px;
208
+ height: 200px;
209
+ margin: 8px 0;
210
+ display: block;
211
+ }
212
+
243
213
  .WRGRRW_message {
244
214
  color: var(--dsw-alias-label-secondary);
215
+ margin: 0;
245
216
  font-size: 12.5px;
217
+ line-height: 1.5;
246
218
  }
247
219
 
248
220
  .WRGRRW_error {
@@ -252,8 +224,6 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
252
224
  .WRGRRW_tableWrap {
253
225
  border: 1px solid var(--dsw-alias-border-l1);
254
226
  border-radius: 10px;
255
- flex: 1;
256
- min-height: 0;
257
227
  overflow: auto;
258
228
  }
259
229
 
@@ -296,12 +266,12 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
296
266
  }
297
267
 
298
268
  .WRGRRW_cards {
299
- grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
269
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
300
270
  gap: 8px;
301
271
  display: grid;
302
272
  }
303
273
 
304
- .WRGRRW_card {
274
+ .WRGRRW_stat {
305
275
  border: 1px solid var(--dsw-alias-border-l1);
306
276
  border-radius: 10px;
307
277
  padding: 10px;
@@ -313,6 +283,7 @@ html[data-dsh-rez-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-act
313
283
  }
314
284
 
315
285
  .WRGRRW_cardValue {
286
+ color: var(--dsw-alias-label-primary);
316
287
  font-size: 15px;
317
288
  font-weight: 600;
318
289
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rezti/dsh-rez-suite",
3
3
  "description": "ReZ-TI employee plugin for DeepSeek Harness: one install enables company MCP (Odoo / Nextcloud / WeCom / Weixin-ClawBot / Home Assistant) and work identity.",
4
- "version": "0.1.3",
4
+ "version": "0.1.5",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "^22.19.0 || >=24.0.0"
@@ -28,7 +28,9 @@
28
28
  "inject": [
29
29
  "@deepseek-ai/dsh-client-runtime",
30
30
  "@deepseek-ai/dsh-client-connection",
31
- "@deepseek-ai/dsh-client-ui-settings"
31
+ "@deepseek-ai/dsh-client-locale",
32
+ "@deepseek-ai/dsh-client-ui-settings",
33
+ "@deepseek-ai/dsh-client-ui-settings-plugins"
32
34
  ],
33
35
  "platform": "web"
34
36
  }
@@ -36,13 +38,13 @@
36
38
  "dependencies": {
37
39
  "@modelcontextprotocol/sdk": "^1.30.0",
38
40
  "zod": "^4.4.3",
39
- "@rezti/dsh-rez-ha-bridge": "0.1.0",
41
+ "@rezti/dsh-rez-ha-bridge": "0.1.4",
42
+ "@rezti/dsh-rez-sso": "0.1.4",
43
+ "@rezti/dsh-rez-nextcloud": "0.1.4",
40
44
  "@rezti/dsh-rez-intent": "0.1.3",
41
- "@rezti/dsh-rez-nextcloud": "0.1.0",
42
- "@rezti/dsh-rez-sso": "0.1.3",
43
- "@rezti/dsh-rez-odoo": "0.1.0",
44
- "@rezti/dsh-rez-wechat": "0.1.3",
45
- "@rezti/dsh-rez-token-manager": "0.1.3"
45
+ "@rezti/dsh-rez-odoo": "0.1.4",
46
+ "@rezti/dsh-rez-token-manager": "0.1.3",
47
+ "@rezti/dsh-rez-wechat": "0.1.4"
46
48
  },
47
49
  "peerDependencies": {
48
50
  "react": "^18.2.0",
@@ -1,17 +1,16 @@
1
1
  /**
2
- * Browser-half entry for dsh-rez-suite — runs inside the dsh web GUI.
3
- * Registers locale dictionaries and mounts the Rez Suite panel (sidebar entry
4
- * plus center-column view). DOM mounting problems are logged, never thrown.
2
+ * Browser-half entry for dsh-rez-suite.
3
+ * Registers locale dictionaries and contributes a native Settings card
4
+ * (设置 插件 → 插件配置) plus a Plugins tab. Do not mount a sidebar
5
+ * takeover over the conversation column.
5
6
  */
6
7
 
7
8
  import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
8
9
  import type {} from '@deepseek-ai/dsh-client-locale/client'
10
+ import type {} from '@deepseek-ai/dsh-client-ui-settings/client'
9
11
  import type {} from '@deepseek-ai/dsh-client-ui-slots'
10
- import { RezApi } from './api.ts'
11
12
  import { en, zh, type RezKey } from './locales.ts'
12
- import { mountPanel } from './mount.tsx'
13
- import { PanelController } from './panel/controller.ts'
14
- import { mountSidebarEntry } from './sidebar-entry.ts'
13
+ import { RezPluginCard, RezSettingsPage } from './settings-card.tsx'
15
14
 
16
15
  const NS = 'dsh-rez-suite'
17
16
 
@@ -19,27 +18,40 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
19
18
  interface LocaleNamespaceMap {
20
19
  'dsh-rez-suite': RezKey
21
20
  }
21
+ interface SlotMap {
22
+ 'settings.plugin.item': {
23
+ kind: 'list'
24
+ scope: 'root'
25
+ owner: { children?: never }
26
+ }
27
+ 'settings.plugins.tab': {
28
+ kind: 'list'
29
+ scope: 'root'
30
+ owner: { children?: never }
31
+ }
32
+ }
22
33
  }
23
34
 
24
35
  export const inject = ['slots', 'locale']
25
36
 
26
- export type { PanelControllerSnapshot } from './panel/controller.ts'
27
- export type { RezPanelProps } from './panel/RezPanel.tsx'
28
37
  export type { RezKey } from './locales.ts'
29
38
 
30
39
  export function apply(ctx: ClientContext): void {
40
+ const t = ctx.locale.bind(NS)
31
41
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-rez-suite: dictionaries')
32
42
 
33
- const controller = new PanelController()
34
- const api = new RezApi()
35
- const disposers: Array<() => void> = []
36
- try {
37
- disposers.push(mountSidebarEntry(controller))
38
- disposers.push(mountPanel(controller, api))
39
- } catch (error) {
40
- console.warn('[dsh-rez-suite] mount failed:', error)
41
- }
42
- ctx.effect(() => () => {
43
- for (const dispose of disposers.splice(0)) dispose()
44
- }, 'dsh-rez-suite: ui mounts')
43
+ ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
44
+ name: 'settings.plugin.item',
45
+ id: 'rez-suite',
46
+ order: 40,
47
+ locale: NS,
48
+ }, RezPluginCard))
49
+
50
+ ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
51
+ name: 'settings.plugins.tab',
52
+ id: 'rez',
53
+ order: 20,
54
+ label: () => t('settings.title'),
55
+ locale: NS,
56
+ }, RezSettingsPage))
45
57
  }
@@ -5,6 +5,8 @@
5
5
  export const zh = {
6
6
  'entry.label': 'Rez',
7
7
  'entry.tooltip': 'Rez Suite 配置与审计面板',
8
+ 'settings.title': 'ReZ-TI',
9
+ 'settings.description': '公司 MCP(Odoo / Nextcloud / 企微 / HA)与个人微信扫码通道。',
8
10
  'panel.title': 'Rez Suite',
9
11
  'tab.config': '配置',
10
12
  'tab.weixin': '微信',
@@ -99,6 +101,8 @@ export type RezKey = keyof typeof zh
99
101
  export const en: Record<RezKey, string> = {
100
102
  'entry.label': 'Rez',
101
103
  'entry.tooltip': 'Rez Suite configuration and audit panel',
104
+ 'settings.title': 'ReZ-TI',
105
+ 'settings.description': 'Company MCP (Odoo / Nextcloud / WeCom / HA) and personal WeChat scan-and-chat.',
102
106
  'panel.title': 'Rez Suite',
103
107
  'tab.config': 'Config',
104
108
  'tab.weixin': 'WeChat',
@@ -48,12 +48,12 @@ export function AuditTab({ api }: { api: RezApi }) {
48
48
  </div>
49
49
  {error !== '' && <div className={css.error}>{error}</div>}
50
50
  <div className={css.cards}>
51
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.totalCalls')}</div><div className={css.cardValue}>{audit.totalCalls}</div></div>
52
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.inputTokens')}</div><div className={css.cardValue}>{audit.totalInputTokens}</div></div>
53
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.outputTokens')}</div><div className={css.cardValue}>{audit.totalOutputTokens}</div></div>
54
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.totalCost')}</div><div className={css.cardValue}>{audit.totalCost.toFixed(4)}</div></div>
55
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.monthCost')}</div><div className={css.cardValue}>{audit.monthCost.toFixed(4)}</div></div>
56
- <div className={css.card}><div className={css.cardLabel}>{tt('audit.budget')}</div><div className={css.cardValue}>{audit.monthlyBudget.toFixed(2)}</div></div>
51
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.totalCalls')}</div><div className={css.cardValue}>{audit.totalCalls}</div></div>
52
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.inputTokens')}</div><div className={css.cardValue}>{audit.totalInputTokens}</div></div>
53
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.outputTokens')}</div><div className={css.cardValue}>{audit.totalOutputTokens}</div></div>
54
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.totalCost')}</div><div className={css.cardValue}>{audit.totalCost.toFixed(4)}</div></div>
55
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.monthCost')}</div><div className={css.cardValue}>{audit.monthCost.toFixed(4)}</div></div>
56
+ <div className={css.stat}><div className={css.cardLabel}>{tt('audit.budget')}</div><div className={css.cardValue}>{audit.monthlyBudget.toFixed(2)}</div></div>
57
57
  </div>
58
58
  <div className={css.tableWrap}>
59
59
  <table className={css.table}>