尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证AI trade assistant — describe the job, get a one-trip material list with aisle numbers
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Describe the job. Get a one-trip material list with aisle numbers.
Trades lose hours and margin on the second trip to the supply store — the fitting that didn't fit, the tool left back at the shop, the size that was wrong.
Ask Danny takes a job described the way someone actually says it:
and returns one list: materials with quantities and specs, the tools needed, a rough price, and the aisle number at Home Depot, Lowe's, or AutoZone.
The two problems this has to solve查看完整 README ↗Describe the job. Get the steps, the parts, the cost, and where to find each part.
ask-danny-ai.com · Live, free beta
Trades lose hours and margin on the second trip to the supply store — the fitting that didn't fit, the tool left back at the shop, the size that was wrong.
Ask Danny takes a job described the way someone actually says it:
"My toilet keeps running"
and returns the steps to fix it plus one list: materials with quantities and specs, the tools needed, a rough price, and where each part is at Home Depot, Lowe's, or AutoZone.
Models invent products. A general model will happily produce a plausible part number for something that does not exist. So the server retrieves from a curated inventory (products.json, 249 products across 10 trade buckets) and injects the matches into its own prompt. Anything not in the inventory is included but marked low confidence.
Aisle numbers get the same treatment. A number is shown only when someone has checked it in that store; the model is told never to give one, and any that slips through is dropped. Every other part shows its department and section ("Plumbing — toilet repair"), and in four mapped Los Angeles Home Depots, which row that department is in and what it sits next to. No store has been checked yet, so today every part shows a department. The goal is 75–80% of shown aisle numbers correct at one store, and that ratio is the number worth improving before anything else.
Models sell the expensive part. Asked why an AC runs but does not cool, a model will reach for refrigerant. The usual answer is a $20 capacitor. The system prompt carries per-trade check-order guidance — capacitor before refrigerant, flapper before a new toilet, coils before a compressor, battery before a starter, jam wrench before a new disposal — because selling someone the costly part when a cheap one usually fixes it is the worst thing this tool can do.
There is also a hard stop above all of it: for a gas smell, a suspected leak, carbon monoxide, sparking or burning wiring, or standing water near live electricity, it returns no materials at all and says to leave and call the utility or the fire department. A short list of nothing plus the right instruction is the correct answer.
Several models answer independently, then one synthesises. This is not majority voting — a judge reads the drafts and produces a single list, weighing safety, technical correctness and compatibility.
Browser (index.html)
│
└── POST /api/council
│
▼
netlify/functions/ai-council.js
│
├── retrieval over products.json (server-side, not client-supplied)
├── system prompt built server-side (never accepted from the request)
├── persistent rate limit (Netlify Blobs — not enforcing yet, see Security)
│
├──► Gemini ─┐
├──► Groq ─┼──► drafts
│ │
└──► judge ───┘ synthesises one list
│
└── aisle numbers only from checked store data
If the council cannot be reached the client falls back to /api/ai, a single-model path that carries the same server-owned prompt and the same safety rules.
A circuit breaker opens after three consecutive failures from a provider and retries with a single trial request after a cooldown, so one sick provider does not slow every request.
| Voice input | Describe the job hands-free (Web Speech API) |
| Repair steps | 3 to 8 steps, safety first; none for hazards, only safe checks for pro work |
| Photo and video input | Show the problem instead of describing it; a video becomes four frames on the device |
| Store layouts | Where each department is in four mapped LA Home Depots, after asking for location once |
| Multi-store compare | Home Depot vs Lowe's, side by side |
| Tool checklist | What to bring, per trade |
| Offline mode | Last result cached for the truck |
| Quantity calculator | Coverage, runs and counts |
| Job history | Firestore when signed in, localStorage as a guest |
| Usage ring | How many free lists are left today |
Trades: Plumbing · HVAC · Carpentry · Auto · Appliance
Plans: free is 5 lists a day with up to 4 drafters, all on free-tier providers. Pro (40/hour, paid models) is built but not sold — verifyProToken() returns false until real accounts exist, and the tier is never taken from the request.
Architecture is easy to add and hard to justify. The thing that actually tells you whether this works is a set of real jobs and someone qualified marking the answers.
| Path | What it is |
|---|---|
eval/jobs.json | 58 jobs phrased as real people speak, 13 of them traps |
eval/run.js | Runs them against the live API, writes a CSV with columns for a tradesperson to grade |
eval/local-check.js | 200 checks against mocked providers — every deploy runs them and stops on a failure |
eval/run.js --compare claude | Runs every job through the free council and through Claude (Opus 5) with the identical prompt, and writes a blind A/B sheet for a grader plus a separate answer key. Answers whether the paid model is worth it before anyone pays for it. |
The traps are the interesting part: a gas smell must refuse rather than sell parts, an AC that won't cool must reach for the capacitor and not refrigerant, a humming disposal needs a jam wrench and not a new unit, a load-bearing wall needs an engineer, and a prompt injection must produce a normal list and leak nothing.
local-check.js runs both handlers in-process against scripted providers and has caught two ReferenceErrors that node --check could not see. Run it before every deploy.
body.system and forwarded it, which let anyone replace the instructions wholesale — safety rules included. It is now read and discarded./api/ai was *, which let any website spend our provider quota from a browser.verifiedAisles and the server trusted them, so a crafted request could assert any aisle it liked.connectLambda drops the URL that strong-consistency reads need. Each handler now installs it itself, and local-check.js tests that.LIST_KEY is set, so a copy of the store, or an export taken with a stolen admin token, is ciphertext. The blob key stays a hash of the address, so lookups never decrypt. Set it with netlify env:set LIST_KEY "$(openssl rand -base64 32)"..github/workflows/claude-security-review.yml). It needs a CLAUDE_API_KEY repository secret and skips itself without one; fork and Dependabot PRs never get the key.npm audit for vulnerable dependencies, CodeQL for the code itself, plus the same pre-deploy checks. Dependabot opens update PRs. See .github/workflows/security.yml.netlify.toml sets HSTS, X-Frame-Options: DENY, , a strict referrer policy, and a permissions policy denying camera, payment, USB and motion sensors.CSP: script-src allows no 'unsafe-inline'. Every inline onclick was replaced with delegated listeners, and the three remaining inline scripts are allowed by SHA-256 hash. eval/csp-hashes.js regenerates the hashes and local-check.js fails if they drift, because a stale hash blocks all JavaScript. style-src still allows 'unsafe-inline' for the inline CSS, which is lower risk since styles cannot execute.
To report a vulnerability, see SECURITY.md.
Analytics load only after the visitor accepts — Consent Mode defaults every category to denied before any tag can run, and declining is the same size and weight as accepting. Every user acknowledges that AI can be wrong and that they are 18 or older before using the app, and each result carries an AI-generated label on the result itself, so a printed or screenshotted list still says a machine wrote it.
Photos are sent to an AI provider to answer one request and are not stored. No face recognition, no biometric extraction. Job history for guests never leaves the device.
See privacy.html, terms.html and cookies.html.
python3 -m http.server 4173
Then open http://localhost:4173/index.html.
On localhost the page talks to a local Ollama model instead of the deployed functions (USE_LOCAL is set from the hostname), so the AI features need Ollama running.
Before any deploy:
node eval/local-check.js
| Path | What it is |
|---|---|
index.html | The entire client app |
products.json | Curated per-trade inventory used for retrieval |
netlify/functions/ai-council.js | The council: retrieval, prompt, drafters, judge, rate limiting |
netlify/functions/ai-proxy.js | Single-model fallback, same server-owned prompt |
eval/ | Job set, live harness, and pre-deploy checks |
netlify.toml | Security headers, CSP, redirects |
firestore.rules | Owner-only Firestore access rules |
privacy.html terms.html cookies.html | Disclosure, DMCA agent, AI policy |
Live and free while in beta. Accounts are not wired up yet — Firebase config is still a placeholder, so everyone is a guest and history stays on the device.
Material lists are generated by AI and are not checked by a licensed tradesperson. Verify quantities, specs and store locations before buying, and hire a professional for gas, electrical or structural work.
| Asset | Source | Licence |
|---|---|---|
| DM Sans | Google Fonts | SIL Open Font License 1.1 |
| Interface icons | Feather Icons, inlined as SVG | MIT |
og-image.png | Generated by this repo's own script | Ours |
Product data in products.json | Compiled by hand for this project | Ours |
Store names (Home Depot, Lowe's, AutoZone) and their colours are used to identify where an item is sold. No affiliation or endorsement is implied.
Source-available, not open source. See LICENSE.
© 2026 Matthew John Sanchez. All rights reserved.
nosniff