Files
deepseek-harness/packages/boot/plugin-manager/src/patch.ts
T
Turtle b173f3e2a2 revert(plugin): drop preset-scoped profile patches; ship optional tools as global Host rows
Remove the `{ preset, insert }` / `{ preset, id, ...override }` profile patch
operation added in #5773, together with the app-boot compiler and reload drain,
config-editor filtering, plugin-manager preset row inventory and retained-module
removal checks, the read-only preset rows on the Plugins page, and the
agent-preset-registry row identities that served them.

Session search, Ralph, persistent terminals, Codex, and Claude Code bundles now
insert ordinary Host rows whose tools register in the global tool layer, like the
earlier optional bundles. Every preset, including minimal, sees them, and toggling
a bundle updates live Agents without new composition generations.
2026-10-07 20:46:37 +08:00

44 lines
1.8 KiB
TypeScript

/** Comment-preserving profile plugin enablement edits. */
import { readFile } from 'node:fs/promises'
import { isMap, isSeq, parseDocument } from 'yaml'
import { loadOptionalPatches } from '@deepseek-ai/dsh-app-boot'
import { writeFileAtomic } from '@deepseek-ai/dsh-atomic-write'
/** Replace the last matching override or append one after existing insertions.
* @param filename Current profile patch file.
* @param id Unique composition entry id.
* @param name Module name used to match name-qualified overrides.
* @param enabled Desired entry enablement.
* @returns Whether the file changed.
*/
export async function writePluginEnabled(filename: string, id: string, name: string, enabled: boolean): Promise<boolean> {
let text: string
try {
text = await readFile(filename, 'utf8')
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
text = '[]\n'
}
const document = parseDocument(text, {
customTags: [{ tag: 'tag:yaml.org,2002:js', resolve: (value: string) => value }],
})
const error = document.errors[0]
if (error !== undefined) throw error
if (!isSeq(document.contents)) throw new Error('Profile patch must be a YAML sequence')
loadOptionalPatches('dsh', filename)
const items = document.contents.items
const target = items.findLast((item, index) => {
if (!isMap(item) || document.getIn([index, 'id']) !== id || item.has('insert')) return false
const expectedName = document.getIn([index, 'name'])
return !expectedName || expectedName === name
})
if (isMap(target)) {
if (document.getIn([items.indexOf(target), 'disabled']) === !enabled) return false
document.setIn([items.indexOf(target), 'disabled'], !enabled)
} else {
document.add({ id, disabled: !enabled })
}
await writeFileAtomic(filename, String(document), { mode: 0o600 })
return true
}