builtins.test.ts 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { describe, expect } from "bun:test"
  2. import { Effect, Layer } from "effect"
  3. import * as TestClock from "effect/testing/TestClock"
  4. import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
  5. import { Location } from "@opencode-ai/core/location"
  6. import { FSUtil } from "@opencode-ai/core/fs-util"
  7. import { Global } from "@opencode-ai/core/global"
  8. import { AbsolutePath } from "@opencode-ai/core/schema"
  9. import { InstructionBuiltIns } from "@opencode-ai/core/instructions/builtins"
  10. import { location } from "../fixture/location"
  11. import { testEffect } from "../lib/effect"
  12. import { readInitial, readUpdate } from "../lib/instructions"
  13. const directory = AbsolutePath.make(FSUtil.resolve("/repo/packages/core"))
  14. const projectDirectory = AbsolutePath.make(FSUtil.resolve("/repo"))
  15. const timestamp = Date.parse("2026-06-03T12:00:00.000Z")
  16. const localDate = (time: number) => new Date(time).toDateString()
  17. const locationLayer = Layer.succeed(
  18. Location.Service,
  19. Location.Service.of(
  20. location(
  21. { directory },
  22. { projectDirectory, vcs: { type: "git", store: AbsolutePath.make(FSUtil.resolve("/repo/.git")) } },
  23. ),
  24. ),
  25. )
  26. const it = testEffect(
  27. AppNodeBuilder.build(InstructionBuiltIns.node, [
  28. [Location.node, locationLayer],
  29. [Global.node, Global.layerWith({ config: "/global" })],
  30. ]),
  31. )
  32. describe("InstructionBuiltIns", () => {
  33. it.effect("loads location-scoped environment and host-local date instructions", () =>
  34. Effect.gen(function* () {
  35. yield* TestClock.setTime(timestamp)
  36. const context = yield* InstructionBuiltIns.Service
  37. const initialized = yield* readInitial(yield* context.load())
  38. expect(initialized.text).toBe(
  39. [
  40. "Here is some useful information about the environment you are running in:",
  41. "<env>",
  42. ` Working directory: ${directory}`,
  43. ` Workspace root folder: ${projectDirectory}`,
  44. " Is directory a git repo: yes",
  45. ` Platform: ${process.platform}`,
  46. "</env>",
  47. "",
  48. `Today's date: ${localDate(timestamp)}`,
  49. ].join("\n"),
  50. )
  51. }),
  52. )
  53. it.effect("updates the date without repeating unchanged environment instructions", () =>
  54. Effect.gen(function* () {
  55. yield* TestClock.setTime(timestamp)
  56. const context = yield* InstructionBuiltIns.Service
  57. const initialized = yield* readInitial(yield* context.load())
  58. yield* TestClock.setTime(timestamp + 24 * 60 * 60 * 1000)
  59. const refreshed = yield* readUpdate(yield* context.load(), initialized)
  60. expect(refreshed.text).toBe(`Today's date is now: ${localDate(timestamp + 24 * 60 * 60 * 1000)}`)
  61. }),
  62. )
  63. it.effect("does not update again within the same local calendar day", () =>
  64. Effect.gen(function* () {
  65. yield* TestClock.setTime(timestamp)
  66. const context = yield* InstructionBuiltIns.Service
  67. const initialized = yield* readInitial(yield* context.load())
  68. yield* TestClock.setTime(timestamp + 60 * 60 * 1000)
  69. expect((yield* readUpdate(yield* context.load(), initialized)).changed).toBe(false)
  70. }),
  71. )
  72. })