loader.spec.ts 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /**
  2. * REAL-composition tier (packages/AGENTS.md): boot the examples-owned
  3. * tool-pwsh Loader fixture as a subprocess through the same app/boot path a
  4. * deployment uses, execute real foreground and background pwsh commands
  5. * through the tool registry, and assert the assembled model-visible surface:
  6. * schema, prompt section, and rendered results. Self-skips when no `pwsh`
  7. * executable exists (a CI accommodation for hosts without PowerShell).
  8. */
  9. import { readFile } from 'node:fs/promises'
  10. import { join } from 'node:path'
  11. import { fileURLToPath } from 'node:url'
  12. import { spawnSync } from 'node:child_process'
  13. import { describe, expect, it } from 'vitest'
  14. import { runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
  15. import { resolvePwshPath } from '@deepseek-ai/dsh-pwsh-local'
  16. // The probe follows the executor's own resolution (Program Files installs on
  17. // Windows are found even when bare `pwsh` is not on PATH).
  18. const hasPwsh = spawnSync(resolvePwshPath(), ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', '$true'], { encoding: 'utf8' }).status === 0
  19. const driver = fileURLToPath(new URL(
  20. './fixtures/loader/driver.ts',
  21. import.meta.url,
  22. ))
  23. const configPath = fileURLToPath(new URL(
  24. './fixtures/loader/cordis.yml',
  25. import.meta.url,
  26. ))
  27. const repoTsconfig = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))
  28. interface PwshLoaderReport {
  29. schemaHasRunInBackground: boolean
  30. promptHasMarkerSection: boolean
  31. foregroundText: string
  32. backgroundText: string
  33. }
  34. describe.skipIf(!hasPwsh)('tool-pwsh through a real Loader composition', () => {
  35. // Self-hosted Windows runners reach ~40s for this smoke under the full
  36. // coverage load (measured on the 192-thread CI pool), against the
  37. // 30s default process deadline. Give the subprocess headroom so the
  38. // assembled boot completes instead of being SIGKILLed mid-load.
  39. const processTimeoutMs = 90_000
  40. it('registers the pwsh surface and renders real foreground and background results', async () => {
  41. let report: PwshLoaderReport | undefined
  42. const { stderr } = await runLoaderSmoke({
  43. label: 'tool-pwsh loader smoke',
  44. tempDirPrefix: 'tool-pwsh-loader-',
  45. binScript: driver,
  46. libBinScript: driver,
  47. configPath,
  48. tsconfigPath: repoTsconfig,
  49. processTimeoutMs,
  50. inspect: async (cwd) => {
  51. report = JSON.parse(await readFile(join(cwd, 'pwsh-loader-report.json'), 'utf8')) as PwshLoaderReport
  52. },
  53. })
  54. expect(stderr).not.toContain('UNHANDLED')
  55. expect(report).toBeDefined()
  56. expect(report).toMatchObject({
  57. schemaHasRunInBackground: true,
  58. promptHasMarkerSection: true,
  59. })
  60. expect(report?.foregroundText).toBe('loader-ok\n')
  61. expect(report?.backgroundText).toContain('loader-bg-ok')
  62. expect(report?.backgroundText).toContain('[status: completed, exit code: 0]')
  63. // 15s of vitest headroom past the subprocess deadline, mirroring
  64. // LOADER_SMOKE_TEST_TIMEOUT_MS's margin over its process window.
  65. }, processTimeoutMs + 15_000)
  66. })