dsh-structured 0.9.6 → 0.9.9
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.md +19 -0
- package/README.md +274 -273
- package/docs/0.9-FINAL-RELEASE.md +22 -0
- package/docs/1.0-BASELINE.md +38 -0
- package/docs/1.0-GATE.md +39 -0
- package/docs/1.0-PERSONA-SPEC.md +59 -0
- package/lib/client.js +4 -4
- package/lib/index.js +518 -517
- package/package.json +102 -99
- package/scripts/theme-contrast.mjs +2 -2
- package/scripts/theme-hue-distance.mjs +55 -0
- package/src/client.js +2 -2
- package/src/index.js +516 -515
- package/test/client-cards.test.mjs +145 -140
- package/test/fixtures/persona-gate/no-persona.md +8 -0
- package/test/fixtures/persona-gate/persona-append.md +9 -0
- package/test/fixtures/persona-gate/style-override.md +8 -0
- package/test/structured.test.mjs +8 -0
- package/test/theme.test.mjs +8 -1
package/package.json
CHANGED
|
@@ -1,99 +1,102 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-structured",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Structured output for DSH: no-label title card first, then tables/lists/steps; per-session switch and style.md override. 让 DSH 的每条实质回复默认结构化。",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "lib/index.js",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"author": "MYCAIGC",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/feigo313/dsh-structured.git"
|
|
12
|
-
},
|
|
13
|
-
"homepage": "https://github.com/feigo313/dsh-structured#readme",
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/feigo313/dsh-structured/issues"
|
|
16
|
-
},
|
|
17
|
-
"publishConfig": {
|
|
18
|
-
"access": "public",
|
|
19
|
-
"registry": "https://registry.npmjs.org"
|
|
20
|
-
},
|
|
21
|
-
"keywords": [
|
|
22
|
-
"deepseek",
|
|
23
|
-
"harness",
|
|
24
|
-
"dsh",
|
|
25
|
-
"dsh-plugin",
|
|
26
|
-
"output-style",
|
|
27
|
-
"structured-output"
|
|
28
|
-
],
|
|
29
|
-
"exports": {
|
|
30
|
-
".": "./lib/index.js",
|
|
31
|
-
"./client": "./lib/client.js",
|
|
32
|
-
"./locale/*.json": "./locale/*.json",
|
|
33
|
-
"./icon": "./icon.svg",
|
|
34
|
-
"./package.json": "./package.json"
|
|
35
|
-
},
|
|
36
|
-
"dsh": {
|
|
37
|
-
"bundle": {
|
|
38
|
-
"patch": "./cordis.patch.yml"
|
|
39
|
-
},
|
|
40
|
-
"client": {
|
|
41
|
-
"platform": "web",
|
|
42
|
-
"inject": [
|
|
43
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
44
|
-
],
|
|
45
|
-
"immediately": true
|
|
46
|
-
},
|
|
47
|
-
"compatibility": {
|
|
48
|
-
"dshReleases": {
|
|
49
|
-
"0.1.7-rc.2": "compatible",
|
|
50
|
-
"0.2.0-rc.2": "compatible",
|
|
51
|
-
"0.2.1-rc.1": "compatible",
|
|
52
|
-
"0.2.1-rc.2": "compatible",
|
|
53
|
-
"0.2.1-rc.3": "compatible",
|
|
54
|
-
"0.3.0-rc.1": "compatible"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
"files": [
|
|
59
|
-
"lib",
|
|
60
|
-
"src",
|
|
61
|
-
"scripts",
|
|
62
|
-
"docs",
|
|
63
|
-
"!docs/FULL-TEST-PROMPT.md",
|
|
64
|
-
"!docs/FULL-TEST-REPORT.md",
|
|
65
|
-
"!docs/RE-AUDIT-REPORT.md",
|
|
66
|
-
"!docs/PUBLISH-READY.md",
|
|
67
|
-
"!docs/RELEASE-NOTES-0.7.4.md",
|
|
68
|
-
"!docs/MAINTENANCE*.md",
|
|
69
|
-
"!docs/ACCEPTANCE-0.9.1.md",
|
|
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
|
-
"@deepseek-ai/schemastery": "^3.18.0"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-structured",
|
|
3
|
+
"version": "0.9.9",
|
|
4
|
+
"description": "Structured output for DSH: no-label title card first, then tables/lists/steps; per-session switch and style.md override. 让 DSH 的每条实质回复默认结构化。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "MYCAIGC",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/feigo313/dsh-structured.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/feigo313/dsh-structured#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/feigo313/dsh-structured/issues"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public",
|
|
19
|
+
"registry": "https://registry.npmjs.org"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"deepseek",
|
|
23
|
+
"harness",
|
|
24
|
+
"dsh",
|
|
25
|
+
"dsh-plugin",
|
|
26
|
+
"output-style",
|
|
27
|
+
"structured-output"
|
|
28
|
+
],
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./lib/index.js",
|
|
31
|
+
"./client": "./lib/client.js",
|
|
32
|
+
"./locale/*.json": "./locale/*.json",
|
|
33
|
+
"./icon": "./icon.svg",
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"dsh": {
|
|
37
|
+
"bundle": {
|
|
38
|
+
"patch": "./cordis.patch.yml"
|
|
39
|
+
},
|
|
40
|
+
"client": {
|
|
41
|
+
"platform": "web",
|
|
42
|
+
"inject": [
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
44
|
+
],
|
|
45
|
+
"immediately": true
|
|
46
|
+
},
|
|
47
|
+
"compatibility": {
|
|
48
|
+
"dshReleases": {
|
|
49
|
+
"0.1.7-rc.2": "compatible",
|
|
50
|
+
"0.2.0-rc.2": "compatible",
|
|
51
|
+
"0.2.1-rc.1": "compatible",
|
|
52
|
+
"0.2.1-rc.2": "compatible",
|
|
53
|
+
"0.2.1-rc.3": "compatible",
|
|
54
|
+
"0.3.0-rc.1": "compatible"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"lib",
|
|
60
|
+
"src",
|
|
61
|
+
"scripts",
|
|
62
|
+
"docs",
|
|
63
|
+
"!docs/FULL-TEST-PROMPT.md",
|
|
64
|
+
"!docs/FULL-TEST-REPORT.md",
|
|
65
|
+
"!docs/RE-AUDIT-REPORT.md",
|
|
66
|
+
"!docs/PUBLISH-READY.md",
|
|
67
|
+
"!docs/RELEASE-NOTES-0.7.4.md",
|
|
68
|
+
"!docs/MAINTENANCE*.md",
|
|
69
|
+
"!docs/ACCEPTANCE-0.9.1.md",
|
|
70
|
+
"!docs/ACCEPTANCE-0.9.7.md",
|
|
71
|
+
"!docs/ACCEPTANCE-0.9.8.md",
|
|
72
|
+
"!docs/ACCEPTANCE-0.9.9.md",
|
|
73
|
+
"assets/screenshots",
|
|
74
|
+
"screenshots.json",
|
|
75
|
+
"test",
|
|
76
|
+
"cordis.patch.yml",
|
|
77
|
+
"locale/*.json",
|
|
78
|
+
"icon.svg",
|
|
79
|
+
"README.md",
|
|
80
|
+
"ACCEPTANCE.md",
|
|
81
|
+
"CHANGELOG.md",
|
|
82
|
+
"LICENSE"
|
|
83
|
+
],
|
|
84
|
+
"scripts": {
|
|
85
|
+
"build": "node scripts/build.mjs",
|
|
86
|
+
"pretest": "node scripts/build.mjs",
|
|
87
|
+
"test": "node --test test/*.test.mjs",
|
|
88
|
+
"theme-contrast": "node scripts/theme-contrast.mjs",
|
|
89
|
+
"prepack": "node scripts/build.mjs"
|
|
90
|
+
},
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": ">=22",
|
|
93
|
+
"dsh": ">=0.1.7-rc.2 <0.4.0-0"
|
|
94
|
+
},
|
|
95
|
+
"peerDependencies": {
|
|
96
|
+
"@deepseek-ai/schemastery": "^3.18.0"
|
|
97
|
+
},
|
|
98
|
+
"devDependencies": {
|
|
99
|
+
"@deepseek-ai/schemastery": "^3.18.0",
|
|
100
|
+
"linkedom": "0.18.14"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -30,12 +30,12 @@ export const THEME_TOKENS = {
|
|
|
30
30
|
anthropic: {
|
|
31
31
|
light: {
|
|
32
32
|
surface: '#FAF9F5', surface2: '#F5F1E8', text: '#141413', muted: '#6B6359',
|
|
33
|
-
border: '#E5E0D5', accent: '#CC785C', accentText: '#A14A2E', success: '#266B4D', warn: '#
|
|
33
|
+
border: '#E5E0D5', accent: '#CC785C', accentText: '#A14A2E', success: '#266B4D', warn: '#806000', error: '#8C1D18',
|
|
34
34
|
codeBg: '#F5F1E8', codeText: '#141413',
|
|
35
35
|
},
|
|
36
36
|
dark: {
|
|
37
37
|
surface: '#1F1E1D', surface2: '#2A2825', text: '#F5F1E8', muted: '#A8A29A',
|
|
38
|
-
border: '#3A3733', accent: '#E8A087', accentText: '#E8A087', success: '#6FBF9A', warn: '#
|
|
38
|
+
border: '#3A3733', accent: '#E8A087', accentText: '#E8A087', success: '#6FBF9A', warn: '#EAB308', error: '#F28B82',
|
|
39
39
|
codeBg: '#171614', codeText: '#F5F1E8',
|
|
40
40
|
},
|
|
41
41
|
},
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** 0.9.8:品牌 accent 与语义 status 的 hue 分离检查(阈值 25°)。 */
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
import { THEME_TOKENS } from './theme-contrast.mjs'
|
|
5
|
+
|
|
6
|
+
export const HUE_THRESHOLD = 25
|
|
7
|
+
|
|
8
|
+
function rgb(hex) {
|
|
9
|
+
return [1, 3, 5].map((offset) => parseInt(hex.slice(offset, offset + 2), 16))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function hue(hex) {
|
|
13
|
+
const [r, g, b] = rgb(hex).map((channel) => channel / 255)
|
|
14
|
+
const max = Math.max(r, g, b)
|
|
15
|
+
const min = Math.min(r, g, b)
|
|
16
|
+
const delta = max - min
|
|
17
|
+
if (delta === 0) return 0
|
|
18
|
+
let value
|
|
19
|
+
if (max === r) value = ((g - b) / delta) % 6
|
|
20
|
+
else if (max === g) value = (b - r) / delta + 2
|
|
21
|
+
else value = (r - g) / delta + 4
|
|
22
|
+
value *= 60
|
|
23
|
+
return value < 0 ? value + 360 : value
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function hueDistance(a, b) {
|
|
27
|
+
const diff = Math.abs(hue(a) - hue(b)) % 360
|
|
28
|
+
return diff > 180 ? 360 - diff : diff
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function checkHueSeparation() {
|
|
32
|
+
const results = []
|
|
33
|
+
const failures = []
|
|
34
|
+
for (const [theme, modes] of Object.entries(THEME_TOKENS)) {
|
|
35
|
+
for (const [mode, token] of Object.entries(modes)) {
|
|
36
|
+
for (const status of ['success', 'warn']) {
|
|
37
|
+
const distance = hueDistance(token.accent, token[status])
|
|
38
|
+
const row = { theme, mode, status, distance, threshold: HUE_THRESHOLD }
|
|
39
|
+
results.push(row)
|
|
40
|
+
if (distance < HUE_THRESHOLD) failures.push(row)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { results, failures }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
48
|
+
const { results, failures } = checkHueSeparation()
|
|
49
|
+
for (const row of results) console.log(`${row.theme}/${row.mode} accent-${row.status}: ${row.distance.toFixed(1)}°`)
|
|
50
|
+
if (failures.length > 0) {
|
|
51
|
+
console.error(JSON.stringify(failures, null, 2))
|
|
52
|
+
process.exit(1)
|
|
53
|
+
}
|
|
54
|
+
console.log(`PASS ${results.length} hue checks`)
|
|
55
|
+
}
|
package/src/client.js
CHANGED
|
@@ -129,12 +129,12 @@ body[data-ds-dark-theme][data-dsh-structured-theme="codex"] [class*="_markdown_"
|
|
|
129
129
|
}
|
|
130
130
|
body[data-dsh-structured-theme="anthropic"] [class*="_markdown_"]{
|
|
131
131
|
--ds-surface:#FAF9F5;--ds-surface-2:#F5F1E8;--ds-text:#141413;--ds-muted:#6B6359;
|
|
132
|
-
--ds-border:#E5E0D5;--ds-accent:#CC785C;--ds-accent-text:#A14A2E;--ds-success:#266B4D;--ds-warn:#
|
|
132
|
+
--ds-border:#E5E0D5;--ds-accent:#CC785C;--ds-accent-text:#A14A2E;--ds-success:#266B4D;--ds-warn:#806000;--ds-error:#8C1D18;
|
|
133
133
|
--ds-code-bg:#F5F1E8;--ds-code-text:#141413;
|
|
134
134
|
}
|
|
135
135
|
body[data-ds-dark-theme][data-dsh-structured-theme="anthropic"] [class*="_markdown_"]{
|
|
136
136
|
--ds-surface:#1F1E1D;--ds-surface-2:#2A2825;--ds-text:#F5F1E8;--ds-muted:#A8A29A;
|
|
137
|
-
--ds-border:#3A3733;--ds-accent:#E8A087;--ds-accent-text:#E8A087;--ds-success:#6FBF9A;--ds-warn:#
|
|
137
|
+
--ds-border:#3A3733;--ds-accent:#E8A087;--ds-accent-text:#E8A087;--ds-success:#6FBF9A;--ds-warn:#EAB308;--ds-error:#F28B82;
|
|
138
138
|
--ds-code-bg:#171614;--ds-code-text:#F5F1E8;
|
|
139
139
|
}
|
|
140
140
|
[class*="_markdown_"] p{margin:.72em 0}
|