Skip to content

feat(openclaw): 增加 OpenClaw 工具配置支持#11

Draft
krisxia0506 wants to merge 1 commit into
mainfrom
codex/add-openclaw-support
Draft

feat(openclaw): 增加 OpenClaw 工具配置支持#11
krisxia0506 wants to merge 1 commit into
mainfrom
codex/add-openclaw-support

Conversation

@krisxia0506
Copy link
Copy Markdown
Collaborator

变更内容

  • 新增 OpenClawTool,通过 openclaw config set/unset 写入和清理七牛相关配置。
  • 注册 openclaw 工具,并支持 openclaw / claw 别名用于 auth reload 和 enter。
  • 为 OpenClaw provider 配置、模型引用、写入操作和清理操作增加 node:test 覆盖。
  • 更新英文/中文 README,补充 OpenClaw 使用方式、配置结构和排障说明。

设计边界

  • 只管理七牛 custom provider、env.QINIU_API_KEY、默认模型和对应模型别名。
  • 不接管 OpenClaw 的 gateway、channels、daemon、workspace、pairing 等配置。
  • 使用 OpenClaw 官方配置 CLI 做 JSON5 局部写入,避免在本工具内实现 JSON5 合并器。

Fixes #10

验证

  • pnpm test

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request expands the CLI helper to support Codex and OpenClaw integrations, enabling users to configure these assistants with Qiniu AI API endpoints. The changes include a new OpenClawTool implementation, registration of the tool in the manager, and updated documentation. Review feedback identifies a bug in base URL construction that could lead to redundant path segments, a logic error in the configuration status check, and a lack of error handling when executing external CLI commands. Additionally, a recommendation was made to refactor duplicated tool resolution logic into a shared utility.


export function buildOpenClawProviderConfig(baseUrl: string, model: string): Record<string, unknown> {
return {
baseUrl: `${baseUrl.replace(/\/+$/, '')}/v1`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Unconditionally appending /v1 to the baseUrl can lead to incorrect URLs if the provided baseUrl already includes the version suffix (e.g., https://api.qnaigc.com/v1 would become https://api.qnaigc.com/v1/v1). It's safer to check if the suffix is already present.

Suggested change
baseUrl: `${baseUrl.replace(/\/+$/, '')}/v1`,
baseUrl: baseUrl.replace(/\/+$/, '').endsWith('/v1') ? baseUrl.replace(/\/+$/, '') : `${baseUrl.replace(/\/+$/, '')}/v1`,

getConfig(): Record<string, unknown> {
return {
configPath: getOpenClawConfigPath(),
configured: this.getModelConfig()?.sonnetModel?.startsWith(`${PROVIDER_NAME}/`) || hasOpenClawConfigFile(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The logic for the configured property is incorrect. this.getModelConfig() already slices off the ${PROVIDER_NAME}/ prefix, so calling startsWith on its result will always return false. Additionally, if getModelConfig() returns a valid configuration, it means the tool is already configured for Qiniu, making the redundant check unnecessary.

Suggested change
configured: this.getModelConfig()?.sonnetModel?.startsWith(`${PROVIDER_NAME}/`) || hasOpenClawConfigFile(),
configured: !!this.getModelConfig() || hasOpenClawConfigFile(),

Comment on lines +154 to +158
function runOpenClawOperations(operations: OpenClawOperation[]): void {
for (const args of operations) {
execFileSync('openclaw', args, { stdio: 'pipe' });
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The runOpenClawOperations function does not handle potential execution errors. If the openclaw CLI is not installed or if a command fails, execFileSync will throw an exception that could crash the application. Consider wrapping the execution in a try-catch block to provide a more user-friendly error message or to handle the failure gracefully.

Suggested change
function runOpenClawOperations(operations: OpenClawOperation[]): void {
for (const args of operations) {
execFileSync('openclaw', args, { stdio: 'pipe' });
}
}
function runOpenClawOperations(operations: OpenClawOperation[]): void {
try {
for (const args of operations) {
execFileSync('openclaw', args, { stdio: 'pipe' });
}
} catch (error) {
throw new Error(`Failed to execute OpenClaw command: ${error instanceof Error ? error.message : String(error)}`);
}
}

Comment thread src/commands/auth.ts
Comment on lines 11 to 16
function resolveToolName(tool: string): string {
if (tool === 'claude' || tool === 'claude-code') return 'claude-code';
if (tool === 'codex' || tool === 'openai-codex') return 'codex';
if (tool === 'openclaw' || tool === 'claw') return 'openclaw';
return tool;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The resolveToolName function is duplicated in both src/commands/auth.ts and src/lib/command.ts. This duplication makes the code harder to maintain. Consider moving this utility function to a shared location, such as src/lib/tool-manager.ts or a dedicated utility file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

支持 OpenClaw 配置七牛 AI 端点

1 participant