Skip to content

Consolidate on the yaml library and retire js-yaml #734

Description

@williamthorsen

Problem

The repo depends on two YAML libraries: js-yaml (4.2.0) and yaml (2.9.0, the eemeli/yaml library). Newer code uses yaml; older modules and some tests still use js-yaml. Carrying two libraries for one job adds dependency surface, splits idioms, and forces contributors to know which one to reach for.

Context

packages/kb is exclusively on yaml and relies on its richer API (parseDocument, isMap/isPair/isScalar/isSeq, CST position tracking), so reverting to js-yaml is not viable. The migration toward yaml is already organically underway: every recently written module uses it. The @eemeli/yaml name (the library's pre-1.0 scoped publication) is unpublished and now 404s on npm; the canonical package is the unscoped yaml.

Remaining js-yaml usage (verified against the branch):

  • Source: packages/agents/src/lib/frontmatter-merger.ts, packages/agents/src/lib/tool-name-rewriter.ts, packages/run-core/src/resolve-base-dir.ts
  • Tests: packages/agents/src/commands/__tests__/install.test.ts, packages/agents/src/lib/__tests__/preferences-schema.test.ts
  • Comments that name js-yaml (no longer accurate after the swap): frontmatter-merger.ts, preferences-schema.test.ts, resolve-base-dir.test.ts

Every call site uses yaml.load only — there are no yaml.dump call sites in scope.

Dependency state differs per package:

  • packages/agents already declares yaml@2.9.0 → removal-only (drop js-yaml, @types/js-yaml).
  • packages/run-core declares only js-yaml → must add yaml@2.9.0 and drop js-yaml, @types/js-yaml.

The swap is behavior-preserving here (verified empirically): js-yaml 4.x already parses with YAML 1.2 core-schema semantics, matching yaml; the undefined-vs-null empty-input difference is absorbed by the isRecord() guard at every call site; and the malformed-input catch in resolve-base-dir.ts is error-type-agnostic, so the YAMLExceptionYAMLParseError change is invisible.

Proposed solution

Replace each yaml.load(x) with yaml's parse(x), using the named-import idiom already established in packages/agents (import { parse as parseYaml } from 'yaml'). Add yaml@2.9.0 to packages/run-core, which currently lacks it; packages/agents already declares it. Remove js-yaml and @types/js-yaml from both package.json files once no imports remain. Refresh the three comments that name js-yaml so they describe the yaml API (or drop the reference). No stringify/dump work is required — no such call sites exist. Confirm the full suite passes.

Acceptance criteria

Must have

  • No js-yaml imports remain anywhere in the repo (source or tests).
  • js-yaml and @types/js-yaml are removed from every package.json.
  • yaml is declared as a dependency of every package that imports it (run-core gains yaml@2.9.0; agents already declares it).
  • Each migrated call site preserves existing parse behavior, including empty-input and malformed-input handling.
  • Comments and test fixtures no longer reference js-yaml where the code no longer uses it.
  • Behavior at migrated call sites stays covered by existing or added tests, and the full test suite passes.

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions