dsh-cerebrum 0.1.0 → 0.1.1
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.md +2 -0
- package/lib/api.js +4 -1
- package/lib/client.js +97 -0
- package/lib/config.js +5 -0
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,6 +55,8 @@ dsh plugin --profile desktop add D:\workspace\dsh-cerebrum
|
|
|
55
55
|
|
|
56
56
|
装好插件后,输入框上方会出现 🧠 芯片:显示当前情绪、记忆量、好感度级别;点击展开**大脑仪表盘**(效价/唤醒/支配条、DA/5-HT/NE/ACh、五因素、记忆/技能/意图/好感)。
|
|
57
57
|
|
|
58
|
+
- **不喜欢可以关掉**:面板里的 🙈 隐藏芯片(点小 🧠 恢复);彻底关闭用配置 `ui.enabled: false`(重启宿主生效,芯片完全不出现);
|
|
59
|
+
- 面板可**拖动**(按住标题栏)、可 **📌 固定**到输入栏上方成横条;
|
|
58
60
|
- 数据来自宿主内置的 127.0.0.1 只读 API(`http://127.0.0.1:18734`,端口可配 `config.api.port`);
|
|
59
61
|
- UI 只读:修改记忆/情绪仍通过 `cerebrum_*` 工具;
|
|
60
62
|
- 免构建 client bundle(`lib/client.js`),与宿主同一个安装包——**装一个插件,大脑 + 面板都有**。
|
package/lib/api.js
CHANGED
|
@@ -31,7 +31,7 @@ const send = (res, status, payload) => {
|
|
|
31
31
|
res.end(JSON.stringify(payload))
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export const startBrainApi = (service, { port = 18734, logger = console } = {}) => {
|
|
34
|
+
export const startBrainApi = (service, { port = 18734, ui = { enabled: true }, logger = console } = {}) => {
|
|
35
35
|
const server = http.createServer((req, res) => {
|
|
36
36
|
if (req.method === 'OPTIONS') return send(res, 204, {})
|
|
37
37
|
if (req.method !== 'GET') return send(res, 405, { error: 'method not allowed' })
|
|
@@ -40,6 +40,9 @@ export const startBrainApi = (service, { port = 18734, logger = console } = {})
|
|
|
40
40
|
switch (url.pathname) {
|
|
41
41
|
case '/ping':
|
|
42
42
|
return send(res, 200, { ok: true, name: 'dsh-cerebrum', uptimeMs: Date.now() - service.startedAt })
|
|
43
|
+
case '/ui':
|
|
44
|
+
// The client respects this: ui.enabled=false removes the chip entirely.
|
|
45
|
+
return send(res, 200, { enabled: ui.enabled !== false })
|
|
43
46
|
case '/state': {
|
|
44
47
|
const sessionId = url.searchParams.get('session') || undefined
|
|
45
48
|
return send(res, 200, service.state(sessionId))
|
package/lib/client.js
CHANGED
|
@@ -68,11 +68,31 @@ window.__ModuleLoader__.load({
|
|
|
68
68
|
var [open, setOpen] = useState(false)
|
|
69
69
|
var [pinned, setPinned] = useState(false)
|
|
70
70
|
var [pos, setPos] = useState(null)
|
|
71
|
+
var [uiEnabled, setUiEnabled] = useState(true)
|
|
72
|
+
var [hidden, setHidden] = useState(function () {
|
|
73
|
+
try {
|
|
74
|
+
return localStorage.getItem('cerebrum.hidden') === '1'
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
var [miniPos, setMiniPos] = useState(function () {
|
|
80
|
+
try {
|
|
81
|
+
var raw = localStorage.getItem('cerebrum.miniPos')
|
|
82
|
+
return raw ? JSON.parse(raw) : null
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return null
|
|
85
|
+
}
|
|
86
|
+
})
|
|
71
87
|
var panelRef = useRef(null)
|
|
72
88
|
var dragRef = useRef(null)
|
|
73
89
|
|
|
74
90
|
useEffect(function () {
|
|
75
91
|
var alive = true
|
|
92
|
+
// The host decides whether users opted out of the whole chip.
|
|
93
|
+
get('/ui').then(function (data) {
|
|
94
|
+
if (alive && data && data.enabled === false) setUiEnabled(false)
|
|
95
|
+
})
|
|
76
96
|
var tick = function () {
|
|
77
97
|
get('/state' + (sessionId ? '?session=' + encodeURIComponent(sessionId) : '')).then(function (data) {
|
|
78
98
|
if (alive && data) setState(data)
|
|
@@ -86,6 +106,82 @@ window.__ModuleLoader__.load({
|
|
|
86
106
|
}
|
|
87
107
|
}, [sessionId])
|
|
88
108
|
|
|
109
|
+
var hideChip = function () {
|
|
110
|
+
setHidden(true)
|
|
111
|
+
try {
|
|
112
|
+
localStorage.setItem('cerebrum.hidden', '1')
|
|
113
|
+
} catch (err) {}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
var restoreChip = function () {
|
|
117
|
+
setHidden(false)
|
|
118
|
+
try {
|
|
119
|
+
localStorage.removeItem('cerebrum.hidden')
|
|
120
|
+
} catch (err) {}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var startMiniDrag = function (event) {
|
|
124
|
+
var rect = event.currentTarget.getBoundingClientRect()
|
|
125
|
+
var start = { mx: event.clientX, my: event.clientY, x: rect.left, y: rect.top, moved: 0 }
|
|
126
|
+
var latest = null
|
|
127
|
+
var move = function (ev) {
|
|
128
|
+
var dx = ev.clientX - start.mx
|
|
129
|
+
var dy = ev.clientY - start.my
|
|
130
|
+
start.moved = Math.max(start.moved, Math.abs(dx) + Math.abs(dy))
|
|
131
|
+
latest = {
|
|
132
|
+
x: Math.max(4, Math.min(window.innerWidth - 30, start.x + dx)),
|
|
133
|
+
y: Math.max(4, Math.min(window.innerHeight - 30, start.y + dy)),
|
|
134
|
+
}
|
|
135
|
+
setMiniPos(latest)
|
|
136
|
+
}
|
|
137
|
+
var up = function () {
|
|
138
|
+
window.removeEventListener('mousemove', move)
|
|
139
|
+
window.removeEventListener('mouseup', up)
|
|
140
|
+
if (latest) {
|
|
141
|
+
try {
|
|
142
|
+
localStorage.setItem('cerebrum.miniPos', JSON.stringify(latest))
|
|
143
|
+
} catch (err) {}
|
|
144
|
+
}
|
|
145
|
+
if (start.moved < 4) restoreChip()
|
|
146
|
+
}
|
|
147
|
+
window.addEventListener('mousemove', move)
|
|
148
|
+
window.addEventListener('mouseup', up)
|
|
149
|
+
event.preventDefault()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!uiEnabled) return null
|
|
153
|
+
if (hidden) {
|
|
154
|
+
var miniStyle = {
|
|
155
|
+
position: 'fixed',
|
|
156
|
+
zIndex: 1001,
|
|
157
|
+
display: 'flex',
|
|
158
|
+
alignItems: 'center',
|
|
159
|
+
justifyContent: 'center',
|
|
160
|
+
width: '24px',
|
|
161
|
+
height: '24px',
|
|
162
|
+
borderRadius: '999px',
|
|
163
|
+
background: 'rgba(16,26,40,.85)',
|
|
164
|
+
border: '1px solid #1f2c3f',
|
|
165
|
+
cursor: 'grab',
|
|
166
|
+
fontSize: '13px',
|
|
167
|
+
userSelect: 'none',
|
|
168
|
+
opacity: 0.75,
|
|
169
|
+
boxShadow: '0 2px 10px rgba(0,0,0,.35)',
|
|
170
|
+
}
|
|
171
|
+
if (miniPos) {
|
|
172
|
+
miniStyle.left = miniPos.x + 'px'
|
|
173
|
+
miniStyle.top = miniPos.y + 'px'
|
|
174
|
+
} else {
|
|
175
|
+
miniStyle.right = '16px'
|
|
176
|
+
miniStyle.bottom = '96px'
|
|
177
|
+
}
|
|
178
|
+
return createElement('span', {
|
|
179
|
+
style: miniStyle,
|
|
180
|
+
title: '拖动可移动;单击恢复大脑芯片(config.ui.enabled=false 可彻底关闭)',
|
|
181
|
+
onMouseDown: startMiniDrag,
|
|
182
|
+
}, '🧠')
|
|
183
|
+
}
|
|
184
|
+
|
|
89
185
|
var chipStyle = {
|
|
90
186
|
display: 'flex',
|
|
91
187
|
alignItems: 'center',
|
|
@@ -216,6 +312,7 @@ window.__ModuleLoader__.load({
|
|
|
216
312
|
createElement('span', { style: { fontWeight: 700 } }, '🧠 大脑仪表盘'),
|
|
217
313
|
createElement('span', null,
|
|
218
314
|
createElement('button', { type: 'button', style: btnStyle, title: pinned ? '取消固定(恢复浮动)' : '固定到输入栏上方', 'data-no-drag': '1', onClick: function () { setPinned(!pinned) } }, pinned ? '📌 已固定' : '📌 固定'),
|
|
315
|
+
createElement('button', { type: 'button', style: btnStyle, title: '隐藏大脑芯片(点小 🧠 恢复)', 'data-no-drag': '1', onClick: hideChip }, '🙈'),
|
|
219
316
|
createElement('button', { type: 'button', style: btnStyle, title: '收起', 'data-no-drag': '1', onClick: function () { setOpen(false) } }, '✕'),
|
|
220
317
|
))
|
|
221
318
|
|
package/lib/config.js
CHANGED
|
@@ -46,6 +46,10 @@ export const DEFAULT_CONFIG = {
|
|
|
46
46
|
enabled: true,
|
|
47
47
|
port: 18734,
|
|
48
48
|
},
|
|
49
|
+
/** Client UI (the brain chip/dashboard). Users who dislike it can switch it off. */
|
|
50
|
+
ui: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
},
|
|
49
53
|
autoCapture: {
|
|
50
54
|
enabled: true,
|
|
51
55
|
maxTextChars: 2000,
|
|
@@ -115,6 +119,7 @@ export const resolveConfig = (raw, { home = resolveHome(), cwd = process.cwd() }
|
|
|
115
119
|
merged.workingMemory.slots = Math.round(clampNumber(merged.workingMemory.slots, 4, 1, 9))
|
|
116
120
|
merged.api.enabled = merged.api.enabled !== false
|
|
117
121
|
merged.api.port = Math.round(clampNumber(merged.api.port, 18734, 1024, 65535))
|
|
122
|
+
merged.ui.enabled = merged.ui.enabled !== false
|
|
118
123
|
merged.autoCapture.maxTextChars = Math.round(clampNumber(merged.autoCapture.maxTextChars, 2000, 200, 20000))
|
|
119
124
|
merged.autoCapture.toolResultChars = Math.round(clampNumber(merged.autoCapture.toolResultChars, 300, 40, 4000))
|
|
120
125
|
merged.autoCapture.minChars = Math.round(clampNumber(merged.autoCapture.minChars, 6, 0, 500))
|
package/lib/index.js
CHANGED
|
@@ -57,7 +57,7 @@ export function apply(ctx, rawConfig = {}) {
|
|
|
57
57
|
|
|
58
58
|
// Read-only loopback API powering the optional client UI (dock + dashboard).
|
|
59
59
|
if (config.api.enabled) {
|
|
60
|
-
const api = startBrainApi(service, { port: config.api.port })
|
|
60
|
+
const api = startBrainApi(service, { port: config.api.port, ui: config.ui })
|
|
61
61
|
ctx.effect(() => () => api.close(), 'cerebrum:brain-api')
|
|
62
62
|
}
|
|
63
63
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-cerebrum",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Brain-inspired cognitive architecture for DeepSeek Harness: hippocampal episodic memory, cortical semantic memory, spreading-activation recall, appraisal-based emotion, neuromodulator state, Big Five personality and dual-process judgment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|