Skip to content

fix(web): tool auto-resolution + workspace-scoped ToolShed URL (on top of #91)#92

Merged
davelopez merged 9 commits into
davelopez:mainfrom
jmchilton:web_tool_resolution_fixes
Jun 19, 2026
Merged

fix(web): tool auto-resolution + workspace-scoped ToolShed URL (on top of #91)#92
davelopez merged 9 commits into
davelopez:mainfrom
jmchilton:web_tool_resolution_fixes

Conversation

@jmchilton

Copy link
Copy Markdown
Collaborator

Builds on #91 (list-form step resolution, native tool_state routing, gxformat2 connection completion). This PR = #91 + a tool-util bump and the client-side fixes that make web-mode tool resolution actually work. Until #91 merges its commits show here too; afterward this reduces to the two new commits.

What's new on top of #91

chore(deps): bump @galaxy-tool-util/* 1.8.0 → 1.8.2

1.8.2 strips in-memory-only derived fields (connected_paths, unique_tools) at serialize time, so clean/convert output no longer leaks them as stray keys that downstream schema validators reject.

fix(web): enable tool auto-resolution + workspace-scoped ToolShed URL

Two related gaps that left web-mode tool resolution non-functional:

  • (A) Browser language clients now pass toolAutoResolution, matching the node desktop clients (client/src/extension.ts). Without it the web server's autoResolutionEnabled stayed false, so opening a workflow never auto-fetched/cached its tools — no tool_state completion and a spurious "uncached tool_state" diagnostic. One-line parity fix.
  • (B) galaxyWorkflows.toolShed.url scope machinewindow so it can be set in workspace .vscode/settings.json (machine scope is user-settings-only). Lets a repo pin its ToolShed and unblocks web, where machine-scoped settings don't reach the language worker. toolCache.directory stays machine (a real filesystem path).

A and B are complementary: A arms the fetch-on-open trigger, B lets the URL reach the worker.

Not included

  • Single-client PopulateToolCacheCommand (native-only) — fix lives in web_tool_cache_wiring.
  • ToolShed CORS for browser fetch is a ToolShed-server limitation (needs a CORS-enabled shed or proxy), not addressable here.

Tests

  • Server: 456 passing. Client: 58 passing. Lint clean.
  • Manually verified in vscode-test-web: opening a .gxwf.yml now auto-resolves its tool, clears the diagnostic, and tool_state select/property-name completions work (captured for docs).

🤖 Generated with Claude Code

jmchilton and others added 5 commits June 18, 2026 12:04
… steps

- list-form `steps:` now resolve upstream outputs for source completion (b1)
- native tool_state no longer false-flags a required param satisfied only by
  an `in:` connection rather than an inline value (b3)
- bump @galaxy-tool-util/{schema,core,search} 1.7.2 -> 1.8.0
- delegate `in:`/`out:` shorthand expansion to upstream normalizeStepIn /
  normalizeStepOut (covers map-to-list multi-source); add shared getNodeValue
  AST->value helper in server-common

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
drop "gap 2" plan jargon and old-impl post-mortem from the two
format2 tool_state regression test docstrings; state the current
invariant instead

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…olve IWC test against real cat1

Two CI e2e failures, both surfaced (not caused) by list-form step
validation + native tool_state routing:

- native legacy-tool-state hint was skipped when the tool was uncached
  (cache-miss `continue` jumped past the hint). The "Clean workflow"
  quick fix re-encodes string state without the tool, so emit the hint
  regardless of cache; gate only Pass-B param validation on hasCached.
- IWC profile e2e fixture used a list-form cat1 step that, once
  validated, emitted a cache-miss under the basic profile. cat1 is
  shed-resolvable by bare id with a pinned version, so pin cat1 1.0.0,
  populate it, and reset only the profile (not the cache dir) so the
  step stays resolved. Fixture connection moved to an `in:` block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1.8.2 strips in-memory-only derived fields (connected_paths, unique_tools)
at serialize time, so clean/convert output no longer leaks them as stray
keys that downstream validators reject.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A) Browser language clients now pass toolAutoResolution, matching the node
   desktop clients. Without it the web server's autoResolutionEnabled stayed
   false, so opening a workflow never auto-fetched/cached its tools -> no
   tool_state completion and a spurious uncached-tool_state diagnostic.

B) galaxyWorkflows.toolShed.url scope machine -> window so it can be set in
   workspace .vscode/settings.json (machine scope is user-settings-only). Lets
   a repo pin its ToolShed and unblocks web where machine settings don't reach
   the worker. toolCache.directory stays machine (real filesystem path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@davelopez davelopez left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things I noticed in the base PR (#91):

  • The opening IWC workflow populates empty cache from ToolShed integration test is silently skipped or waits indefinitely (See https://github.com/davelopez/galaxy-workflows-vscode/actions/runs/27825642994/job/82349230624?pr=92#step:11:219). If I manually run pnpm run test:e2e, I can observe that when this test is running, it just waits for some seconds and then continues with the next test. But if I click the Tool cache icon in the status bar to populate the cache, then the test passes, so something is preventing the auto-cache.

    Image
  • Given this example:

    class: GalaxyWorkflow
    inputs:
      input_data:
        type: data
    outputs: {}
    steps:
      fastp_step:
        tool_id: toolshed.g2.bx.psu.edu/repos/iuc/fastp/fastp
        tool_version: 1.1.0+galaxy0
        state:
          duplicated_reads: "" <--- using a string here is not valid, but crashes instead of failing validation

    This is the error message in the stacktrace:
    Error: Container parameter "filter_options" (gx_section) has string value — expected dict/list. This indicates legacy parameter encoding which is not supported. Decode the workflow first.

Thank you so much for all the fixes and improvements. Whenever you are satisfied with the features, let me know, and we can publish a new release 🚀

jmchilton and others added 4 commits June 19, 2026 11:44
… container

A format2/native step state with a scalar where a container param
(gx_section/repeat/conditional) is expected made the schema walker throw,
crashing the whole validation pass (davelopez PR#92 review). Catch the throw
in the shared validation loop, emit an Error diagnostic at the offending
param's range, and continue so other steps still validate. Clean message
strips the native-decode jargon; unmatched errors get a generic diagnostic
rather than vanishing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The auto-cache e2e test opened the shared fixture URI directly; when that
document was already open, VS Code reused it and onDidOpen never fired, so
scheduleResolution never ran — the test silently skipped (davelopez PR#92
review). Open a fresh temp copy so onDidOpen always fires.

Hardening:
- getToolCacheStatus now reports autoResolutionEnabled; the test asserts it
  true (network-independent) so a gate regression fails loudly, not skips.
- onDidOpen no longer swallows a rejected scheduleResolution; logs instead.
- add unit test for the scheduleResolution -> populateCache wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stream fix

The schema walker's string-valued-container error is now a typed diagnostic
emitted by @galaxy-tool-util/schema itself (PR jmchilton/galaxy-tool-util-ts#144),
so the downstream try/catch + message-regex is no longer needed. Remove
runObjectStateValidationLoop's catch (back to a plain validator call) and the
STRING_CONTAINER_RE / paramNameFromContainerError / buildToolStateErrorDiagnostic
helpers + their unit tests. The native integration test now models the new
contract (validator returns the located diagnostic instead of throwing).

NOTE: requires @galaxy-tool-util/schema bump to the release containing #144
(>= 1.8.3). Against the pinned 1.8.2 the format2 integration test
"section param has a string value" stays red because 1.8.2 still throws.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1.9.0 ships the typed StringContainerError + located diagnostic
(jmchilton/galaxy-tool-util-ts#144), so the schema-aware validators now return
a diagnostic instead of throwing on a scalar-valued container param. Unblocks
the preceding workaround-removal: full server suite (460) green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jmchilton

Copy link
Copy Markdown
Collaborator Author

🤖 Posted by Claude (AI assistant) on jmchilton's behalf — not written by them personally.

Thanks David — both addressed, and the second one ended up getting fixed at the right level upstream rather than worked around here.

1. Auto-cache test silently skipping

Root cause: the test opened the shared fixture URI, but when that document was already open VS Code reused it and onDidOpen never fired — so scheduleResolution never ran and the test fell through to its offline-skip. Fixed in 4bcb75e:

  • Opens a fresh temp copy so onDidOpen always fires (matches the manual "Populate Tool Cache" path you found works).
  • Hardened the gate: getToolCacheStatus now reports autoResolutionEnabled, and the test asserts it true up front — so a gate regression fails loudly instead of masquerading as "offline". (The network-dependent part still skips when genuinely offline, which is the only remaining skip.)
  • onDidOpen no longer swallows a rejected resolution — it logs.

2. String-valued container crashing instead of failing validation

You're right that crashing was wrong. Rather than catch-and-convert in the extension, I fixed the contract violation in @galaxy-tool-util itself, since that's where the walker and the "validators return diagnostics" contract live: jmchilton/galaxy-tool-util-ts#144 (released in 1.9.0). The walker now throws a typed StringContainerError (carrying the param path + container type, mirroring the existing UnknownKeyError), and the diagnostic-returning validators map it to a located ToolStateDiagnostic instead of letting it escape. Conversion paths still throw, and the message is unchanged so the CLI/web message.includes(...) consumers keep working.

Downstream then just consumes the diagnostic: this PR bumps to 1.9.0 (ea65cb7) and removes the interim regex/try-catch workaround (cee0142). Your fastp example now surfaces a clean error on the offending param instead of crashing the pass.

Server suite 460 green, client 58 green, lint clean.

@davelopez davelopez left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it is fixed! Great, thanks!

@davelopez
davelopez merged commit 60d99c9 into davelopez:main Jun 19, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants