loader-composition.spec.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { mkdtemp, rm, writeFile } from 'node:fs/promises'
  2. import { tmpdir } from 'node:os'
  3. import { join } from 'node:path'
  4. import { pathToFileURL } from 'node:url'
  5. import { Context } from '@deepseek-ai/cordis'
  6. import Include from '@deepseek-ai/cordis-plugin-include'
  7. import Loader from '@deepseek-ai/cordis-plugin-loader'
  8. import { afterEach, describe, expect, it } from 'vitest'
  9. import WebhookRuntime, {
  10. WebhookDeliveryId,
  11. WebhookRuleId,
  12. WebhookSourceId,
  13. } from '../src/index.ts'
  14. let root: string | undefined
  15. let context: Context | undefined
  16. afterEach(async () => {
  17. await context?.fiber.dispose()
  18. context = undefined
  19. if (root !== undefined) await rm(root, { recursive: true, force: true })
  20. root = undefined
  21. })
  22. describe('real Loader composition', () => {
  23. it('loads the default Service export and an effect-scoped rule', { timeout: 60_000 }, async () => {
  24. root = await mkdtemp(join(tmpdir(), 'dsh-webhook-loader-'))
  25. const configPath = join(root, 'cordis.yml')
  26. await writeFile(configPath, [
  27. '- name: fixture-dependencies',
  28. "- name: '@deepseek-ai/dsh-webhook'",
  29. '- name: fixture-rule',
  30. '',
  31. ].join('\n'))
  32. const called = Promise.withResolvers<boolean>()
  33. const dependencies = {
  34. name: 'fixture-dependencies',
  35. apply(ctx: Context) {
  36. for (const service of [
  37. 'agents', 'agentDefaultModel', 'agentPresets', 'permissionPresets', 'sessionTitle', 'workspaceRegistry',
  38. ]) {
  39. ctx.provide(service as never, {} as never)
  40. }
  41. },
  42. }
  43. const rule = {
  44. name: 'fixture-rule',
  45. inject: ['webhookRuntime'],
  46. apply(ctx: Context) {
  47. ctx.webhookRuntime.register({
  48. id: WebhookRuleId('loader-rule'),
  49. kind: 'fixture',
  50. run() {
  51. called.resolve(true)
  52. return null
  53. },
  54. })
  55. },
  56. }
  57. context = new Context()
  58. context.baseUrl = pathToFileURL(root).href + '/'
  59. await context.plugin(Loader)
  60. context.loader.builtins.include = Include
  61. const modules = new Map<string, unknown>([
  62. ['fixture-dependencies', dependencies],
  63. ['@deepseek-ai/dsh-webhook', WebhookRuntime],
  64. ['fixture-rule', rule],
  65. ])
  66. context.loader.internal = {
  67. version: 'v2',
  68. async import(specifier: string) {
  69. if (!modules.has(specifier)) throw new Error(`unexpected Loader import: ${specifier}`)
  70. return modules.get(specifier)
  71. },
  72. } as unknown as NonNullable<typeof context.loader.internal>
  73. await context.loader.create({
  74. name: 'cordis:include',
  75. config: { path: pathToFileURL(configPath).href },
  76. })
  77. await context.loader.await()
  78. expect([...context.loader.entries()].filter(entry => entry.fiber === undefined && !entry.disabled)).toEqual([])
  79. context.webhookRuntime.dispatch({
  80. kind: 'fixture',
  81. source: WebhookSourceId('loader'),
  82. deliveryId: WebhookDeliveryId('loader-delivery'),
  83. event: {},
  84. receivedAt: 1,
  85. })
  86. await called.promise
  87. })
  88. })