profile-continuation.worker.ts 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /** End-to-end SDK continuation through built dsh sdk-minimal with an explicitly mounted file editor. */
  2. import { mkdir, writeFile } from 'node:fs/promises'
  3. import { join } from 'node:path'
  4. import { performance } from 'node:perf_hooks'
  5. import { DeepSeekHarness } from '@deepseek-ai/dsh-sdk-client'
  6. import { assertBuiltBenchmarkRuntime } from '../support/built-worker.ts'
  7. import { PARENT_ID, resultText, WORKLOAD } from './workload.ts'
  8. /** Parent-observed wall time, including profile launch and SDK shutdown. */
  9. export interface ProfileReport {
  10. readonly totalMs: number
  11. readonly bootMs: number
  12. readonly turnsMs: number
  13. readonly closeMs: number
  14. readonly requests: number
  15. readonly toolCalls: number
  16. }
  17. async function run(root: string): Promise<ProfileReport> {
  18. const home = join(root, 'home')
  19. const cwd = join(root, 'workspace')
  20. await mkdir(cwd, { recursive: true })
  21. await mkdir(home, { recursive: true })
  22. await writeFile(join(cwd, 'synthetic.txt'), resultText(0))
  23. const patch = join(root, 'profile.patch.yml')
  24. await writeFile(patch, [
  25. '- id: llm-deepseek', ' disabled: true',
  26. '- id: sessions', ' config:', ' root: ' + JSON.stringify(join(root, 'profile-sessions')), ' compression: zstd',
  27. '- insert:',
  28. ' - id: fs-local', " name: '@deepseek-ai/dsh-fs-local'",
  29. ' - id: str-replace-editor', " name: '@deepseek-ai/dsh-tool-str-replace-editor'",
  30. ' - id: benchmark-model', ' name: ' + JSON.stringify(join(import.meta.dirname, 'profile-adapter.js')),
  31. '',
  32. ].join('\n'))
  33. const env: NodeJS.ProcessEnv = {
  34. PATH: process.env.PATH, HOME: home, USERPROFILE: home,
  35. DSH_AGENTS_HOME: join(home, 'agents'),
  36. }
  37. const harness = new DeepSeekHarness({
  38. dshBin: join(import.meta.dirname, '..', '..', '..', 'apps', 'cli', 'lib', 'bin.js'),
  39. profile: 'sdk-minimal', dshHome: home, processCwd: cwd, cwd,
  40. provider: 'bench', model: 'bench', patches: [patch], env,
  41. initializeTimeoutMs: 15_000, requestTimeoutMs: 15_000,
  42. })
  43. let closing: Promise<void> | undefined
  44. const close = (): Promise<void> => closing ??= harness.close()
  45. let expired = false
  46. const deadline = setTimeout(() => {
  47. expired = true
  48. // The awaited finally close below reports shutdown failures; this only requests cancellation.
  49. void close().catch(() => undefined)
  50. }, 40_000)
  51. let requests = 0
  52. let toolCalls = 0
  53. const start = performance.now()
  54. try {
  55. await harness.start()
  56. const booted = performance.now()
  57. for (let turn = 0; turn < WORKLOAD.profileTurns; turn++) {
  58. const result = await harness.run('Read the synthetic file ' + String(turn), { sessionId: PARENT_ID })
  59. requests += result.events.filter(event => event.type === 'assistant/message').length
  60. for (const event of result.events) {
  61. if (event.type !== 'tool/result') continue
  62. const result = event.data.message.content[0]
  63. if (result.isError || !result.content.some(block => block.type === 'text' && block.text.includes('export const synthetic = 42;'))) {
  64. throw new Error('profile benchmark did not read the synthetic file')
  65. }
  66. toolCalls++
  67. }
  68. }
  69. const turnsDone = performance.now()
  70. await close()
  71. const end = performance.now()
  72. if (expired || requests !== WORKLOAD.profileTurns * 2 || toolCalls !== WORKLOAD.profileTurns * WORKLOAD.toolsPerLiveTurn) {
  73. throw new Error('profile benchmark did not finish every model request and real tool call')
  74. }
  75. return { totalMs: end - start, bootMs: booted - start, turnsMs: turnsDone - booted, closeMs: end - turnsDone, requests, toolCalls }
  76. } finally {
  77. clearTimeout(deadline)
  78. await close()
  79. }
  80. }
  81. assertBuiltBenchmarkRuntime(import.meta.url, { '@deepseek-ai/dsh-sdk-client': import.meta.resolve('@deepseek-ai/dsh-sdk-client') })
  82. const [root] = process.argv.slice(2)
  83. if (root === undefined) throw new Error('usage: profile-continuation.worker.js <root>')
  84. process.stdout.write(JSON.stringify(await run(root)) + '\n')