@lievclouds/dsh-cortex 0.3.3 → 0.3.6
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/client.js +142 -153
- package/index.js +9 -7
- package/package.json +1 -1
- package/src/cortex-ui/dsh/css-overrides.css +8 -0
- package/src/cortex-ui/dsh/wrapper.template.js +141 -152
- package/src/cortex-ui/renderer/pages/NebulaPage.tsx +12 -10
package/index.js
CHANGED
|
@@ -41,14 +41,16 @@ export function apply(ctx, config) {
|
|
|
41
41
|
name: 'dsh-cortex.tools',
|
|
42
42
|
order: 500,
|
|
43
43
|
text: [
|
|
44
|
-
'## Cortex (dsh-cortex plugin,
|
|
45
|
-
'
|
|
46
|
-
'-
|
|
44
|
+
'## Cortex (dsh-cortex plugin, always active)',
|
|
45
|
+
'This plugin is installed and injects this guide automatically: the cortex_* tools below are available in every conversation without a skill or an MCP server.',
|
|
46
|
+
'When the user asks for ANY authorized penetration-testing work (渗透测试 / SRC / 漏洞挖掘 / 安全评估 / 资产与接口侦察 / 内网横向 / 漏洞复测), use the Cortex tools proactively instead of relying on memory:',
|
|
47
|
+
'- Reuse memory first: `cortex_list_snapshots` + `cortex_get_snapshot` for task progress, `cortex_list_vulns` + `cortex_get_asset` for existing findings/assets; `cortex_list_assets` before repeating recon.',
|
|
48
|
+
'- Persist confirmed findings: dedupe with `cortex_list_vulns`, then `cortex_save_vuln` (reproduction_steps in Markdown).',
|
|
49
|
+
'- Persist recon context: `cortex_sync_asset_info` (mode=merge) for fingerprints, interfaces (raw HTTP), leaks and test parameters.',
|
|
47
50
|
'- Status / retest: `cortex_update_vuln_status`, `cortex_append_retest` (append-only, never overwrite original evidence).',
|
|
48
|
-
'-
|
|
49
|
-
'
|
|
50
|
-
'Examples
|
|
51
|
-
'If a tools call fails, report the failure; never claim a record was stored without a successful result.',
|
|
51
|
+
'- Summaries: `cortex_internal_overview`, `cortex_graph_summary`.',
|
|
52
|
+
'Do not skip these calls merely because no skill was loaded. If a tool call fails, report the failure; never claim a record was saved without a successful result.',
|
|
53
|
+
'Examples: “列出 Cortex 里的高危漏洞”, “把刚才确认的漏洞写入 Cortex”, “把 127.0.0.1:8080 的接口同步到资产库”, “把 VULN-… 标记为已确认并追加复测结论”.',
|
|
52
54
|
].join('\n'),
|
|
53
55
|
}),
|
|
54
56
|
'dsh-cortex: usage prompt',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lievclouds/dsh-cortex",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Cortex workbench for DeepSeek Harness: the original Cortex UI (vulnerabilities, assets, internal operations, Memory Nebula, snapshots, retest) as a native DSH panel, plus 12 native agent tools so DSH conversations use the local Cortex SQLite without MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -99,6 +99,14 @@
|
|
|
99
99
|
border: 3px solid transparent;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/* DSH draws its native window buttons above the page in the top-right corner.
|
|
103
|
+
Right-hand inspector sheets start at the very top edge, so their header
|
|
104
|
+
actions (export / close) ended up underneath those buttons. Move every sheet
|
|
105
|
+
below that band; the overlay still dims the area behind it. */
|
|
106
|
+
.dshc-cortex-root .sheet-content {
|
|
107
|
+
top: calc(0.875rem + 2.25rem);
|
|
108
|
+
}
|
|
109
|
+
|
|
102
110
|
/* ------------------------------------------------------------------------- */
|
|
103
111
|
/* DSH shell adaptations */
|
|
104
112
|
/* ------------------------------------------------------------------------- */
|
|
@@ -1,152 +1,141 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-cortex client bundle — Cortex original UI port for DeepSeek Harness.
|
|
3
|
-
*
|
|
4
|
-
* GENERATED FILE: built by scripts/build-cortex-ui.mjs from
|
|
5
|
-
* src/cortex-ui/**. Do not edit; run `node scripts/build-cortex-ui.mjs`.
|
|
6
|
-
*
|
|
7
|
-
* The Cortex renderer (React + Tailwind) is mounted into a Shadow DOM so its
|
|
8
|
-
* stylesheet cannot leak into the DSH shell. DSH provides React 18.3.1 through
|
|
9
|
-
* the platform module table; the bundled UI shares that instance.
|
|
10
|
-
*/
|
|
11
|
-
window.__ModuleLoader__.load({
|
|
12
|
-
id: __CORTEX_PACKAGE_NAME__,
|
|
13
|
-
factory: (require) => {
|
|
14
|
-
'use strict'
|
|
15
|
-
const React = require('react')
|
|
16
|
-
globalThis.__DSH_CORTEX_REACT__ = React
|
|
17
|
-
|
|
18
|
-
const UI_CSS = __CORTEX_UI_STYLES__
|
|
19
|
-
const FONT_FACES_CSS = __CORTEX_FONT_FACES__
|
|
20
|
-
const LOGO_DATA_URL = __CORTEX_LOGO_DATA_URL__
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
window.setTimeout(runAcceptanceProbe, 1500)
|
|
144
|
-
} catch (error) {
|
|
145
|
-
/* probe optional */
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return { name: 'dsh-cortex', inject: ['slots'], apply }
|
|
151
|
-
},
|
|
152
|
-
})
|
|
1
|
+
/**
|
|
2
|
+
* dsh-cortex client bundle — Cortex original UI port for DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* GENERATED FILE: built by scripts/build-cortex-ui.mjs from
|
|
5
|
+
* src/cortex-ui/**. Do not edit; run `node scripts/build-cortex-ui.mjs`.
|
|
6
|
+
*
|
|
7
|
+
* The Cortex renderer (React + Tailwind) is mounted into a Shadow DOM so its
|
|
8
|
+
* stylesheet cannot leak into the DSH shell. DSH provides React 18.3.1 through
|
|
9
|
+
* the platform module table; the bundled UI shares that instance.
|
|
10
|
+
*/
|
|
11
|
+
window.__ModuleLoader__.load({
|
|
12
|
+
id: __CORTEX_PACKAGE_NAME__,
|
|
13
|
+
factory: (require) => {
|
|
14
|
+
'use strict'
|
|
15
|
+
const React = require('react')
|
|
16
|
+
globalThis.__DSH_CORTEX_REACT__ = React
|
|
17
|
+
|
|
18
|
+
const UI_CSS = __CORTEX_UI_STYLES__
|
|
19
|
+
const FONT_FACES_CSS = __CORTEX_FONT_FACES__
|
|
20
|
+
const LOGO_DATA_URL = __CORTEX_LOGO_DATA_URL__
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* Chromium ignores @font-face rules that live inside a Shadow DOM
|
|
24
|
+
* stylesheet, so the inlined Inter / JetBrains Mono faces are injected into
|
|
25
|
+
* document.head once (fonts are document-level and then also apply inside
|
|
26
|
+
* the shadow tree). The element is removed when the plugin unloads.
|
|
27
|
+
*/
|
|
28
|
+
let fontStyleElement = null
|
|
29
|
+
function installFontFaces() {
|
|
30
|
+
if (fontStyleElement || !FONT_FACES_CSS) return
|
|
31
|
+
const style = document.createElement('style')
|
|
32
|
+
style.setAttribute('data-dsh-cortex-fonts', '')
|
|
33
|
+
style.textContent = FONT_FACES_CSS
|
|
34
|
+
document.head.appendChild(style)
|
|
35
|
+
fontStyleElement = style
|
|
36
|
+
}
|
|
37
|
+
function uninstallFontFaces() {
|
|
38
|
+
if (!fontStyleElement) return
|
|
39
|
+
try {
|
|
40
|
+
fontStyleElement.remove()
|
|
41
|
+
} catch (error) {
|
|
42
|
+
/* ignore */
|
|
43
|
+
}
|
|
44
|
+
fontStyleElement = null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* ---- vendored Cortex renderer (esbuild IIFE, exposes __DSH_CORTEX_UI__) ---- */
|
|
48
|
+
__CORTEX_UI_BUNDLE__
|
|
49
|
+
/* -------------------------------------------------------------------------- */
|
|
50
|
+
|
|
51
|
+
const ui = globalThis.__DSH_CORTEX_UI__
|
|
52
|
+
if (!ui || typeof ui.mount !== 'function') {
|
|
53
|
+
throw new Error('[dsh-cortex] Cortex UI bundle did not initialize')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Original Cortex product mark (white glyph on the dark rounded square). */
|
|
57
|
+
function PanelIcon(props) {
|
|
58
|
+
const size = props && typeof props.size === 'number' ? props.size : 16
|
|
59
|
+
const inner = Math.max(8, Math.round(size * 0.56))
|
|
60
|
+
return React.createElement(
|
|
61
|
+
'span',
|
|
62
|
+
{
|
|
63
|
+
'aria-hidden': true,
|
|
64
|
+
style: {
|
|
65
|
+
display: 'flex',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
justifyContent: 'center',
|
|
68
|
+
width: size,
|
|
69
|
+
height: size,
|
|
70
|
+
borderRadius: Math.round(size * 0.26),
|
|
71
|
+
background: 'hsl(224 18% 10%)',
|
|
72
|
+
flex: 'none',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
React.createElement('img', {
|
|
76
|
+
src: LOGO_DATA_URL,
|
|
77
|
+
width: inner,
|
|
78
|
+
height: inner,
|
|
79
|
+
alt: '',
|
|
80
|
+
draggable: false,
|
|
81
|
+
style: { display: 'block', objectFit: 'contain' },
|
|
82
|
+
}),
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Mounts the unmodified Cortex App inside this DSH panel. */
|
|
87
|
+
function CortexPanel() {
|
|
88
|
+
const hostRef = React.useRef(null)
|
|
89
|
+
React.useEffect(() => {
|
|
90
|
+
const host = hostRef.current
|
|
91
|
+
if (!host || typeof host.attachShadow !== 'function') return undefined
|
|
92
|
+
let handle = null
|
|
93
|
+
try {
|
|
94
|
+
handle = ui.mount(host, UI_CSS)
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('[dsh-cortex] Cortex UI mount failed', error)
|
|
97
|
+
}
|
|
98
|
+
return () => {
|
|
99
|
+
if (!handle) return
|
|
100
|
+
try {
|
|
101
|
+
handle.destroy()
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('[dsh-cortex] Cortex UI unmount failed', error)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}, [])
|
|
107
|
+
return React.createElement('div', {
|
|
108
|
+
ref: hostRef,
|
|
109
|
+
style: { height: '100%', width: '100%', minHeight: 0, overflow: 'hidden' },
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function apply(ctx) {
|
|
114
|
+
try {
|
|
115
|
+
ctx.effect(() => {
|
|
116
|
+
installFontFaces()
|
|
117
|
+
return () => uninstallFontFaces()
|
|
118
|
+
}, 'dsh-cortex: document font faces')
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('[dsh-cortex] font-face install failed', error)
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
ctx.slots.inject('sidebar.panellist', () =>
|
|
124
|
+
ctx.slots.register(
|
|
125
|
+
{ name: 'sidebar.panellist', id: 'cortex', order: 5, label: () => 'Cortex' },
|
|
126
|
+
PanelIcon,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('[dsh-cortex] sidebar.panellist registration failed', error)
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
ctx.slots.inject('main', () => ctx.slots.register({ name: 'main', key: 'cortex' }, CortexPanel))
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error('[dsh-cortex] main panel registration failed', error)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { name: 'dsh-cortex', inject: ['slots'], apply }
|
|
140
|
+
},
|
|
141
|
+
})
|
|
@@ -627,16 +627,8 @@ export function NebulaPage({ dataVersion, onOpenDetail }: NebulaPageProps) {
|
|
|
627
627
|
}
|
|
628
628
|
}, [setFullscreenModeSafe])
|
|
629
629
|
|
|
630
|
-
//
|
|
631
|
-
|
|
632
|
-
if (fullscreenMode === 'off') return undefined
|
|
633
|
-
const onKeyDown = (event: KeyboardEvent): void => {
|
|
634
|
-
if (event.key === 'Escape') leaveFullscreen()
|
|
635
|
-
}
|
|
636
|
-
window.addEventListener('keydown', onKeyDown)
|
|
637
|
-
return () => window.removeEventListener('keydown', onKeyDown)
|
|
638
|
-
}, [fullscreenMode, leaveFullscreen])
|
|
639
|
-
|
|
630
|
+
// Declared before the Escape effect below: referencing it in that effect's
|
|
631
|
+
// dependency array from a later `const` is a temporal-dead-zone ReferenceError.
|
|
640
632
|
const leaveFullscreen = useCallback((): void => {
|
|
641
633
|
const doc = document as any
|
|
642
634
|
// Always attempt the native exit even when fullscreenElement is not exposed:
|
|
@@ -650,6 +642,16 @@ export function NebulaPage({ dataVersion, onOpenDetail }: NebulaPageProps) {
|
|
|
650
642
|
setFullscreenModeSafe('off')
|
|
651
643
|
}, [setFullscreenModeSafe])
|
|
652
644
|
|
|
645
|
+
// Escape leaves either mode (native also exits itself; calling exit is safe).
|
|
646
|
+
useEffect(() => {
|
|
647
|
+
if (fullscreenMode === 'off') return undefined
|
|
648
|
+
const onKeyDown = (event: KeyboardEvent): void => {
|
|
649
|
+
if (event.key === 'Escape') leaveFullscreen()
|
|
650
|
+
}
|
|
651
|
+
window.addEventListener('keydown', onKeyDown)
|
|
652
|
+
return () => window.removeEventListener('keydown', onKeyDown)
|
|
653
|
+
}, [fullscreenMode, leaveFullscreen])
|
|
654
|
+
|
|
653
655
|
const handleToggleFullscreen = useCallback(() => {
|
|
654
656
|
const element = sectionRef.current
|
|
655
657
|
if (element === null) return
|