DeepSeek Harness 源码实战第3章:Profile / Bundle / Patch——dsh 的装配系统
DeepSeek Harness æºç å®æç¬¬3ç« ï¼Profile / Bundle / Patchââdsh çè£ é ç³»ç»
ææµªç« 2026-08-18 0 é 读8åéDeepSeek Harness æºç å®æç¬¬3ç« ï¼Profile / Bundle / Patchââdsh çè£ é ç³»ç»
ç³»åï¼DeepSeek Harness æºç 宿
åæä»åºï¼github.com/deepseek-aiâ¦
æ¹ä¸è¡é ç½®ï¼æ´ä¸ªäº§åçå½¢æå°±åäºã
ä¸ä¸ç« æä»¬è®²äº Cordis æä»¶å¼æï¼ç¥éäº dsh çææåè½é½æ¯æä»¶ãä½ä½ å¯è½ä¸ç´å¨æ³ä¸ä¸ªé®é¢ï¼è¿äºæä»¶æ¯æä¹è¢«ç»è£
å°ä¸èµ·çï¼è°å³å®å è½½åªäºæä»¶ãè°è¦çè°ï¼è¿ä¸ç« å°±æ¥æ dsh çè£
é
ç³»ç»ââä¸ä¸ªæ¦å¿µã䏿¡å¯å¨é¾ãä¸å¥æ¿æ¢è¯ä¹ã
ææ¯ææµªç«ï¼è¿ä¸ç« æä»¬æ·±å
¥ apps/cli/src/ å packages/boot/ çæºç ï¼ç dsh ä»ä¸è¡å½ä»¤å°ä¸æ£µæä»¶æ ï¼ä¸é´å°åºåçäºä»ä¹ã
3.1 ä¸ä¸ªæ¦å¿µè¾¨æï¼Bundle / Profile / Patch
dsh çè£ é ç³»ç»æä¸ä¸ªæ ¸å¿æ¦å¿µãå ç¨ä¸å¥è¯å®ä¹æ¯ä¸ä¸ªï¼åå±å¼è®²ã
- Bundleï¼ç»åå
ï¼ï¼Cordis é
置项åæè½½ä»£ç çååæ ¼å¼ã宿¯ä¸ç»æä»¶çãæå
ãï¼æå
¥çå
容å§ç»å¯ä»¥è¢«ä¸å± patch è¦çãå¨èªå·±ç
package.jsonçdsh.bundleåæ®µä¸å£°æèªå·±ç patch æä»¶è·¯å¾ã - Profileï¼è£
é
æ¡£æ¡ï¼ï¼åæ¾å¨ Harness home ä¸çå
·åç»è£
ãå®ååºèªå·±å æ¾çç»åå
ï¼
dsh.profileåæ®µï¼ï¼åæ¾èªå·±å®è£ çæ å¤æä»¶ï¼å¹¶ä¿åç¨æ·èªå·±çcordis.patch.ymlãwebåheadlessä½ä¸ºæ¨¡æ¿éåè¡ç交ä»ã - Patchï¼è¡¥ä¸ï¼ï¼æ id å®ä½æä¸ªæ¡ç®å¹¶æ¿æ¢å ¶æ´ä¸ª configï¼é ç½®ï¼ï¼ææå ¥æ°æ¡ç®ã䏿¯æ·±åå¹¶ï¼æ¯æ´è¡æ¿æ¢ã
ä¸è ä¹é´çå ³ç³»å¯ä»¥è¿æ ·çè§£ï¼
Profileï¼è£
é
æ¡£æ¡ï¼= ä¸ä»½ç»è£
æ¸
å
â
âââ bundles åè¡¨ï¼æé¡ºåºï¼
â âââ dsh-baseï¼åºç¡å±ï¼æ¨¡åéé
å¨ãå·¥å
·ãæä¹
åãæ²ç®±ã审æ¹çç¥ã设置ãåæ®ã饿µï¼
â âââ dsh-web-appï¼Web åºç¨å±ï¼hostãAPI gatewayãHMRï¼
â âââ dsh-headlessï¼æ æå¡å¨ç忬¡è¿è¡å¨ï¼
â
âââ cordis.patch.ymlï¼ç¨æ·å±è¦çï¼
â âââ æ id æ¿æ¢ææå
¥æ¡ç®
â
âââ æ 夿件ï¼éè¿ dsh plugin å®è£
ï¼
Patch å±çº§ï¼èªåºåä¸å å ï¼:
空é
ç½® []
â Bundle ç patchï¼æ profile ååºç顺åºï¼
â Profile èªå·±ç cordis.patch.yml
â Home 级 $DSH_HOME/cordis.patch.yml
â --patch å½ä»¤è¡ä¸´æ¶ overlay
â æç»é
ç½®æ
对æ¯è¡¨ï¼
| æ¦å¿µ | æ¯ä»ä¹ | è°å建 | å¯è¢«è°è¦ç |
|---|---|---|---|
| Bundle | ä¸ç»æä»¶çæå åå | dsh 宿¹æç¬¬ä¸æ¹ | Profile patch / Home patch / å½ä»¤è¡ overlay |
| Profile | ä¸ä»½ç»è£ æ¸ å | ç¨æ·ï¼æéåè¡ç交ä»ç模æ¿ï¼ | ä¸å± patch |
| Patch | æ id æ´è¡æ¿æ¢ | ç¨æ·ç¼å | æ´ä¸å±ç patch |
ä¸ä¸ªæ¦å¿µå¨åèªç package.json ä¸éè¿ dsh åæ®µå£°æï¼dsh.profile ååºä¸ä¸ª profile çç»åå
ï¼dsh.bundle æåä¸ä¸ªç»åå
ç patch æä»¶ã
éå¥ï¼Bundle æ¯ç ï¼Profile æ¯å¾çº¸ï¼Patch æ¯ä½ æ¿ç¬å¨å¾çº¸ä¸ç»çä¿®æ¹ã
3.2 å¯å¨é¾æè§£ï¼ä» bin.ts å°æä»¶æ
ç°å¨æ¥è¿½è¸ªä¸æ¬¡å®æ´çå¯å¨è¿ç¨ã以 dsh --profile web 为ä¾ã
ç¬¬ä¸æ¥ï¼åæ°è§£æ
å
¥å£å¨ apps/cli/src/bin.tsï¼ä¸ä¸ç« å·²ç»çè¿å®ç䏿¨¡å¼ååãè¿éèç¦ profile 模å¼ï¼
// apps/cli/src/bin.tsï¼èéï¼
const invocation = parseDshArgs(process.argv.slice(2), readVersion())
switch (invocation.mode) {
case 'profile': {
const { runProfile } = await import('./profile-boot.ts')
await runProfile({
environment: loadLayeredEnv('dsh'),
profile: invocation.profile,
patchFiles: invocation.patches,
args: invocation.args,
})
break
}
// ...
}
parseDshArgs è¿åä¸ä¸ªå¤å«èåï¼discriminated unionï¼ï¼mode åæ®µå³å®èµ°åªä¸ªåæ¯ãprofile 模å¼ä¸ï¼å®æç¯å¢å¿«ç
§ãprofile åãpatch overlay è·¯å¾ãå
é¨åæ°å
¨é¨ä¼ ç» runProfileã
ç¬¬äºæ¥ï¼åæ patch å±
runProfile å¨ apps/cli/src/profile-boot.ts ä¸å®ä¹ãå®å
è°ç¨ composeProfile åæ patch å±ï¼
// apps/cli/src/profile-boot.tsï¼èéï¼
function composeProfile(name: string, patchFiles: readonly string[]): ComposedProfile {
const profile = prepareProfile(name)
const homePatches = loadOptionalPatches(NAME, homePatchPath()) ?? []
const overlays = patchFiles.flatMap(file => loadOverlayPatches(NAME, resolve(file)))
const bundlePatches = profile.layers.flatMap(layer => layer.patches)
const rows = new Map<string, EntryOptions>()
for (const row of composeEntries([bundlePatches, profile.patches, homePatches, overlays])) {
if (typeof row.id === 'string') rows.set(row.id, row)
}
// ... agent-presets æ ¹è·¯å¾æ³¨å
¥ + 饿µå¼å
³
return { profile, bundlePatches, homePatches, overlays: composedOverlays, rows }
}
è¿æ®µä»£ç çé»è¾æ¯ï¼
prepareProfile(name)å è½½ profileï¼è¯»åå®ç bundles å表homePatcheså è½½ Home 级 patchï¼$DSH_HOME/cordis.patch.ymlï¼overlayså è½½å½ä»¤è¡--patchæå®çä¸´æ¶ overlaybundlePatchesä» profile çå bundle 屿å patchcomposeEntriesæåå± patch åææç»æ¡ç®å表ï¼å¹¶å»ºç« id ç´¢å¼
注æ composeEntries çåæ°é¡ºåºï¼[bundlePatches, profile.patches, homePatches, overlays]ãè¿å°±æ¯å å 顺åºââåé¢çè¦çåé¢çã
ç¬¬ä¸æ¥ï¼éåæ ¹é ç½®
prepareProfile éæä¸ä¸ªå®¹æè¢«å¿½ç¥çç»èï¼
// apps/cli/src/profile-boot.tsï¼èéï¼
export function prepareProfile(name: string, userLayer = true): Profile {
healProfilesModuleFallback(INSTALL_ANCHOR)
const profile = loadProfile(NAME, name, INSTALL_ANCHOR, undefined, { userLayer })
writeFileSync(join(profile.dir, PROFILE_ROOT_FILENAME), PROFILE_ROOT_CONFIG)
return profile
}
PROFILE_ROOT_CONFIG æ¯ä¸ä¸ªç©ºå表 []ï¼æ¯æ¬¡å¯å¨é½éåã为ä»ä¹ï¼å 为 Cordis ç Loader æä¸ä¸ªååæºå¶ââæä»¶èªæå¸è½½æ¶ä¼æä¹
åå½åé
ç½®æ ã妿ä¸éç½®ï¼ä¸æ¬¡ç»åçè¡ä¼è¢«åºåè¿æ ¹æä»¶ï¼ä¸æ¬¡å¯å¨æ¶æ¯ä¸ª bundle çæå
¥æä½ä¼éå¤ä¸éã
PROFILE_ROOT_CONFIG çå
容就æ¯ä¸¤è¡æ³¨éå ä¸ä¸ªç©ºæ°ç»ï¼
# dsh profile root â an empty entry list. The tree is composed as patches:
# each bundle in package.json's dsh.profile.bundles, then cordis.patch.yml, then any
# --patch overlays. Edit cordis.patch.yml, not this file.
[]
注éæç¡®è¯´äºï¼æ´ä¸ªé ç½®æ æ¯ patch å å åºæ¥çï¼ä¸è¦ç´æ¥ç¼è¾è¿ä¸ªæä»¶ã
éå¥ï¼æ¯æ¬¡å¯å¨é½ä»ç©ºå表å¼å§ï¼å°±åæ¯å¤©æ©ä¸æç½æ¿æ¦å¹²åãè¿ä¸æ¯å¼ºè¿«çï¼æ¯é²æ¢ç¶æç´¯ç§¯çå·¥ç¨çºªå¾ã
ç¬¬åæ¥ï¼boot æè½½
åæå® patch å±åï¼è°ç¨ boot 彿°æè½½é
ç½®æ ï¼
// apps/cli/src/profile-boot.tsï¼èéï¼
const ctx = await boot(NAME, rootConfig, structuredClone(allPatches(composed)), (hostCtx) => {
app.current = hostCtx
hostCtx.provide(DSH_LAUNCH_ENVIRONMENT_KEY, options.environment)
provideCmdline(hostCtx, {
args: options.args,
exit: code => void shutdown.shutdown(code),
})
})
注æä¸ä¸ªç»èï¼
structuredClone(allPatches(composed))ââæ·±æ·è´ patch åè¡¨ãæ³¨éè§£éäºåå ï¼Include 伿 insert è¡æå¼ç¨æå ¥æè½½æ ï¼åç»ç id å®å patch ä¼åå°ä¿®æ¹è¿äºå¯¹è±¡ã妿䏿·è´ï¼ç¨æ·å±çè¦ç伿¸éè¿ bundle çå å对象ï¼å¯¼è´æ¤éè¦çæ¶æ æ³æ¢å¤ã(hostCtx) => { ... }æ¯ host åè°ï¼å¨é ç½®æ æ¡ç®æè½½ä¹åæ§è¡ï¼ç¨æ¥æä¾å ¨å±æå¡ï¼ç¯å¢å¿«ç §ãå½ä»¤è¡åæ°ãéåºæ¥å£ï¼ãbootè¿å root Contextï¼ä¹å°±æ¯ Cordis æä»¶æ çæ ¹èç¹ã
ç¬¬äºæ¥ï¼HMR çéè½½
boot 宿åï¼è¿ä¼è®¾ç½® patch æä»¶ççéè½½çè§ï¼
// apps/cli/src/profile-boot.tsï¼èéï¼
await watchUserPatches(ctx, {
binName: NAME,
filename: composed.profile.patchPath,
compose: composeLive,
})
await watchUserPatches(ctx, {
binName: NAME,
filename: homePatchPath(),
compose: composeLive,
})
两个 watcher åå«çè§ profile 级å home 级ç cordis.patch.ymlãæä»¶åæ´æ¶ï¼è°ç¨ composeLive éæ°åæ patch å±ï¼ä¸å
å« bundle å±ï¼å 为 bundle å±ä¸å¯çéè½½ï¼ï¼ç¶åéç¥ Cordis Loader éæ°æè½½åå½±åçæ¡ç®ã
composeLive çå®ç°æä¸ä¸ªéè¦çå
éé»è¾ï¼
const composeLive = (): PatchOptions[] => structuredClone([
...composed.bundlePatches,
...loadOptionalPatches(NAME, composed.profile.patchPath) ?? [],
...loadOptionalPatches(NAME, homePatchPath()) ?? [],
...composed.overlays,
])
æ¯æ¬¡éæ°åæé½ä¼ fresh cloneï¼å ¨æ°å éï¼ï¼åå åç¬¬åæ¥ä¸æ ·ââ鲿¢ insert è¡çå¼ç¨å«å导è´ç¶ææ¸éã
å¯å¨é¾æ»ç»
1. dsh --profile web
2. parseDshArgs â mode='profile', profile='web'
3. runProfile â composeProfile
3a. prepareProfile â loadProfile + éåç©ºæ ¹é
ç½®
3b. å è½½ homePatches + overlays + bundlePatches
3c. composeEntries åææç»æ¡ç®å表
4. boot(NAME, rootConfig, patches, hostCallback)
4a. Cordis Loader 读åé
ç½®æ
4b. ææ¡ç®å®ä¾åæä»¶
4c. æ¯ä¸ªæä»¶æ³¨å ctx æå¡
4d. è¿å root Context
5. watchUserPatches à 2ï¼profile 级 + home 级 HMRï¼
6. web-app bundle çæä»¶å¯å¨ Web Server â http://127.0.0.1:3080
3.3 Patch çæ¿æ¢è¯ä¹ï¼æ id æ´è¡æ¿æ¢ï¼ä¸æ¯æ·±åå¹¶
è¿æ¯ dsh è£ é ç³»ç»éæå®¹æè¸©åçç¹ã
Patch çæ¿æ¢è¯ä¹æ¯ãæ id å®ä½æä¸ªæ¡ç®ï¼æ¿æ¢å ¶æ´ä¸ª configããæ³¨æï¼æ´ä¸ª configï¼ä¸æ¯æ·±åå¹¶ï¼deep mergeï¼ï¼ä¸æ¯é¨åè¦çãå¦æä½ patch ä¸ä¸ªæ¡ç®ï¼ä½ æä¾ç config å°±æ¯æç»ç»æï¼åæ¥ç config ä¼å®å ¨æ¶å¤±ã
æ¥çä¸ä¸ªå¯¹æ¯ãå设 bundle å±å®ä¹äºä¸ä¸ªæ¡ç®ï¼
# bundle å±
- id:
tool-bash
config:
timeoutMs:
30000
retryPolicy:
maxRetries:
3
backoffMs:
1000
env:
DSH_SHELL:
bash
ç°å¨ä½ æ³æ¹ timeoutï¼åäºä¸ä¸ª patchï¼
æ·±åå¹¶è¯ä¹ï¼dsh ä¸è¿æ ·å·¥ä½ï¼ï¼
# åæ³çæ·±åå¹¶ç»æï¼ä¸æ£ç¡®ï¼
- id:
tool-bash
config:
timeoutMs:
60000
# â 被è¦ç
retryPolicy:
# â ä¿ç
maxRetries:
3
backoffMs:
1000
env:
# â ä¿ç
DSH_SHELL:
bash
dsh çå®é è¯ä¹ï¼æ´è¡æ¿æ¢ï¼ï¼
# å®é
ç»æï¼config 被æ´ä½æ¿æ¢
- id:
tool-bash
config:
timeoutMs:
60000
# â åªæè¿ä¸ª
# â retryPolicy 没äº
# â env 没äº
å¦æä½ æ³æ¹ä¸ä¸ªå段ä½ä¿çå ¶ä»å段ï¼ä½ éè¦å¨ patch éæææå段é½åä¸ãè¿æ¯è®¾è®¡å³çï¼ä¸æ¯ bugã
为ä»ä¹è¿æ ·è®¾è®¡ï¼å 为深åå¹¶çè¯ä¹ä¸ç´è§ââ彿å¤å± patch å å æ¶ï¼æ·±åå¹¶çè¡ä¸ºä¼åå¾é¾ä»¥é¢æµãæ´è¡æ¿æ¢è½ç¶åèµ·æ¥æ´å°å¦ï¼ä½ç»æå®å ¨å¯é¢æµï¼ä½ çå°çå°±æ¯æç»å¼ï¼ä¸éè¦æ¨æå®æ¯æä¹åå¹¶åºæ¥çã
éå¥ï¼æ·±åå¹¶æ¯ä¾¿å©è´´ï¼æ´è¡æ¿æ¢æ¯ååãåè 好åä¸å¥½è¯»ï¼åè 好读ä¸å¥½åãdsh éæ©äºå¥½è¯»ã
æ¥çå®é é ç½®æ çå½ä»¤ï¼
dsh --profile web --dump-config
è¿ä¼æå°æç»åæçé
ç½®æ ï¼è®©ä½ 确认åªäºæ¡ç®è¢«å è½½ãåªäºè¢« patch æ¿æ¢äºã--dump-default-config ååªæå° bundle å±ï¼ä¸å
å«ç¨æ·å±å overlayã
3.4 CLI 模å¼å ¨è§
dsh ç CLI æä¸ä¸ªæ¨¡å¼ï¼å¨ bin.ts ç switch éï¼åä¸¤ä¸ªè¯æ³ç³ï¼å¨ args.ts éï¼ã宿´å½ä»¤éæ¥è¡¨ï¼
| å½ä»¤ | æ¨¡å¼ | 说æ |
|---|---|---|
dsh --profile web | profile | å¯å¨ web profile |
dsh web | profile | --profile web çå«å |
dsh --profile headless "task" | profile | 忬¡ä»»å¡ï¼æå°ç»æéåº |
dsh --profile tui --patch ./extra.yml | profile | èªå®ä¹ profile + é¢å¤ overlay |
dsh --profile tui --resume <session> | profile | æ¢å¤æå®ä¼è¯ï¼--resume æ¯å
é¨åæ°ï¼ |
dsh --profile web --dump-config | dump-config | æå° web profile ç宿´é ç½®æ |
dsh --profile web --dump-default-config | dump-config | æå° web profile ç bundle å±ï¼ä¸å«ç¨æ·å±ï¼ |
dsh plugin --profile tui add <pkg> | plugin | ç» tui profile å®è£ æä»¶ |
dsh plugin --profile tui remove <pkg> | plugin | ç§»é¤æä»¶ |
æ¯ä¸ªæ¨¡å¼çéç¨åºæ¯ï¼
profile 模å¼ï¼æ¥å¸¸ä½¿ç¨ãå¯å¨ä¸ä¸ª profile çæå¡ï¼Web Serverãheadless runner çï¼ï¼åæ°ä¼ éç» profile å é¨çåºç¨æä»¶ã
dump-config 模å¼ï¼è°è¯åææ¡£ãä¸å¯å¨æå¡ï¼åªæå°é
ç½®æ ãå½ä½ ç profile è¡ä¸ºä¸å¯¹æ¶ï¼å
ç¨è¿ä¸ªçå®é
é
ç½®æ¯ä¸æ¯ä½ ææçãæ³¨æ dump-config 䏿¥ååºç¨åæ°ï¼--dump-config åå
é¨åæ°äºæ¥ï¼ï¼å 为é
ç½®æ å¨åºç¨åæ°æ³¨å
¥ä¹å就已ç»ç¡®å®äºã
plugin 模å¼ï¼æä»¶ç®¡çãæåæ°åæ ·è½¬åç» pnpmï¼å¨ profile ç®å½éæ§è¡ãçä»·äº cd $DSH_HOME/profiles/<name> && pnpm <args>ã
web å«åçå®ä¹ï¼
// apps/cli/src/args.tsï¼èéï¼
const web = program.command('web')
.description('boot the web profile (alias of --profile web)')
.helpOption(false)
.allowUnknownOption()
.passThroughOptions()
.enablePositionalOptions()
.argument('[args...]', 'arguments for the web app')
.option('--patch <path>', 'extra patch-list overlay', collect)
.option('--dump-config', 'print the composed web-profile tree and exit')
.action((args: string[], options: BootOptions) => {
rejectParentOptions('web')
resolved = resolveBoot(web, 'web', options, args)
})
注æ rejectParentOptions('web')ââweb åå½ä»¤ä¸æ¥åç¶å½ä»¤ç --profileã--patchã--dump-configãè¿é²æ¢äº dsh --profile tui web è¿ç§æ æä¹çç»åã
3.5 é»è®¤è£ é ï¼dsh-baseãdsh-web-appãdsh-headless
dsh éåè¡ç交ä»äºä¸ä¸ª bundleï¼ææä¸¤ç§é»è®¤ profileã
dsh-baseï¼ç¬¬ä¸å±åºç¡
dsh-base æ¯æ¯ä¸ª profile ç第ä¸å±ãå®å
å«ï¼
| å 容 | 说æ |
|---|---|
| 模åéé å¨ | LLM éé 卿³¨åå° ctx.llm |
| å·¥å · | æ ¸å¿å·¥å ·æ³¨åå° ctx.tools |
| æä¹ å | ä¼è¯æ¥å¿åå¨ï¼JSONLï¼JSON Linesï¼æ¯è¡ä¸ä¸ª JSON 对象ï¼/ SQLiteï¼ |
| æ²ç®±ä¸å®¡æ¹çç¥ | è¿ç¨æ²ç®±ãæä»¶ç³»ç»çº¦æãæä½å®¡æ¹ |
| 设置 | ctx.settings æå¡ |
| åæ® | ctx.credentials æå¡ |
| 饿µ | å¯éç OpenTelemetry 饿µ |
dsh-base è¿è´è´£å¹³å°é¨æ§ãå¨ Windowsï¼win32ï¼ä¸ï¼åªå®è£
PowerShellï¼pwshï¼æ ï¼bash-sandbox å tool-bash 被ç¦ç¨ãå¨ POSIXï¼Linux/macOSï¼ä¸ï¼åªå®è£
bash æ ãè¿æ¯éè¿ bundle å±ç disabled åæ®µæå¹³å°æ¡ä»¶æ§å¶çã
dsh-web-appï¼æµè§å¨åºç¨
dsh-web-app å¨ dsh-base ä¹ä¸å¢å ï¼
- Web hostï¼å®¿ä¸»ç«¯æå¡ï¼
- API gatewayï¼API ç½å ³ï¼
- æµè§å¨æä»¶è¡¨ï¼client ç«¯æ¨¡åæ³¨åï¼
- HMRï¼Hot Module Replacementï¼çæ¨¡åæ¿æ¢ï¼æ¯æ
dsh web å°±æ¯ dsh-base + dsh-web-app çç»åã
dsh-headlessï¼ä¸æ¬¡æ§è¿è¡å¨
dsh-headless å¨ dsh-base ä¹ä¸å¢å ä¸ä¸ª headless runnerââæ¥æ¶ä¸ä¸ªä»»å¡åç¬¦ä¸²ï¼æ§è¡å®æ¯åæå°ç»æå¹¶éåºãå®å
¨ä¸å¸¦æå¡å¨ã
dsh --profile headless "run the tests" éå CIï¼Continuous Integrationï¼æç»éæï¼åºæ¯ï¼ä¸éè¦ UIï¼ä¸éè¦äº¤äºï¼è·å®å°±èµ°ã
èªå®ä¹ profile æ¥éª¤
å¦æä½ æ³å建èªå·±ç profileï¼
- å¤å¶ä¸ä¸ªæ¨¡æ¿ profile ç®å½å°
$DSH_HOME/profiles/my-profile/ - ç¼è¾
package.jsonï¼è®¾ç½®dsh.profile.bundlesååºä½ éè¦ç bundle - å建
cordis.patch.ymlï¼æ id æ¿æ¢ææå ¥æ¡ç® - ç¨
dsh plugin --profile my-profile add <pkg>å®è£ æ 夿件 - è¿è¡
dsh --profile my-profile - ç¨
dsh --profile my-profile --dump-configæ£æ¥é ç½®æ
馿¬¡ä½¿ç¨ä¸ä¸ªæ° profile åæ¶ï¼dsh ä¼èªå¨åå§å模æ¿ã
éå¥ï¼Profile 䏿¯é ç½®æä»¶ï¼æ¯ä¸ä»½ç»è£ ååãä½ ç¾åï¼å£°æ bundlesï¼ï¼dsh æåå交ä»ï¼æè½½æä»¶æ ï¼ã
æ¬ç« å°ç»
| è¦ç¹ | 说æ |
|---|---|
| Bundle | ä¸ç»æä»¶çæå ååï¼æå ¥çå 容å¯è¢«ä¸å±è¦ç |
| Profile | å ·åç»è£ æ¸ åï¼ååº bundles + åæ¾æ 夿件 + ä¿å cordis.patch.yml |
| Patch | æ id æ´è¡æ¿æ¢æ¡ç®ç configï¼ä¸æ¯æ·±åå¹¶ |
| å å é¡ºåº | 空 [] â bundle patches â profile patch â home patch â --patch overlay |
| å¯å¨é¾ | parseDshArgs â runProfile â composeProfile â boot â HMR watcher |
| æ ¹é ç½®éå | æ¯æ¬¡å¯å¨éå为空 []ï¼é²æ¢ Loader åå导è´é ç½®è¨è |
| structuredClone | patch 对象深æ·è´ï¼é²æ¢ insert è¡å¼ç¨å«å导è´ç¶ææ¸é |
| CLI 䏿¨¡å¼ | profileï¼å¯å¨ï¼/ dump-configï¼æ¥çé ç½®ï¼/ pluginï¼ç®¡çæä»¶ï¼ |
| ä¸ä¸ª bundle | dsh-baseï¼åºç¡ï¼/ dsh-web-appï¼Web åºç¨ï¼/ dsh-headlessï¼ä¸æ¬¡æ§è¿è¡ï¼ |
| å¹³å°é¨æ§ | win32 åªè£ pwsh æ ï¼POSIX åªè£ bash æ |
ä¸ç« é¢å
è£ é ç³»ç»ææ¸ æ¥äºï¼æä»¶æ ä¹æèµ·æ¥äºãä¸ä¸ç« æä»¬è¦æ·±å ¥ dsh çæ°æ®æ ¸å¿ââSession ä¼è¯æ¥å¿ãä½ ä¼çå°ä¸ºä»ä¹ dsh çè天记å½å ¶å®åªæ¯æ¥å¿çä¸ä¸ªæå½±ï¼ä»¥å为ä»ä¹è¿ä¸ªè®¾è®¡å³ç影忷±è¿ã
ææ¯ææµªç«ï¼è£ é ç³»ç»è¿ä¸ç« ä¿¡æ¯éæ¯è¾å¤§ï¼å»ºè®®æ¶èååå¤çãä½ ç agent 项ç®éï¼é ç½®æ¯æä¹ç»è£ çï¼è¯è®ºåºèèã
ç³»åè¿åº¦ï¼3/8 ï½ ä¸ä¸ç« ï¼Session ä¼è¯æ¥å¿ââåä¸äºå®æº
Aitishiku.com