8 Commits

Author SHA1 Message Date
jackson-jia-914 e9c1af03f6 feat(llm): add disableThinking option to suppress reasoning in extraction models (#228)
Support multiple inference engines and model providers via a strategy
enum so each receives its own thinking-disabling field in
chat-completion request bodies.

Strategies:
- "vllm"      → chat_template_kwargs: { enable_thinking: false }  (vLLM / SGLang)
- "deepseek"  → enable_thinking: false  (DeepSeek official API)
- "dashscope" → enable_thinking: false  (Alibaba DashScope / Qwen)
- "openai"    → reasoning_effort: "low"  (OpenAI o-series, cannot fully disable)
- "anthropic" → thinking: { type: "disabled" }  (Anthropic Claude)
- "kimi"      → thinking: { type: "disabled" }  (Kimi / Moonshot)
- "gemini"    → thinking_config: { thinking_budget: 0 }  (Google Gemini)

Defaults to false (no wrapper). Also accepts boolean true as a shorthand
for "vllm" for convenience.

Covered paths:
- StandaloneLLMRunner (OpenClaw plugin + gateway): llm.disableThinking,
  wired through parseConfig, tdai-core, seed-runtime, and gateway config
  (TDAI_LLM_DISABLE_THINKING env also accepts strategy names).
- Offload local mode (L1/L1.5/L2): separate offload.disableThinking.

The fetch wrapper lives in src/utils/no-think-fetch.ts with a
STRATEGY_TRANSFORMERS map for clean dispatch. StandaloneLLMRunner builds
it once in the constructor; LocalLlmClient caches it at construction
time and passes it through to callLlm().

Add vitest unit tests for all 7 strategies, normalization, validation,
embedding skip, and non-JSON tolerance (20 tests total).

Signed-off-by: jackson.jia <jiazhenghua0@gmail.com>
2026-06-24 18:02:25 +08:00
MicroGrey 093ddd293a test(offload): cover auth-profile apiKey resolver
Add unit tests for resolveApiKeyFromAuthProfile covering the four
resolution branches: api_key profile returns the plaintext key,
oauth/token-only providers return undefined, providers with no profile
return undefined, and keyRef-only (no plaintext) profiles are skipped.
Also covers the older-host case where the provider-auth SDK subpath is
unavailable.

To keep the test self-contained (no real OpenClaw install or on-disk
auth-profile store), resolveApiKeyFromAuthProfile gains an optional
fourth parameter to inject a fake provider-auth SDK loader. Production
callers pass three arguments and keep loading the real SDK via require.

Signed-off-by: MicroGrey <changyuhang@outlook.com>
2026-06-12 15:13:24 +08:00
MicroGrey a6fd25936c fix(offload): resolve local-llm apiKey from auth-profile store as fallback
When offload.model references a provider whose apiKey is managed via
OpenClaw's auth-profiles mechanism (the recommended default, e.g. set up
with 'openclaw auth'), the local-llm initializer previously only read
models.providers[provider].apiKey in the config tree. If the key was
absent there, LocalLlmClient construction was skipped and L1/L1.5/L2
were disabled with a misleading "missing apiKey" error -- even though the
key existed and the main agent model worked fine.

Fix: add src/offload/auth-profile-key.ts, a synchronous helper that
loads the auth-profile store via openclaw/plugin-sdk/provider-auth and
returns the first api_key-type credential for the provider. The helper
is guarded with try/catch so older OpenClaw versions that do not expose
this SDK subpath degrade silently to the previous behavior.

In index.ts, the apiKey lookup becomes:
  providerCfg?.apiKey ?? resolveApiKeyFromAuthProfile(api, providerKey, logger)

registerOffload() keeps its synchronous contract; no race is introduced
around backendClient assignment.

Closes #90
Signed-off-by: MicroGrey <changyuhang@outlook.com>
2026-06-04 21:36:48 +08:00
Andy He d1534e488f refactor: unify duplicate Logger interfaces into single canonical type (#14)
* refactor: unify duplicate Logger interfaces into single canonical type

23 files had local Logger/StoreLogger/PluginLogger/PipelineLogger/RunnerLogger/ExtractorLogger/TriggerLogger
interface definitions with identical shapes ({debug?, info, warn, error}).

Replace all with imports from the canonical `Logger` in `src/core/types.ts`:
- 17 files: local `interface Logger` → `import type { Logger }`
- 6 files: named variants (StoreLogger, PluginLogger, etc.) → `type X = Logger` alias

Two intentionally different interfaces are preserved:
- `CheckpointLogger` (only info + optional warn) — different contract
- `ensure-hook-policy.ts` Logger (no error) — different contract

Net: -120 lines, zero behavioral change.

Signed-off-by: yuanrengu <heyonggang0811@126.com>

* docs: update Logger JSDoc to reflect canonical relationship

StoreLogger, PluginLogger, etc. are now type aliases of Logger, not the
other way around. Update the comment to clarify this inverted relationship.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: yuanrengu <heyonggang0811@126.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 15:12:46 +08:00
chrishuan 438869bec8 feat: release v0.3.6 2026-05-28 14:32:52 +08:00
Akhilesh Arora bf58853343 fix(offload): preserve non-BMP characters in sanitizeText
UNSAFE_CHAR_RE included the surrogate range [\uD800-\uDFFF] without the `u`
flag, so JS treated strings as UTF-16 code units and stripped each half of
every well-formed non-BMP code point. sanitizeText and sanitizeJsonLine
therefore destroyed emoji, CJK Extension B, math bold, etc. in tool params,
tool results, and ref-md archives.

Adding the `u` flag makes paired surrogates combine into a single code point
before matching, so the [\uD800-\uDFFF] entry now matches only lone (malformed)
surrogates, which is the original intent. All other entries (replacement char,
C0/C1 controls, zero-width chars, line separators, BOM) keep their behavior.

Added a vitest suite covering the preserved and stripped cases.

Closes #30
2026-05-16 22:23:45 +02:00
chrishuan d377b09fbc feat: release v0.3.4 — offload local LLM, CLI restore, bugfix scripts 2026-05-13 14:56:56 +08:00
chrishuan db8f3e516a feat: release v0.3.3 — Hermes adapter, context offload, core refactor 2026-05-13 01:58:18 +08:00