Repository navigation
feat: Add {{fn:}}/{{ft:}}/{{attr:}} YAML language support - #23
Conversation
✅ Valid PR Title
This PR will trigger a minor release when merged to
|
There was a problem hiding this comment.
🟡 Changes recommended
False lint errors and failures in tag ranges and attribute resolution affect the new YAML support.
5 open issues
Project root detection incorrectly requires a global functions directory · New Attribute source matching fails with comments or reordered YAML keys · New Lint checks incorrectly process references inside YAML comments · New Function tag ranges start at the prefix instead of the function name · New Attribute tag ranges start at the prefix instead of the attribute name · New
What changed in this PR
Adds YAML prompt-tag language support to the Agent Studio extension and shares filesystem resolution with the standalone linter.
Changes:
- Adds hover, navigation, and lint checks for
{{fn:}},{{ft:}}, and{{attr:}}. - Separates filesystem resolution from VS Code dependencies and refreshes the extension bundle.
- Updates the VS Code test dependency, development launch configurations, and contributor documentation.
| File | Description |
|---|---|
yarn.lock |
Locks the updated test dependency. |
src/yamlLanguageFeatures.ts |
Adds YAML tag hover and link providers. |
src/test/linter.test.ts |
Tests function and attribute tag validation. |
src/pythonFunctionResolver.ts |
Delegates filesystem operations to the shared resolver. |
src/linter/rules/yamlRules.ts |
Adds unresolved-tag diagnostics. |
src/linter/rules/pythonRules.ts |
Removes the unused VS Code-dependent import. |
src/functionPathResolver.ts |
Introduces shared function and attribute resolution. |
src/extension.ts |
Registers and disposes YAML providers. |
package.json |
Upgrades @vscode/test-electron. |
node_modules/@vscode/test-electron/vitest.config.ts |
Updates dependency test timeouts. |
node_modules/@vscode/test-electron/pipeline.yml |
Updates dependency CI to Node 22. |
node_modules/@vscode/test-electron/package.json |
Records dependency version and runtime requirements. |
node_modules/@vscode/test-electron/out/util.js |
Updates executable and download metadata resolution. |
node_modules/@vscode/test-electron/out/util.d.ts |
Updates utility declarations. |
node_modules/@vscode/test-electron/out/runTest.js |
Updates test launching and output forwarding. |
node_modules/@vscode/test-electron/out/runTest.d.ts |
Declares configurable output streams. |
node_modules/@vscode/test-electron/out/request.js |
Refreshes generated import helpers. |
node_modules/@vscode/test-electron/out/progress.js |
Reports downloaded commit identifiers. |
node_modules/@vscode/test-electron/out/progress.d.ts |
Adds commit metadata to progress reports. |
node_modules/@vscode/test-electron/out/download.test.mjs |
Updates dependency download tests. |
node_modules/@vscode/test-electron/out/download.js |
Updates download error handling and metadata reporting. |
node_modules/@vscode/test-electron/.editorconfig |
Removes the dependency’s bundled editor configuration. |
node_modules/.yarn-integrity |
Refreshes dependency installation metadata. |
dist/extension.js |
Refreshes the packaged extension with language features. |
CONTRIBUTING.md |
Documents local execution, debugging, and testing. |
.vscode/launch.json |
Adds development-host defaults and a debugging alternative. |
Review effort: Balanced
There was a problem hiding this comment.
🟡 Changes recommended
The dependency upgrade conflicts with CI’s Node version, and attribute-location scanning mishandles valid YAML comments and nested value text.
4 open issues
5 resolved since last review
Attribute tag ranges start at the prefix instead of the attribute name Function tag ranges start at the prefix instead of the function name Lint checks incorrectly process references inside YAML comments Attribute source matching fails with comments or reordered YAML keys Project root detection incorrectly requires a global functions directory
Review effort: Balanced
There was a problem hiding this comment.
🟡 Changes recommended
Attribute indexing can miss valid definitions or direct hover and navigation to literal prompt text.
3 open issues
Flow-style mappings inside a block sequence are never indexed. For example,attributes:followed… · New A dash-only line nested inside an attribute value resets the enclosing entry's key indentation. For… · New The flow-style fallback indexesname:text inside scalar values as attribute definitions. In a… · New
2 resolved since last review
Review effort: Balanced
sophyphile
left a comment
There was a problem hiding this comment.
provided some comments. would fix the # one before merge since it's small, the other two can be follow-ups.
since we want to point customers at this and the repo is public, we should probably stop committing node_modules/ and dist/ too. they've been tracked by accident since the initial commit (the .gitignore already ignores both), and they aren't what ships, since the release job rebuilds from a clean install. but they're ~29k of the 30.5k lines in this pr, which buries the real changes.
not on you, we should remove them in a separate pr after this lands.
…tr:}} YAML tags
Adds language support for Agent Studio prompt-template tags in step/topic YAML
files, mirroring the existing conv.functions/flow.functions Python support:
- {{fn:X}} -> global function (functions/X.py)
- {{ft:X}} -> flow-local function (flows/<flow>/functions/X.py)
- {{attr:X}} -> variant attribute (config/variant_attributes.yaml)
Each gets a hover tooltip, Cmd/Ctrl-click navigation, and a lint rule
(invalid-function-tag, invalid-attr-tag) flagging references that don't
resolve.
Also fixes a pre-existing bug where the standalone `adk-lint` CLI bundle
(dist/adk-lint.js) failed to compile, because a dead import in pythonRules.ts
pulled the `vscode` module into its dependency graph, which doesn't exist
outside the extension host. Pure filesystem resolution logic is now split
into src/functionPathResolver.ts (no vscode dependency), shared by both the
extension and the CLI.
Other changes:
- Bump @vscode/test-electron to 3.1.0 (2.5.2 can't launch VS Code 1.110+,
which renamed its macOS executable from Electron to Code).
- .vscode/launch.json: open agent-deployments/agents by default, disable the
marketplace-installed copy of this extension in the dev host, and default
to noDebug (the Node inspector attach was flaky and could leave the host
permanently paused on line 1 with nothing to resume it).
- Add CONTRIBUTING.md documenting all of the above.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- findVariantAttributesPath no longer requires a global functions/
directory (was reusing findProjectRoot, which does); it now walks up
independently looking for config/variant_attributes.yaml, so projects
with only flow-scoped functions still get {{attr:}} resolution.
- resolveVariantAttributeLocation now locates a `name:` key anywhere
within an attributes list entry (not just as the first key), and
tolerates a trailing comment — both previously caused valid attributes
to resolve for linting but silently return no hover/navigation.
- invalid-function-tag / invalid-attr-tag now skip full-line YAML
comments, so commented-out references no longer produce diagnostics.
- Fixed name-range calculation in yamlLanguageFeatures.ts for both
providers: it searched for the name text within the matched tag,
which could match inside the tag's own prefix when the name shared
characters with it (e.g. {{fn:n}}, {{attr:attr}}), producing a
link/hover range over the prefix instead of the name.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- build.yml: bump CI Node to 22, matching release.yml and the engines
requirement of @vscode/test-electron 3.1.0 (>=22) — yarn's engine
check would otherwise reject the install under Node 20.
- resolveVariantAttributeLocation:
- allow a trailing comment on the `attributes:` section header
(e.g. `attributes: # project attributes`)
- skip full-line comments between entries instead of treating them
as a dedent that ends the search
- restrict name: matches to direct keys of the current entry's
mapping (by tracking each entry's key indent), so literal "name:"
text inside a sibling entry's block-scalar value can no longer be
mistaken for a real attribute definition
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Handle two more valid variant_attributes.yaml forms that the block-
style walker couldn't locate (though they parsed fine for lint
purposes via js-yaml): a dash-only list entry (`-` alone, with its
keys indented on following lines) and a flow-style inline sequence
(`attributes: [{name: x, ...}]`), the latter via a best-effort loose
fallback scan since it isn't block-style YAML.
- Replaced the per-reference resolveVariantAttributeLocation calls in
YamlAttrLinkProvider with a single buildVariantAttributeIndex call
per document: previously every {{attr:X}} occurrence independently
re-walked the project directory, re-read, and re-parsed
config/variant_attributes.yaml, repeating O(file size) work per tag.
Now the index (name -> location) is built once and reused for every
tag in the document. resolveVariantAttributeLocation is now a thin
wrapper around the same index for the single-lookup hover case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The hand-rolled line/indentation-based scanner for config/variant_attributes.yaml kept accumulating edge cases across review rounds (comments, reordered keys, dash-only entries, flow-style mappings, block-scalar content that happens to contain "name:"-shaped text) because it was reimplementing YAML parsing by hand. Replaced it with the `yaml` package (source-position aware), which handles every valid form correctly by construction — block scalars are opaque strings to a real parser, so literal text inside them can never be mistaken for structure, and flow-style/dash-only entries parse the same as any other valid YAML. findVariantAttributeNames now just reads the keys of the same index, so there's a single parse path (previously js-yaml for existence-checking and a separate regex walk for position-finding, which could in principle diverge). Adds the `yaml` dependency (zero transitive deps). Added 3 regression tests for the specific forms called out in review: an inline flow-style mapping inside a block sequence, a block-scalar value containing literal dash-prefixed "name:" text, and a flow-style list where an earlier scalar value contains the text of a later attribute's name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
prompt: |- blocks commonly use markdown headings (## ...), which the
linter's isFullLineComment check mistook for commented-out config,
silently skipping {{fn:}}/{{ft:}}/{{attr:}} validation on those lines.
Use the yaml package's parsed ranges to detect real block scalars and
only suppress the comment skip within them.
Also note in CONTRIBUTING.md that .vscode/launch.json assumes
agent-deployments is checked out as a sibling directory.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7bc4cb9 to
3327398
Compare
ATTR_TAG_PATTERN used \w+, which silently skipped names like
site-name in linting, hover, and navigation, even though the
prompt renderer already accepts them via {{attr:([^}]+)}}.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nces" This reverts commit d4eccbc. Attribute names can't contain hyphens: the ADK's _validate_attribute_name (poly/resources/variant_attributes.py) rejects any name that isn't a valid Python identifier on push, and none of the 10,048 attribute names across agent-deployments have one. The [^}]+ pattern d4eccbc copied from the prompt renderer governs the flow viewer's badge styling, not name validation, so widening the linter's pattern to match it doesn't catch any real hyphenated names -- it just stops flagging config/variant_attributes.yaml ids that haven't been translated on pull, which the ADK currently leaves as raw UUIDs in VARIANT_ATTRIBUTES-<uuid> form instead of resolving to the live attribute name. Catching those untranslated ids properly is a separate follow-up. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Attribute names can't contain hyphens — |
dist/ is already gitignored and rebuilt by CI (yarn compile/package), so these shouldn't be committed.


Summary
{{fn:X}}→ global function (functions/X.py){{ft:X}}→ flow-local function (flows/<flow>/functions/X.py){{attr:X}}→ variant attribute (config/variant_attributes.yaml)invalid-function-tag,invalid-attr-tag.adk-lintCLI bundle (dist/adk-lint.js) failed to compile — a dead import inpythonRules.tswas pulling thevscodemodule into its dependency graph, which doesn't exist outside the extension host. Pure filesystem resolution logic is now split intosrc/functionPathResolver.ts(novscodedependency), shared by both the extension and the CLI.@vscode/test-electronto3.1.0(2.5.2can't launch VS Code 1.110+, which renamed its macOS executable fromElectrontoCode)..vscode/launch.json: opensagent-deployments/agentsby default, disables the marketplace-installed copy of this extension in the dev host, and defaults tonoDebug(the Node inspector attach handshake was flaky and could leave the host permanently paused on line 1).CONTRIBUTING.mddocumenting all of the above.Test plan
tsc --noEmitcleaneslint— 0 errors (only pre-existing warnings)yarn test— 98/98 passing, including new tests forinvalid-function-tag/invalid-attr-tagextension.js,adk-lint.js) compile with 0 errorsnode dist/adk-lint.jsruns standalone without crashing🤖 Generated with Claude Code