core-web-profile.snapshot.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { writeFile } from 'node:fs/promises'
  2. import { join } from 'node:path'
  3. import { fileURLToPath } from 'node:url'
  4. import { afterAll, beforeAll, describe, expect, it } from 'vitest'
  5. import type { AgentHandle } from '@deepseek-ai/dsh-agent'
  6. import { CallId } from '@deepseek-ai/dsh-llm'
  7. import { SessionId } from '@deepseek-ai/dsh-session'
  8. import { launchWebScaffold, type WebScaffold } from './scaffold.ts'
  9. const CORE_WEB_OVERLAY = fileURLToPath(new URL('../../cli/config/core-web.cordis.yml', import.meta.url))
  10. describe('core Web profile', () => {
  11. let scaffold: WebScaffold
  12. let agentHandle: AgentHandle
  13. beforeAll(async () => {
  14. scaffold = await launchWebScaffold({
  15. extraOverlayPath: CORE_WEB_OVERLAY,
  16. toolsMode: 'native',
  17. })
  18. agentHandle = await scaffold.ctx.agents.create({
  19. sessionId: SessionId('core-web-profile-smoke'),
  20. meta: { cwd: scaffold.workspaceCwd },
  21. agentOptions: { provider: 'deepseek-official', model: 'deepseek-v4-flash' },
  22. })
  23. })
  24. afterAll(async () => {
  25. const failures: unknown[] = []
  26. await agentHandle?.dispose().catch((error: unknown) => failures.push(error))
  27. await scaffold?.close().catch((error: unknown) => failures.push(error))
  28. if (failures.length === 1) throw failures[0]
  29. if (failures.length > 1) throw new AggregateError(failures, 'core Web profile smoke teardown failed')
  30. })
  31. it('boots and executes both tools through the shipped Web composition', async () => {
  32. const seedPath = join(scaffold.workspaceCwd, 'profile-smoke.txt')
  33. await writeFile(seedPath, 'CORE_WEB_EDITOR_OK\n')
  34. const signal = new AbortController().signal
  35. const bash = await scaffold.ctx.tools.execute({
  36. signal,
  37. callId: CallId('core-web-bash-smoke'),
  38. name: 'bash',
  39. arguments: { command: "printf 'CORE_WEB_BASH_OK\\n'" },
  40. agent: agentHandle.agent,
  41. })
  42. const editor = await scaffold.ctx.tools.execute({
  43. signal,
  44. callId: CallId('core-web-editor-smoke'),
  45. name: 'str_replace_editor',
  46. arguments: { command: 'view', path: seedPath },
  47. agent: agentHandle.agent,
  48. })
  49. const text = (result: typeof bash): string => result.content
  50. .filter(block => block.type === 'text')
  51. .map(block => block.text)
  52. .join('')
  53. .replaceAll(scaffold.workspaceCwd, '{{cwd}}')
  54. .trimEnd()
  55. expect({
  56. tools: scaffold.ctx.tools.schemas().map(tool => tool.name),
  57. bash: text(bash),
  58. editor: text(editor),
  59. }).toMatchInlineSnapshot(`
  60. {
  61. "bash": "CORE_WEB_BASH_OK",
  62. "editor": "Here's the content of {{cwd}}/profile-smoke.txt with line numbers (which has a total of 2 lines):
  63. 1 CORE_WEB_EDITOR_OK
  64. 2",
  65. "tools": [
  66. "bash",
  67. "str_replace_editor",
  68. ],
  69. }
  70. `)
  71. const entries = [...scaffold.ctx.loader.entries()]
  72. expect(entries.find(entry => entry.options.id === 'persistent-bash')?.fiber).toBeDefined()
  73. expect(entries.find(entry => entry.options.id === 'pty-local')?.fiber).toBeDefined()
  74. expect(entries.find(entry => entry.options.id === 'str-replace-editor')?.fiber).toBeDefined()
  75. })
  76. })