index.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /**
  2. * Headless one-shot app composition: the default agent spine, JSONL session
  3. * persistence, and one fresh top-level agent. The CLI driver owns task
  4. * submission and output; the app deliberately mounts no interactive or logging
  5. * front door so stdout remains protocol-pure.
  6. * @module @deepseek-ai/dsh-cli-demo
  7. */
  8. import type { Context } from 'cordis'
  9. import z from 'schemastery'
  10. import { SessionId } from '@deepseek-ai/dsh-session'
  11. import ToolRegistry, { type Config as ToolsConfig } from '@deepseek-ai/dsh-tools'
  12. import * as agentCore from '@deepseek-ai/dsh-agent-spine-demo'
  13. import SessionPersistenceJsonl, {
  14. JsonlCompressionSchema,
  15. type JsonlCompression,
  16. } from '@deepseek-ai/dsh-session-persistence-jsonl'
  17. import * as sessionCheckpointPolicy from '@deepseek-ai/dsh-session-checkpoint-policy'
  18. import * as workspaceContext from '@deepseek-ai/dsh-workspace-context'
  19. const DEFAULT_PERSISTENCE_ROOT = './.sessions'
  20. export const name = 'cli-demo'
  21. /** App config forwarded to the spine, configured agent, and JSONL backend. */
  22. export interface Config {
  23. /** Provider route for the configured agent. */
  24. provider: string
  25. /** Model name for the configured agent; a matching adapter must be registered. */
  26. model: string
  27. /** Bundled agent-loop concurrency cap; `1` is serial and omission uses its default. */
  28. maxParallelToolCalls?: number
  29. /** Deployment persona forwarded to the system-prompt plugin. */
  30. persona?: string
  31. /** Explicit model-facing tool order forwarded to the system-prompt plugin. */
  32. toolOrder?: string[]
  33. /** Tool-registry presentation config forwarded through agent-spine-demo. */
  34. tools?: ToolsConfig
  35. /** DeepSeek Harness home directory exposed to bash and used for local skill discovery. */
  36. dshHome?: string
  37. /** Fallback session-title limits forwarded through agent-spine-demo. */
  38. sessionTitle?: NonNullable<agentCore.Config['sessionTitle']>
  39. /** Directory the JSONL session backend writes under. Defaults to `./.sessions`. */
  40. persistenceRoot?: string
  41. /** JSONL artifact encoding; defaults to checksummed Zstandard frames. */
  42. persistenceCompression?: JsonlCompression
  43. /** Skill registry, local-provider, and model-facing consumer config. */
  44. skills?: agentCore.SkillConfig
  45. /** Model-facing bash tool config forwarded through agent-spine-demo. */
  46. toolBash?: NonNullable<agentCore.Config['toolBash']>
  47. /** Generic background-task control-tool config forwarded through agent-spine-demo. */
  48. toolTasks?: NonNullable<agentCore.Config['toolTasks']>
  49. /** Bounded transient model-request retry policy forwarded through agent-spine-demo. */
  50. llmRetry?: NonNullable<agentCore.Config['llmRetry']>
  51. /** Controls automatic AGENTS.md/CLAUDE.md loading; configure a byte budget or set `false`. */
  52. workspaceContext: agentCore.Config['workspaceContext']
  53. }
  54. // Each front door keeps a complete Loader schema so its deployment contract is
  55. // readable without a cross-package config facade.
  56. /* jscpd:ignore-start */
  57. export const Config: z<Config> = z.object({
  58. provider: z.string().required(),
  59. model: z.string().required(),
  60. maxParallelToolCalls: z.number().step(1).min(1),
  61. persistenceRoot: z.string().default(DEFAULT_PERSISTENCE_ROOT),
  62. persistenceCompression: JsonlCompressionSchema,
  63. persona: z.string(),
  64. dshHome: z.string(),
  65. sessionTitle: agentCore.SessionTitleConfigSchema,
  66. skills: agentCore.SkillConfigSchema,
  67. // Absent means lexicographic order; schemastery's native array default is [].
  68. toolOrder: z.array(z.string()).default(undefined as unknown as string[]),
  69. tools: ToolRegistry.Config,
  70. toolBash: agentCore.ToolBashConfigSchema,
  71. toolTasks: z.union([z.const(false), agentCore.ToolTasksConfigSchema]),
  72. llmRetry: agentCore.LlmRetryConfigSchema,
  73. workspaceContext: z.union([z.const(false), workspaceContext.Config]).required(),
  74. })
  75. /* jscpd:ignore-end */
  76. /**
  77. * Compose the UI-less spine, a fresh top-level agent rooted at the process cwd,
  78. * and JSONL persistence. Swappable adapters, executors, and product tools stay
  79. * in the leaf `cordis.yml`.
  80. * @param ctx - app context that owns the composed child plugins.
  81. * @param config - validated app configuration.
  82. */
  83. export function apply(ctx: Context, config: Config): void {
  84. ctx.plugin(agentCore, {
  85. ...agentCore.pickSpineConfig(config),
  86. agents: [{ id: SessionId('main'), provider: config.provider, model: config.model, cwd: process.cwd() }],
  87. })
  88. ctx.plugin(SessionPersistenceJsonl, {
  89. root: config.persistenceRoot ?? DEFAULT_PERSISTENCE_ROOT,
  90. ...(config.persistenceCompression === undefined ? {} : { compression: config.persistenceCompression }),
  91. })
  92. ctx.plugin(sessionCheckpointPolicy)
  93. }