fix(code-mode): schema and doc fixes for tool discovery
Summary
Allows the following prompt to work occasionally with code mode in dumber LLM like gpt-5-nano
Search for web_scrape and text_editor tools. Use them to save https://httpbingo.org/get to /tmp/result.txt.
Main fixes
- read_module: schema param "module_path" → "path" to match handler
- from_mcp_tool: dereference $ref via unbinder, handle oneOf+const for enums
- Descriptions: remove JS-like syntax that confused LLM
Type of Change
- [ ] Feature
- [x] Bug fix
- [ ] Refactor / Code quality
- [ ] Performance improvement
- [ ] Documentation
- [x] Tests
- [ ] Security fix
- [ ] Build / Release
- [ ] Other (specify below)
AI Assistance
- [x] This PR was created or reviewed with AI assistance
Testing
Added a test and used the mentioned prompt successfully
$ cargo run -p goose-cli --release -- session --with-builtin code_execution,developer,computercontroller
Compiling goose v1.17.0 (/Users/codefromthecrypt/oss/goose/crates/goose)
Compiling goose-mcp v1.17.0 (/Users/codefromthecrypt/oss/goose/crates/goose-mcp)
Compiling goose-bench v1.17.0 (/Users/codefromthecrypt/oss/goose/crates/goose-bench)
Compiling goose-cli v1.17.0 (/Users/codefromthecrypt/oss/goose/crates/goose-cli)
Finished `release` profile [optimized] target(s) in 55.33s
Running `target/release/goose session --with-builtin code_execution,developer,computercontroller`
starting session | provider: tetrate model: gpt-5-nano
session id: 20251218_28
working directory: /Users/codefromthecrypt/oss/goose
goose is running! Enter your instructions, or try asking what goose can do.
Context: ○○○○○○○○○○ 0% (0/272000 tokens)
( O)> Search for web_scrape and text_editor tools. Use them to save https://httpbingo.org/get to /tmp/result.txt.
─── search_modules | code_execution ──────────────────────────
terms: web_scrape
─── search_modules | code_execution ──────────────────────────
terms: text_editor
◇ Goose would like to call the above tool, do you allow?
│ Allow
│
◇ Goose would like to call the above tool, do you allow?
│ Allow
│
─── read_module | code_execution ──────────────────────────
path: computercontroller/web_scrape
─── read_module | code_execution ──────────────────────────
path: developer/text_editor
─── read_module | code_execution ──────────────────────────
module_path: computercontroller/web_scrape
─── read_module | code_execution ──────────────────────────
module_path: developer/text_editor
─── execute_code | code_execution ──────────────────────────
code: import { web_scrape } from "computercontroller";
import { text_editor } from "developer";
const scrapeRes = web_scrape({ url: "https://httpbingo.org/get", save_as: "text" });
let contentPath = null;
if (typeo...
◇ Goose would like to call the above tool, do you allow?
│ Allow
│
## Result
- Saved to: /tmp/result.txt
- Operation was performed in a single batch execute_code call as requested.
### Content saved (snippet)
```json
{
"args": {},
"headers": {
"Accept": ["text/markdown, */*"],
"Host": ["httpbingo.org"],
"User-Agent": ["goose/1.0"],
"Via": ["2 fly.io, 2 fly.io"],
"X-Forwarded-For": ["115.135.62.233, 66.241.125.232"],
"X-Forwarded-Port": ["443"],
"X-Forwarded-Proto": ["https"],
"X-Forwarded-Ssl": ["on"],
"X-Request-Start": ["t=1766094281000630"]
},
"method": "GET",
"origin": "115.135.62.233",
"url": "https://httpbingo.org/get"
}
If you’d like, I can:
- View the full file content from /tmp/result.txt
- Save the content in another format (e.g., JSON) or at another path
- Fetch a similar URL and save to a different location for comparison
Commands to proceed:
- View: text_editor({ command: "view", path: "/tmp/result.txt" })
- Save as JSON: web_scrape({ url: "https://httpbingo.org/get", save_as: "json" }) and then write to a file
- Save to another path: text_editor({ command: "write", path: "/tmp/result_json.txt", file_text: "
" })
⏱️ Elapsed time: 2m 00s Context: ○○○○○○○○○○ 2% (4951/272000 tokens)
### Related Issues
Overlap with #6160 which fixes the schema bug differently by changing everything from path -> module_path. This chose to go the other way since module is already in the enclosing name cc @tlongwell-block
Fixes #6147
race condition.. I'll fix this back to module_path everywhere
@michaelneale on
is ok - but could be expanded to say that it can happen (I didn't know!) - anything else we are missing?
if we are keen on using the schema dep, I can add more cases to the handling besides oneOf so no bombs like other things coming up as 'any' making the llm guess what the params might be.
@codefromthecrypt sure - also that Live test failure - is that legit that it is tripping up qwen? (or can't be, as this is only code mode now?)
will take out of draft when done
@michaelneale I think we're good. I looked at the live tests and think that qwen fail earlier was just a flake. I've pushed several times to re-trigger and it hasn't failed again.
@michaelneale gonna mergeroo this one. The live provider tests are flakey this hasn't anything to do with it. In the last week ~1 in 5 times across any branch flaked.