dsh-advisor 0.1.0
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 +21 -0
- package/README.i18n.yaml +7 -0
- package/README.md +303 -0
- package/README.zh.md +166 -0
- package/cordis.patch.yml +6 -0
- package/lib/advisor-runtime.d.ts +242 -0
- package/lib/advisor-runtime.js +662 -0
- package/lib/advisor-runtime.js.map +1 -0
- package/lib/client/advisor-card.d.ts +90 -0
- package/lib/client/advisor-store.d.ts +310 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/locales.d.ts +40 -0
- package/lib/client.d.ts +1 -0
- package/lib/client.js +840 -0
- package/lib/commands.d.ts +136 -0
- package/lib/commands.js +185 -0
- package/lib/commands.js.map +1 -0
- package/lib/config.d.ts +74 -0
- package/lib/config.js +93 -0
- package/lib/config.js.map +1 -0
- package/lib/delivery.d.ts +129 -0
- package/lib/delivery.js +169 -0
- package/lib/delivery.js.map +1 -0
- package/lib/emission-guard.d.ts +99 -0
- package/lib/emission-guard.js +155 -0
- package/lib/emission-guard.js.map +1 -0
- package/lib/gateway.d.ts +116 -0
- package/lib/gateway.js +214 -0
- package/lib/gateway.js.map +1 -0
- package/lib/index.d.ts +48 -0
- package/lib/index.js +485 -0
- package/lib/index.js.map +1 -0
- package/lib/kinds.d.ts +38 -0
- package/lib/kinds.js +24 -0
- package/lib/kinds.js.map +1 -0
- package/lib/prompts.d.ts +22 -0
- package/lib/prompts.js +38 -0
- package/lib/prompts.js.map +1 -0
- package/lib/settings.d.ts +96 -0
- package/lib/settings.js +141 -0
- package/lib/settings.js.map +1 -0
- package/lib/transcript.d.ts +257 -0
- package/lib/transcript.js +530 -0
- package/lib/transcript.js.map +1 -0
- package/package.json +90 -0
- package/scripts/build-client.mjs +268 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Client bundle build (plan dsh-advisor-settings-n2, task 2 — KD-S5): emits
|
|
4
|
+
* the closure-factory CJS artifact the dsh web loader consumes —
|
|
5
|
+
* `window.__ModuleLoader__.load({ id: 'dsh-advisor', factory: (require) => {
|
|
6
|
+
* … return module.exports; } })`. Externals resolve through the loader module
|
|
7
|
+
* table — the frozen `CLIENT_EXTERNALS` (platform seed entries + the
|
|
8
|
+
* documented `@deepseek-ai/dsh-client-runtime/client` exemption); everything
|
|
9
|
+
* else inlines. The web shell's ClientModuleHostService serves the artifact at
|
|
10
|
+
* `/plugins/dsh-advisor/client.js` and executes it as a CLASSIC <script>, so
|
|
11
|
+
* the emitted text must contain NO `import.meta` and no top-level ESM
|
|
12
|
+
* statements (either is a parse-time SyntaxError).
|
|
13
|
+
*
|
|
14
|
+
* A purity gate (esbuild onResolve) rejects any non-external, non-inline-safe
|
|
15
|
+
* `@deepseek-ai/*` VALUE import — type-only imports are erased by esbuild's
|
|
16
|
+
* TS loader before resolution and never reach the gate; cross-plugin
|
|
17
|
+
* collaboration goes through cordis services. The in-script contract
|
|
18
|
+
* assertions then re-check the artifact (requires ⊆ CLIENT_EXTERNALS, no
|
|
19
|
+
* `import.meta`, no ESM statements).
|
|
20
|
+
*
|
|
21
|
+
* Build tool: esbuild (explicit devDependency — the repo is pnpm/node; this
|
|
22
|
+
* is the node-port of mstar's bun `build-client-bundle.ts`). CSS Modules are
|
|
23
|
+
* now inlined (mirror of the dsh tsdown preset's dsh-css-modules-inline):
|
|
24
|
+
* `*.module.css` side-effect imports compile through lightningcss
|
|
25
|
+
* ([hash]_[local], minified) and emit a guarded `<style data-plugin>`
|
|
26
|
+
* injection stub into the bundle — the deferred-styling extension point is
|
|
27
|
+
* closed (plan Review Gate Summary, qc1 S-2).
|
|
28
|
+
*
|
|
29
|
+
* Declarations: runs `tsc -p tsconfig.client.json` (emitDeclarationOnly) into
|
|
30
|
+
* `lib/client/`, then writes the flat re-export `lib/client.d.ts`
|
|
31
|
+
* (`export * from './client/index.js'`) that `exports["./client"].types`
|
|
32
|
+
* points at — same shape as the mstar client bundle.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { build } from 'esbuild'
|
|
36
|
+
import { transform } from 'lightningcss'
|
|
37
|
+
import { createRequire } from 'node:module'
|
|
38
|
+
import { spawnSync } from 'node:child_process'
|
|
39
|
+
import { readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
40
|
+
import { basename, join } from 'node:path'
|
|
41
|
+
|
|
42
|
+
const require = createRequire(import.meta.url)
|
|
43
|
+
|
|
44
|
+
const ID = 'dsh-advisor'
|
|
45
|
+
const ENTRY = 'src/client/index.ts'
|
|
46
|
+
const OUT_FILE = 'lib/client.js'
|
|
47
|
+
|
|
48
|
+
/** Loader module table (KD-S5): platform seed entries plus the documented runtime/client exemption. */
|
|
49
|
+
export const CLIENT_EXTERNALS = [
|
|
50
|
+
'react',
|
|
51
|
+
'react/jsx-runtime',
|
|
52
|
+
'react-dom',
|
|
53
|
+
'react-dom/client',
|
|
54
|
+
'@deepseek-ai/cordis',
|
|
55
|
+
'@deepseek-ai/dsh-client-ui-slots',
|
|
56
|
+
'@deepseek-ai/dsh-client-web-react',
|
|
57
|
+
'@deepseek-ai/dsh-client-ui-primitives',
|
|
58
|
+
'@deepseek-ai/dsh-client-schema-form',
|
|
59
|
+
'@deepseek-ai/dsh-client-runtime/client',
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
/** Virtual-id wrapper keeping module CSS away from esbuild's own css pipeline (mirror of dsh tsdown.client.ts dsh-css-modules-inline). */
|
|
63
|
+
const CSS_VIRTUAL_PREFIX = '\0dsh-css:'
|
|
64
|
+
const CSS_VIRTUAL_SUFFIX = '.mjs'
|
|
65
|
+
/** Namespace esbuild requires on non-file paths returned from onResolve. */
|
|
66
|
+
const CSS_NAMESPACE = 'dsh-css-modules'
|
|
67
|
+
|
|
68
|
+
/** Wire/type layers with no shared runtime identity that may inline (tsdown.client.ts mirror). */
|
|
69
|
+
const INLINE_SAFE = /^@deepseek-ai\/dsh-(host-apiproxy|session|llm|tools|brand)(\/|$)/
|
|
70
|
+
/** Generated descriptor/codec contribution with no shared runtime identity. */
|
|
71
|
+
const GENERATED_REMOTE = /^@deepseek-ai\/dsh-[a-z0-9]+(?:-[a-z0-9]+)*\/remote$/
|
|
72
|
+
|
|
73
|
+
const result = await build({
|
|
74
|
+
entryPoints: [ENTRY],
|
|
75
|
+
outfile: OUT_FILE,
|
|
76
|
+
bundle: true,
|
|
77
|
+
format: 'cjs',
|
|
78
|
+
platform: 'browser',
|
|
79
|
+
target: 'es2020',
|
|
80
|
+
// Automatic JSX runtime (T2 review Critical-1): the CLASSIC transform emits
|
|
81
|
+
// a free `React.createElement` global that the loader module table does not
|
|
82
|
+
// provide -> ReferenceError on first render. The automatic runtime emits
|
|
83
|
+
// `require("react/jsx-runtime")` instead, which IS a frozen CLIENT_EXTERNALS
|
|
84
|
+
// entry (below) and the loader answers it — same as dsh-private's bundles.
|
|
85
|
+
jsx: 'automatic',
|
|
86
|
+
// Externals resolve through the loader module table (the injected require);
|
|
87
|
+
// a require() the table cannot answer is a guaranteed runtime throw, so the
|
|
88
|
+
// rule is the table list itself: no opinion for table entries, bundle
|
|
89
|
+
// everything else (no peer auto-externalization).
|
|
90
|
+
external: [...CLIENT_EXTERNALS],
|
|
91
|
+
// zustand-style deps read process.env.NODE_ENV and probe
|
|
92
|
+
// import.meta.env.MODE; the loader executes the bundle as a classic script
|
|
93
|
+
// where a literal `import.meta` is a SyntaxError. Defining the full
|
|
94
|
+
// `import.meta.env` object erases every reference. Both keys honor the
|
|
95
|
+
// build's NODE_ENV so a dev build keeps dev-branch semantics; artifacts
|
|
96
|
+
// default to production.
|
|
97
|
+
define: {
|
|
98
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'production'),
|
|
99
|
+
'import.meta.env.MODE': JSON.stringify(process.env.NODE_ENV ?? 'production'),
|
|
100
|
+
'import.meta.env': JSON.stringify({ MODE: process.env.NODE_ENV ?? 'production' }),
|
|
101
|
+
},
|
|
102
|
+
// Closure-factory handoff (KD-S5): `module`/`exports` are declared inside
|
|
103
|
+
// the factory body; the factory returns that surface to the loader.
|
|
104
|
+
banner: {
|
|
105
|
+
js: `window.__ModuleLoader__.load({ id: ${JSON.stringify(ID)}, factory: (require) => {\nvar module = { exports: {} }; var exports = module.exports;`,
|
|
106
|
+
},
|
|
107
|
+
footer: {
|
|
108
|
+
js: 'return module.exports; } });',
|
|
109
|
+
},
|
|
110
|
+
plugins: [{
|
|
111
|
+
// Bundle purity gate (build-time mirror of the value-import boundary):
|
|
112
|
+
// platform seed entries stay external, inline-safe wire layers inline,
|
|
113
|
+
// and every other @deepseek-ai value import is a build error — a
|
|
114
|
+
// cross-plugin value import either inlines a duplicate runtime instance
|
|
115
|
+
// or requires a specifier the frozen module table cannot answer.
|
|
116
|
+
name: 'dsh-client-bundle-purity',
|
|
117
|
+
setup(build) {
|
|
118
|
+
build.onResolve({ filter: /^@deepseek-ai\// }, (args) => {
|
|
119
|
+
if (CLIENT_EXTERNALS.includes(args.path)) return undefined // platform module: external wins
|
|
120
|
+
if (INLINE_SAFE.test(args.path) || GENERATED_REMOTE.test(args.path)) return undefined // wire contribution: inline is the point
|
|
121
|
+
throw new Error(
|
|
122
|
+
`client bundle purity: "${args.path}" is not a platform module (CLIENT_EXTERNALS), an inline-safe wire layer, or a generated /remote contribution — `
|
|
123
|
+
+ 'cross-plugin value imports are forbidden; collaborate through cordis services (type-only imports are erased and never reach this gate)',
|
|
124
|
+
)
|
|
125
|
+
})
|
|
126
|
+
},
|
|
127
|
+
}, {
|
|
128
|
+
// CSS Modules inline injection (dsh tsdown.client.ts dsh-css-modules-inline
|
|
129
|
+
// mirror): side-effect `*.module.css` imports compile through lightningcss
|
|
130
|
+
// ([hash]_[local], minified) and the module exports the hashed class map.
|
|
131
|
+
// The emitted stub injects one guarded `<style data-plugin>` per module
|
|
132
|
+
// file at factory execution; the web shell's loader cleans up plugin-owned
|
|
133
|
+
// tags by `style[data-plugin=<id>]` + per-module `data-plugin-css`.
|
|
134
|
+
name: 'dsh-css-modules-inline',
|
|
135
|
+
setup(build) {
|
|
136
|
+
build.onResolve({ filter: /\.module\.css$/ }, (args) => {
|
|
137
|
+
// Absolute physical path, wrapped in the virtual id (suffix keeps esbuild off its own CSS pipeline).
|
|
138
|
+
return { path: CSS_VIRTUAL_PREFIX + join(args.resolveDir, args.path) + CSS_VIRTUAL_SUFFIX, namespace: CSS_NAMESPACE }
|
|
139
|
+
})
|
|
140
|
+
build.onLoad({ filter: /^\0dsh-css:/, namespace: CSS_NAMESPACE }, (args) => {
|
|
141
|
+
const fileId = args.path.slice(CSS_VIRTUAL_PREFIX.length, -CSS_VIRTUAL_SUFFIX.length)
|
|
142
|
+
const source = readFileSync(fileId)
|
|
143
|
+
const { code, exports: cssExports } = transform({
|
|
144
|
+
filename: fileId,
|
|
145
|
+
code: source,
|
|
146
|
+
cssModules: { pattern: '[hash]_[local]' },
|
|
147
|
+
minify: true,
|
|
148
|
+
})
|
|
149
|
+
const classMap = {}
|
|
150
|
+
// Deterministic emit (F-2, QC consolidated): sort the export entries by
|
|
151
|
+
// local name so the class-map JSON literal's key order is byte-stable
|
|
152
|
+
// across consecutive builds (lightningcss insertion order is
|
|
153
|
+
// nondeterministic → M7/M9 bundle non-idempotency).
|
|
154
|
+
for (const [local, exp] of Object.entries(cssExports ?? {}).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) classMap[local] = exp.name
|
|
155
|
+
// One <style data-plugin> per module file; idempotent under re-evaluation.
|
|
156
|
+
// The emitted stub is the EXACT mirror of the dsh tsdown preset's
|
|
157
|
+
// dsh-css-modules-inline load() output: the guard is only the
|
|
158
|
+
// `typeof document` + `data-plugin-css` presence check, and the class
|
|
159
|
+
// map rides the default export as a JSON literal. The advisor card
|
|
160
|
+
// imports that default binding and consumes its classes in JSX, so
|
|
161
|
+
// the export — and the whole stub — survives bundling unchanged.
|
|
162
|
+
//
|
|
163
|
+
// tagId selector-safety (F-5, QC consolidated): the guard builds
|
|
164
|
+
// `style[data-plugin-css=<JSON.stringify(tagId)>]` via JS escaping,
|
|
165
|
+
// NOT CSS escaping — so tagId (`dsh-advisor/<basename>`) must stay
|
|
166
|
+
// CSS-attribute-selector-safe: no `"`, no `\`, no `]`. CSS-module
|
|
167
|
+
// basenames satisfy this by construction (plain [A-Za-z0-9_.-] file
|
|
168
|
+
// names), which is why the virtual id is allowed to carry one.
|
|
169
|
+
const contents = [
|
|
170
|
+
`const css = ${JSON.stringify(code.toString())};`,
|
|
171
|
+
`const tagId = ${JSON.stringify(`${ID}/${basename(fileId)}`)};`,
|
|
172
|
+
`if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css=' + JSON.stringify(tagId) + ']') === null) {`,
|
|
173
|
+
` const tag = document.createElement('style');`,
|
|
174
|
+
` tag.dataset.plugin = ${JSON.stringify(ID)};`,
|
|
175
|
+
` tag.dataset.pluginCss = tagId;`,
|
|
176
|
+
` tag.textContent = css;`,
|
|
177
|
+
` document.head.appendChild(tag);`,
|
|
178
|
+
`}`,
|
|
179
|
+
`export default ${JSON.stringify(classMap)};`,
|
|
180
|
+
].join('\n')
|
|
181
|
+
// F-3 (QC consolidated): declare the physical css file as a watch
|
|
182
|
+
// dependency (mirror of the dsh tsdown preset's addWatchFile(fileId)),
|
|
183
|
+
// so a watch-mode build rebuilds when the module css changes.
|
|
184
|
+
return { loader: 'js', contents, watchFiles: [fileId] }
|
|
185
|
+
})
|
|
186
|
+
},
|
|
187
|
+
}],
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
if (result.errors.length > 0) {
|
|
191
|
+
throw new Error(`client bundle build failed:\n${result.errors.map((e) => e.text).join('\n')}`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Inline bundle-contract assertions (KD-S5): the emitted text must carry the
|
|
195
|
+
// closure-factory load handoff, must not VALUE-import `@deepseek-ai/*` outside
|
|
196
|
+
// the frozen externals table, and must contain NO `import.meta` / ESM
|
|
197
|
+
// statements — the web loader executes this file as a classic <script>.
|
|
198
|
+
//
|
|
199
|
+
// F-1 (QC consolidated): esbuild stamps the virtual CSS-module id — including
|
|
200
|
+
// a raw NUL byte and the builder's absolute path — into an output comment
|
|
201
|
+
// (`// dsh-css-modules:\0dsh-css:<abs path>.mjs`). Strip those comment lines
|
|
202
|
+
// so the shipped/served artifact carries neither the NUL byte nor a local
|
|
203
|
+
// machine path (the regex matches the observed esbuild 0.28 comment form;
|
|
204
|
+
// the \x00 is the raw byte, [^\n]* the rest of the line, gm spans all of them).
|
|
205
|
+
const bundleText = readFileSync(OUT_FILE, 'utf8')
|
|
206
|
+
.replace(/^\/\/ dsh-css-modules:\x00[^\n]*\n/gm, '')
|
|
207
|
+
// The strip must land in the artifact itself, not just the in-memory text.
|
|
208
|
+
writeFileSync(OUT_FILE, bundleText)
|
|
209
|
+
if (!bundleText.includes('window.__ModuleLoader__.load(') || !bundleText.includes(JSON.stringify(ID))) {
|
|
210
|
+
throw new Error('client bundle contract: the closure-factory load handoff with the plugin id is missing')
|
|
211
|
+
}
|
|
212
|
+
for (const match of bundleText.matchAll(/require\(\s*["'](@deepseek-ai\/[^"']+)["']\s*\)/g)) {
|
|
213
|
+
const specifier = match[1]
|
|
214
|
+
if (!CLIENT_EXTERNALS.includes(specifier)) {
|
|
215
|
+
throw new Error(`client bundle contract: "${specifier}" VALUE import survived the purity gate`)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (bundleText.includes('import.meta') || /(^|\n)\s*(import|export)\s/.test(bundleText)) {
|
|
219
|
+
throw new Error('client bundle contract: emitted bundle contains import.meta / ESM statements — the classic-script loader would fail to parse it')
|
|
220
|
+
}
|
|
221
|
+
// F-1 regression (QC consolidated): the artifact must never ship a raw NUL
|
|
222
|
+
// byte or the builder's absolute machine path — both leaked through esbuild's
|
|
223
|
+
// virtual-module comment (`// dsh-css-modules:\0…`) and stripped above.
|
|
224
|
+
if (bundleText.includes('\u0000')) {
|
|
225
|
+
throw new Error('client bundle contract: emitted bundle contains a NUL byte — esbuild virtual-module comment not stripped')
|
|
226
|
+
}
|
|
227
|
+
if (bundleText.includes('/Users/')) {
|
|
228
|
+
throw new Error('client bundle contract: emitted bundle leaks a builder machine path ("/Users/")')
|
|
229
|
+
}
|
|
230
|
+
// CSS-modules inline wiring: the bundle must carry the guarded <style
|
|
231
|
+
// data-plugin> injection stub and the tagId of the advisor card module
|
|
232
|
+
// (the loader cleans up plugin-owned tags by `style[data-plugin=<id>]` +
|
|
233
|
+
// `data-plugin-css`; without this wiring the card renders unstyled).
|
|
234
|
+
for (const fragment of [
|
|
235
|
+
'data-plugin',
|
|
236
|
+
'document.head.appendChild',
|
|
237
|
+
'dsh-advisor/advisor-card.module.css',
|
|
238
|
+
]) {
|
|
239
|
+
if (!bundleText.includes(fragment)) {
|
|
240
|
+
throw new Error(`client bundle contract: CSS-modules inline wiring missing — "${fragment}" not in the emitted bundle`)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Quote-agnostic: esbuild's printer normalizes string quotes, so accept both.
|
|
244
|
+
if (!/document\.createElement\(['"]style['"]\)/.test(bundleText)) {
|
|
245
|
+
throw new Error('client bundle contract: CSS-modules inline wiring missing — document.createElement("style") not in the emitted bundle')
|
|
246
|
+
}
|
|
247
|
+
// F-2 (QC consolidated): pin the attribution the loader cleanup keys on —
|
|
248
|
+
// the web shell removes plugin-owned tags by `style[data-plugin=<id>]`, so the
|
|
249
|
+
// stub must actually assign tag.dataset.plugin (not just carry the literal
|
|
250
|
+
// "data-plugin" string). Quote/whitespace-normalized: match the assignment.
|
|
251
|
+
if (!/tag\.dataset\.plugin\s*=/.test(bundleText)) {
|
|
252
|
+
throw new Error('client bundle contract: CSS-modules inline wiring missing — tag.dataset.plugin attribution (loader cleanup key) not in the emitted bundle')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Declarations for `exports["./client"].types`: tsc emits the client .d.ts
|
|
256
|
+
// tree into lib/client/ (emitDeclarationOnly), then we write the flat
|
|
257
|
+
// re-export so the locked export path stays stable regardless of the internal
|
|
258
|
+
// layout (same shape as the mstar client bundle).
|
|
259
|
+
const tscBin = require.resolve('typescript/bin/tsc')
|
|
260
|
+
rmSync('lib/client', { recursive: true, force: true })
|
|
261
|
+
const tsc = spawnSync(process.execPath, [tscBin, '-p', 'tsconfig.client.json'], { stdio: 'inherit' })
|
|
262
|
+
if (tsc.status !== 0) {
|
|
263
|
+
throw new Error(`client bundle declarations failed (tsc -p tsconfig.client.json, exit ${String(tsc.status)})`)
|
|
264
|
+
}
|
|
265
|
+
const clientDts = join('lib', 'client.d.ts')
|
|
266
|
+
writeFileSync(clientDts, `export * from './client/index.js'\n`)
|
|
267
|
+
|
|
268
|
+
console.log(`build-client: ${ENTRY} -> ${OUT_FILE} (closure-factory CJS) + ${clientDts}`)
|