Repository navigation
Releases: seokhoonj/thinchat
Release list
v0.3.2
Loosen the credbox dependency pin to lower-bound-only (drop the speculative <0.5 upper cap on an internally-owned sibling), so a future credbox minor does not force a cascade re-release and co-installed siblings never conflict on the shared dependency. No functional change.
thinchat 0.3.1 — lazy credential store
Builds the credential store lazily, on the first key call, instead of at import. A malformed THINCHAT_STORE_APP / THINCHAT_NAMESPACE override — the host-embedding redirect Credentials.for_app exists to serve — no longer aborts import thinchat; any credbox binding fault is translated to a CredentialStoreError at the call site, so a foreign exception type never escapes.
Pins credbox>=0.4.0,<0.5. credbox 0.4.0 defers store-binding validation to first store access, so passing api_key= (or setting a provider's *_API_KEY env var) resolves without ever validating or touching the store binding.
thinchat 0.3.0
thinchat 0.3.0
Credential storage moves from xdg-kit to credbox, complete() now returns a Completion
result object, and two provider defaults that had broken against current APIs are fixed. This
release is backward-compatible for library callers; the one behavior change is CLI-only (below).
Changed
- Credential store: xdg-kit → credbox. The store keeps the same path and format
(~/.config/thinchat/credentials.json, mode 0600), so keys saved with an earlier version are
read unchanged — apip install -Upicks up credbox and drops xdg-kit automatically. The
re-exportedSecret(masked in logs/tracebacks;.reveal()for the plaintext) is now
credbox's type.
Added
Completionresult object —complete()/acomplete()return aCompletion, astr
subclass (so every existing caller is unchanged) that also carries.finish_reason,
.truncated(True when the reply hit the token cap),.usage, and.model. You can now tell a
finished reply from one cut off at the token cap.- Per-call
model=andextra={...}on every verb — override the model for one call, and
splat provider-specific request fields (OpenAIseed, Anthropicthinking, …) into the
request.extrakeys are provider-specific and reach the request only, not the reply. AuthError(a subclass ofLLMError) for a rejected credential (HTTP 401/403), and
LLMError.status_codeso a caller can tell a transient 5xx from a permanent 4xx without
matching on the message text.Typing :: Typedclassifier, aSECURITY.md, and a Changelog link in the project metadata.
Fixed
- Gemini embeddings work out of the box again — the default embed model was
text-embedding-004, which Google shut down; it is nowgemini-embedding-001. - OpenAI completions work on current reasoning models — the reply cap is now sent as
max_completion_tokensfor OpenAI (its newer models rejectmax_tokens); the Gemini/Ollama
compat layers still receivemax_tokens. - Hardened the key-leak protection — the SDK-error →
LLMErrormapping is now fully total
(a hostile error object cannot make it raise and re-chain the key-bearing error onto the
traceback), control characters (incl. C1) are neutralized in error detail, and aRetry-After
that is non-finite/negative/absurdly large is treated as no hint. - Stricter embedding-response validation — mixed/duplicate/out-of-range indices and
non-numeric vector elements are rejected asLLMErrorinstead of misaligning or crashing.
CLI
thinchat get <provider>on a missing key now writes to stderr and exits non-zero (was
stdout + exit 0), sokey=$(thinchat get X)in a script captures an empty value and a testable
exit code. (The one behavior change in this release.)thinchat listprints a short legend clarifying it reflects the file store only (an env var
still resolves but is not shown).
Docs
- README rewritten to lead with what thinchat adds over the raw SDKs (leak-safe keys, one shared
credential store), a dedicated API keys section (store → env →api_key=, by
recommendation), and a restyled flow diagram. English/Korean kept in sync.
Compatibility
- Library callers: backward-compatible.
Completionis astr;model=/extra=are new
optional keyword args;AuthErroris anLLMErrorsubclass, soexcept LLMErrorstill catches
it. Env-var users are unaffected; file-store users' saved keys are read unchanged. - Only breaking change: the CLI
thinchat getexit/stream behavior above (affects a shell
script parsing its output, not the Python API).
v0.2.0
Add an on-disk credential store and a thinchat CLI, backed by xdg-kit. A provider key now resolves through api_key= > <PROVIDER>_API_KEY env > ~/.config/thinchat/credentials.json (0600); thinchat set/get/list/unset manage the store, and set_api_key/get_api_key/stored_providers/unset_api_key expose it programmatically. The pure-library core (make_client(api_key=...)) is unchanged and never reads a file. API keys are now redacted from LLM error messages and their cause chain.
v0.1.3
Add RateLimitError — a typed 429 rate limit.
A rate limit (HTTP 429) that outlives the vendor SDK's own retries now surfaces as RateLimitError instead of a generic LLMError. It is a subclass of LLMError (so existing handlers still catch it) and carries retry_after — the Retry-After wait in seconds when the service sent one, else None. Both provider clients map the SDK's 429 across completion, embedding, and streaming; the actual backoff stays in the SDK (via max_retries), so no retry loop is added.
v0.1.2
Full Changelog: https://github.com/seokhoonj/thinchat/commits/v0.1.2