model-selection-settings.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /** Host-owned opt-in setting for model-selectable subagent delegation. */
  2. import { Context, Service } from '@deepseek-ai/cordis'
  3. import z from '@deepseek-ai/schemastery'
  4. import type {} from '@deepseek-ai/dsh-settings'
  5. import {
  6. AllowedModelRouteSchema,
  7. assertAllowedModelRoutes,
  8. type AllowedModelRoute,
  9. } from './model-selection.ts'
  10. declare module '@deepseek-ai/cordis' {
  11. interface Context {
  12. /** User preference sampled when a new Session receives delegation tools. */
  13. subagentModelSelection: SubagentModelSelectionConfig
  14. }
  15. }
  16. /** User-settings section for model-selectable subagent delegation. */
  17. export const SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE = 'subagent-model-selection'
  18. /** Stored user preference; the shipped composition defaults it off. */
  19. export interface SubagentModelSelectionSettings {
  20. /** Whether newly composed top-level Sessions receive model selection. */
  21. enabled: boolean
  22. /** Exact child LLM routes offered to newly composed top-level Sessions. */
  23. allowedModels: AllowedModelRoute[]
  24. }
  25. /** Schema served to settings clients for the opt-in preference. */
  26. export const SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA: z<SubagentModelSelectionSettings> = z.object({
  27. enabled: z.boolean().default(false),
  28. allowedModels: z.array(AllowedModelRouteSchema).default([]),
  29. })
  30. /** Optional deployment base for the preference. */
  31. export interface Config {
  32. /** Initial enabled state inherited when the user document does not override it. */
  33. enabled?: boolean
  34. /** Initial route list inherited when the user document does not override it. */
  35. allowedModels?: AllowedModelRoute[]
  36. }
  37. /** Singleton settings owner read when delegation tools are composed for a Session. */
  38. export class SubagentModelSelectionConfig extends Service {
  39. static Config: z<Config> = z.object({
  40. enabled: z.boolean().default(false),
  41. allowedModels: z.array(AllowedModelRouteSchema).default([]),
  42. })
  43. private source: () => SubagentModelSelectionSettings
  44. constructor(ctx: Context, config: Config = {}) {
  45. super(ctx, 'subagentModelSelection')
  46. // Cordis supplies the schema default; the fallback also covers direct construction.
  47. /* v8 ignore next */
  48. const entry: SubagentModelSelectionSettings = {
  49. enabled: config.enabled ?? false,
  50. allowedModels: config.allowedModels ?? [],
  51. }
  52. this.validate(entry)
  53. this.source = () => entry
  54. ctx.inject(['settings'], (settingsCtx) => {
  55. settingsCtx.settings.installSection(
  56. ctx,
  57. SUBAGENT_MODEL_SELECTION_SETTINGS_NAMESPACE,
  58. SUBAGENT_MODEL_SELECTION_SETTINGS_SCHEMA,
  59. entry,
  60. {
  61. setSource: (source) => { this.source = source },
  62. validate: (value) => { this.validate(value) },
  63. // Consumers snapshot per Session, so a settings update never rebuilds
  64. // the tool definitions of a Session that is already running.
  65. onChange: () => {},
  66. },
  67. )
  68. })
  69. }
  70. /**
  71. * Read a detached selection preference for the next eligible Session composition.
  72. * @returns the enabled state and exact allowed routes.
  73. */
  74. current(): SubagentModelSelectionSettings {
  75. const current = this.source()
  76. return {
  77. enabled: current.enabled,
  78. allowedModels: current.allowedModels.map(route => ({ ...route })),
  79. }
  80. }
  81. private validate(value: SubagentModelSelectionSettings): void {
  82. assertAllowedModelRoutes(value.allowedModels)
  83. if (value.enabled && value.allowedModels.length === 0) {
  84. throw new Error('enabled subagent model selection requires at least one allowed model')
  85. }
  86. }
  87. }
  88. export const name = 'subagent-model-selection-settings'
  89. export default SubagentModelSelectionConfig