* ♻️ refactor(cli): collect every product-naming string into one module
The CLI's identity was spread across a dozen files: bin names in
`utils/completion.ts`, the config directory duplicated in five places, the
systemd unit name defined twice, the product name in a handful of command
descriptions, and — least visibly — inside `buildNotifyProtocol`, a prompt
handed to heterogeneous agents that the model then repeats back to the
user.
That is fine for a single distribution and leaves a white-label build with
no seam. Several of these are reached at runtime along paths no UI gating
can intercept, and one of them is a prompt, so there is nothing to gate.
`src/constants/identity.ts` now holds all of them. Values are upstream's,
unchanged, and the default build's observable output is identical —
verified by building with this repo's own config and diffing what the CLI
prints:
Usage: lh [options] [command]
LobeHub CLI - manage and connect to LobeHub services
complete -o nosort -F _lobehub_completion lh lobe lobehub
lh - LobeHub CLI - manage and connect to LobeHub services
Two things that were already wrong, fixed on the way:
- `skillLocator.ts` compared `pkg.name` against a hardcoded
`'@lobehub/cli'`, so the package-root walk breaks for any fork or
rename. It reads `cliPackageName` now, which is the same value from
the same package.json.
- `constants/auth.ts` exposed a single API-key env var name. It is a
list now, most-preferred first, so a distribution can introduce its
own prefix without breaking a variable a user already exported. Only
USER-set variables moved; `LOBEHUB_SERVER`, `LOBEHUB_JWT` and the
agent-run ids are injected by the desktop app and the server, so
renaming those needs all three sides to move together and is left
alone.
`man/roff.ts` also stops hardcoding `LH` and `@lobehub/cli` in the roff
header, taking them from the bin name and `pkg.ts` instead — the man page
described a command that would not exist under any other name.
* ♻️ refactor(api-key): make the key prefix a slot instead of a literal
`sk-lh-` was hardcoded in four places and asserted in four test files. It
is the one brand string a deployment's end users actually handle — they
copy it out of the UI, paste it into CI config, quote it in support
threads — so on a white-label distribution it undoes the rebranding
everywhere else.
It is also load-bearing rather than cosmetic. `validateApiKeyFormat` is
what the OpenAPI auth middleware uses to tell an API key from an OIDC
JWT, so generation and validation must read the same value or every
issued key fails auth as a malformed JWT. That is why the prefix is one
constant now, used by both.
`API_KEY_PREFIX` defaults to `sk-lh-`, so upstream's behaviour is
unchanged — verified by generating a key and round-tripping it through
the validator.
Two deliberate choices in the implementation:
- Validation compares the prefix with `startsWith` and tests only the
16-character suffix against a static pattern, rather than
interpolating the prefix into a RegExp. The prefix is data flowing
into a pattern, and escaping it correctly is a thing to get wrong;
this way there is nothing to escape and the check stays correct for
whatever prefix a distribution picks.
- The tests derive their fixtures from the constant instead of
hardcoding a spelling, so they pass for any prefix. Several of them
fed a literal straight into `validateApiKeyFormat`, so they would
have gone red the moment anyone overrode it — failing on the
override rather than on a real defect.
`spec.ts`'s `bearerFormat` follows the constant too; it is the public
API document, so it was advertising a format the deployment no longer
issues.
* ♻️ refactor(cli): collect the completion word-index env var into identity.ts
CLI_COMPLETION_CWORD_ENV joins the other product-naming strings in
identity.ts. `LOBEHUB_COMP_CWORD` was the one string the earlier
identity refactor (a65fa6a9) missed — it's set by the generated
completion script and read right back by `__complete` in the same
process, so it never surfaces in help text and slipped past every
rendered-output check.
Purely internal plumbing (unlike CLI_API_KEY_ENV_NAMES), so no
back-compat list is needed: both sides always come from the one
installed binary.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* 🛡️ fix(api-key): fall back to sk-lh- when a distribution override omits the slot
A downstream `@lobechat/business-const` override replaces the whole module
instead of extending it, so one written before this slot existed simply
omits API_KEY_PREFIX rather than inheriting upstream's default — that
either fails typecheck or, if typecheck is skipped, crashes key generation
and validation on undefined.length.
Resolve it once in packages/utils/apiKey.ts with an explicit runtime
fallback to 'sk-lh-', and have every other consumer (openapi spec, tests)
import the resolved constant from there instead of the raw slot.
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* fix command issue
* add run command UI
* fix API key
* add apikey page
* add apikey
* 🐛 fix: update apiKey model tests to use new sk-lh- prefix format
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* ✨ feat(openapi): add API key hash support for secure storage
* ✨ feat(openapi): enhance message translation and knowledge base functionality
- Added MessageTranslationController and associated routes for managing message translations, including fetching, creating, updating, and deleting translations.
- Introduced KnowledgeBaseController with routes for CRUD operations on knowledge bases, including file management and access control.
- Updated existing message and translation routes to improve structure and naming consistency.
- Refactored related services and types to support new features and ensure type safety.
This update enhances the API's capabilities for handling message translations and knowledge base management, improving overall functionality and user experience.
* fix: allow OWNER scope to list agents in agents route
- Add OWNER scope to AGENT_READ permission check
- Aligns list behavior with AgentService.queryAgents ownership filter
- Allows owner-scoped users to list their own agents
* 🔧 refactor(rbac): improve import structure in rbac.ts
- Changed import statements to separate type imports from regular imports for better clarity and organization.
- This refactor enhances code readability and maintains consistency in the import structure.
* fix: 修复 chunk 服务与 async router 的循环依赖
- 将 createAsyncCaller 的静态导入改为动态导入 (await import)
- 打破 file.ts -> chunk/index.ts -> async/index.ts 的循环依赖链
- 使用 --skip-dynamic-imports 参数的 dpdm 验证循环依赖已解决
* 🐛 fix: resolve CI failures
* test: 补充 apiKey、KeyVaultsEncrypt、ChunkService 单测至 100% 覆盖率
- test(database): 补充 apiKey.ts query() 解密失败分支测试
- test(server): 补充 KeyVaultsEncrypt 非法密钥/密文格式 getUserKeyVaults 测试
- test(server): 新增 ChunkService 完整测试覆盖异步任务创建/触发/失败回写
所有新增测试通过 (46/46),目标文件覆盖率均达 100%