Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4311254
feat: [ENG-2687] language selection foundation — BrvConfig.language +…
danhdoan May 26, 2026
25b7a70
Merge pull request #710 from campfirein/feat/ENG-2687-language-founda…
danhdoan May 26, 2026
31c7f19
feat: [ENG-2688] language selection tool-mode injection — kickoff/cor…
danhdoan May 26, 2026
10984fd
Merge pull request #711 from campfirein/feat/ENG-2688-tool-mode-injec…
danhdoan May 26, 2026
91e76be
feat: [ENG-2689] CJK-aware BM25 tokenizer — unblock Chinese / Japanes…
danhdoan May 26, 2026
c19c5bf
Merge pull request #712 from campfirein/feat/ENG-2689-tokenizer-cjk
danhdoan May 26, 2026
dbe72c0
test: [ENG-2690] language selection validation — end-to-end roundtrip…
danhdoan May 26, 2026
4341ed7
Merge pull request #713 from campfirein/feat/ENG-2690-validation
danhdoan May 26, 2026
0163bbc
feat: [ENG-2691] brv config set/get + language-selection release notes
danhdoan May 26, 2026
f52cc29
Merge pull request #714 from campfirein/feat/ENG-2691-cli-release
danhdoan May 26, 2026
19c9b6b
feat: [ENG-2974] enum settings + register language.mode/language.code…
cuongdo-byterover May 27, 2026
f40e188
feat: [ENG-2974] render language settings in TUI + WebUI Configuration
cuongdo-byterover May 27, 2026
fe56936
feat: [ENG-2974] read language from daemon settings + deprecate brv c…
cuongdo-byterover May 27, 2026
aa7282d
test: [ENG-2974] update FileSettingsStore.list keyset to include lang…
cuongdo-byterover May 27, 2026
7ee702d
fix: [ENG-2974] satisfy WebUI strict-mode tsc — narrow enum onValueCh…
cuongdo-byterover May 27, 2026
dbf2509
fix: [ENG-2974] surface LANGUAGE category in brv settings list
RyanNg1403 May 27, 2026
2df0c85
fix: [ENG-2974] route curate language read through daemon transport
RyanNg1403 May 27, 2026
f467c29
fix: [ENG-2974] relocate SETTINGS_KEYS to shared + cover language read
RyanNg1403 May 27, 2026
0f723c8
fix: [ENG-2974] address auto-reviewer follow-ups on the language-sett…
RyanNg1403 May 27, 2026
c68322c
Merge pull request #724 from campfirein/feat/ENG-2974
danhdoan May 28, 2026
a45bf98
chore: sync main after HTML conversion & Agentless mode is merged
danhdoan May 28, 2026
773db4b
feat: [ENG-3002] add language selection to onboarding tour
DatPham-6996 May 29, 2026
88164f5
Merge pull request #736 from campfirein/feat/ENG-3002
DatPham-6996 May 29, 2026
c148c92
Merge branch 'main' into proj/language-selection
danhdoan Jun 1, 2026
d7f3bf6
refactor: [ENG-2974] remove `brv config` CLI — settings is the only l…
danhdoan Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable user-facing changes to ByteRover CLI will be documented in this file.

## [Unreleased]

### Added
- **ByteRover preserves your input language by default.** When you curate context in Russian, Chinese, Japanese, Vietnamese, or any other language, the calling agent's LLM is now instructed to author body text in the same language (the schema — tag names, attribute names, enum values, paths — stays English so tooling is unaffected). Configure with the new `brv config set` command:
- `brv config set language.mode auto` — match the user's input language (default).
- `brv config set language.mode fixed` + `brv config set language.code <iso>` — force a specific language. ISO 639-1 codes accepted: `ar`, `de`, `el`, `en`, `es`, `fi`, `fr`, `he`, `hi`, `id`, `it`, `ja`, `ko`, `nl`, `no`, `pl`, `pt`, `ru`, `sv`, `th`, `tr`, `uk`, `vi`, `zh`.
- `brv config get language.mode` / `brv config get language.code` — read back the current setting.

CJK queries (Chinese, Japanese, Korean) are now searchable in BM25 — the tokenizer was previously whitespace-only and treated entire CJK sentences as one token. **Restoration recipe** for users who prefer the prior implicit-English behavior: `brv config set language.code en` then `brv config set language.mode fixed`. Reported by Dmitriy K — thanks for the thorough reproduction in [#616](https://github.com/campfirein/byterover-cli/issues/616).
Comment on lines +8 to +13
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (blocking — user-facing): The release notes describe brv config set/get language.* as the public surface, but commit d7f3bf6 ("remove brv config CLI — settings is the only language surface") deleted the entire brv config command in this same PR. A user who reads these notes and runs brv config set language.mode auto will hit Command not found — and so will the restoration recipe at the bottom (brv config set language.code en then brv config set language.mode fixed), which is the headline "don't lose your prior behavior" path for the people most likely to care.

The canonical surface is now brv settings set language.mode|code (and brv settings get … to read back). The supported-codes list and the restoration recipe also need updating.

Suggested edit:

Suggested change
- **ByteRover preserves your input language by default.** When you curate context in Russian, Chinese, Japanese, Vietnamese, or any other language, the calling agent's LLM is now instructed to author body text in the same language (the schema — tag names, attribute names, enum values, paths — stays English so tooling is unaffected). Configure with the new `brv config set` command:
- `brv config set language.mode auto` — match the user's input language (default).
- `brv config set language.mode fixed` + `brv config set language.code <iso>` — force a specific language. ISO 639-1 codes accepted: `ar`, `de`, `el`, `en`, `es`, `fi`, `fr`, `he`, `hi`, `id`, `it`, `ja`, `ko`, `nl`, `no`, `pl`, `pt`, `ru`, `sv`, `th`, `tr`, `uk`, `vi`, `zh`.
- `brv config get language.mode` / `brv config get language.code` — read back the current setting.
CJK queries (Chinese, Japanese, Korean) are now searchable in BM25 — the tokenizer was previously whitespace-only and treated entire CJK sentences as one token. **Restoration recipe** for users who prefer the prior implicit-English behavior: `brv config set language.code en` then `brv config set language.mode fixed`. Reported by Dmitriy K — thanks for the thorough reproduction in [#616](https://github.com/campfirein/byterover-cli/issues/616).
- **ByteRover preserves your input language by default.** When you curate context in Russian, Chinese, Japanese, Vietnamese, or any other language, the calling agent's LLM is now instructed to author body text in the same language (the schema — tag names, attribute names, enum values, paths — stays English so tooling is unaffected). Configure with `brv settings`:
- `brv settings set language.mode auto` — match the user's input language (default).
- `brv settings set language.mode fixed` + `brv settings set language.code <iso>` — force a specific language. ISO 639-1 codes accepted: `ar`, `de`, `el`, `en`, `es`, `fi`, `fr`, `he`, `hi`, `id`, `it`, `ja`, `ko`, `nl`, `no`, `pl`, `pt`, `ru`, `sv`, `th`, `tr`, `uk`, `vi`, `zh`.
- `brv settings get language.mode` / `brv settings get language.code` — read back the current setting.
CJK queries (Chinese, Japanese, Korean) are now searchable in BM25 — the tokenizer was previously whitespace-only and treated entire CJK sentences as one token. **Restoration recipe** for users who prefer the prior implicit-English behavior: `brv settings set language.code en` then `brv settings set language.mode fixed`. Reported by Dmitriy K — thanks for the thorough reproduction in [#616](https://github.com/campfirein/byterover-cli/issues/616).

Also note that the PR body still references the deprecation-gate cases (Case 6) as part of the harness migration; per the d7f3bf6 commit message those were also removed (language-selection-e2e went 22 → 20). Worth a quick sweep on the PR description so future archaeology lines up with the final commit.

## [3.16.1]

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion src/agent/infra/agent/cipher-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import type {ToolProvider} from '../tools/tool-provider.js'
import type {AgentConfig} from './agent-schemas.js'
import type {ProviderUpdateConfig} from './provider-update-config.js'

import {SETTINGS_KEYS} from '../../../server/core/domain/entities/settings.js'
import {TransportStateEventNames} from '../../../server/core/domain/transport/schemas.js'
import {agentLog} from '../../../server/utils/process-logger.js'
import {SETTINGS_KEYS} from '../../../shared/types/settings-keys.js'
import {getEffectiveMaxInputTokens, resolveRegistryProvider} from '../../core/domain/llm/index.js'
import {STREAMING_EVENT_NAMES} from '../../core/domain/streaming/types.js'
import {ToolName} from '../../core/domain/tools/constants.js'
Expand Down
159 changes: 159 additions & 0 deletions src/agent/infra/tools/implementations/cjk-tokenizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/**
* BM25 tokenizer with CJK bigram segmentation.
*
* MiniSearch 7.2.0's default tokenizer splits on `\p{Z}\p{P}` (Unicode
* whitespace + punctuation). Latin / Cyrillic / Vietnamese / European
* scripts use whitespace between words and tokenize correctly. CJK scripts
* do not — a sentence like `认证系统使用JWT令牌` becomes a single token,
* so a query for `认证` against indexed CJK content returns zero matches.
*
* Empirical confirmation before this fix (MiniSearch 7.2.0):
*
* const ms = new MiniSearch({fields: ['t'], idField: 'id'})
* ms.addAll([{id: 1, t: '认证系统使用JWT令牌'}])
* ms.search('认证') // → [] — broken
* ms.search('Привет мир') // → matches as expected
*
* This tokenizer preserves the default behavior for whitespace-separated
* scripts and adds overlapping-bigram segmentation for CJK runs. Mixed
* Latin+CJK tokens (e.g. `JWT令牌`) split at the script boundary so the
* Latin portion stays a real word token.
*
* Wired via the top-level `tokenize` option on MiniSearch — per the
* library docs and source (`MiniSearch.js:1564-1566`), that single option
* applies at both index and query time unless `searchOptions.tokenize`
* is set, which we leave unset.
*/

/**
* Unicode ranges treated as CJK for the purposes of bigram segmentation.
* Anything outside these ranges is "non-CJK" and tokenizes by whitespace
* boundaries only.
*
* - `0x4E00–0x9FFF`: CJK Unified Ideographs (Chinese, Japanese kanji)
* - `0x3040–0x309F`: Hiragana
* - `0x30A0–0x30FF`: Katakana
* - `0xAC00–0xD7AF`: Hangul Syllables (Korean)
*
* CJK Extension A/B/C/… are deliberately excluded — they appear in academic
* / historical text but rarely in user content. If a user's corpus needs
* them, extend this list and bump `INDEX_SCHEMA_VERSION` in
* `search-knowledge-service.ts` so cached indexes invalidate.
*/
const CJK_RANGES: ReadonlyArray<readonly [number, number]> = [
[0x4E_00, 0x9F_FF],
[0x30_40, 0x30_9F],
[0x30_A0, 0x30_FF],
[0xAC_00, 0xD7_AF],
]
Comment thread
danhdoan marked this conversation as resolved.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (non-blocking, zh-TW coverage): The ranges deliberately exclude CJK Extension A (0x3400-0x4DBF), which covers ~6,500 codepoints in active use across Traditional Chinese — proper nouns, place names, corporate names, academic and historical text in zh-TW and zh-HK corpora. The comment defends the exclusion as "rarely in user content," which holds on aggregate but optimistically for Taiwan/HK knowledge bases.

Extension A is BMP, so for...of handles it without surrogate-pair work, and the bigram-index cost is proportional to occurrences (effectively zero on non-zh-TW corpora). Adding it is one line:

Suggested change
]
const CJK_RANGES: ReadonlyArray<readonly [number, number]> = [
[0x34_00, 0x4D_BF],
[0x4E_00, 0x9F_FF],
[0x30_40, 0x30_9F],
[0x30_A0, 0x30_FF],
[0xAC_00, 0xD7_AF],
]

The maintainer note already points at INDEX_SCHEMA_VERSION = 7 for invalidation — that's the cost. If you'd rather stay conservative, leaving as-is is fine; log a follow-up the first time a zh-TW user reports search misses on rare characters.


function isCjkCodePoint(cp: number): boolean {
for (const [lo, hi] of CJK_RANGES) {
if (cp >= lo && cp <= hi) return true
}

return false
}

/**
* Whitespace + punctuation split, matching MiniSearch's default
* `SPACE_OR_PUNCTUATION` regex. Kept verbatim so a future upstream tweak
* is easy to spot via diff.
*/
const SPACE_OR_PUNCTUATION = /[\p{Z}\p{P}]+/u

/**
* Split a token at boundaries between CJK and non-CJK runs.
*
* - `'JWT令牌'` → `['JWT', '令牌']` (script boundary at index 3)
* - `'认证'` → `['认证']` (single CJK run)
* - `'JWT'` → `['JWT']` (single non-CJK run)
*/
function splitAtCjkBoundary(token: string): string[] {
const segments: string[] = []
let current = ''
let currentIsCjk: boolean | undefined

// Iterate by code point so any future range extension into the
// supplementary plane handles surrogate pairs correctly. The current
// four ranges are all BMP, so `for...of` is equivalent to char-by-char
// here — but cheap to be correct.
for (const ch of token) {
const cp = ch.codePointAt(0)
if (cp === undefined) continue
const charIsCjk = isCjkCodePoint(cp)

if (currentIsCjk === undefined) {
current = ch
currentIsCjk = charIsCjk
} else if (charIsCjk === currentIsCjk) {
current += ch
} else {
segments.push(current)
current = ch
currentIsCjk = charIsCjk
}
}

if (current.length > 0) segments.push(current)

return segments
}

/**
* Emit overlapping bigrams for a CJK run.
*
* - `'认证系统'` (4 chars) → `['认证', '证系', '系统']`
* - `'认证'` (2 chars) → `['认证']`
* - `'认'` (1 char) → `['认']` (unigram fallback so single-char tokens are searchable)
*
* Bigrams are the standard CJK IR compromise: unigrams are too noisy
* (common chars like `的` dominate scoring), trigrams are too sparse
* (miss 2-character compound matches).
*/
function cjkBigrams(run: string): string[] {
const chars = [...run]
if (chars.length <= 1) return chars

const grams: string[] = []
for (let i = 0; i < chars.length - 1; i++) {
grams.push(chars[i] + chars[i + 1])
}

return grams
}

/**
* Tokenize text for BM25 indexing and querying.
*
* Algorithm:
* 1. Split on Unicode whitespace + punctuation (matches MiniSearch default).
* 2. For each resulting token, split at CJK ↔ non-CJK script boundaries.
* 3. For non-CJK segments, emit the segment as-is.
* 4. For CJK segments, emit overlapping bigrams.
*
* The result is the union — Latin / Cyrillic / Vietnamese behave exactly
* as the MiniSearch default, while CJK runs become searchable.
*/
export function tokenizeWithCjk(text: string): string[] {
const out: string[] = []

for (const wsToken of text.split(SPACE_OR_PUNCTUATION)) {
if (wsToken.length === 0) continue

for (const segment of splitAtCjkBoundary(wsToken)) {
if (segment.length === 0) continue

// `splitAtCjkBoundary` returns single-script segments, so the
// first code point's classification applies to the whole segment.
const firstCp = segment.codePointAt(0)
if (firstCp !== undefined && isCjkCodePoint(firstCp)) {
out.push(...cjkBigrams(segment))
} else {
out.push(segment)
}
}
}

return out
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
import {getFormatForRead} from '../../../../server/infra/render/format/format-detector.js'
import {ElementAxisIndex} from '../../../../server/infra/render/reader/element-axis-index.js'
import {readHtmlTopicSync} from '../../../../server/infra/render/reader/html-reader.js'
import {tokenizeWithCjk} from './cjk-tokenizer.js'
import {isPathLikeQuery, matchMemoryPath, parseSymbolicQuery} from './memory-path-matcher.js'
import {
buildReferenceIndex,
Expand All @@ -52,10 +53,7 @@ import {
const MAX_CONTEXT_TREE_FILES = 10_000
const DEFAULT_CACHE_TTL_MS = 5000

/**
* Bump when MINISEARCH_OPTIONS fields/boost change to invalidate cached indexes.
* v7 (ENG-3021): include `<img>` alt + src in HTML topic indexed content.
*/
/** Bump when MINISEARCH_OPTIONS fields/boost change to invalidate cached indexes */
const INDEX_SCHEMA_VERSION = 7

/** Only include results whose normalized score is at least this fraction of the top result's score */
Expand Down Expand Up @@ -174,6 +172,12 @@ const MINISEARCH_OPTIONS = {
prefix: true,
},
storeFields: ['title', 'path'] as string[],
// Custom tokenizer adds CJK bigram segmentation alongside the default
// whitespace split. Without it, queries against Chinese / Japanese /
// Korean content return zero matches even when the content is curated
// correctly — see `cjk-tokenizer.ts`. Top-level `tokenize` applies to
// both indexing and querying per MiniSearch's API.
tokenize: tokenizeWithCjk,
}

interface IndexedDocument {
Expand Down
80 changes: 78 additions & 2 deletions src/oclif/commands/curate/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import {Args, Command, Flags} from '@oclif/core'

import type {BrvConfigLanguage} from '../../../server/core/domain/entities/brv-config.js'
import type {CurateSessionEnvelope} from '../../lib/curate-session.js'

import {ProjectConfigStore} from '../../../server/infra/config/file-config-store.js'
import {SettingsEvents, type SettingsListResponse} from '../../../shared/transport/events/settings-events.js'
import {SETTINGS_KEYS} from '../../../shared/types/settings-keys.js'
import {
continueSession,
deleteCurateResponseFile,
Expand Down Expand Up @@ -122,17 +126,19 @@ Bad examples:
protected async dispatchContinuation(args: {
confirmOverwrite: boolean
format: 'json' | 'text'
language?: BrvConfigLanguage
projectRoot: string
response: string
sessionId: string
}): Promise<CurateSessionEnvelope> {
const {confirmOverwrite, format, projectRoot, response, sessionId} = args
const {confirmOverwrite, format, language, projectRoot, response, sessionId} = args
let envelope: CurateSessionEnvelope | undefined
await withDaemonRetry(async (client) => {
envelope = await continueSession({
client,
confirmOverwrite,
format,
language,
projectRoot,
response,
sessionId,
Expand Down Expand Up @@ -466,11 +472,16 @@ Bad examples:
// this path so the agent retains the source it already paid an
// LLM call to produce.
const confirmOverwrite = flags.overwrite ?? false
// Read fresh per continuation — mirrors kickoff so a mid-session
// language change (rare) is honored on the next correction prompt.
// The same fallback chain applies (daemon settings → project config).
const language = await this.resolveLanguagePreference(projectRoot)
let dispatchEnvelope: CurateSessionEnvelope
try {
dispatchEnvelope = await this.dispatchContinuation({
confirmOverwrite,
format,
language,
projectRoot,
response,
sessionId,
Expand Down Expand Up @@ -550,9 +561,74 @@ Bad examples:
return
}

const envelope = await kickoffSession({content, projectRoot: resolveProjectRoot()})
const projectRoot = resolveProjectRoot()
const language = await this.resolveLanguagePreference(projectRoot)
const envelope = await kickoffSession({content, language, projectRoot})
this.emitToolModeEnvelope(envelope, format)
}

/**
* Resolve the language preference. Daemon settings (the source of
* truth) take precedence; a per-project `.brv/config.json language`
* field acts as a fallback for users who configured language before
* it moved to global settings.
*
* Note on precedence: only daemon `mode: 'fixed'` short-circuits the
* fallback. An explicit daemon `mode: 'auto'` reads as "no opinion"
* and falls through to project config, so a stale project-config
* `fixed/X` will still win. This is intentional for the migration
* window — distinguishing "user explicitly chose auto" from "user
* never touched settings" needs raw-overrides access that the
* transport doesn't expose today, and the bug only manifests for
* users with a pre-existing per-project `language` field. Revisit
* once project-config language is fully sunset.
*/
private async resolveLanguagePreference(projectRoot: string): Promise<BrvConfigLanguage | undefined> {
const fromSettings = await readLanguageFromSettings()
if (fromSettings !== undefined) return fromSettings

try {
const config = await new ProjectConfigStore().read(projectRoot)
return config?.language
} catch {
return undefined
}
}
Comment on lines +586 to +596
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (non-blocking): Precedence bug: an explicit daemon mode: 'auto' cannot override a stale per-project {mode: 'fixed', code: …} because readLanguageFromSettings returns undefined for any non-fixed daemon mode and resolveLanguagePreference then falls through to project config. This is documented in the docstring as intentional during the migration window, but the comment buries the lede — the function name suggests "no opinion" while the behavior is "no opinion only when daemon says fixed."

Worth at least logging the override edge-case for forensics (the docstring already says "revisit once project-config language is fully sunset"), and tracking the project-config sunset as a follow-up in the PR's "Out of scope" list (already noted). Confirm the WebUI Settings → Language → "auto" toggle messaging makes it clear that a project-config override may still apply mid-migration, or users will report "I clicked auto but it's still writing in Russian" until the sunset lands.

Comment on lines +570 to +596
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (non-blocking — but worth tracking): With brv config now removed (per commit d7f3bf6), this fallback's job has shifted from "honor a current-but-deprecated surface" to "honor stale state nobody can write any more." A user mid-migration whose .brv/config.json still has {language: {mode: 'fixed', code: 'ru'}} and who then flips daemon language.mode to auto will not see auto take effect — readLanguageFromSettings returns undefined for any non-fixed daemon mode, and the project-config fixed wins via this fallthrough.

That's the same precedence quirk the prior auto-reviewer flagged (the docstring at L575-585 calls it out and defers it to the project-config sunset). The new wrinkle is that the user has no way to clear the stale state — there's no brv config set ... to write auto over it, and editing .brv/config.json by hand is undocumented. So the fallback now acts as a one-way migration trap rather than a graceful bridge.

Two ways forward:

  1. Honor explicit auto — change readLanguageFromSettings to return {mode: 'auto'} when the daemon explicitly says auto (instead of undefined), and treat that as "user has opinions, do not consult fallback." Closes the trap cleanly and matches what a user expects after toggling the WebUI Language → auto control.
  2. Drop the project-config fallback entirely in a follow-up PR — the PR description's "Out of scope" already names this, but with brv config gone the fallback no longer serves a live surface; it only matters for users upgrading from a pre-ENG-2974 build.

(1) is a small, surgical change behind a unit test; (2) needs a migration sweep but cleans up the legacy code path. (1) makes (2) safer to land later. Worth at least surfacing on the WebUI Language → auto control with a one-line "if you previously configured a per-project language, it may still apply" hint until (1) lands, to avoid the "I clicked auto but it's still writing in Russian" report.

}

/**
* Reads the language preference from daemon settings via the same
* `SettingsEvents.LIST` transport every other settings consumer uses.
*
* Exported (and accepts a `DaemonClientOptions`) so tests can drive
* `withDaemonRetry` with a stubbed transport client. Returns `undefined`
* on any non-fixed mode, missing/non-string code, or daemon error —
* callers should treat `undefined` as "no opinion" and fall back to
* project config / the auto clause.
*
* Uses a tight retry budget by default (1 retry, 0ms delay) because this
* runs on every `brv curate` kickoff: `withDaemonRetry`'s 10× retries ×
* 1s default would block kickoff for ~9s when the daemon is unreachable
* before the catch trips the project-config fallback. The caller can
* override either field by passing it in `options`.
*/
export async function readLanguageFromSettings(
options?: DaemonClientOptions,
): Promise<BrvConfigLanguage | undefined> {
try {
const response = await withDaemonRetry<SettingsListResponse>(
async (client) => client.requestWithAck<SettingsListResponse>(SettingsEvents.LIST),
{maxRetries: 1, retryDelayMs: 0, ...options},
)
const byKey = new Map(response.items.map((item) => [item.key, item.current]))
const mode = byKey.get(SETTINGS_KEYS.LANGUAGE_MODE)
const code = byKey.get(SETTINGS_KEYS.LANGUAGE_CODE)
if (mode !== 'fixed') return undefined
if (typeof code !== 'string') return undefined
return {code, mode: 'fixed'}
} catch {
return undefined
}
}

/**
Expand Down
8 changes: 7 additions & 1 deletion src/oclif/commands/settings/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ export default class SettingsGet extends Command {
this.log(` range: ${range}`)
}

if (item.type === 'enum' && item.options !== undefined && item.options.length > 0) {
this.log(` allowed: ${item.options.join(', ')}`)
}

this.log(` scope: ${item.scope ?? 'global'}`)
}

Expand All @@ -99,12 +103,14 @@ export default class SettingsGet extends Command {
if (item.category !== undefined) payload.category = item.category
if (item.unit !== undefined) payload.unit = item.unit
if (item.scope !== undefined) payload.scope = item.scope
if (item.type === 'enum' && item.options !== undefined) payload.options = item.options
return payload
}
}

function renderValue(item: SettingsItemDTO, value: boolean | number): string {
function renderValue(item: SettingsItemDTO, value: boolean | number | string): string {
if (typeof value === 'boolean') return value ? 'true' : 'false'
if (typeof value === 'string') return value
return renderInteger(item, value)
}

Expand Down
Loading
Loading