composition-echo-llm.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import type { Context } from 'cordis'
  2. import type {
  3. GenerateOptions,
  4. LlmModelInfo,
  5. LlmResolvedModelInfo,
  6. StreamChunk,
  7. } from '@deepseek-ai/dsh-llm'
  8. import { LlmAdapter } from '@deepseek-ai/dsh-llm'
  9. /** Terminal marker the preset smoke waits for before it asks the TUI to exit. */
  10. export const COMPOSITION_REPLY_TEXT = 'Shipped composition acknowledged.'
  11. // Provider id and model the keyless tail routes `main` to; that overlay is the
  12. // only caller, so the pair lives here as plain constants.
  13. const COMPOSITION_PROVIDER = 'composition-keyless'
  14. const COMPOSITION_MODEL = 'composition-keyless-model'
  15. /**
  16. * Network-free adapter for the shipped-composition smoke. It answers every
  17. * request — tool-ful agent turns and the tool-less auxiliary calls alike — with
  18. * one fixed text and never calls a tool, because the assertion under test is the
  19. * assembled tool catalog the loop logs, not any tool's behavior.
  20. */
  21. class CompositionEchoAdapter extends LlmAdapter {
  22. override listModels(provider: string): Promise<readonly LlmModelInfo[]> {
  23. return Promise.resolve([{ provider, id: COMPOSITION_MODEL, name: 'Preset Keyless' }])
  24. }
  25. override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
  26. return Promise.resolve({ provider, id: model, name: 'Preset Keyless', context: { contextWindow: 128_000 } })
  27. }
  28. override async * stream(_options: GenerateOptions): AsyncIterable<StreamChunk> {
  29. yield { type: 'block-start', index: 0, blockType: 'text' }
  30. for (const char of COMPOSITION_REPLY_TEXT) yield { type: 'text-delta', index: 0, text: char }
  31. yield { type: 'block-end', index: 0, block: { type: 'text', text: COMPOSITION_REPLY_TEXT } }
  32. yield { type: 'usage', usage: { inputTokens: 20, outputTokens: COMPOSITION_REPLY_TEXT.length } }
  33. yield { type: 'finish', reason: { kind: 'stop' } }
  34. }
  35. }
  36. export const name = 'composition-echo-llm'
  37. export const inject = ['llm']
  38. /**
  39. * Register the network-free adapter the shipped-composition smoke routes through.
  40. * @param ctx - the loader-mounted plugin context.
  41. */
  42. export function apply(ctx: Context): void {
  43. ctx.llm.registerAdapter([COMPOSITION_PROVIDER], new CompositionEchoAdapter())
  44. }