fix: local Ollama serves web tools on a different path
This commit is contained in:
@@ -204,6 +204,10 @@ This extension does not use GPS. That would mean CoreLocation on macOS, which ha
|
||||
|
||||
Web search results and fetched pages can be large. Lam truncates them before they reach the model.
|
||||
|
||||
**The web tools use a different path per host, and there is no path that works for both.** Ollama Cloud serves `/api/web_search` and `/api/web_fetch`; a local daemon serves the same operations under `/api/experimental/`. Both were probed directly: the cloud route answers `401` without a key, which means it exists, and its experimental alias is a `404`; a local 0.35.1 does the exact opposite. This was a live bug, because the extension posted to the cloud path on every host, so pointing it at a local server turned every web call into a 404 and the model, handed a failure and no explanation, told the user its web tools were not configured. The other path is now tried when the first answers 404, since that means the route is absent rather than the request being refused.
|
||||
|
||||
**Lam is told what it is.** `describeRuntime` in `history.ts` appends a short paragraph naming the model, the server it is served by, whether a `:cloud` name means the conversation leaves the machine, which tools are actually available, and whether it can read images. It is appended even when the user has written their own system prompt, because none of it is a matter of style. Without it the model guessed, and the guesses were confident and wrong: a local model described Vicinae as "a desktop launcher for Ollama", reported its own web tools as unavailable, and answered a question about an attached screenshot by reasoning out loud about whether it was able to see, instead of describing it.
|
||||
|
||||
**A turn that runs out of tool calls still ends in an answer.** The loop stops after 8 rounds by default, and the first version of it stopped by throwing away every preamble the model had written and returning a notice about the loop: asked for the fish in every Valheim biome, it researched for five rounds and then said nothing useful at all. The budget is now spent on a *closing round* with the tools taken away and an instruction to answer from what was gathered and to name what it could not confirm. So the worst case is a partial answer that says what is missing, rather than an app-generated message about its own control flow. If the closing round produces nothing either, the last preamble is used, and only then a notice. The closing round is why the default cap is 8 rather than 5: the extra round is not more searching, it is the answer.
|
||||
|
||||
The cap is a preference rather than a constant, because how many rounds a question needs is a property of the question and of the model. `Unlimited` is there for research that genuinely needs a dozen pages.
|
||||
@@ -333,6 +337,8 @@ The hand-off goes through `snip` specifically rather than straight to `chat` on
|
||||
|
||||
**An attached image is sent once and never replayed.** It is the largest thing a request can carry, so `buildMessages` attaches it to the question it belongs to and drops it afterwards, exactly as it already drops tool output. The cost is that a follow-up about a screenshot needs the image attached again; the alternative is re-sending every screenshot in the conversation on every turn. Only the path and mime type go into storage: `MAX_STORED_CHARS_PER_TURN` exists so one turn cannot dominate `LocalStorage`, and base64 would blow past it on a single 1080p capture.
|
||||
|
||||
**Whether the model can see is a tri-state, and the prompt gets the whole answer.** `canSeeImages` stays fail-closed, because offering the snip action to a model that cannot read would waste the selection gesture. But the system prompt needs `"unknown"` kept apart from `"no"`: telling a model it cannot see when the check merely failed is a false claim about the user's setup, and telling it nothing is what made it reason about its own capability instead of describing the image it had been sent. A model name that does not exist on the server is the common way to end up at `"unknown"`, which is one more reason the Models command picks names from the list rather than taking them typed.
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
|
||||
Reference in New Issue
Block a user