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.
44 lines
1.8 KiB
TypeScript
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
|
|
}
|