index.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * Default model selection for an Agent without a session-specific selection.
  3. *
  4. * @module @deepseek-ai/dsh-agent-default-model
  5. */
  6. import { Context, Service } from '@deepseek-ai/cordis'
  7. import z from '@deepseek-ai/schemastery'
  8. import type { ModelSelection } from '@deepseek-ai/dsh-agent'
  9. import { ReasoningEffortId } from '@deepseek-ai/dsh-llm'
  10. import type {} from '@deepseek-ai/dsh-settings'
  11. declare module '@deepseek-ai/cordis' {
  12. interface Context {
  13. /** Default model selection for Agents created without an explicit model. */
  14. agentDefaultModel: AgentDefaultModelConfig
  15. }
  16. }
  17. /** Settings namespace carrying the default model selection for future Agents. */
  18. export const AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE = 'agent-default-model'
  19. /** Stored and composed default model selection. */
  20. export interface AgentDefaultModelSettings {
  21. /** Registered provider route. */
  22. provider: string
  23. /** Provider-owned model id. */
  24. model: string
  25. /** Adapter-owned reasoning effort, or provider/default behavior when absent. */
  26. reasoningEffort?: string
  27. }
  28. /** Schema of the default Agent model settings section. */
  29. export const AGENT_DEFAULT_MODEL_SETTINGS_SCHEMA: z<AgentDefaultModelSettings> = z.object({
  30. provider: z.string().required(),
  31. model: z.string().required(),
  32. reasoningEffort: z.string(),
  33. })
  34. /** Composition entry for the default model selection. */
  35. export interface Config {
  36. /** Registered provider route. */
  37. provider: string
  38. /** Provider-owned model id. */
  39. model: string
  40. }
  41. /** Project stored settings onto the Agent-facing selection type. */
  42. function selection(settings: AgentDefaultModelSettings): ModelSelection {
  43. return {
  44. provider: settings.provider,
  45. model: settings.model,
  46. ...settings.reasoningEffort === undefined
  47. ? {}
  48. : { reasoningEffort: ReasoningEffortId(settings.reasoningEffort) },
  49. }
  50. }
  51. /**
  52. * Owns the default model selection independently of any Host or transport.
  53. * The composition entry remains usable without a settings provider; when one
  54. * is mounted, its user layer is read live.
  55. */
  56. export class AgentDefaultModelConfig extends Service {
  57. static Config: z<Config> = z.object({
  58. provider: z.string().required(),
  59. model: z.string().required(),
  60. })
  61. private source: () => AgentDefaultModelSettings
  62. constructor(ctx: Context, config: Config) {
  63. super(ctx, 'agentDefaultModel')
  64. const entry: AgentDefaultModelSettings = { provider: config.provider, model: config.model }
  65. this.source = () => entry
  66. ctx.inject(['settings'], (settingsCtx) => {
  67. settingsCtx.settings.installSection(ctx, AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE, AGENT_DEFAULT_MODEL_SETTINGS_SCHEMA, entry, {
  68. setSource: (current) => { this.source = current },
  69. // Every consumer reads through currentSelection(), so no registration-level fact
  70. // needs rebuilding when the settings document changes.
  71. onChange: () => {},
  72. })
  73. })
  74. }
  75. /**
  76. * Read the current default model selection.
  77. * @returns a detached provider, model, and optional reasoning selection.
  78. */
  79. currentSelection(): ModelSelection {
  80. return selection(this.source())
  81. }
  82. /**
  83. * Save the complete default model selection. A deployment without a settings
  84. * provider keeps its composition entry.
  85. * @param next - resolved selection accepted by an entry point.
  86. * @returns fulfillment after the optional settings write settles.
  87. */
  88. async saveSelection(next: ModelSelection): Promise<void> {
  89. await this.ctx.get('settings')?.replace(AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE, {
  90. provider: next.provider,
  91. model: next.model,
  92. ...next.reasoningEffort === undefined ? {} : { reasoningEffort: String(next.reasoningEffort) },
  93. })
  94. }
  95. }
  96. export default AgentDefaultModelConfig