524 Commits

Author SHA1 Message Date
KRATOS
ee0d930093 fix(ripgrep): use @vscode/ripgrep package as the builtin source (#911) (#932)
The vendored-binary lookup at vendor/ripgrep/<arch>-<platform>/rg never
resolved in this fork — that directory does not ship — so users without
a system rg had no working fallback. Switch to the @vscode/ripgrep
package so Microsoft maintains the platform/arch matrix and the binary
is delivered via npm.

- src/utils/ripgrep.ts: replace hand-rolled vendor-path resolution with
  rgPath from @vscode/ripgrep. Lazy require so a missing package falls
  through to the system rg branch instead of throwing at import.
  Drop builtinExists from the config args; builtinCommand is now a
  string-or-null. The system override (USE_BUILTIN_RIPGREP=0), the
  Bun-compiled standalone embedded mode, the macOS codesign hook, and
  all retry/timeout/error logic are preserved untouched.
- scripts/build.ts: mark @vscode/ripgrep as external. The package
  resolves rgPath via __dirname at runtime, so bundling would freeze
  the build host's absolute path into dist/cli.mjs.
- src/utils/ripgrep.test.ts: update for the new config shape and add
  tests covering USE_BUILTIN_RIPGREP=0, embedded mode, last-resort
  fallback, and null builtin path.

Tested locally on Linux (Bun 1.3.13). macOS (codesign hook) and
Windows (rg.exe extension) need contributor verification.
2026-04-30 00:58:46 +08:00
ArkhAngelLifeJiggy
0ca4333537 feat: add streaming token counter (#797)
* feat: add streaming token counter

- Add StreamingTokenCounter for real-time token counting during generation
- Tracks output tokens as they arrive from stream
- Calculates tokens per second rate
- Add tests (4 passing)

PR 4A: Streaming Token Counter (Features 1.2, 1.7)

* refactor: move StreamingTokenCounter to separate file

- Extract StreamingTokenCounter from tokens.ts to streamingTokenCounter.ts
- Add getEstimatedRemainingTokens() method
- Update test import

* fix: word-boundary token counting for stable stream totals

- Accumulate raw content, count only at word boundaries
- Eliminates instability from arbitrary chunk boundaries
- Add finalize() to flush remaining content on stream end
- Add characterCount getter for raw content tracking
- Rename getEstimatedRemainingTokens -> getEstimatedGenerationTimeMs
- Add comprehensive tests

* fix: update streamingTokens test for word-boundary API

- Add finalize() call before checking output tokens
- Use characterCount for interim checks
- Add spaces to trigger word boundary counting

* fix: add estimateRemainingTokens/Time methods

- Add estimateRemainingTokens(target) method
- Add estimateRemainingTimeMs(target) method
- Covers non-blocking: now properly estimates remaining tokens

* fix: PR 797 - fix word boundary counting, consolidate tests

Blockers (Vasanthdev2004):
- recountAtWordBoundary now searches forward from lastCountedIndex+1
- Finds NEXT space after already-counted region, not before it
- Provides accurate live token counts during streaming, not just finalize()

Non-blocking (gnanam1990):
- Delete streamingTokens.test.ts, merge tests into streamingTokenCounter.test.ts
- Added interim-counting test to verify counting updates during streaming

* fix: PR 797 - fix word boundary advancement after space

Blocking:
- Fix recountAtWordBoundary to skip past space when searching for next boundary
- After counting at a space, indexOf(' ') returns 0 (the space itself)
- Now starts search from index 1 to find the NEXT word boundary
- Short chunks now properly trigger count advancement

Non-blocking:
- Add test verifying count increases after each word boundary
- Add test for space-skipping behavior
2026-04-29 16:17:00 +08:00
ArkhAngelLifeJiggy
92d297e50e feat: context preloading and hybrid context strategy (#860)
* feat: context preloading and hybrid context strategy

PR 2D - Section 2.7, 2.8:
- Add contextPreload.ts with pattern-based prediction
- Add hybridContextStrategy.ts with cache/fresh balancing
- Optimize for cost vs accuracy
- Add comprehensive tests (13 passing)

* feat: wire hybrid context strategy into API path

- Apply hybrid strategy after normalizeMessagesForAPI
- Feature-flag controlled (HYBRID_CONTEXT_STRATEGY)
- Optimizes cache/fresh balance for API requests

* fix: resolve PR 2D blocking issues

- Fix predictContextNeeds self-assign bug (matchedCategory = category)
- Add test for non-empty predictedNeed
- Preserve conversation tail in hybridStrategy (never drop last 3 messages)
- Add comment for hardcoded 200k cap in claude.ts

Fixes reviewer feedback from gnanam1990 and Vasanthdev2004

* fix: preserve tool_use/tool_result chains in hybridStrategy

- Increase MIN_TAIL to 5 (tool_use -> tool_result -> assistant -> user -> next)
- Add getMessageChain() to preserve paired messages
- Chains kept together in final selection

* fix: PR 860 - tool_use/tool_result pairing and safe token counting

Blocking:
- getMessageChain() now pairs by tool_use.id (block ID) not msg.message.id
- Find tool_use blocks by id, pair with tool_result having matching tool_use_id
- Fixes tool_result surviving while paired tool_use dropped

- Token counting now includes array content (tool_use, tool_result, thinking)
- Not just string content, prevents undercounting prompt size

- Deduplicate messages by UUID when combining chains + split + tail
- Prevents duplicate messages in final request

Non-blocking:
- Add regression test for tool_use/tool_result pairing

* fix: PR 860 - account for actual structured payload size in token counting

Blocking:
- getMessageTokenCount now calculates actual token count for structured blocks
- tool_use: uses JSON.stringify(input).length / 4 + base
- tool_result: counts actual content (string or array of text blocks)
- thinking: counts actual thinking text length / 4
- is_error flag adds small overhead

Non-blocking:
- Add tests for large tool_use input and large thinking blocks
2026-04-29 15:49:46 +08:00
emsanakhchivan
91f93ce615 feat: SDK Foundation — Type Declarations, Errors, and Utilities (#866)
* feat(sdk): add SDK foundation — type declarations, errors, and utilities

Adds standalone SDK building blocks with no SDK source dependencies:
- sdk.d.ts: ambient type declarations for SDK bundle
- coreSchemas.ts + coreTypes.generated.ts: Zod schemas and generated types
- errors.ts: SDK-specific error classes
- validation.ts: input validation utilities
- messageFilters.ts: extracted message filter logic
- handlePromptSubmit.ts: imports from messageFilters
- 16 generated-types tests

* fix(sdk): narrow assertFunction type from broad Function to callable signature

Code review finding: assertFunction used `asserts value is Function` which
accepts any function-like value without narrowing. Changed to
`(...args: any[]) => any` for better type safety.

* fix(sdk): update sdk.d.ts header — manually maintained, not generated

Reviewer noted the header said "Generated from index.ts" but no generator
produces this file. Updated to "Manually maintained — keep in sync with
index.ts". Drift detection added in validate-externals.ts (PR 3).

* fix(sdk): align sdk.d.ts types with canonical coreTypes.generated.ts

Tighten SDK public type contract to resolve reviewer blockers:

- PermissionResult: unknown[] → precise 6-shape discriminated union
  (addRules/replaceRules/removeRules/setMode/addDirectories/removeDirectories)
- SDKSessionInfo: snake_case → camelCase (sessionId, lastModified, etc.)
- ForkSessionResult: session_id → sessionId
- SDKPermissionRequestMessage: uuid + session_id now required
- SDKPermissionTimeoutMessage: added uuid + session_id
- SessionMessage: parent_uuid → parentUuid
- SDKMessage/SDKUserMessage/SDKResultMessage: replaced loose inline
  definitions with re-exports from coreTypes.generated.ts

---------

Co-authored-by: Ali Alakbarli <ali.alakbarli@users.noreply.github.com>
2026-04-29 14:53:01 +08:00
KRATOS
5943c5c269 fix(input): strip leading ! when entering bash mode (#947)
The PromptInput onChange handler had two branches for entering bash
mode: a single-char path that just toggled the mode and a multi-char
paste path that also stripped the leading `!` from the buffer. The
single-char path returned without stripping, so typing a bare `!` into
empty input switched modes but left the literal `!` visible.

Consolidated both paths through a new pure helper `detectModeEntry`
that returns the new mode plus the stripped buffer value, so there is
no longer a branch where the mode character can leak into the buffer.

Fixes #662
2026-04-29 10:29:59 +08:00
Kevin Codex
c0b5535d86 docs: add Atomic Chat partner (#942)
Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-28 23:35:25 +08:00
Vasanth T
d321c8fc6a fix: avoid legacy Windows PasswordVault reads by default (#941)
* fix: avoid legacy Windows PasswordVault reads by default

* fix: isolate model capability override cache

---------

Co-authored-by: OpenClaude Worker 3 <worker-3@openclaude.local>
2026-04-28 23:30:48 +08:00
KRATOS
8106880855 fix(typecheck): make bun run typecheck actionable on main (#473) (#938)
Issue #473 reported that `bun run typecheck` fails on main with ~4400
errors due to repo-foundation drift, masking branch-specific
regressions. Per kevincodex1's guidance ("lets narrow the typecheck
scope for now and then we expand step by step") this PR addresses the
foundational root causes and brings the error count down 60% so the
gate is actionable for branch reviews.

Changes:

- tsconfig.json: bump target to ES2023 + add lib ["ES2023", "DOM"]
  so Array.findLast / findLastIndex resolve (kills 41 TS2550 errors).
  Add `noEmit: true` for typecheck-only mode and
  `allowImportingTsExtensions: true` (kills 40 TS5097 errors). Set
  `noImplicitAny: false` because cleaning up TSX-component implicit
  any is explicitly out of scope per the issue.

- src/global.d.ts: ambient declaration for the build-time MACRO
  global injected by scripts/build.ts via Bun's `define` option
  (kills 9 TS2304 'Cannot find name MACRO' errors).

- src/types/{message,utils,tools}.ts: stubs for the highest-impact
  missing modules from the partial source snapshot (~21 importers
  for message alone). Document the snapshot caveat at the top of each
  stub and reference issue #473 so future readers know they're
  placeholders.

- src/entrypoints/sdk/controlTypes.ts and src/constants/querySource.ts:
  similar one-file stubs unblocking 18 + 19 importers respectively.

- src/entrypoints/agentSdkTypes.ts: append `any`-typed aliases for
  ~70 SDK names that callers expect on the public surface but that
  live in stubbed sub-files (PermissionMode, SDKCompactBoundaryMessage,
  HookEvent, ModelUsage, ModelInfo, etc. — exactly the list from
  auriti's bug-report enumeration).

Verified locally on Linux:
- baseline `bunx tsc --noEmit` on stashed main: 4434 errors
- with PR applied:                              1782 errors (60% drop)
- `bun run build`:                              passes (v0.7.0)
- `bun test`:                                   1632 pass; the 4
   remaining failures (StartupScreen, thinking) reproduce on main
   and are unrelated.
- TS2550 (lib): 41 → 0
- TS5097 (.ts imports): 40 → 0
- TS2304 'MACRO': 9 → 0
- TS2307 missing modules: 587 → 325

Remaining errors are localized to specific stubbed modules and can
be addressed in smaller follow-up issues, matching the issue's
"Definition of done" criterion.
2026-04-28 17:44:26 +08:00
Kevin Codex
4c93a9f9f1 feat: add Opus 4.7 as default model and fix alias/thinking bugs (#928)
- Add CLAUDE_OPUS_4_7_CONFIG and register it in ALL_MODEL_CONFIGS
- Set Opus 4.7 as default for firstParty in getDefaultOpusModel() (3P stays on 4.6 until rollout)
- Fix sonnet[1m] → 404 bug: query.ts was passing raw alias to API without resolving via parseUserSpecifiedModel
- Add opus-4-7 to modelSupportsAdaptiveThinking so it uses { type: 'adaptive' } not { type: 'enabled' }
- Fix duplicate opus47 case and wrong opus46[1m] fallthrough in getPublicModelDisplayName switch
- Update user-facing display strings (picker labels, plan mode description) to reference Opus 4.7
- Add 3P fallback suggestion chain for opus-4-7 → opus-4-6 in validateModel

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-28 17:31:06 +08:00
viudes
6ea3eb6483 feat(api): deterministic request-body serialization via stableStringify (#882)
* feat(api): deterministic request-body serialization via stableStringify

Add `stableStringify` helper that emits JSON with object keys sorted
lexicographically at every depth (arrays preserved). Adopt it in the
OpenAI-compatible shim and the Codex Responses-API shim for the outgoing
request body.

WHY: OpenAI / Kimi / DeepSeek / Codex use implicit prefix caching keyed
on exact request bytes. Spurious insertion-order differences in
spread-merged body objects otherwise invalidate the cache on every turn.
Also a pre-requisite for Anthropic `cache_control` breakpoint hits.

Byte-equivalent to `JSON.stringify` when keys already happen to be in
lexical insertion order, so strictly additive across providers.

* fix(api): preserve circular-ref TypeError in stableStringify + cover GitHub fallback

Replace two-pass sortingReplacer approach with a single-pass deepSort that
tracks ancestor objects via WeakSet, throwing TypeError on cycles (same
contract as native JSON.stringify) and correctly handling DAGs via
try/finally cleanup. Switch the GitHub Copilot /responses fallback in
openaiShim.ts from JSON.stringify to stableStringify so that path is also
byte-stable for prefix caching.

Regression coverage added: top-level cycle, deep nested cycle, DAG safety.

* fix(api): align stableStringify with native JSON.stringify pre-processing

Replicate native JSON.stringify pre-processing inside deepSort so
serialization output matches native behavior beyond key ordering:

- invoke toJSON(key) when present (Date, URL, user classes); pass ''
  at top-level, property name for nested values, index string for
  array elements
- unbox Number/String/Boolean wrappers via valueOf() so new Boolean(false)
  doesn't get truthy-coerced
- run cycle detection on the post-toJSON value so a toJSON returning
  an ancestor still throws TypeError; DAGs continue to not throw
- drop properties whose toJSON returns undefined, matching native

Add focused stableStringify.test.ts (21 cases) asserting equality with
JSON.stringify across toJSON paths, wrapper unboxing, cycle/DAG handling,
and sortKeysDeep parity.
2026-04-27 23:33:15 +08:00
vrdons
f699c1f2fc fix routing path (#923) 2026-04-27 20:05:17 +08:00
github-actions[bot]
52b4c5c2ff chore(main): release 0.7.0 (#817)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
v0.7.0
2026-04-27 11:47:52 +08:00
FluxLuFFy
c6c5f0608c fix: bugs (#885)
* fix: error output truncation (10KB→40KB) and MCP tool bugs

- toolErrors.ts: increase error truncation limit from 10KB to 40KB
  Shell output can be up to 30KB, so 10KB was silently cutting off
  error logs from systemctl, apt, python, etc.

- MCPTool: cache compiled AJV validators (was recompiling every call)
- MCPTool: fix validateInput error message showing [object Object]
- MCPTool: null-guard mapToolResultToToolResultBlockParam
- MCPTool: explicit null check in isResultTruncated
- ReadMcpResourceTool: null-guard mapToolResultToToolResultBlockParam

Tests (84 passing):
- src/utils/toolErrors.test.ts (13 tests)
- src/tools/BashTool/commandSemantics.test.ts (24 tests)
- src/tools/BashTool/utils.test.ts (32 tests)
- src/tools/MCPTool/MCPTool.test.ts (15 tests)

* fix: address review blockers from PR #885

Blocker 1: Fix abort path in callMCPTool
- Previously returned { content: undefined } on AbortError, which masked
  the cancellation and caused mapToolResultToToolResultBlockParam to send
  empty content to the API as if it were a successful result.
- Now converts abort errors to our AbortError class and re-throws, so the
  tool execution framework handles it properly (skips logging, creates
  is_error: true result with [Request interrupted by user for tool use]).

Blocker 2: Fix memory leak in AJV validator cache
- Changed compiledValidatorCache from Map to WeakMap so schemas from
  disconnected/refreshed MCP tools can be garbage collected instead of
  accumulating strong references indefinitely.

Also: null guards now return descriptive indicators instead of empty
strings, making it clear when content is unexpectedly missing.

---------

Co-authored-by: FluxLuFFy <FluxLuFFy@users.noreply.github.com>
Co-authored-by: Fix Bot <fix@openclaw.ai>
2026-04-26 23:11:19 +08:00
Kevin Codex
46a9d3eec4 chore: rebrand user-facing copy to OpenClaude (#851)
* chore: rebrand user-facing copy to OpenClaude

Replace lingering Claude Code branding in CLI, tips, and runtime UI with OpenClaude/openclaude, including the startup tip Gitlawb mention.

Co-Authored-By: Claude GPT-5.4 <noreply@openclaude.dev>

* chore: address branding-sweep review feedback

- PermissionRequest.tsx: rebrand the two remaining "Claude needs your
  approval/permission" notifications to OpenClaude (review-artifact and
  generic tool permission paths).
- main.tsx, teleport.tsx, session.tsx, WebFetchTool/utils.ts,
  skills/bundled/{debug,updateConfig}.ts: replace leftover `claude --…`
  CLI hints and "Claude Code" labels missed by the original sweep.
- main.tsx: drop the inline gitlawb.com marketing copy from the
  stale-prompt tip; keep it a pure rebrand.
- auth.ts: finish the half-rename so both `claude setup-token` and
  `claude auth login` references in the same error block now read
  `openclaude …`.
- mcp/client.ts: keep `name: 'claude-code'` for MCP server allowlist
  compatibility (now explicit via comment) and replace the
  "Anthropic's agentic coding tool" description with an OpenClaude one.
- MCPSettings.tsx: point the empty-server-list hint at
  https://github.com/Gitlawb/openclaude instead of code.claude.com.

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

* chore: replace help link with OpenClaude repo URL

Replace https://code.claude.com/docs/en/overview with
https://github.com/Gitlawb/openclaude in the help screen.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: Claude GPT-5.4 <noreply@openclaude.dev>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-26 22:14:36 +08:00
Kevin Codex
2586a9cddb feat: add xAI as official provider (#865)
* feat: add xAI as official provider

- Add xAI preset to ProviderManager (alphabetical order)
- Add xAI provider detection via XAI_API_KEY
- Add xAI startup screen heuristic (x.ai base URL or grok model)
- Add xAI status display properties
- Add grok-4 and grok-3 context windows
- Add xAI model fallbacks across all tiers
- Fix JSDoc priority order in providerAutoDetect

Co-Authored-By: Claude Opus 4.6 <noreply@openclaude.dev>

* fix(xai): persist relaunch classification for xAI profiles

Addresses reviewer feedback on feat/xai-official-provider:
- isProcessEnvAlignedWithProfile now validates XAI_API_KEY for x.ai
  base URLs, mirroring the Bankr pattern. Without this, relaunch
  skips re-applying the profile, XAI_API_KEY stays unset, and
  getAPIProvider() falls back to 'openai'.
- buildOpenAICompatibleStartupEnv now sets XAI_API_KEY when syncing
  active xAI profile to the legacy fallback file.
- Adds 'xai' to VALID_PROVIDERS and --provider xai CLI flag support.
- Adds xAI detection to providerDiscovery label heuristics.
- Adds 'xai' to legacy ProviderProfile type/isProviderProfile guard.
- Adds targeted tests for relaunch alignment, flag application, and
  discovery labeling.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@openclaude.dev>
Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-26 21:26:44 +08:00
Rayan Alkhelaiwi
d45628c413 fix(startup): show --model flag override on startup screen (#898)
The startup screen was only reading model from env vars and settings,
ignoring the --model CLI flag since it's parsed by Commander.js after
the banner prints. Now eagerly parses --model from argv before rendering
so the displayed model matches what the session will actually use.
2026-04-26 20:24:44 +08:00
TechBrewBoss
6dedffe5ff Add OpenAI responses mode and custom auth headers (#906)
* Add OpenAI profile responses and custom auth header support

* Fix knowledge graph config reference in query loop

* Address OpenAI profile review edge cases

* Remove unused getGlobalConfig import

Delete an unused import of getGlobalConfig from src/query.ts. This cleans up dead code and avoids unused-import lint warnings; no functional behavior changes.

* Address follow-up OpenAI profile review comments

* Refine OpenAI responses auth review fixes

* Fix custom auth header default scheme
2026-04-26 20:24:03 +08:00
emsanakhchivan
a3e728a114 fix(agent): provider-aware fallback for haiku/sonnet aliases (#908)
* fix(agent): provider-aware fallback for haiku/sonnet aliases

Explore agent fails on custom providers (Z.AI GLM, Alibaba Anthropic-compatible,
local OpenAI endpoints) because 'haiku' alias resolves to a non-existent model.

Changes:
- Add isClaudeNativeProvider check (Bedrock, Vertex, Foundry, official Anthropic)
- For non-Claude-native providers, haiku/sonnet aliases inherit parent model
- Add 8 tests for provider-aware fallback behavior

Fixes Explore agent "model not found" errors on custom Anthropic-compatible APIs.

* test(agent): use Bun mock.module() for provider tests

Replace env manipulation with proper Bun mock.module() to reliably
mock getAPIProvider() and isFirstPartyAnthropicBaseUrl() functions.
This ensures tests work correctly on CI where module caching caused
false negatives.

---------

Co-authored-by: Ali Alakbarli <ali.alakbarli@users.noreply.github.com>
2026-04-26 20:08:55 +08:00
Kevin Codex
818689b2ee fix(query): restore system prompt structure and add missing config import (#907)
- import getGlobalConfig — six call sites referenced it without an import;
  five short-circuited via feature() gates, but src/query.ts:1896 always
  ran and crashed every queryLoop iteration with "getGlobalConfig is not
  defined" (e.g. Explore subagent: "Agent failed: getGlobalConfig is not
  defined").
- stop coercing SystemPrompt (string[]) into a template-string before
  appendSystemContext — that made [...systemPrompt] spread the string
  character-by-character, replacing the structured prompt with thousands
  of one-char system blocks. Append arcSummary as its own array element
  instead.
- gate the finalizeArcTurn call behind feature('CONVERSATION_ARC') so it
  matches the rest of the memory-PR call sites and gets dead-code-
  eliminated for users without the flag.

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-26 12:45:09 +08:00
Kevin Codex
d9ae56bc58 fix provider switch not presistingin session (#903)
* fix provider switch not presistingin session

* fix broken tests
2026-04-26 11:15:25 +08:00
Pedry
af9a3caa4d Fix file path and update placeholder key in PLAYBOOK.md (#886)
Updated file paths and placeholder key in PLAYBOOK.md.
2026-04-26 08:20:25 +08:00
chioarub
a0d657ee18 feat(zai): add Z.AI GLM Coding Plan provider preset (#896)
* feat(zai): add Z.AI GLM Coding Plan provider preset

Add dedicated Z.AI provider support for the GLM Coding Plan, enabling
use of GLM-5.1, GLM-5-Turbo, GLM-4.7, and GLM-4.5-Air models through
the OpenAI-compatible shim with proper thinking mode (reasoning_content),
max_tokens handling, and context window sizing.

* fix(zai): unify GLM max output token limits across casing variants

glm-5/glm-4.7 had conservative 16K max output while GLM-5/GLM-4.7
had 131K. Use consistent Z.AI coding plan limits for all GLM variants.

* fix(zai): restore DashScope GLM limits, enable GLM thinking support

- Restore lowercase glm-5/glm-4.7 to 16_384 max output (DashScope limits)
  while keeping Z.AI coding plan high limits on uppercase GLM-* keys only
- Add GLM model support to modelSupportsThinking() so reasoning_content
  is enabled when using GLM-5.x/GLM-4.7 models on Z.AI

* fix(zai): tighten GLM regexes, fix misleading context window comment

- Use precise regex in thinking.ts: exact GLM model matches only,
  no false positives on glm-50/glm-4, includes glm-4.5-air
- Use uppercase-only match in StartupScreen rawModel fallback so
  DashScope lowercase glm-* models aren't mislabeled as Z.AI
- Clarify context window comment: lowercase glm-5.1/glm-5-turbo/
  glm-4.5-air are Z.AI-specific aliases, not DashScope

* fix(zai): scope GLM detection to Z.AI

* improve readability of max_completion_tokens check

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-26 08:18:59 +08:00
3kin0x
29f7579377 feat(memory): implement persistent project-level Knowledge Graph and RAG (#899)
- Shift memory from session-scope to persistent project-scope\n- Add native JSON RAG with BM25-lite ranking\n- Implement passive technical concept extraction (IPs, versions, frameworks)\n- Orchestrate hierarchical context injection in the conversation loop
2026-04-26 08:17:02 +08:00
viudes
9e23c2bec4 feat(api): expose cache metrics in REPL + normalize across providers (#813)
* feat(api): expose cache metrics in REPL + /cache-stats command

* fix(api): normalize Kimi/DeepSeek/Gemini cache fields through shim layer

* test(api): cover /cache-stats rendering + fix CacheMetrics docstring drift

* fix(api): always reset cache turn counter + include date in /cache-stats rows

* refactor(api): unify shim usage builder + add cost-tracker wiring test

* fix(api): classify private-IP/self-hosted OpenAI endpoints as N/A instead of cold

* fix(api): require colon guard on IPv6 ULA prefix to avoid public-host over-match

* perf(api): ring buffer for cache history + hit rate clamp + .localhost TLD

* fix(api): null guards on formatters + document Codex Responses API shape

* fix(api): defensive start-of-turn reset + config gate fallback + env var docs

* fix(api): trust forwarded cache data on self-hosted URLs (data-driven)

* refactor(api): delegate streaming Responses usage to shared makeUsage helper
2026-04-25 12:38:25 +08:00
JATMN
9070220292 Add Kimi Code provider preset and rename Moonshot API preset (#862)
* Add Kimi Code provider preset

* fix desc.

Co-authored-by: Copilot <copilot@github.com>

* more desc. fixes.

* Fix release validation tests

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-25 12:36:54 +08:00
JATMN
26413f6d30 feat(minimax): add /usage support and fix MiniMax quota parsing (#869)
* Add MiniMax usage UI and API support

* Fix MiniMax usage parsing and refresh UI

* Refactor MiniMax usage handling
2026-04-25 12:33:22 +08:00
3kin0x
44f9cac70d Feature/memory pr (#894)
* feat: multi-turn context and conversation arc memory

PR 2E - Section 2.9, 2.10:
- Add multiTurnContext.ts with turn tracking and state preservation
- Add conversationArc.ts with goal/decision/milestone tracking
- Wire into query.ts after tool execution
- Feature-flags: MULTI_TURN_CONTEXT, CONVERSATION_ARC
- Add comprehensive tests (22 passing)

* feat(cli): add /knowledge command to manage native memory

- Add /knowledge enable <yes|no> to toggle Knowledge Graph learning\n- Add /knowledge clear to reset memory\n- Add persistent knowledgeGraphEnabled setting to global config\n- Integrated user setting into the query execution loop

* feat(cli): add /knowledge command (stable local-jsx version)

- Resolve conflicts between .ts and .tsx files\n- Align with LocalJSXCommandCall signature\n- Fix onDone and args errors

* test(cli): fix knowledge command tests by properly isolating global config

* fix(cli): make knowledge command defensive against undefined args and leaky tests

* fix(cli): correct data source for entity count and fix test isolation

* fix(cli): reinforce knowledge test by explicitly defining property on test config

* fix(cli): explicitly define property in test config to avoid undefined in CI

* fix(cli): make knowledge tests resistant to global config mocks in CI

* chore(memory): surgical improvements from architectural audit

- Fix: Implement entity deduplication in Knowledge Graph\n- Fix: Ensure fact extraction from user messages in query loop\n- Fix: Refine regexes for better quality learning (less noise)

---------

Co-authored-by: LifeJiggy <Bloomtonjovish@gmail.com>
2026-04-25 07:19:41 +08:00
JATMN
ff2a380723 Add DeepSeek V4 flash/pro support and DeepSeek thinking compatibility (#877)
* Add DeepSeek V4 support and thinking compatibility

* Fix DeepSeek profile persistence regression

* Align multi-model handling with openai-multi-model
2026-04-25 02:29:46 +08:00
JATMN
c4cb98a4f0 fix: normalize /provider multi-model selection and semicolon parsing (#841)
* fix provider multi-model selection

* fix provider manager multi-model save path
2026-04-25 02:28:14 +08:00
3kin0x
b5f7047358 Feature/memory pr (#889)
* feat: multi-turn context and conversation arc memory

PR 2E - Section 2.9, 2.10:
- Add multiTurnContext.ts with turn tracking and state preservation
- Add conversationArc.ts with goal/decision/milestone tracking
- Wire into query.ts after tool execution
- Feature-flags: MULTI_TURN_CONTEXT, CONVERSATION_ARC
- Add comprehensive tests (22 passing)

* feat(memory): resolve review blockers and integrate native Knowledge Graph into Conversation Arcs

- Fix: Extract text from production block arrays in phase detector\n- Fix: Ensure proper turn segmentation in query loop\n- Fix: Respect options in multi-turn context tracker\n- Feat: Add native Knowledge Graph (Entities/Relations) to ConversationArc architecture\n- Test: Comprehensive test suite for all fixes and new graph features

* test(perf): add automated performance benchmarks for Knowledge Graph extraction and summary

---------

Co-authored-by: LifeJiggy <Bloomtonjovish@gmail.com>
2026-04-25 02:26:02 +08:00
Kevin Codex
64b1014b9a Feat/bankr provider (#888)
* feat(provider): add Bankr LLM Gateway support

Add Bankr as an OpenAI-compatible provider preset with dedicated env vars:
- BNKR_API_KEY, BANKR_BASE_URL, BANKR_MODEL
- Uses X-API-Key header instead of Authorization Bearer
- Base URL: https://llm.bankr.bot/v1
- Default model: claude-opus-4.6

Changes:
- Add 'bankr' to VALID_PROVIDERS and provider flag handling
- Add buildBankrProfileEnv() with env key registration
- Add Bankr detection in startup screen and provider discovery
- Map Bankr env vars to OpenAI-compatible vars in shim
- Add Bankr preset to ProviderManager (alphabetical order)
- Update PRESET_ORDER test to include Bankr

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fixup(provider): address Bankr PR review feedback

1. Map BNKR_API_KEY → OPENAI_API_KEY in providerFlag.ts so
   --provider bankr works with BNKR_API_KEY in non-interactive startup.

2. Remove unconditional BANKR_MODEL read from model.ts; it maps to
   OPENAI_MODEL via providerFlag.ts and openaiShim.ts, preventing
   cross-provider leakage.

3. Use X-API-Key for Bankr model discovery in openaiModelDiscovery.ts
   and providerDiscovery.ts, matching chat request auth.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-24 23:03:45 +08:00
TechBrewBoss
5a21d05741 Persist active provider profile across restarts (#833)
* Persist active provider profile across restarts

* Clear stale startup provider overrides

* Fix provider profile restart fallback

* Fix provider profile restart fallback

* Omit empty OpenAI API key from startup env

* Fix startup override settings typing
2026-04-24 19:36:21 +08:00
Kevin Codex
038f715b7a feat(model): add GPT-5.5 support for Codex provider (#880)
- Bump Codex provider defaults from gpt-5.4 to gpt-5.5 across all ModelConfigs
- Update codexplan alias to resolve to gpt-5.5
- Add gpt-5.5 and gpt-5.5-mini to model picker with reasoning effort mappings
- Add context window and max output token specs for gpt-5.5 family
- Add gpt-5.5 entries to COPILOT_MODELS registry
- Keep official OpenAI API preset at gpt-5.4 (API availability pending)
- Update codexShim tests to expect gpt-5.5 from codexplan alias

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-24 19:06:36 +08:00
Kevin Codex
b694ccfff1 Add sponsors section to README (#874) 2026-04-24 11:47:55 +08:00
KRATOS
dcbe29558a fix(mcp): disable MCP_SKILLS feature flag — source not mirrored (#872)
Closes #856.

MCP servers that expose resources (e.g. RepoPrompt) failed to load
their tools in the open build with:

    Error fetching tools/commands/resources:
    fetchMcpSkillsForClient is not a function

Root cause: scripts/build.ts set MCP_SKILLS: true, which made
feature('MCP_SKILLS') evaluate to true at build time. The guards
around the dynamic skill discovery path therefore stayed live. The
underlying source file src/skills/mcpSkills.ts is not mirrored into
the open tree, so the bundler fell back to its generic missing-module
stub — which only exports `default` for require()-style imports, not
the named `fetchMcpSkillsForClient` binding. At runtime the require
returned an object without that property, and calling it threw.

`openclaude mcp doctor` reported RepoPrompt as healthy because doctor
does not exercise the skills-fetch path.

Fix: flip MCP_SKILLS to false and move it into the "Disabled: missing
source" group. With the flag off, every `if (feature('MCP_SKILLS'))`
guard becomes a no-op at build time, the require() branch is dead
code, and MCP servers with resources load normally via the existing
`Promise.resolve([])` fallbacks already present at each call site.

Also adds scripts/feature-flags-source-guard.test.ts to fail fast if
MCP_SKILLS (or any future flag in the same category) is re-enabled
without the corresponding source file being mirrored first.

Verification:
  - Test fails on main, passes with this fix
  - `bun run build` produces a bundle with no
    `missing-module-stub:../../skills/mcpSkills.js` reference
  - Full `bun test` — 1222 pass / 12 fail (same pre-existing 12 as
    main; new test adds the +1 pass)
2026-04-24 11:35:59 +08:00
KRATOS
a4c6757023 fix(shell): recover when CWD path was replaced by a non-directory (#871)
* fix(shell): recover when CWD path was replaced by a non-directory

Closes #844.

When the session's cached working directory is renamed on disk and
a file is subsequently created at the old path (e.g. `mv orig renamed
&& touch orig`), every Bash tool invocation failed with
`ENOTDIR: not a directory, posix_spawn '/usr/bin/zsh'` (exit 126),
and `!`-prefixed commands silently failed. No recovery was possible
without restarting the session.

Root cause: the pre-spawn guard in `src/utils/Shell.ts:exec()` used
`realpath(cwd)` to detect a missing CWD. `realpath()` succeeds on
any existing path — file or directory — so a path that was replaced
with a regular file slipped past the check. spawn() was then called
with `cwd` pointing at a non-directory and failed with ENOTDIR.

Fix: replace `realpath()` with `stat().isDirectory()` for both the
primary CWD check and the `getOriginalCwd()` fallback check. When
the cached CWD is no longer a directory, fall back to the original
CWD (as before) and update state so subsequent tools recover
transparently.

Verification:
  - Repro: `mkdir -p /tmp/x/orig && mv /tmp/x/orig /tmp/x/renamed
    && touch /tmp/x/orig`, then exec with stale cwd=/tmp/x/orig
  - Before: exit 126, stderr "ENOTDIR: not a directory, posix_spawn"
  - After:  exit 0, cwd transparently recovered to originalCwd
  - `bun test` — no new regressions (pre-existing model/provider
    test failures are unrelated and present on main)

* fix(shell): drop now-unused realpath import
2026-04-24 11:34:08 +08:00
KRATOS
6e58b81937 fix(update): show real package version and give actionable guidance (#870)
The `openclaude update` / `openclaude upgrade` command printed
`Current version: 99.0.0` and, in the development-build branch, exited
with only `Warning: Cannot update development build` (closes #852).

Root cause: `MACRO.VERSION` is hardcoded to `'99.0.0'` in
`scripts/build.ts` as an internal compatibility sentinel so OpenClaude
passes upstream minimum-version guards. The real package version is
exposed separately as `MACRO.DISPLAY_VERSION`. `update.ts` was using
`MACRO.VERSION` for both the version shown to the user and for every
`latestVersion` comparison, which meant:

- Users always saw `99.0.0` as their "current version".
- `99.0.0 >= <any real npm version>`, so the "up to date" and
  "update available" checks could never fire correctly.

Fix (scoped to `src/cli/update.ts`):

- Use `MACRO.DISPLAY_VERSION` for all user-facing version strings and
  version comparisons.
- Replace the dead-end `Warning: Cannot update development build`
  (which exited 1 with no guidance) with actionable instructions for
  both source builds (`git pull && bun install && bun run build`) and
  npm installs (`npm install -g @gitlawb/openclaude@latest`).
- Extend the existing third-party-provider branch to also show the
  current version and the npm reinstall command, so users who
  installed via npm aren't told only to rebuild from source.
2026-04-24 11:33:03 +08:00
0xfandom
e346b8d5ec fix(startup): url authoritative over model name in banner provider detect (#864)
The banner provider branch tested model-name substrings (`/deepseek/`, `/kimi/`,
`/mistral/`, `/llama/`) before aggregator base-URL substrings (`/openrouter/`,
`/together/`, `/groq/`, `/azure/`). When running OpenRouter/Together/Groq with
vendor-prefixed model IDs (e.g. `deepseek/deepseek-chat`, `moonshotai/kimi-k2`,
`deepseek-r1-distill-llama-70b`), the banner mislabelled the provider.

Reorder: explicit env flags (NVIDIA_NIM, MINIMAX_API_KEY) and codex transport
win first; base-URL host checks run before rawModel fallback; rawModel only
fires when the base URL is generic/custom. Add unit tests covering the
aggregator × vendor-prefixed-model matrix plus direct-vendor regressions.

Closes #855
2026-04-24 01:52:27 +08:00
hika, maeng
b750e9e97d fix: make OpenAI fallback context window configurable + support external model lookup (#861)
* fix: make OpenAI fallback context window configurable and support external lookup table

Unknown OpenAI-compatible models fell back to a hardcoded 128k constant,
causing auto-compact to fire prematurely on models with larger windows
(issue #635 follow-up). Two escape hatches are added without touching the
built-in table:

- CLAUDE_CODE_OPENAI_FALLBACK_CONTEXT_WINDOW (number): overrides the 128k
  default for all unknown models.
- CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS (JSON object): per-model overrides that
  take precedence over the built-in OPENAI_CONTEXT_WINDOWS table; supports
  the same provider-qualified and prefix-matching lookup as the built-in path.
- CLAUDE_CODE_OPENAI_MAX_OUTPUT_TOKENS (JSON object): same pattern for output
  token limits.

This lets operators deploy new or private models without patching
openaiContextWindows.ts on every model release.

* docs: add new OpenAI context window env vars to .env.example

Document CLAUDE_CODE_OPENAI_FALLBACK_CONTEXT_WINDOW,
CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS, and
CLAUDE_CODE_OPENAI_MAX_OUTPUT_TOKENS with usage examples.

Addresses reviewer feedback on PR #861.

---------

Co-authored-by: opencode <dev@example.com>
2026-04-24 00:34:08 +08:00
0xfandom
28de94df5d feat: add OPENCLAUDE_DISABLE_TOOL_REMINDERS env var to suppress hidden tool-output reminders (#837)
Gates three injection sites behind OPENCLAUDE_DISABLE_TOOL_REMINDERS:
- FileReadTool cyber-risk mitigation reminder (appended to every Read
  result when the model is not in MITIGATION_EXEMPT_MODELS)
- todo_reminder attachment for TodoWrite usage
- task_reminder attachment for TaskCreate/TaskUpdate usage

All three reminders are model-only side-channel instructions the user
cannot see today. Users who want full transparency over what the model
receives can now opt out without patching dist/cli.mjs on every upgrade.

Default behavior is unchanged when the flag is unset.

Closes #809
2026-04-23 01:37:02 +08:00
0xfandom
23e8cfbd5b fix(test): add missing teammate exports to hookChains integration mock (#840)
mock.module('./teammate.js', ...) only declared getAgentName/getTeamName/
getTeammateColor. Bun applies module mocks process-globally and
mock.restore() does not undo them, so whenever another test file ran
after hookChains.integration.test.ts and reached the real teammate
module it received undefined for isTeammate/isPlanModeRequired/
getAgentId/getParentSessionId.

This surfaced in CI as intermittent failures in
src/commands/provider/provider.test.tsx (TextEntryDialog / wizard
remount / ProviderWizard hides Codex OAuth), because getDefaultAppState
in AppStateStore.ts calls teammateUtils.isTeammate().

Match the mock surface to the real teammate.ts exports so downstream
consumers keep working even after the integration test pollutes the
module cache. Keeps the same behavioral overrides this test needed.

Closes #839
2026-04-23 01:36:42 +08:00
Kevin Codex
531e3f1059 feat(tools): resilient web search and fetch across all providers (#836)
- Add exponential backoff retry to DuckDuckGo adapter (3 attempts with
  jitter) to handle transient rate-limiting and connection errors.
- Add native fetch() fallback in WebFetch when axios hangs with custom
  DNS lookup in bundled contexts.
- Prevent broken native-path fallback for web search on OpenAI shim
  providers (minimax, moonshot, nvidia-nim, etc.) that do not support
  Anthropic's web_search_20250305 tool.
- Cherry-pick existing fixes:
  - a48bd56: cover codex/minimax/nvidia-nim in getSmallFastModel()
  - 31f0b68: 45s budget + raw-markdown fallback for secondary model
  - 446c1e8: sparse Codex /responses payload parsing
  - ae3f0b2: echo reasoning_content on assistant tool-call messages
- Fix domainCheck.test.ts mock modules to include isFirstPartyAnthropicBaseUrl
  and isGithubNativeAnthropicMode exports.

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-23 01:14:00 +08:00
KRATOS
3c4d8435c4 fix: surface actionable error when DuckDuckGo web search is rate-limited (#834)
Non-Anthropic / non-codex providers (minimax, kimi, generic OpenAI-compatible)
fell through to the DDG adapter when no paid search key was configured. DDG's
scraper is blocked on most IPs, so web_search surfaced an opaque "anomaly in
the request" error. Catch that response in the DDG provider and rethrow with
the exact env vars that would unblock the tool, or the option to switch to a
native-search provider.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:58:20 +08:00
Kevin Codex
67de6bd2cf fix(openai-shim): echo reasoning_content on assistant tool-call messages for Moonshot (#828)
Kimi / Moonshot's chat completions endpoint requires that every assistant
message carrying tool_calls also carry reasoning_content when the
"thinking" feature is active. When an agent sends prior-turn assistant
history back (standard multi-turn / subagent / Explore patterns), the
shim previously stripped the thinking block:

  case 'thinking':
  case 'redacted_thinking':
    // Strip thinking blocks for OpenAI-compatible providers.
    break

That's correct for providers that would mis-interpret serialized
<thinking> tags, but Moonshot validates the schema strictly and rejects
with:

  API Error: 400 {"error":{"message":"thinking is enabled but
  reasoning_content is missing in assistant tool call message at
  index N","type":"invalid_request_error"}}

Reproducer: launch with Kimi profile, run any tool-using command
(Explore, Bash, etc.) — every request after the first 400s.

Fix: in convertMessages(), when the per-request flag
preserveReasoningContent is set (only for Moonshot baseUrls today),
attach the original thinking block's text as reasoning_content on the
outgoing OpenAI-shaped assistant message. Other providers continue to
strip (unknown-field rejection risk).

OpenAIMessage type grows a reasoning_content?: string field.
convertMessages() accepts an options object and threads the flag
through; the only call site (_doOpenAIRequest) gates via
isMoonshotBaseUrl(request.baseUrl).

Tests (openaiShim.test.ts):
  - Moonshot: echoes reasoning_content on assistant tool-call messages
    (regression for the reported 400)
  - non-Moonshot providers do NOT receive reasoning_content (guards
    against leaking the field to strict-parse endpoints)

Full suite: 1195/1195 pass under --max-concurrency=1. PR scan clean.

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-22 22:47:57 +08:00
0xfandom
4d559c9135 docs(env): document OPENCLAUDE_DISABLE_STRICT_TOOLS in .env.example (#826)
Code support was merged in #770 but the .env.example entry was
missed, leaving users without a discoverable way to find the flag.

Closes #737
2026-04-22 22:16:47 +08:00
JATMN
b7b83eff13 Fix bracketed paste blocking provider form submit (#818) 2026-04-22 19:48:33 +08:00
Urvish L.
44a2c30d5f feat: implement Hook Chains runtime integration for self-healing agent mesh MVP (#711)
* feat: implement Hook Chains runtime integration for self-healing agent mesh MVP

- Add Hook Chains config loader, evaluator, and dispatcher in src/utils/hookChains.ts
- Wire PostToolUseFailure hook dispatch in executePostToolUseFailureHooks()
- Wire TaskCompleted hook dispatch in executeTaskCompletedHooks()
- Integrate fallback-agent launcher with permission preservation (canUseTool threading)
- Add safety hardening for config-read errors (try-catch protection)
- Update docs with MVP runtime trigger explanation
- Add 10 unit tests and 4 integration tests covering config, rules, guards, and actions

This completes the self-healing agent mesh MVP by enabling declarative rule-based
responses to tool failures and task completions, with fallback agent spawning,
team notification, and capacity warming actions.

* Update docs/hook-chains.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/utils/hookChains.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: address PR #711 review blockers for Hook Chains

- Gate hook-chain dispatch behind feature('HOOK_CHAINS') and default env gate to off
- Remove committed local artifact (agent.log) and ignore it in .gitignore
- Revert hook dispatcher signature threading changes for canUseTool
- Use ToolUseContext metadata hookChainsCanUseTool for fallback launch permissions
- Make spawn_fallback_agent fail explicitly when launcher context is unavailable
- Add config cache max age and guard map size limits to bound runtime memory
- Update docs and tests for default-off gating and explicit fallback failure

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-22 19:40:23 +08:00
ArkhAngelLifeJiggy
5b9cd21e37 feat: add streaming optimizer and structured request logging (#703)
* Integrate request logging and streaming optimizer

- Add logApiCallStart/End for API request tracking with correlation IDs
- Add streaming state tracking with processStreamChunk
- Flush buffer and log stream stats at stream end
- Resolve merge conflict with main branch

* feat: add streaming optimizer and structured request logging

* fix: address PR review feedback

- Remove buffering from streamingOptimizer - now purely observational
- Use logForDebugging instead of console.log for structured logging
- Remove dead code (streamResponse, bufferedStreamResponse, etc.)
- Use existing logging infrastructure instead of raw console.log
- Keep only used functions: createStreamState, processStreamChunk, getStreamStats

* test: add unit tests for requestLogging and streamingOptimizer

- streamingOptimizer.test.ts: 6 tests for createStreamState, processStreamChunk, getStreamStats
- requestLogging.test.ts: 6 tests for createCorrelationId, logApiCallStart, logApiCallEnd

* fix: correct durationMs test to be >= 0 instead of exactly 0

* fix: address PR #703 blockers and non-blockers

1. BLOCKER FIX: Skip clone() for streaming responses
   - Only call response.clone() + .json() for non-streaming requests
   - For streaming, usage comes via stream chunks anyway

2. NON-BLOCKER: Document dead code in flushStreamBuffer
   - Added comment explaining it's a no-op kept for API compat

3. NON-BLOCKER: vi.mock in tests - left as-is (test framework issue)

* fix: address all remaining non-blockers for PR #703

1. Remove dead code: flushStreamBuffer call and unused import
2. Fix test for Bun: remove vi.mock, use simple no-throw tests
2026-04-22 15:36:07 +08:00
ArkhAngelLifeJiggy
e92e5274b2 feat: add model-specific tokenizers and compression ratio detection (#799)
- ModelTokenizerConfig for different model families
- getTokenizerConfig() / getBytesPerTokenForModel()
- Content type detection (json, code, prose, list, technical)
- COMPRESSION_RATIOS - empirical ratios per content type
- estimateWithBounds() - confidence intervals

Features: 1.1, 1.14, 1.15
Tests: 13 passing
2026-04-22 13:24:12 +08:00
github-actions[bot]
86bce4ae74 chore(main): release 0.6.0 (#786)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
v0.6.0
2026-04-22 09:41:30 +08:00