* Apps: normalize filetype associations to bare lowercase extensions
Suggested-apps lookups match app_filetype_association rows against the
bare lowercase extension ('docx'), but writes stored whatever the
developer typed. Rows like '.docx' never matched, so those apps
silently dropped out of Open With suggestions.
AppStore now canonicalizes on write (trim, lowercase, strip leading
dots, dedupe, drop empties) and tolerates the dotted legacy form on
read: getAppsByFiletype normalizes the requested extension, matches
both 'docx' and '.docx', and dedupes apps associated under both forms.
Cache invalidation keys are normalized the same way. Existing dotted
rows work without a data migration.
* Update apps tests for extension canonicalization
Adjust apps API tests to match current normalization behavior for `filetypeAssociations`: extension values are stored as lowercase bare extensions (e.g. `.txt` -> `txt`), while MIME types remain unchanged. Added inline comments in both test suites to document this expected remap.
Completions-family providers used truthy spreads, so temperature: 0 and
max_tokens: 0 were stripped before the SDK call. Align with Responses
providers that already use !== undefined.
* feat: add Speechify TTS driver
Adds a SpeechifyTTSProvider under the ai-tts driver (mirrors the xAI/
ElevenLabs REST-provider shape), registered in TTSDriver alongside the
existing providers. Wires puter-js txt2speech with provider: "speechify"
support, default voice/model, and the speechify-tts driver alias.
Every outbound request sets Speechify-Caller: puter; base URL is
https://api.speechify.ai only; default model is simba-3.2.
* fix: replace placeholder voice IDs with real simba-3.2/simba-english voices
DEFAULT_VOICE and the starter voice catalog used invalid IDs (henry,
cliff, kristy, george, aria) that the real API rejects with 400. Swapped
in confirmed-real voices from a live GET /v1/voices call: geffen_32,
dominic_32, harper_32, hugh_32, imogen_32, and alec for the
simba-english model-override test.
* fix: purge remaining placeholder voice IDs from client, docs, and types
The previous fix only covered the backend provider — the client-side
default in tts.js, its test, the txt2speech docs page, and the ai.d.ts
type comment all still referenced the invalid henry/cliff/kristy/george/
aria set. All replaced with the live-verified voices (geffen_32 default).
Also corrects the docs link to docs.speechify.ai.
Adds Infron (https://infron.ai) as an aggregator provider for the
puter-chat-completion driver, following the OpenRouter provider as
reference per doc/contributing-apis.md.
- OpenAI-compatible gateway at llm.onerouter.pro/v1
- Dynamic model catalog (kv-cached 15 min, authenticated fetch),
filtered to chat-capable LLM entries
- Bills the gateway-reported authoritative cost when present
(usage: {include: true}); falls back to catalog per-token pricing
- Registered as an aggregator so its aliases never shadow
first-party providers
- Offline unit tests (mocked SDK/axios against a real test server)
plus an env-gated integration test
* typeify subdomains wip
* initial (untested) logic for LocalWorkerService
* Make it work, add lifecycle expiry since workers are process heavy in current implementation
* fix type errors
---------
Co-authored-by: Daniel Salazar <daniel.salazar@puter.com>
* Alpha: compaction support for OpenAI and Anthropic
* update lock
* fix billing for anthropic compactions
* Fix max_tokens bug in together provider
* Fix responses compaction