Repository navigation
Releases: AboveColin/HA-Jev
Release list
1.22.3
1.22.3 changes no code. Jev is now in the HACS default list, and this release brings the README that says so to the HACS page: search HACS for Jev, Download, restart.
Bugs now have a form on GitHub that asks for your versions, your provider and the diagnostics file. Questions about setup go to Discussions.
1.22.2
1.22.2 fixes a double full stop from 1.22.1. A refused Box question read ...rejected as invalid: Invalid request.. A box needs Jev 1.14. The box_refused message and the repair card for a failed weekly house check now put one full stop after the API's message.
1.22.1
1.22.1 uses jevclient 1.3.1. An error from the API now shows the API's message, not the whole JSON body.
- Before:
...rejected as invalid: {"detail":{"error_type":"api_usage_error","message":"Invalid request."}} - After:
...rejected as invalid: Invalid request.
This changes the text of a refused Box question (box_refused) and the reply the setup and reconfigure forms show when the API refuses a key or an account has no credit. Nothing else changes.
1.22.0
1.22.0 adds Jev 1.14: Jev can look at your cameras, and find where something is in a picture.
Cameras and images
jev.noul,jev.choice,jev.scoreandjev.asktakeimages:, a list of camera and image entities. The current picture of each goes in beside the state, named like an entity, so a question can say "the front door camera". It works alone or with a target.- The AI Task entity takes attachments. A camera, an image entity or an image file is sent. A video or any other file is refused before the request.
- The API takes each side from 280 to 1568 pixels and does not resize, so a 1920 x 1080 frame is refused as it comes. Jev scales every picture into that range, turns it upright from its EXIF orientation and sends it as a JPEG.
- A picture is billed by its size: 2 input tokens for each 28 x 28 pixel square. A 16:9 camera frame is 3,584 tokens, about $0.00015. The daily budget counts it before the request.
- Question sensors, the conversation agent, the preview and the house check send text only.
Find where something is
jev.boxtakes one camera or image entity and what to find. It returnsleft,top,rightandbottomas fractions of the picture, aconfidence, and the camera's ownwidthandheight.jev.asktakestype: boxbeside the other questions.- Box needs Jev 1.14. A new entry asks
jev-latest, which still answers as 1.13, so addmodel: jev-1.14.0to the call. If you leave it out, the error says so. - A box always comes back, also when the thing is not there. Read the confidence, or ask a yes/no question beside it.
A model per call
Every action takes model:, which asks that model for that call only. The entry's model and its version sensor stay as they are.
Upgrading
Nothing changes until you add images:, an attachment or jev.box to an automation. TypeSafe calls images and Box "dreamer-ready", which in its words means not yet up to its standards to call ready for production.
Receipts, live on 2026-10-16
1.21.0
1.21.0 puts the provider in a list. Setup asks for a provider and a key, and the address and the model come with the provider.
The providers
| Provider | Address | Model | Price per million input tokens |
|---|---|---|---|
| Jev (TypeSafe) | https://api.typesafe.ai |
jev-latest |
$0.042 |
| SubQ Snap | https://api.subq.ai |
subq-snap-preview |
$0.09 |
| OpenRouter | https://openrouter.ai/api |
~typesafe/jev-latest |
TypeSafe's, until you set OpenRouter's |
| Local server | the one you give | jev-latest |
$0 |
- Advanced still holds the address and the model. Leave them empty to use the provider's own. A local server needs its address there, and setup says so (
url_required) instead of sending a request. - An empty key for a hosted provider is refused without a request. Only a local server can work without a key.
- The cost sensor starts at the provider's price. The price option still overrides it.
- Reconfigure can change the provider, and keeps every entity and its history.
- The install page warns that SubQ keeps request data by default.
Upgrading
Entries made before 1.21.0 stored only an address. The migration to minor version 3 names the provider from that address: the TypeSafe, SubQ and OpenRouter addresses map to their provider, and any other address becomes a local server. Nothing sends a request during the migration.
Receipts
- SubQ answered the setup probe live on 2026-10-11 with
subq-snap-preview: 86 input tokens, 493 ms. - SubQ's price is from docs.subq.ai/using-the-api/models, read on 2026-10-11: $0.09 per million input tokens, output free.
1.20.0
1.20.0 adds a house check that opens Repairs cards. jev.calibrate now tells you how much of the time a noul can decide without you. Houses with more than 150 exposed entities can reach every entity by name again. After the upgrade, nothing sends a new request until you turn it on.
The house check
jev.house_check looks for three kinds of problem and opens a Repairs card for each one.
- When an integration loses its device or its server, all of its entities go unavailable. So they share one card, which gives the count and three examples. On a test instance, 518 unavailable entities made 5 cards.
- Each card gives you a choice. Ignore stops the reports for those entities. Snooze stops them for 30 days. Turn off is on a card for a single light, switch or fan that is on.
- The house check never changes a lock, a cover, a climate entity or a valve.
jev.undo_house_checkputs back what a turn-off changed, brightness included.- A card closes by itself when a later run that checks for its problem no longer finds it. A run with
use_jev: falseleaves the "looks wrong" cards open. Cards stay after a restart. - The "looks wrong" request describes the entities that are exposed to Assist and that Jev can control, up to 150. On a test instance with 6 of those entities it cost 773 input tokens. A house with more entities sends a longer description.
Read the house check page for the fields, the response and the cards.
How much can a noul decide alone
jev.calibrate already found the threshold with the best f1 from recorder history. Its response now also has error_budget, which answers this question: if a wrong answer may happen only once in 100 (error_rate: 0.01), or once in 20 (0.05), how much of the time can the noul decide without you?
yes_at: act at or above this probability.no_below: do nothing below this probability.- Between the two, ask a person.
automatedis the part of the time outside that band. yes_wrongandno_wrongare how often each side was really wrong in the window.
A side is null if no threshold kept it inside the rate. A noul that stays near 0.5 automates nothing. The model cannot tell, so you must decide.
Read Tuning a threshold.
More than 150 exposed entities
The conversation agent sends at most 150 entities with a command. Before this release, it kept the first 150 by entity_id, so a light late in the alphabet could not be reached by its name. Now it keeps the 150 whose names, aliases, area and floor best match the words of the command. If two entities match equally, the entity in the room that heard the command goes first. Chinese, Japanese and Korean names match character by character.
- With 150 or fewer exposed entities, nothing changes.
- The request stays the same size. On a laptop, ranking 1,000 entities took 4 ms and 2,000 took 10 ms. We have not measured on slower Home Assistant hardware.
- The conversation trace lists what the cap left out, in
left_out_by_cap.
What you can set up
-
Run the free checks first, so you can see what they find without a request:
action: jev.house_check data: use_jev: false
-
To run the full check every week, go to Settings, Devices & services, Jev, Configure, then turn on Check the house once a week. It runs at 10:00, 7 or more days after the last full check. If it cannot reach Jev, for example because the daily budget is spent, the free checks still open their cards, and one more card says why the Jev check did not run.
-
For a noul that you use in an automation, run
jev.calibrateafter a week of history. Putyes_atin the high threshold of the Act when sure, ask when unsure blueprint andno_belowin its low threshold. The sliders move in steps of 0.05, so roundyes_atup andno_belowdown.
Upgrading
Nothing to configure. The weekly house check is off by default, so an upgrade sends no new requests. The conversation agent sends the same request as in 1.19.1 when 150 or fewer entities are exposed.
ruff, mypy --strict over 25 source files, mkdocs build --strict and hassfest: all exit 0.
pytest: 882 passed, 12 skipped, 97% coverage.
1.19.1
The setup form now says what the server answered. Before, any failure other than a rejected key, a 404 or an invalid model showed "could not reach the API at that address", and nothing went to the log.
Setup
- A server that answers with an error shows "The server answered with an error:" followed by its reply. This covers a 5xx, a rate limit and a reply with no answers.
- A 402 has its own text: "The account at this address has no credit (HTTP 402). Add credit with the provider, then try again." OpenRouter sends a 402 to a valid key on an account with no credit.
- "Could not reach the API" now means that no answer arrived.
- A rejected key shows "The server rejected this key". It said "TypeSafe rejected this key" to OpenRouter users too.
- Every failed setup check writes a warning to the Home Assistant log, with the address and the reason.
- The texts are in all 14 languages.
- The troubleshooting page has a row for each setup error.
Tests
- The blueprint tests start at a fixed time. A test that started a second before a full hour asked Jev twice, because of a recheck at minute 0.
Upgrading
Nothing to configure. The request to the model is the same as in 1.19.0.
ruff, mypy --strict over 22 source files and mkdocs build --strict: all exit 0.
pytest: 837 passed, 12 skipped, 97% coverage.
1.19.0
25 blueprints to import with one click. Each one asks Jev one thing and runs your actions on the answer. The blueprint page has an import button for each.
Start from your own question
Seven blueprints take your question and your actions, and fit any house: ask a yes or no question, pick one of several, rate something on a scale, act when sure and ask when unsure, triage a message, call an LLM only when it is worth it, and keep a situation helper up to date.
One situation each
- Appliances. Laundry done and forgotten, start the dishwasher at a good moment, an appliance left on by mistake, lights or media left on in an empty room, a fridge or freezer getting warm, and which low batteries matter this week.
- Climate and weather. A window left open while heating, a ventilation speed, rain coming while something is open, watering the garden tonight, umbrella and coat for today, and charging the car now or later.
- People and the door. Something left on when everyone leaves, anything to deal with before bed, who is at the door, a parcel on its way, motion while nobody is home, and whether an appointment needs preparing.
What each one costs
Each description gives the most calls a day it makes with the default inputs. State triggers wait for a hold time and skip unavailable and unknown. A cooldown stops a flapping sensor from asking again and again. An unavailable sensor reaches Jev as unknown, not as 0. Where a template can decide, it decides for free. A dry forecast, for example, makes no call.
No blueprint opens a lock, an alarm, a garage door or a gate. The ventilation and car blueprints may operate their own fan or charger. Every other action is yours.
Tested
156 cases fire each blueprint's real trigger in a test Home Assistant with a mocked Jev, and check which of your actions ran and what they could read. Each blueprint also ran once against a live Home Assistant 2026.9.3 with the real API: 51 calls, 29,009 input tokens, $0.0012. That run found two faults, which this release fixes:
- Met.no gives the rain amount in mm and no rain chance. The forecast blueprints now send the amount, and the rain blueprint asks when more than 0 mm is forecast.
- A calendar event with no location now reaches Jev as "none given", and Home Assistant logs no template warning.
Share yours
CONTRIBUTING.md has the rules for a new blueprint and how to write its test case. If you do not want to write it yourself, open a blueprint idea.
Actions
jev.noul treats an empty true_means or false_means as not given, and jev.choice does the same for an empty option description. Before, the action sent an empty criterion to the model. A blueprint input that the user leaves blank gives such an empty value.
Upgrading
Nothing to configure. Blueprints need Home Assistant 2026.9.0 or newer.
1.18.0
Temperature questions now get a temperature. "What's the temperature in the living room?" used to go to the fallback agent, or to the state question, which answers with a heater's mode.
Voice
- A new action sends temperature questions to Home Assistant's own temperature intent. With a room, Home Assistant reads the temperature sensor set for that room in its area settings, then a climate device in the room. With a heater, thermostat or air conditioner named, it reads that device. With neither, it reads the room of the satellite that heard the command. The answer is the language's own sentence: "24.8 degrees", "24,8 fok", "24,8 Grad".
- A room that holds only a temperature sensor is now offered to the model, when the sensor is exposed to Assist and is in that room.
- The question that sends lists, messages, the time and the weather to the fallback agent is reworded. The old wording sent every temperature question away before the action was read. "How warm is it outside" still goes to the fallback agent, which answers with the weather.
- "What does the bedroom heater read" now gives the heater's temperature, not its mode. A split between the state question and the temperature question now answers, because neither changes anything.
- A temperature asked of a whole floor, of a device that is not a climate device, or with no room and no satellite goes to the fallback agent.
On a test house with 11 devices, 31 commands in 6 languages, 3 runs each: 90 of 93 as in 1.17.2. Room temperature questions in English, Hungarian, Dutch, German and Polish: 24 of 24.
Known misses
"what does the heater in the bedroom show", and the same question in Dutch and German, still answer with the heater's mode.
Upgrading
Nothing to configure. The request to the model has a new action, and rooms with a temperature sensor are marked in it.
ruff, mypy --strict, mkdocs build --strict and hassfest: all exit 0.
pytest: 597 passed, 12 skipped, 96.94% coverage.
1.17.2
A command for one device no longer acts on its whole room, and a confident answer is no longer sent away because the names share a word.
Voice
- When the model said one device was meant but was unsure which, a confident room answer turned on every device of that kind in the room. "Włącz lampkę pod szafkami." turned on every kitchen light. Now the room backs the device only when the room holds no other device of that kind. In any other case the sentence goes to the fallback agent. On a Polish test house with 61 entities, 16 commands, 3 runs each: 1.17.1 acted on the wrong devices in 7 runs, 1.17.2 in none, and 1 run that 1.17.1 got wrong now goes to the fallback agent.
- A device the model picked with confidence was sent to the fallback agent when other names shared a word with the command, such as "light" or "the". "turn on the little light under the cabinets" went to the fallback agent with "3 devices fit the name". Now only a name said in full can tie with a confident answer. On a test house with 11 devices, 31 commands in 6 languages, 3 runs each: paraphrases acted on the right device in 60 runs of 60, up from 51.
- Two devices with the same name still get a question, as before.
Upgrading
Nothing to configure. The request to the model is the same as in 1.17.1.
ruff, mypy --strict over 22 source files, mkdocs build --strict and hassfest: all exit 0.
pytest: 581 passed, 12 skipped, 96.95% coverage.
