TEDI v0.3.92
Added
- Local AI models (Ollama, llama.cpp, vLLM) now work end to end. Bring-your-own-key already covered the hosted providers, but a local endpoint was rejected before it could ever connect: the model builder demanded an API key, so a keyless Ollama or llama.cpp server could not be used at all. A loopback base URL (
127.x/localhost/[::1]) now counts as keyless, while a remote gateway still gets the actionable "add a key" message instead of a bare 401, and one-click presets were added for Ollama (:11434), llama.cpp (:8080) and vLLM (:8000). See config.ts, OpenAICompatibleBlock.tsx. - Editor autocomplete works with every provider, not just three. Ghost-text completion was hardwired to Cerebras / Groq / LM Studio, so anyone holding only an OpenAI, Anthropic or local key got nothing. It now runs on all ten providers with a fast default model each, and the settings block gained a model-id field so a local model name can be entered directly. See autocomplete/provider.ts, AutocompleteBlock.tsx.
- A
read_browser_consoletool so the AI can see what a page logged. A document-start capture script foldsconsole.error/warn,onerrorand unhandled rejections into a 200-entry ring buffer (so load-time errors are caught too) that the AI drains on demand, closing the browser-debug loop that nothing in the app previously closed. This brings the AI command count to 103. See preview/embed.rs, browser/lib/native.ts. - The AI can read images.
read_filenow falls back to a binary read and returns real image files (PNG/JPEG/GIF/WebP) as image parts, capped at 4 MB; SVG stays text. See tools/fs.ts. - Extension API:
ctx.ai,ctx.paths.homeand clickable status items. Extensions can now read the live AI state and, behind the newai:configure/ai:promptpermissions, set the model, toggle sub-agents, or send a prompt (setApprovalModeis deliberately not exposed, since it is the one AI setting that persists across restarts).StatusItem.onClickrenders a real button instead of a click-hijacking span, andctx.paths.homewas added. See host.ts, registries.ts. - A refreshed model line-up. Added GPT-5.x, Claude Opus 4.8 / Sonnet 5 / Fable 5, Gemini 3.5, Grok 4.5 and newer Groq models; every legacy id is kept so an existing saved selection never breaks. See config.ts.
Changed
- Forced sub-agent fan-out now keys off breadth, not message length. A study verb paired with a breadth cue ("audit the whole codebase", "analisa arsitektur sistem ini") reliably pins the first step to a sub-agent fan-out, while narrow single-file study ("pahami fungsi ini", "analyze the whole file") still does not. The previous fixed 40-character floor rejected genuinely broad but short requests, so the breadth word - not the sentence length - now makes the call. See orchestrationIntent.ts.
- Cheaper AI turns on gateways without prompt caching. Per-step history compaction used to rewrite old messages on every provider, which busts the prefix cache on those that have one; it now only does so for cache-less gateways and when the payload is actually large, and Anthropic prompt-cache breakpoints are re-applied per step (capped so they never exceed the four-breakpoint ceiling). See compact.ts, cache.ts.
- The install review shows what an extension's AI tools actually say. Contributed AI-tool descriptions - the text injected into every AI turn, and the real prompt-injection surface - are now disclosed before you consent, not just the tool names. See InstallReviewDialog.tsx.
Fixed
- Keyless local models now appear in the model pickers. A provider-level filter dropped the entire OpenAI-Compatible provider whenever the shared key slot was empty, so a working keyless local endpoint's models were hidden from both the chat model dropdown and the default-model picker, and the per-instance readiness check downstream never ran. The provider is now gated per instance, so a loopback endpoint's models show and are selectable. See ModelDropdown.tsx, DefaultModelDropdown.tsx.
- A floated terminal honors your scrollback setting. The pop-out terminal hardcoded a 10,000-line scrollback, ignoring the preference and doubling the memory a user who lowered it had asked to save; it now reads the setting and follows later changes. See FloatTerminal.tsx.
- Installing an extension can no longer leave an uninstallable "ghost". The TypeScript manifest schema was stricter than the Rust validator, so an extension Rust accepted but TypeScript rejected installed with a success toast yet never appeared in Settings and could not be removed from the UI. The schemas were relaxed to match the backend and the invariant documented. See manifest.ts.
- A bad extension manifest and a failed activation clean up after themselves. A malformed manifest now surfaces a toast instead of a silent console warning, and an extension whose
activatethrew no longer leaves its settings card and commands on screen until restart. See loader.ts.
Security
- Extension risk tiers no longer under-warn on wildcard permissions. The install badge derived its risk level separately from what a permission actually grants, so broad patterns (
*:*,invoke*,s*,shell:*,*fs_*) all granted a high-risk capability while badging only medium. The tier is now derived by probing the real permission check, andmcp_(which can launch arbitrary binaries) and the newai:permissions are rated high. See permissions.ts. - One extension can no longer silently install or approve another. The extension-management commands (
ext_install_from_zip/_from_github/ext_enable/ext_disable/ext_uninstall) were added to the hard-deny invoke list, since reaching them would let an extension mint install-time consent for a second one. See permissions.ts. - A cross-provider credential leak in autocomplete is closed. The completion key was held in a bare ref while the provider was read fresh from the store, so switching provider and then typing shipped the previous provider's API key to the new provider's endpoint. The key reference now carries its provider provenance and is re-checked after the async key fetch. See EditorPane.tsx, autocomplete/provider.ts.
- Unattended sub-agent shells are now scope-checked. An autonomous worker's
bashwas the one tool with no scope enforcement; its commands now run their path tokens through the same secret deny-list and out-of-scope check the file tools use, blocking obvious reads likecat ~/.ssh/id_rsaor absolute paths outside the workspace. It raises the bar rather than sandboxing (a shell cannot be fully scoped by inspecting a string), and only the auto-approved worker path is affected - the approval-gated main agent is unchanged. See security.ts, tools/shell.ts.
macOS users: if Gatekeeper says TEDI "can't be opened because Apple cannot check it for malicious software" or "is damaged and can't be opened", drag the app to /Applications and run this once in Terminal:
xattr -cr /Applications/TEDI.app