instructions.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { Effect, Option, Schema } from "effect"
  2. import { Instructions } from "@opencode-ai/core/instructions"
  3. export interface State {
  4. readonly values: Readonly<Record<string, Schema.Json>>
  5. }
  6. export const state = (values: Readonly<Record<string, Schema.Json>>): State => ({ values })
  7. const hashes = (values: Readonly<Record<string, Schema.Json>>): Instructions.Values =>
  8. Object.fromEntries(Object.entries(values).map(([key, value]) => [key, Instructions.hash(value)]))
  9. export const readInitial = (instructions: Instructions.List) =>
  10. Effect.gen(function* () {
  11. const admission = yield* Instructions.read(instructions).pipe(Effect.flatMap(Instructions.diff))
  12. const current = state(
  13. Object.fromEntries(
  14. Object.entries(admission.delta).flatMap(([key, hash]) =>
  15. hash === "removed" ? [] : [[key, admission.blobs[hash]]],
  16. ),
  17. ),
  18. )
  19. return { ...current, text: Instructions.renderInitial(instructions, current.values) }
  20. })
  21. export const readUpdate = (instructions: Instructions.List, previous: State) =>
  22. Effect.gen(function* () {
  23. const admission = yield* Instructions.read(instructions).pipe(
  24. Effect.flatMap((observed) => Instructions.diff(observed, hashes(previous.values))),
  25. )
  26. const delta = Object.fromEntries(
  27. Object.entries(admission.delta).map(([key, hash]) => [
  28. key,
  29. hash === "removed" ? Option.none() : Option.some(admission.blobs[hash]),
  30. ]),
  31. ) as Readonly<Record<string, Option.Option<Schema.Json>>>
  32. const values = Instructions.applyDelta(previous.values, delta)
  33. return {
  34. values,
  35. text: Instructions.renderUpdate(instructions, previous.values, delta),
  36. changed: Object.keys(admission.delta).length > 0,
  37. }
  38. })